| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | /**************************************************************************
 | 
					
						
							|  |  |  |  * Copyright (c) 2011, Intel Corporation. | 
					
						
							|  |  |  |  * All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify it | 
					
						
							|  |  |  |  * under the terms and conditions of the GNU General Public License, | 
					
						
							|  |  |  |  * version 2, as published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope it will be useful, but WITHOUT | 
					
						
							|  |  |  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
					
						
							|  |  |  |  * more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License along with | 
					
						
							|  |  |  |  * this program; if not, write to the Free Software Foundation, Inc., | 
					
						
							|  |  |  |  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "psb_drv.h"
 | 
					
						
							|  |  |  | #include "mid_bios.h"
 | 
					
						
							|  |  |  | #include "mdfld_output.h"
 | 
					
						
							|  |  |  | #include "mdfld_dsi_output.h"
 | 
					
						
							|  |  |  | #include "tc35876x-dsi-lvds.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/intel_scu_ipc.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
 | 
					
						
							|  |  |  | #define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
 | 
					
						
							|  |  |  | #define BLC_PWM_FREQ_CALC_CONSTANT 32
 | 
					
						
							|  |  |  | #define MHz 1000000
 | 
					
						
							|  |  |  | #define BRIGHTNESS_MIN_LEVEL 1
 | 
					
						
							|  |  |  | #define BRIGHTNESS_MAX_LEVEL 100
 | 
					
						
							|  |  |  | #define BRIGHTNESS_MASK	0xFF
 | 
					
						
							|  |  |  | #define BLC_POLARITY_NORMAL 0
 | 
					
						
							|  |  |  | #define BLC_POLARITY_INVERSE 1
 | 
					
						
							|  |  |  | #define BLC_ADJUSTMENT_MAX 100
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MDFLD_BLC_PWM_PRECISION_FACTOR    10
 | 
					
						
							|  |  |  | #define MDFLD_BLC_MAX_PWM_REG_FREQ        0xFFFE
 | 
					
						
							|  |  |  | #define MDFLD_BLC_MIN_PWM_REG_FREQ        0x2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
 | 
					
						
							|  |  |  | #define MDFLD_BACKLIGHT_PWM_CTL_SHIFT	(16)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct backlight_device *mdfld_backlight_device; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int mdfld_set_brightness(struct backlight_device *bd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct drm_device *dev = | 
					
						
							|  |  |  | 		(struct drm_device *)bl_get_data(mdfld_backlight_device); | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = dev->dev_private; | 
					
						
							|  |  |  | 	int level = bd->props.brightness; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DRM_DEBUG_DRIVER("backlight level set to %d\n", level); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Perform value bounds checking */ | 
					
						
							|  |  |  | 	if (level < BRIGHTNESS_MIN_LEVEL) | 
					
						
							|  |  |  | 		level = BRIGHTNESS_MIN_LEVEL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (gma_power_begin(dev, false)) { | 
					
						
							|  |  |  | 		u32 adjusted_level = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * Adjust the backlight level with the percent in | 
					
						
							|  |  |  | 		 * dev_priv->blc_adj2 | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		adjusted_level = level * dev_priv->blc_adj2; | 
					
						
							|  |  |  | 		adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; | 
					
						
							|  |  |  | 		dev_priv->brightness_adjusted = adjusted_level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (mdfld_get_panel_type(dev, 0) == TC35876X) { | 
					
						
							|  |  |  | 			if (dev_priv->dpi_panel_on[0] || | 
					
						
							|  |  |  | 					dev_priv->dpi_panel_on[2]) | 
					
						
							|  |  |  | 				tc35876x_brightness_control(dev, | 
					
						
							|  |  |  | 						dev_priv->brightness_adjusted); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if (dev_priv->dpi_panel_on[0]) | 
					
						
							|  |  |  | 				mdfld_dsi_brightness_control(dev, 0, | 
					
						
							|  |  |  | 						dev_priv->brightness_adjusted); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (dev_priv->dpi_panel_on[2]) | 
					
						
							|  |  |  | 			mdfld_dsi_brightness_control(dev, 2, | 
					
						
							|  |  |  | 					dev_priv->brightness_adjusted); | 
					
						
							|  |  |  | 		gma_power_end(dev); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* cache the brightness for later use */ | 
					
						
							|  |  |  | 	dev_priv->brightness = level; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-08 16:11:14 +00:00
										 |  |  | static int mdfld_get_brightness(struct backlight_device *bd) | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct drm_device *dev = | 
					
						
							|  |  |  | 		(struct drm_device *)bl_get_data(mdfld_backlight_device); | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = dev->dev_private; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* return locally cached var instead of HW read (due to DPST etc.) */ | 
					
						
							|  |  |  | 	return dev_priv->brightness; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct backlight_ops mdfld_ops = { | 
					
						
							|  |  |  | 	.get_brightness = mdfld_get_brightness, | 
					
						
							|  |  |  | 	.update_status  = mdfld_set_brightness, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int device_backlight_init(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = (struct drm_psb_private *) | 
					
						
							|  |  |  | 		dev->dev_private; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; | 
					
						
							|  |  |  | 	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-08 16:11:14 +00:00
										 |  |  | static int mdfld_backlight_init(struct drm_device *dev) | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct backlight_properties props; | 
					
						
							|  |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(&props, 0, sizeof(struct backlight_properties)); | 
					
						
							|  |  |  | 	props.max_brightness = BRIGHTNESS_MAX_LEVEL; | 
					
						
							|  |  |  | 	props.type = BACKLIGHT_PLATFORM; | 
					
						
							|  |  |  | 	mdfld_backlight_device = backlight_device_register("mdfld-bl", | 
					
						
							|  |  |  | 				NULL, (void *)dev, &mdfld_ops, &props); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (IS_ERR(mdfld_backlight_device)) | 
					
						
							|  |  |  | 		return PTR_ERR(mdfld_backlight_device); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = device_backlight_init(dev); | 
					
						
							|  |  |  | 	if (ret) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL; | 
					
						
							|  |  |  | 	mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL; | 
					
						
							|  |  |  | 	backlight_update_status(mdfld_backlight_device); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct backlight_device *mdfld_get_backlight_device(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 | 
					
						
							|  |  |  | 	return mdfld_backlight_device; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * mdfld_save_display_registers | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Description: We are going to suspend so save current display | 
					
						
							|  |  |  |  * register state. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | static int mdfld_save_display_registers(struct drm_device *dev, int pipenum) | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = dev->dev_private; | 
					
						
							|  |  |  | 	struct medfield_state *regs = &dev_priv->regs.mdfld; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum]; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	const struct psb_offset *map = &dev_priv->regmap[pipenum]; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:33 +01:00
										 |  |  | 	u32 *mipi_val; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* register */ | 
					
						
							|  |  |  | 	u32 mipi_reg = MIPI; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	switch (pipenum) { | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	case 0: | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:33 +01:00
										 |  |  | 		mipi_val = ®s->saveMIPI; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 1: | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:33 +01:00
										 |  |  | 		mipi_val = ®s->saveMIPI; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		/* register */ | 
					
						
							|  |  |  | 		mipi_reg = MIPI_C; | 
					
						
							|  |  |  | 		/* pointer to values */ | 
					
						
							|  |  |  | 		mipi_val = ®s->saveMIPI_C; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		DRM_ERROR("%s, invalid pipe number.\n", __func__); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Pipe & plane A info */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	pipe->dpll = PSB_RVDC32(map->dpll); | 
					
						
							|  |  |  | 	pipe->fp0 = PSB_RVDC32(map->fp0); | 
					
						
							|  |  |  | 	pipe->conf = PSB_RVDC32(map->conf); | 
					
						
							|  |  |  | 	pipe->htotal = PSB_RVDC32(map->htotal); | 
					
						
							|  |  |  | 	pipe->hblank = PSB_RVDC32(map->hblank); | 
					
						
							|  |  |  | 	pipe->hsync = PSB_RVDC32(map->hsync); | 
					
						
							|  |  |  | 	pipe->vtotal = PSB_RVDC32(map->vtotal); | 
					
						
							|  |  |  | 	pipe->vblank = PSB_RVDC32(map->vblank); | 
					
						
							|  |  |  | 	pipe->vsync = PSB_RVDC32(map->vsync); | 
					
						
							|  |  |  | 	pipe->src = PSB_RVDC32(map->src); | 
					
						
							|  |  |  | 	pipe->stride = PSB_RVDC32(map->stride); | 
					
						
							|  |  |  | 	pipe->linoff = PSB_RVDC32(map->linoff); | 
					
						
							|  |  |  | 	pipe->tileoff = PSB_RVDC32(map->tileoff); | 
					
						
							|  |  |  | 	pipe->size = PSB_RVDC32(map->size); | 
					
						
							|  |  |  | 	pipe->pos = PSB_RVDC32(map->pos); | 
					
						
							|  |  |  | 	pipe->surf = PSB_RVDC32(map->surf); | 
					
						
							|  |  |  | 	pipe->cntr = PSB_RVDC32(map->cntr); | 
					
						
							|  |  |  | 	pipe->status = PSB_RVDC32(map->status); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*save palette (gamma) */ | 
					
						
							|  |  |  | 	for (i = 0; i < 256; i++) | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		pipe->palette[i] = PSB_RVDC32(map->palette + (i << 2)); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	if (pipenum == 1) { | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); | 
					
						
							|  |  |  | 		regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); | 
					
						
							|  |  |  | 		regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*mipi_val = PSB_RVDC32(mipi_reg); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * mdfld_restore_display_registers | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Description: We are going to resume so restore display register state. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum) | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* To get  panel out of ULPS mode. */ | 
					
						
							|  |  |  | 	u32 temp = 0; | 
					
						
							|  |  |  | 	u32 device_ready_reg = DEVICE_READY_REG; | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = dev->dev_private; | 
					
						
							|  |  |  | 	struct mdfld_dsi_config *dsi_config = NULL; | 
					
						
							|  |  |  | 	struct medfield_state *regs = &dev_priv->regs.mdfld; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum]; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	const struct psb_offset *map = &dev_priv->regmap[pipenum]; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:33 +01:00
										 |  |  | 	u32 i; | 
					
						
							|  |  |  | 	u32 dpll; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	u32 timeout = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	/* register */ | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	u32 mipi_reg = MIPI; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* values */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	u32 dpll_val = pipe->dpll; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	u32 mipi_val = regs->saveMIPI; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	switch (pipenum) { | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	case 0: | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 		dpll_val &= ~DPLL_VCO_ENABLE; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		dsi_config = dev_priv->dsi_configs[0]; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 1: | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 		dpll_val &= ~DPLL_VCO_ENABLE; | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		mipi_reg = MIPI_C; | 
					
						
							|  |  |  | 		mipi_val = regs->saveMIPI_C; | 
					
						
							|  |  |  | 		dsi_config = dev_priv->dsi_configs[1]; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		DRM_ERROR("%s, invalid pipe number.\n", __func__); | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*make sure VGA plane is off. it initializes to on after reset!*/ | 
					
						
							|  |  |  | 	PSB_WVDC32(0x80000000, VGACNTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	if (pipenum == 1) { | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, map->dpll); | 
					
						
							|  |  |  | 		PSB_RVDC32(map->dpll); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		PSB_WVDC32(pipe->fp0, map->fp0); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		dpll = PSB_RVDC32(map->dpll); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!(dpll & DPLL_VCO_ENABLE)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* When ungating power of DPLL, needs to wait 0.5us
 | 
					
						
							|  |  |  | 			   before enable the VCO */ | 
					
						
							|  |  |  | 			if (dpll & MDFLD_PWR_GATE_EN) { | 
					
						
							|  |  |  | 				dpll &= ~MDFLD_PWR_GATE_EN; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 				PSB_WVDC32(dpll, map->dpll); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 				/* FIXME_MDFLD PO - change 500 to 1 after PO */ | 
					
						
							|  |  |  | 				udelay(500); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 			PSB_WVDC32(pipe->fp0, map->fp0); | 
					
						
							|  |  |  | 			PSB_WVDC32(dpll_val, map->dpll); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 			/* FIXME_MDFLD PO - change 500 to 1 after PO */ | 
					
						
							|  |  |  | 			udelay(500); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dpll_val |= DPLL_VCO_ENABLE; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 			PSB_WVDC32(dpll_val, map->dpll); | 
					
						
							|  |  |  | 			PSB_RVDC32(map->dpll); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* wait for DSI PLL to lock */ | 
					
						
							|  |  |  | 			while (timeout < 20000 && | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 			  !(PSB_RVDC32(map->conf) & PIPECONF_DSIPLL_LOCK)) { | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 				udelay(150); | 
					
						
							|  |  |  | 				timeout++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (timeout == 20000) { | 
					
						
							|  |  |  | 				DRM_ERROR("%s, can't lock DSIPLL.\n", | 
					
						
							|  |  |  | 								__func__); | 
					
						
							|  |  |  | 				return -EINVAL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* Restore mode */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	PSB_WVDC32(pipe->htotal, map->htotal); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->hblank, map->hblank); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->hsync, map->hsync); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->vtotal, map->vtotal); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->vblank, map->vblank); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->vsync, map->vsync); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->src, map->src); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->status, map->status); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*set up the plane*/ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	PSB_WVDC32(pipe->stride, map->stride); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->linoff, map->linoff); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->tileoff, map->tileoff); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->size, map->size); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->pos, map->pos); | 
					
						
							|  |  |  | 	PSB_WVDC32(pipe->surf, map->surf); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 	if (pipenum == 1) { | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 		/* restore palette (gamma) */ | 
					
						
							|  |  |  | 		/*DRM_UDELAY(50000); */ | 
					
						
							|  |  |  | 		for (i = 0; i < 256; i++) | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 			PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL); | 
					
						
							|  |  |  | 		PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*TODO: resume HDMI port */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*TODO: resume pipe*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*enable the plane*/ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		PSB_WVDC32(pipe->cntr & ~DISPLAY_PLANE_ENABLE, map->cntr); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*set up pipe related registers*/ | 
					
						
							|  |  |  | 	PSB_WVDC32(mipi_val, mipi_reg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*setup MIPI adapter + MIPI IP registers*/ | 
					
						
							|  |  |  | 	if (dsi_config) | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:16 +01:00
										 |  |  | 		mdfld_dsi_controller_init(dsi_config, pipenum); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (in_atomic() || in_interrupt()) | 
					
						
							|  |  |  | 		mdelay(20); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		msleep(20); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*enable the plane*/ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	PSB_WVDC32(pipe->cntr, map->cntr); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (in_atomic() || in_interrupt()) | 
					
						
							|  |  |  | 		mdelay(20); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		msleep(20); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* LP Hold Release */ | 
					
						
							|  |  |  | 	temp = REG_READ(mipi_reg); | 
					
						
							|  |  |  | 	temp |= LP_OUTPUT_HOLD_RELEASE; | 
					
						
							|  |  |  | 	REG_WRITE(mipi_reg, temp); | 
					
						
							|  |  |  | 	mdelay(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Set DSI host to exit from Utra Low Power State */ | 
					
						
							|  |  |  | 	temp = REG_READ(device_ready_reg); | 
					
						
							|  |  |  | 	temp &= ~ULPS_MASK; | 
					
						
							|  |  |  | 	temp |= 0x3; | 
					
						
							|  |  |  | 	temp |= EXIT_ULPS_DEV_READY; | 
					
						
							|  |  |  | 	REG_WRITE(device_ready_reg, temp); | 
					
						
							|  |  |  | 	mdelay(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	temp = REG_READ(device_ready_reg); | 
					
						
							|  |  |  | 	temp &= ~ULPS_MASK; | 
					
						
							|  |  |  | 	temp |= EXITING_ULPS; | 
					
						
							|  |  |  | 	REG_WRITE(device_ready_reg, temp); | 
					
						
							|  |  |  | 	mdelay(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*enable the pipe*/ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 	PSB_WVDC32(pipe->conf, map->conf); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* restore palette (gamma) */ | 
					
						
							|  |  |  | 	/*DRM_UDELAY(50000); */ | 
					
						
							|  |  |  | 	for (i = 0; i < 256; i++) | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mdfld_save_registers(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* mdfld_save_cursor_overlay_registers(dev); */ | 
					
						
							|  |  |  | 	mdfld_save_display_registers(dev, 0); | 
					
						
							|  |  |  | 	mdfld_save_display_registers(dev, 2); | 
					
						
							|  |  |  | 	mdfld_disable_crtc(dev, 0); | 
					
						
							|  |  |  | 	mdfld_disable_crtc(dev, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mdfld_restore_registers(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	mdfld_restore_display_registers(dev, 2); | 
					
						
							|  |  |  | 	mdfld_restore_display_registers(dev, 0); | 
					
						
							|  |  |  | 	/* mdfld_restore_cursor_overlay_registers(dev); */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mdfld_power_down(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* FIXME */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mdfld_power_up(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* FIXME */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | /* Medfield  */ | 
					
						
							|  |  |  | static const struct psb_offset mdfld_regmap[3] = { | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		.fp0 = MRST_FPA0, | 
					
						
							|  |  |  | 		.fp1 = MRST_FPA1, | 
					
						
							|  |  |  | 		.cntr = DSPACNTR, | 
					
						
							|  |  |  | 		.conf = PIPEACONF, | 
					
						
							|  |  |  | 		.src = PIPEASRC, | 
					
						
							|  |  |  | 		.dpll = MRST_DPLL_A, | 
					
						
							|  |  |  | 		.htotal = HTOTAL_A, | 
					
						
							|  |  |  | 		.hblank = HBLANK_A, | 
					
						
							|  |  |  | 		.hsync = HSYNC_A, | 
					
						
							|  |  |  | 		.vtotal = VTOTAL_A, | 
					
						
							|  |  |  | 		.vblank = VBLANK_A, | 
					
						
							|  |  |  | 		.vsync = VSYNC_A, | 
					
						
							|  |  |  | 		.stride = DSPASTRIDE, | 
					
						
							|  |  |  | 		.size = DSPASIZE, | 
					
						
							|  |  |  | 		.pos = DSPAPOS, | 
					
						
							|  |  |  | 		.surf = DSPASURF, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		.addr = MRST_DSPABASE, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 		.status = PIPEASTAT, | 
					
						
							|  |  |  | 		.linoff = DSPALINOFF, | 
					
						
							|  |  |  | 		.tileoff = DSPATILEOFF, | 
					
						
							|  |  |  | 		.palette = PALETTE_A, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		.fp0 = MDFLD_DPLL_DIV0, | 
					
						
							|  |  |  | 		.cntr = DSPBCNTR, | 
					
						
							|  |  |  | 		.conf = PIPEBCONF, | 
					
						
							|  |  |  | 		.src = PIPEBSRC, | 
					
						
							|  |  |  | 		.dpll = MDFLD_DPLL_B, | 
					
						
							|  |  |  | 		.htotal = HTOTAL_B, | 
					
						
							|  |  |  | 		.hblank = HBLANK_B, | 
					
						
							|  |  |  | 		.hsync = HSYNC_B, | 
					
						
							|  |  |  | 		.vtotal = VTOTAL_B, | 
					
						
							|  |  |  | 		.vblank = VBLANK_B, | 
					
						
							|  |  |  | 		.vsync = VSYNC_B, | 
					
						
							|  |  |  | 		.stride = DSPBSTRIDE, | 
					
						
							|  |  |  | 		.size = DSPBSIZE, | 
					
						
							|  |  |  | 		.pos = DSPBPOS, | 
					
						
							|  |  |  | 		.surf = DSPBSURF, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		.addr = MRST_DSPBBASE, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 		.status = PIPEBSTAT, | 
					
						
							|  |  |  | 		.linoff = DSPBLINOFF, | 
					
						
							|  |  |  | 		.tileoff = DSPBTILEOFF, | 
					
						
							|  |  |  | 		.palette = PALETTE_B, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		.fp0 = MRST_FPA0,	/* This is what the old code did ?? */ | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 		.cntr = DSPCCNTR, | 
					
						
							|  |  |  | 		.conf = PIPECCONF, | 
					
						
							|  |  |  | 		.src = PIPECSRC, | 
					
						
							|  |  |  | 		/* No DPLL_C */ | 
					
						
							|  |  |  | 		.dpll = MRST_DPLL_A, | 
					
						
							|  |  |  | 		.htotal = HTOTAL_C, | 
					
						
							|  |  |  | 		.hblank = HBLANK_C, | 
					
						
							|  |  |  | 		.hsync = HSYNC_C, | 
					
						
							|  |  |  | 		.vtotal = VTOTAL_C, | 
					
						
							|  |  |  | 		.vblank = VBLANK_C, | 
					
						
							|  |  |  | 		.vsync = VSYNC_C, | 
					
						
							|  |  |  | 		.stride = DSPCSTRIDE, | 
					
						
							|  |  |  | 		.size = DSPBSIZE, | 
					
						
							|  |  |  | 		.pos = DSPCPOS, | 
					
						
							|  |  |  | 		.surf = DSPCSURF, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:31:22 +01:00
										 |  |  | 		.addr = MDFLD_DSPCBASE, | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 		.status = PIPECSTAT, | 
					
						
							|  |  |  | 		.linoff = DSPCLINOFF, | 
					
						
							|  |  |  | 		.tileoff = DSPCTILEOFF, | 
					
						
							|  |  |  | 		.palette = PALETTE_C, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int mdfld_chip_setup(struct drm_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct drm_psb_private *dev_priv = dev->dev_private; | 
					
						
							| 
									
										
										
										
											2012-05-11 11:33:03 +01:00
										 |  |  | 	if (pci_enable_msi(dev->pdev)) | 
					
						
							|  |  |  | 		dev_warn(dev->dev, "Enabling MSI failed!\n"); | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 	dev_priv->regmap = mdfld_regmap; | 
					
						
							|  |  |  | 	return mid_chip_setup(dev); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | const struct psb_ops mdfld_chip_ops = { | 
					
						
							|  |  |  | 	.name = "mdfld", | 
					
						
							|  |  |  | 	.accel_2d = 0, | 
					
						
							|  |  |  | 	.pipes = 3, | 
					
						
							|  |  |  | 	.crtcs = 3, | 
					
						
							| 
									
										
										
										
											2012-04-28 23:20:42 +02:00
										 |  |  | 	.lvds_mask = (1 << 1), | 
					
						
							|  |  |  | 	.hdmi_mask = (1 << 1), | 
					
						
							| 
									
										
										
										
											2012-05-21 15:27:30 +01:00
										 |  |  | 	.cursor_needs_phys = 0, | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	.sgx_offset = MRST_SGX_OFFSET, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 11:30:53 +01:00
										 |  |  | 	.chip_setup = mdfld_chip_setup, | 
					
						
							| 
									
										
										
										
											2012-03-08 16:02:20 +00:00
										 |  |  | 	.crtc_helper = &mdfld_helper_funcs, | 
					
						
							|  |  |  | 	.crtc_funcs = &psb_intel_crtc_funcs, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.output_init = mdfld_output_init, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 | 
					
						
							|  |  |  | 	.backlight_init = mdfld_backlight_init, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.save_regs = mdfld_save_registers, | 
					
						
							|  |  |  | 	.restore_regs = mdfld_restore_registers, | 
					
						
							|  |  |  | 	.power_down = mdfld_power_down, | 
					
						
							|  |  |  | 	.power_up = mdfld_power_up, | 
					
						
							|  |  |  | }; |