brintos

brintos / linux-shallow public Read only

0
0
Text · 22.1 KiB · 138f153 Raw
806 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright © 2006-2007 Intel Corporation4 *5 * Authors:6 *	Eric Anholt <eric@anholt.net>7 *	Dave Airlie <airlied@linux.ie>8 *	Jesse Barnes <jesse.barnes@intel.com>9 */10 11#include <linux/i2c.h>12#include <linux/pm_runtime.h>13 14#include <drm/drm_crtc_helper.h>15#include <drm/drm_modeset_helper_vtables.h>16#include <drm/drm_simple_kms_helper.h>17 18#include "intel_bios.h"19#include "power.h"20#include "psb_drv.h"21#include "psb_intel_drv.h"22#include "psb_intel_reg.h"23 24/*25 * LVDS I2C backlight control macros26 */27#define BRIGHTNESS_MAX_LEVEL 10028#define BRIGHTNESS_MASK 0xFF29#define BLC_I2C_TYPE	0x0130#define BLC_PWM_TYPT	0x0231 32#define BLC_POLARITY_NORMAL 033#define BLC_POLARITY_INVERSE 134 35#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)36#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)37#define PSB_BLC_PWM_PRECISION_FACTOR	(10)38#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)39#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)40 41struct psb_intel_lvds_priv {42	/*43	 * Saved LVDO output states44	 */45	uint32_t savePP_ON;46	uint32_t savePP_OFF;47	uint32_t saveLVDS;48	uint32_t savePP_CONTROL;49	uint32_t savePP_CYCLE;50	uint32_t savePFIT_CONTROL;51	uint32_t savePFIT_PGM_RATIOS;52	uint32_t saveBLC_PWM_CTL;53 54	struct gma_i2c_chan *i2c_bus;55};56 57 58/*59 * Returns the maximum level of the backlight duty cycle field.60 */61static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)62{63	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);64	u32 ret;65 66	if (gma_power_begin(dev, false)) {67		ret = REG_READ(BLC_PWM_CTL);68		gma_power_end(dev);69	} else /* Powered off, use the saved value */70		ret = dev_priv->regs.saveBLC_PWM_CTL;71 72	/* Top 15bits hold the frequency mask */73	ret = (ret &  BACKLIGHT_MODULATION_FREQ_MASK) >>74					BACKLIGHT_MODULATION_FREQ_SHIFT;75 76        ret *= 2;	/* Return a 16bit range as needed for setting */77        if (ret == 0)78                dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",79                        REG_READ(BLC_PWM_CTL), dev_priv->regs.saveBLC_PWM_CTL);80	return ret;81}82 83/*84 * Set LVDS backlight level by I2C command85 *86 * FIXME: at some point we need to both track this for PM and also87 * disable runtime pm on MRST if the brightness is nil (ie blanked)88 */89static int psb_lvds_i2c_set_brightness(struct drm_device *dev,90					unsigned int level)91{92	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);93 94	struct gma_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;95	u8 out_buf[2];96	unsigned int blc_i2c_brightness;97 98	struct i2c_msg msgs[] = {99		{100			.addr = lvds_i2c_bus->target_addr,101			.flags = 0,102			.len = 2,103			.buf = out_buf,104		}105	};106 107	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *108			     BRIGHTNESS_MASK /109			     BRIGHTNESS_MAX_LEVEL);110 111	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)112		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;113 114	out_buf[0] = dev_priv->lvds_bl->brightnesscmd;115	out_buf[1] = (u8)blc_i2c_brightness;116 117	if (i2c_transfer(&lvds_i2c_bus->base, msgs, 1) == 1) {118		dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",119			dev_priv->lvds_bl->brightnesscmd,120			blc_i2c_brightness);121		return 0;122	}123 124	dev_err(dev->dev, "I2C transfer error\n");125	return -1;126}127 128 129static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)130{131	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);132 133	u32 max_pwm_blc;134	u32 blc_pwm_duty_cycle;135 136	max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);137 138	/*BLC_PWM_CTL Should be initiated while backlight device init*/139	BUG_ON(max_pwm_blc == 0);140 141	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;142 143	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)144		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;145 146	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;147	REG_WRITE(BLC_PWM_CTL,148		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |149		  (blc_pwm_duty_cycle));150 151        dev_info(dev->dev, "Backlight lvds set brightness %08x\n",152		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |153		  (blc_pwm_duty_cycle));154 155	return 0;156}157 158/*159 * Set LVDS backlight level either by I2C or PWM160 */161void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)162{163	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);164 165	dev_dbg(dev->dev, "backlight level is %d\n", level);166 167	if (!dev_priv->lvds_bl) {168		dev_err(dev->dev, "NO LVDS backlight info\n");169		return;170	}171 172	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)173		psb_lvds_i2c_set_brightness(dev, level);174	else175		psb_lvds_pwm_set_brightness(dev, level);176}177 178/*179 * Sets the backlight level.180 *181 * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight().182 */183static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)184{185	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);186	u32 blc_pwm_ctl;187 188	if (gma_power_begin(dev, false)) {189		blc_pwm_ctl = REG_READ(BLC_PWM_CTL);190		blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;191		REG_WRITE(BLC_PWM_CTL,192				(blc_pwm_ctl |193				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));194		dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |195					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));196		gma_power_end(dev);197	} else {198		blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL &199				~BACKLIGHT_DUTY_CYCLE_MASK;200		dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |201					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));202	}203}204 205/*206 * Sets the power state for the panel.207 */208static void psb_intel_lvds_set_power(struct drm_device *dev, bool on)209{210	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);211	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;212	u32 pp_status;213 214	if (!gma_power_begin(dev, true)) {215	        dev_err(dev->dev, "set power, chip off!\n");216		return;217        }218 219	if (on) {220		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |221			  POWER_TARGET_ON);222		do {223			pp_status = REG_READ(PP_STATUS);224		} while ((pp_status & PP_ON) == 0);225 226		psb_intel_lvds_set_backlight(dev,227					     mode_dev->backlight_duty_cycle);228	} else {229		psb_intel_lvds_set_backlight(dev, 0);230 231		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &232			  ~POWER_TARGET_ON);233		do {234			pp_status = REG_READ(PP_STATUS);235		} while (pp_status & PP_ON);236	}237 238	gma_power_end(dev);239}240 241static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)242{243	struct drm_device *dev = encoder->dev;244 245	if (mode == DRM_MODE_DPMS_ON)246		psb_intel_lvds_set_power(dev, true);247	else248		psb_intel_lvds_set_power(dev, false);249 250	/* XXX: We never power down the LVDS pairs. */251}252 253static void psb_intel_lvds_save(struct drm_connector *connector)254{255	struct drm_device *dev = connector->dev;256	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);257	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);258	struct psb_intel_lvds_priv *lvds_priv =259		(struct psb_intel_lvds_priv *)gma_encoder->dev_priv;260 261	lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);262	lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);263	lvds_priv->saveLVDS = REG_READ(LVDS);264	lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL);265	lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE);266	/*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/267	lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);268	lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL);269	lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);270 271	/*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/272	dev_priv->backlight_duty_cycle = (dev_priv->regs.saveBLC_PWM_CTL &273						BACKLIGHT_DUTY_CYCLE_MASK);274 275	/*276	 * If the light is off at server startup,277	 * just make it full brightness278	 */279	if (dev_priv->backlight_duty_cycle == 0)280		dev_priv->backlight_duty_cycle =281		psb_intel_lvds_get_max_backlight(dev);282 283	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",284			lvds_priv->savePP_ON,285			lvds_priv->savePP_OFF,286			lvds_priv->saveLVDS,287			lvds_priv->savePP_CONTROL,288			lvds_priv->savePP_CYCLE,289			lvds_priv->saveBLC_PWM_CTL);290}291 292static void psb_intel_lvds_restore(struct drm_connector *connector)293{294	struct drm_device *dev = connector->dev;295	u32 pp_status;296	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);297	struct psb_intel_lvds_priv *lvds_priv =298		(struct psb_intel_lvds_priv *)gma_encoder->dev_priv;299 300	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",301			lvds_priv->savePP_ON,302			lvds_priv->savePP_OFF,303			lvds_priv->saveLVDS,304			lvds_priv->savePP_CONTROL,305			lvds_priv->savePP_CYCLE,306			lvds_priv->saveBLC_PWM_CTL);307 308	REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL);309	REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL);310	REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS);311	REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON);312	REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF);313	/*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/314	REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE);315	REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL);316	REG_WRITE(LVDS, lvds_priv->saveLVDS);317 318	if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) {319		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |320			POWER_TARGET_ON);321		do {322			pp_status = REG_READ(PP_STATUS);323		} while ((pp_status & PP_ON) == 0);324	} else {325		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &326			~POWER_TARGET_ON);327		do {328			pp_status = REG_READ(PP_STATUS);329		} while (pp_status & PP_ON);330	}331}332 333enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector,334				 struct drm_display_mode *mode)335{336	struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);337	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);338	struct drm_display_mode *fixed_mode =339					dev_priv->mode_dev.panel_fixed_mode;340 341	if (gma_encoder->type == INTEL_OUTPUT_MIPI2)342		fixed_mode = dev_priv->mode_dev.panel_fixed_mode2;343 344	/* just in case */345	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)346		return MODE_NO_DBLESCAN;347 348	/* just in case */349	if (mode->flags & DRM_MODE_FLAG_INTERLACE)350		return MODE_NO_INTERLACE;351 352	if (fixed_mode) {353		if (mode->hdisplay > fixed_mode->hdisplay)354			return MODE_PANEL;355		if (mode->vdisplay > fixed_mode->vdisplay)356			return MODE_PANEL;357	}358	return MODE_OK;359}360 361bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,362				  const struct drm_display_mode *mode,363				  struct drm_display_mode *adjusted_mode)364{365	struct drm_device *dev = encoder->dev;366	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);367	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;368	struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);369	struct drm_encoder *tmp_encoder;370	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;371	struct gma_encoder *gma_encoder = to_gma_encoder(encoder);372 373	if (gma_encoder->type == INTEL_OUTPUT_MIPI2)374		panel_fixed_mode = mode_dev->panel_fixed_mode2;375 376	/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */377	if (!IS_MRST(dev) && gma_crtc->pipe == 0) {378		pr_err("Can't support LVDS on pipe A\n");379		return false;380	}381	if (IS_MRST(dev) && gma_crtc->pipe != 0) {382		pr_err("Must use PIPE A\n");383		return false;384	}385	/* Should never happen!! */386	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,387			    head) {388		if (tmp_encoder != encoder389		    && tmp_encoder->crtc == encoder->crtc) {390			pr_err("Can't enable LVDS and another encoder on the same pipe\n");391			return false;392		}393	}394 395	/*396	 * If we have timings from the BIOS for the panel, put them in397	 * to the adjusted mode.  The CRTC will be set up for this mode,398	 * with the panel scaling set up to source from the H/VDisplay399	 * of the original mode.400	 */401	if (panel_fixed_mode != NULL) {402		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;403		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;404		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;405		adjusted_mode->htotal = panel_fixed_mode->htotal;406		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;407		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;408		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;409		adjusted_mode->vtotal = panel_fixed_mode->vtotal;410		adjusted_mode->clock = panel_fixed_mode->clock;411		drm_mode_set_crtcinfo(adjusted_mode,412				      CRTC_INTERLACE_HALVE_V);413	}414 415	/*416	 * XXX: It would be nice to support lower refresh rates on the417	 * panels to reduce power consumption, and perhaps match the418	 * user's requested refresh rate.419	 */420 421	return true;422}423 424static void psb_intel_lvds_prepare(struct drm_encoder *encoder)425{426	struct drm_device *dev = encoder->dev;427	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);428	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;429 430	if (!gma_power_begin(dev, true))431		return;432 433	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);434	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &435					  BACKLIGHT_DUTY_CYCLE_MASK);436 437	psb_intel_lvds_set_power(dev, false);438 439	gma_power_end(dev);440}441 442static void psb_intel_lvds_commit(struct drm_encoder *encoder)443{444	struct drm_device *dev = encoder->dev;445	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);446	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;447 448	if (mode_dev->backlight_duty_cycle == 0)449		mode_dev->backlight_duty_cycle =450		    psb_intel_lvds_get_max_backlight(dev);451 452	psb_intel_lvds_set_power(dev, true);453}454 455static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,456				struct drm_display_mode *mode,457				struct drm_display_mode *adjusted_mode)458{459	struct drm_device *dev = encoder->dev;460	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);461	u32 pfit_control;462 463	/*464	 * The LVDS pin pair will already have been turned on in the465	 * psb_intel_crtc_mode_set since it has a large impact on the DPLL466	 * settings.467	 */468 469	/*470	 * Enable automatic panel scaling so that non-native modes fill the471	 * screen.  Should be enabled before the pipe is enabled, according to472	 * register description and PRM.473	 */474	if (mode->hdisplay != adjusted_mode->hdisplay ||475	    mode->vdisplay != adjusted_mode->vdisplay)476		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |477				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |478				HORIZ_INTERP_BILINEAR);479	else480		pfit_control = 0;481 482	if (dev_priv->lvds_dither)483		pfit_control |= PANEL_8TO6_DITHER_ENABLE;484 485	REG_WRITE(PFIT_CONTROL, pfit_control);486}487 488/*489 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.490 */491static int psb_intel_lvds_get_modes(struct drm_connector *connector)492{493	struct drm_device *dev = connector->dev;494	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);495	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;496	int ret = 0;497 498	if (!IS_MRST(dev))499		ret = psb_intel_ddc_get_modes(connector, connector->ddc);500 501	if (ret)502		return ret;503 504	if (mode_dev->panel_fixed_mode != NULL) {505		struct drm_display_mode *mode =506		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);507		if (!mode)508			return 0;509 510		drm_mode_probed_add(connector, mode);511		return 1;512	}513 514	return 0;515}516 517void psb_intel_lvds_destroy(struct drm_connector *connector)518{519	struct gma_connector *gma_connector = to_gma_connector(connector);520	struct gma_i2c_chan *ddc_bus = to_gma_i2c_chan(connector->ddc);521 522	gma_i2c_destroy(ddc_bus);523	drm_connector_cleanup(connector);524	kfree(gma_connector);525}526 527int psb_intel_lvds_set_property(struct drm_connector *connector,528				       struct drm_property *property,529				       uint64_t value)530{531	struct drm_encoder *encoder = connector->encoder;532 533	if (!encoder)534		return -1;535 536	if (!strcmp(property->name, "scaling mode")) {537		struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);538		uint64_t curval;539 540		if (!crtc)541			goto set_prop_error;542 543		switch (value) {544		case DRM_MODE_SCALE_FULLSCREEN:545			break;546		case DRM_MODE_SCALE_NO_SCALE:547			break;548		case DRM_MODE_SCALE_ASPECT:549			break;550		default:551			goto set_prop_error;552		}553 554		if (drm_object_property_get_value(&connector->base,555						     property,556						     &curval))557			goto set_prop_error;558 559		if (curval == value)560			goto set_prop_done;561 562		if (drm_object_property_set_value(&connector->base,563							property,564							value))565			goto set_prop_error;566 567		if (crtc->saved_mode.hdisplay != 0 &&568		    crtc->saved_mode.vdisplay != 0) {569			if (!drm_crtc_helper_set_mode(encoder->crtc,570						      &crtc->saved_mode,571						      encoder->crtc->x,572						      encoder->crtc->y,573						      encoder->crtc->primary->fb))574				goto set_prop_error;575		}576	} else if (!strcmp(property->name, "backlight")) {577		if (drm_object_property_set_value(&connector->base,578							property,579							value))580			goto set_prop_error;581		else582                        gma_backlight_set(encoder->dev, value);583	} else if (!strcmp(property->name, "DPMS")) {584		const struct drm_encoder_helper_funcs *hfuncs585						= encoder->helper_private;586		hfuncs->dpms(encoder, value);587	}588 589set_prop_done:590	return 0;591set_prop_error:592	return -1;593}594 595static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = {596	.dpms = psb_intel_lvds_encoder_dpms,597	.mode_fixup = psb_intel_lvds_mode_fixup,598	.prepare = psb_intel_lvds_prepare,599	.mode_set = psb_intel_lvds_mode_set,600	.commit = psb_intel_lvds_commit,601};602 603const struct drm_connector_helper_funcs604				psb_intel_lvds_connector_helper_funcs = {605	.get_modes = psb_intel_lvds_get_modes,606	.mode_valid = psb_intel_lvds_mode_valid,607	.best_encoder = gma_best_encoder,608};609 610const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {611	.dpms = drm_helper_connector_dpms,612	.fill_modes = drm_helper_probe_single_connector_modes,613	.set_property = psb_intel_lvds_set_property,614	.destroy = psb_intel_lvds_destroy,615};616 617/**618 * psb_intel_lvds_init - setup LVDS connectors on this device619 * @dev: drm device620 * @mode_dev: mode device621 *622 * Create the connector, register the LVDS DDC bus, and try to figure out what623 * modes we can display on the LVDS panel (if present).624 */625void psb_intel_lvds_init(struct drm_device *dev,626			 struct psb_intel_mode_device *mode_dev)627{628	struct gma_encoder *gma_encoder;629	struct gma_connector *gma_connector;630	struct psb_intel_lvds_priv *lvds_priv;631	struct drm_connector *connector;632	struct drm_encoder *encoder;633	struct drm_display_mode *scan;	/* *modes, *bios_mode; */634	struct drm_crtc *crtc;635	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);636	struct gma_i2c_chan *ddc_bus;637	u32 lvds;638	int pipe;639	int ret;640 641	gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);642	if (!gma_encoder) {643		dev_err(dev->dev, "gma_encoder allocation error\n");644		return;645	}646	encoder = &gma_encoder->base;647 648	gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);649	if (!gma_connector) {650		dev_err(dev->dev, "gma_connector allocation error\n");651		goto err_free_encoder;652	}653 654	lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);655	if (!lvds_priv) {656		dev_err(dev->dev, "LVDS private allocation error\n");657		goto err_free_connector;658	}659 660	gma_encoder->dev_priv = lvds_priv;661 662	connector = &gma_connector->base;663	gma_connector->save = psb_intel_lvds_save;664	gma_connector->restore = psb_intel_lvds_restore;665 666	/* Set up the DDC bus. */667	ddc_bus = gma_i2c_create(dev, GPIOC, "LVDSDDC_C");668	if (!ddc_bus) {669		dev_printk(KERN_ERR, dev->dev,670			   "DDC bus registration " "failed.\n");671		goto err_free_lvds_priv;672	}673 674	ret = drm_connector_init_with_ddc(dev, connector,675					  &psb_intel_lvds_connector_funcs,676					  DRM_MODE_CONNECTOR_LVDS,677					  &ddc_bus->base);678	if (ret)679		goto err_ddc_destroy;680 681	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);682	if (ret)683		goto err_connector_cleanup;684 685	gma_connector_attach_encoder(gma_connector, gma_encoder);686	gma_encoder->type = INTEL_OUTPUT_LVDS;687 688	drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);689	drm_connector_helper_add(connector,690				 &psb_intel_lvds_connector_helper_funcs);691	connector->display_info.subpixel_order = SubPixelHorizontalRGB;692	connector->interlace_allowed = false;693	connector->doublescan_allowed = false;694 695	/*Attach connector properties*/696	drm_object_attach_property(&connector->base,697				      dev->mode_config.scaling_mode_property,698				      DRM_MODE_SCALE_FULLSCREEN);699	drm_object_attach_property(&connector->base,700				      dev_priv->backlight_property,701				      BRIGHTNESS_MAX_LEVEL);702 703	/*704	 * Set up I2C bus705	 * FIXME: distroy i2c_bus when exit706	 */707	lvds_priv->i2c_bus = gma_i2c_create(dev, GPIOB, "LVDSBLC_B");708	if (!lvds_priv->i2c_bus) {709		dev_printk(KERN_ERR,710			dev->dev, "I2C bus registration failed.\n");711		goto err_encoder_cleanup;712	}713	lvds_priv->i2c_bus->target_addr = 0x2C;714	dev_priv->lvds_i2c_bus =  lvds_priv->i2c_bus;715 716	/*717	 * LVDS discovery:718	 * 1) check for EDID on DDC719	 * 2) check for VBT data720	 * 3) check to see if LVDS is already on721	 *    if none of the above, no panel722	 * 4) make sure lid is open723	 *    if closed, act like it's not there for now724	 */725 726	/*727	 * Attempt to get the fixed panel mode from DDC.  Assume that the728	 * preferred mode is the right one.729	 */730	mutex_lock(&dev->mode_config.mutex);731	psb_intel_ddc_get_modes(connector, &ddc_bus->base);732 733	list_for_each_entry(scan, &connector->probed_modes, head) {734		if (scan->type & DRM_MODE_TYPE_PREFERRED) {735			mode_dev->panel_fixed_mode =736			    drm_mode_duplicate(dev, scan);737			DRM_DEBUG_KMS("Using mode from DDC\n");738			goto out;	/* FIXME: check for quirks */739		}740	}741 742	/* Failed to get EDID, what about VBT? do we need this? */743	if (dev_priv->lfp_lvds_vbt_mode) {744		mode_dev->panel_fixed_mode =745			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);746 747		if (mode_dev->panel_fixed_mode) {748			mode_dev->panel_fixed_mode->type |=749				DRM_MODE_TYPE_PREFERRED;750			DRM_DEBUG_KMS("Using mode from VBT\n");751			goto out;752		}753	}754 755	/*756	 * If we didn't get EDID, try checking if the panel is already turned757	 * on.	If so, assume that whatever is currently programmed is the758	 * correct mode.759	 */760	lvds = REG_READ(LVDS);761	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;762	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);763 764	if (crtc && (lvds & LVDS_PORT_EN)) {765		mode_dev->panel_fixed_mode =766		    psb_intel_crtc_mode_get(dev, crtc);767		if (mode_dev->panel_fixed_mode) {768			mode_dev->panel_fixed_mode->type |=769			    DRM_MODE_TYPE_PREFERRED;770			DRM_DEBUG_KMS("Using pre-programmed mode\n");771			goto out;	/* FIXME: check for quirks */772		}773	}774 775	/* If we still don't have a mode after all that, give up. */776	if (!mode_dev->panel_fixed_mode) {777		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");778		goto err_unlock;779	}780 781	/*782	 * Blacklist machines with BIOSes that list an LVDS panel without783	 * actually having one.784	 */785out:786	mutex_unlock(&dev->mode_config.mutex);787	return;788 789err_unlock:790	mutex_unlock(&dev->mode_config.mutex);791	gma_i2c_destroy(lvds_priv->i2c_bus);792err_encoder_cleanup:793	drm_encoder_cleanup(encoder);794err_connector_cleanup:795	drm_connector_cleanup(connector);796err_ddc_destroy:797	gma_i2c_destroy(ddc_bus);798err_free_lvds_priv:799	kfree(lvds_priv);800err_free_connector:801	kfree(gma_connector);802err_free_encoder:803	kfree(gma_encoder);804}805 806