xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/gma500/cdv_intel_lvds.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright © 2006-2011 Intel Corporation
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors:
6*4882a593Smuzhiyun  *	Eric Anholt <eric@anholt.net>
7*4882a593Smuzhiyun  *	Dave Airlie <airlied@linux.ie>
8*4882a593Smuzhiyun  *	Jesse Barnes <jesse.barnes@intel.com>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/dmi.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/pm_runtime.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <drm/drm_simple_kms_helper.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include "cdv_device.h"
18*4882a593Smuzhiyun #include "intel_bios.h"
19*4882a593Smuzhiyun #include "power.h"
20*4882a593Smuzhiyun #include "psb_drv.h"
21*4882a593Smuzhiyun #include "psb_intel_drv.h"
22*4882a593Smuzhiyun #include "psb_intel_reg.h"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /**
25*4882a593Smuzhiyun  * LVDS I2C backlight control macros
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun #define BRIGHTNESS_MAX_LEVEL 100
28*4882a593Smuzhiyun #define BRIGHTNESS_MASK 0xFF
29*4882a593Smuzhiyun #define BLC_I2C_TYPE	0x01
30*4882a593Smuzhiyun #define BLC_PWM_TYPT	0x02
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define BLC_POLARITY_NORMAL 0
33*4882a593Smuzhiyun #define BLC_POLARITY_INVERSE 1
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
36*4882a593Smuzhiyun #define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)
37*4882a593Smuzhiyun #define PSB_BLC_PWM_PRECISION_FACTOR	(10)
38*4882a593Smuzhiyun #define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
39*4882a593Smuzhiyun #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun struct cdv_intel_lvds_priv {
42*4882a593Smuzhiyun 	/**
43*4882a593Smuzhiyun 	 * Saved LVDO output states
44*4882a593Smuzhiyun 	 */
45*4882a593Smuzhiyun 	uint32_t savePP_ON;
46*4882a593Smuzhiyun 	uint32_t savePP_OFF;
47*4882a593Smuzhiyun 	uint32_t saveLVDS;
48*4882a593Smuzhiyun 	uint32_t savePP_CONTROL;
49*4882a593Smuzhiyun 	uint32_t savePP_CYCLE;
50*4882a593Smuzhiyun 	uint32_t savePFIT_CONTROL;
51*4882a593Smuzhiyun 	uint32_t savePFIT_PGM_RATIOS;
52*4882a593Smuzhiyun 	uint32_t saveBLC_PWM_CTL;
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun  * Returns the maximum level of the backlight duty cycle field.
57*4882a593Smuzhiyun  */
cdv_intel_lvds_get_max_backlight(struct drm_device * dev)58*4882a593Smuzhiyun static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
61*4882a593Smuzhiyun 	u32 retval;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (gma_power_begin(dev, false)) {
64*4882a593Smuzhiyun 		retval = ((REG_READ(BLC_PWM_CTL) &
65*4882a593Smuzhiyun 			  BACKLIGHT_MODULATION_FREQ_MASK) >>
66*4882a593Smuzhiyun 			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 		gma_power_end(dev);
69*4882a593Smuzhiyun 	} else
70*4882a593Smuzhiyun 		retval = ((dev_priv->regs.saveBLC_PWM_CTL &
71*4882a593Smuzhiyun 			  BACKLIGHT_MODULATION_FREQ_MASK) >>
72*4882a593Smuzhiyun 			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	return retval;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /**
78*4882a593Smuzhiyun  * Sets the backlight level.
79*4882a593Smuzhiyun  *
80*4882a593Smuzhiyun  * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
81*4882a593Smuzhiyun  */
cdv_intel_lvds_set_backlight(struct drm_device * dev,int level)82*4882a593Smuzhiyun static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
85*4882a593Smuzhiyun 	u32 blc_pwm_ctl;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (gma_power_begin(dev, false)) {
88*4882a593Smuzhiyun 		blc_pwm_ctl =
89*4882a593Smuzhiyun 			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
90*4882a593Smuzhiyun 		REG_WRITE(BLC_PWM_CTL,
91*4882a593Smuzhiyun 				(blc_pwm_ctl |
92*4882a593Smuzhiyun 				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
93*4882a593Smuzhiyun 		gma_power_end(dev);
94*4882a593Smuzhiyun 	} else {
95*4882a593Smuzhiyun 		blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL &
96*4882a593Smuzhiyun 				~BACKLIGHT_DUTY_CYCLE_MASK;
97*4882a593Smuzhiyun 		dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |
98*4882a593Smuzhiyun 					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /**
103*4882a593Smuzhiyun  * Sets the power state for the panel.
104*4882a593Smuzhiyun  */
cdv_intel_lvds_set_power(struct drm_device * dev,struct drm_encoder * encoder,bool on)105*4882a593Smuzhiyun static void cdv_intel_lvds_set_power(struct drm_device *dev,
106*4882a593Smuzhiyun 				     struct drm_encoder *encoder, bool on)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
109*4882a593Smuzhiyun 	u32 pp_status;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (!gma_power_begin(dev, true))
112*4882a593Smuzhiyun 		return;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (on) {
115*4882a593Smuzhiyun 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
116*4882a593Smuzhiyun 			  POWER_TARGET_ON);
117*4882a593Smuzhiyun 		do {
118*4882a593Smuzhiyun 			pp_status = REG_READ(PP_STATUS);
119*4882a593Smuzhiyun 		} while ((pp_status & PP_ON) == 0);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 		cdv_intel_lvds_set_backlight(dev,
122*4882a593Smuzhiyun 				dev_priv->mode_dev.backlight_duty_cycle);
123*4882a593Smuzhiyun 	} else {
124*4882a593Smuzhiyun 		cdv_intel_lvds_set_backlight(dev, 0);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
127*4882a593Smuzhiyun 			  ~POWER_TARGET_ON);
128*4882a593Smuzhiyun 		do {
129*4882a593Smuzhiyun 			pp_status = REG_READ(PP_STATUS);
130*4882a593Smuzhiyun 		} while (pp_status & PP_ON);
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 	gma_power_end(dev);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
cdv_intel_lvds_encoder_dpms(struct drm_encoder * encoder,int mode)135*4882a593Smuzhiyun static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
138*4882a593Smuzhiyun 	if (mode == DRM_MODE_DPMS_ON)
139*4882a593Smuzhiyun 		cdv_intel_lvds_set_power(dev, encoder, true);
140*4882a593Smuzhiyun 	else
141*4882a593Smuzhiyun 		cdv_intel_lvds_set_power(dev, encoder, false);
142*4882a593Smuzhiyun 	/* XXX: We never power down the LVDS pairs. */
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
cdv_intel_lvds_save(struct drm_connector * connector)145*4882a593Smuzhiyun static void cdv_intel_lvds_save(struct drm_connector *connector)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
cdv_intel_lvds_restore(struct drm_connector * connector)149*4882a593Smuzhiyun static void cdv_intel_lvds_restore(struct drm_connector *connector)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
cdv_intel_lvds_mode_valid(struct drm_connector * connector,struct drm_display_mode * mode)153*4882a593Smuzhiyun static enum drm_mode_status cdv_intel_lvds_mode_valid(struct drm_connector *connector,
154*4882a593Smuzhiyun 			      struct drm_display_mode *mode)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	struct drm_device *dev = connector->dev;
157*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
158*4882a593Smuzhiyun 	struct drm_display_mode *fixed_mode =
159*4882a593Smuzhiyun 					dev_priv->mode_dev.panel_fixed_mode;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	/* just in case */
162*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
163*4882a593Smuzhiyun 		return MODE_NO_DBLESCAN;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	/* just in case */
166*4882a593Smuzhiyun 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
167*4882a593Smuzhiyun 		return MODE_NO_INTERLACE;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	if (fixed_mode) {
170*4882a593Smuzhiyun 		if (mode->hdisplay > fixed_mode->hdisplay)
171*4882a593Smuzhiyun 			return MODE_PANEL;
172*4882a593Smuzhiyun 		if (mode->vdisplay > fixed_mode->vdisplay)
173*4882a593Smuzhiyun 			return MODE_PANEL;
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun 	return MODE_OK;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
cdv_intel_lvds_mode_fixup(struct drm_encoder * encoder,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)178*4882a593Smuzhiyun static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
179*4882a593Smuzhiyun 				  const struct drm_display_mode *mode,
180*4882a593Smuzhiyun 				  struct drm_display_mode *adjusted_mode)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
183*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
184*4882a593Smuzhiyun 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
185*4882a593Smuzhiyun 	struct drm_encoder *tmp_encoder;
186*4882a593Smuzhiyun 	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* Should never happen!! */
189*4882a593Smuzhiyun 	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
190*4882a593Smuzhiyun 			    head) {
191*4882a593Smuzhiyun 		if (tmp_encoder != encoder
192*4882a593Smuzhiyun 		    && tmp_encoder->crtc == encoder->crtc) {
193*4882a593Smuzhiyun 			pr_err("Can't enable LVDS and another encoder on the same pipe\n");
194*4882a593Smuzhiyun 			return false;
195*4882a593Smuzhiyun 		}
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	/*
199*4882a593Smuzhiyun 	 * If we have timings from the BIOS for the panel, put them in
200*4882a593Smuzhiyun 	 * to the adjusted mode.  The CRTC will be set up for this mode,
201*4882a593Smuzhiyun 	 * with the panel scaling set up to source from the H/VDisplay
202*4882a593Smuzhiyun 	 * of the original mode.
203*4882a593Smuzhiyun 	 */
204*4882a593Smuzhiyun 	if (panel_fixed_mode != NULL) {
205*4882a593Smuzhiyun 		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
206*4882a593Smuzhiyun 		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
207*4882a593Smuzhiyun 		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
208*4882a593Smuzhiyun 		adjusted_mode->htotal = panel_fixed_mode->htotal;
209*4882a593Smuzhiyun 		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
210*4882a593Smuzhiyun 		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
211*4882a593Smuzhiyun 		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
212*4882a593Smuzhiyun 		adjusted_mode->vtotal = panel_fixed_mode->vtotal;
213*4882a593Smuzhiyun 		adjusted_mode->clock = panel_fixed_mode->clock;
214*4882a593Smuzhiyun 		drm_mode_set_crtcinfo(adjusted_mode,
215*4882a593Smuzhiyun 				      CRTC_INTERLACE_HALVE_V);
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/*
219*4882a593Smuzhiyun 	 * XXX: It would be nice to support lower refresh rates on the
220*4882a593Smuzhiyun 	 * panels to reduce power consumption, and perhaps match the
221*4882a593Smuzhiyun 	 * user's requested refresh rate.
222*4882a593Smuzhiyun 	 */
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return true;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
cdv_intel_lvds_prepare(struct drm_encoder * encoder)227*4882a593Smuzhiyun static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
230*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
231*4882a593Smuzhiyun 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	if (!gma_power_begin(dev, true))
234*4882a593Smuzhiyun 		return;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
237*4882a593Smuzhiyun 	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
238*4882a593Smuzhiyun 					  BACKLIGHT_DUTY_CYCLE_MASK);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	cdv_intel_lvds_set_power(dev, encoder, false);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	gma_power_end(dev);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
cdv_intel_lvds_commit(struct drm_encoder * encoder)245*4882a593Smuzhiyun static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
248*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
249*4882a593Smuzhiyun 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (mode_dev->backlight_duty_cycle == 0)
252*4882a593Smuzhiyun 		mode_dev->backlight_duty_cycle =
253*4882a593Smuzhiyun 		    cdv_intel_lvds_get_max_backlight(dev);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	cdv_intel_lvds_set_power(dev, encoder, true);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
cdv_intel_lvds_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)258*4882a593Smuzhiyun static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
259*4882a593Smuzhiyun 				struct drm_display_mode *mode,
260*4882a593Smuzhiyun 				struct drm_display_mode *adjusted_mode)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	struct drm_device *dev = encoder->dev;
263*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
264*4882a593Smuzhiyun 	struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);
265*4882a593Smuzhiyun 	u32 pfit_control;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	/*
268*4882a593Smuzhiyun 	 * The LVDS pin pair will already have been turned on in the
269*4882a593Smuzhiyun 	 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
270*4882a593Smuzhiyun 	 * settings.
271*4882a593Smuzhiyun 	 */
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	/*
274*4882a593Smuzhiyun 	 * Enable automatic panel scaling so that non-native modes fill the
275*4882a593Smuzhiyun 	 * screen.  Should be enabled before the pipe is enabled, according to
276*4882a593Smuzhiyun 	 * register description and PRM.
277*4882a593Smuzhiyun 	 */
278*4882a593Smuzhiyun 	if (mode->hdisplay != adjusted_mode->hdisplay ||
279*4882a593Smuzhiyun 	    mode->vdisplay != adjusted_mode->vdisplay)
280*4882a593Smuzhiyun 		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
281*4882a593Smuzhiyun 				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
282*4882a593Smuzhiyun 				HORIZ_INTERP_BILINEAR);
283*4882a593Smuzhiyun 	else
284*4882a593Smuzhiyun 		pfit_control = 0;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	pfit_control |= gma_crtc->pipe << PFIT_PIPE_SHIFT;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (dev_priv->lvds_dither)
289*4882a593Smuzhiyun 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	REG_WRITE(PFIT_CONTROL, pfit_control);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun /**
295*4882a593Smuzhiyun  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
296*4882a593Smuzhiyun  */
cdv_intel_lvds_get_modes(struct drm_connector * connector)297*4882a593Smuzhiyun static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct drm_device *dev = connector->dev;
300*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
301*4882a593Smuzhiyun 	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
302*4882a593Smuzhiyun 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
303*4882a593Smuzhiyun 	int ret;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	ret = psb_intel_ddc_get_modes(connector, &gma_encoder->i2c_bus->adapter);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (ret)
308*4882a593Smuzhiyun 		return ret;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (mode_dev->panel_fixed_mode != NULL) {
311*4882a593Smuzhiyun 		struct drm_display_mode *mode =
312*4882a593Smuzhiyun 		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
313*4882a593Smuzhiyun 		drm_mode_probed_add(connector, mode);
314*4882a593Smuzhiyun 		return 1;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	return 0;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun /**
321*4882a593Smuzhiyun  * cdv_intel_lvds_destroy - unregister and free LVDS structures
322*4882a593Smuzhiyun  * @connector: connector to free
323*4882a593Smuzhiyun  *
324*4882a593Smuzhiyun  * Unregister the DDC bus for this connector then free the driver private
325*4882a593Smuzhiyun  * structure.
326*4882a593Smuzhiyun  */
cdv_intel_lvds_destroy(struct drm_connector * connector)327*4882a593Smuzhiyun static void cdv_intel_lvds_destroy(struct drm_connector *connector)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	psb_intel_i2c_destroy(gma_encoder->i2c_bus);
332*4882a593Smuzhiyun 	drm_connector_unregister(connector);
333*4882a593Smuzhiyun 	drm_connector_cleanup(connector);
334*4882a593Smuzhiyun 	kfree(connector);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
cdv_intel_lvds_set_property(struct drm_connector * connector,struct drm_property * property,uint64_t value)337*4882a593Smuzhiyun static int cdv_intel_lvds_set_property(struct drm_connector *connector,
338*4882a593Smuzhiyun 				       struct drm_property *property,
339*4882a593Smuzhiyun 				       uint64_t value)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	struct drm_encoder *encoder = connector->encoder;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	if (!strcmp(property->name, "scaling mode") && encoder) {
344*4882a593Smuzhiyun 		struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);
345*4882a593Smuzhiyun 		uint64_t curValue;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 		if (!crtc)
348*4882a593Smuzhiyun 			return -1;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 		switch (value) {
351*4882a593Smuzhiyun 		case DRM_MODE_SCALE_FULLSCREEN:
352*4882a593Smuzhiyun 			break;
353*4882a593Smuzhiyun 		case DRM_MODE_SCALE_NO_SCALE:
354*4882a593Smuzhiyun 			break;
355*4882a593Smuzhiyun 		case DRM_MODE_SCALE_ASPECT:
356*4882a593Smuzhiyun 			break;
357*4882a593Smuzhiyun 		default:
358*4882a593Smuzhiyun 			return -1;
359*4882a593Smuzhiyun 		}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		if (drm_object_property_get_value(&connector->base,
362*4882a593Smuzhiyun 						     property,
363*4882a593Smuzhiyun 						     &curValue))
364*4882a593Smuzhiyun 			return -1;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 		if (curValue == value)
367*4882a593Smuzhiyun 			return 0;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		if (drm_object_property_set_value(&connector->base,
370*4882a593Smuzhiyun 							property,
371*4882a593Smuzhiyun 							value))
372*4882a593Smuzhiyun 			return -1;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 		if (crtc->saved_mode.hdisplay != 0 &&
375*4882a593Smuzhiyun 		    crtc->saved_mode.vdisplay != 0) {
376*4882a593Smuzhiyun 			if (!drm_crtc_helper_set_mode(encoder->crtc,
377*4882a593Smuzhiyun 						      &crtc->saved_mode,
378*4882a593Smuzhiyun 						      encoder->crtc->x,
379*4882a593Smuzhiyun 						      encoder->crtc->y,
380*4882a593Smuzhiyun 						      encoder->crtc->primary->fb))
381*4882a593Smuzhiyun 				return -1;
382*4882a593Smuzhiyun 		}
383*4882a593Smuzhiyun 	} else if (!strcmp(property->name, "backlight") && encoder) {
384*4882a593Smuzhiyun 		if (drm_object_property_set_value(&connector->base,
385*4882a593Smuzhiyun 							property,
386*4882a593Smuzhiyun 							value))
387*4882a593Smuzhiyun 			return -1;
388*4882a593Smuzhiyun 		else
389*4882a593Smuzhiyun                         gma_backlight_set(encoder->dev, value);
390*4882a593Smuzhiyun 	} else if (!strcmp(property->name, "DPMS") && encoder) {
391*4882a593Smuzhiyun 		const struct drm_encoder_helper_funcs *helpers =
392*4882a593Smuzhiyun 					encoder->helper_private;
393*4882a593Smuzhiyun 		helpers->dpms(encoder, value);
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 	return 0;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static const struct drm_encoder_helper_funcs
399*4882a593Smuzhiyun 					cdv_intel_lvds_helper_funcs = {
400*4882a593Smuzhiyun 	.dpms = cdv_intel_lvds_encoder_dpms,
401*4882a593Smuzhiyun 	.mode_fixup = cdv_intel_lvds_mode_fixup,
402*4882a593Smuzhiyun 	.prepare = cdv_intel_lvds_prepare,
403*4882a593Smuzhiyun 	.mode_set = cdv_intel_lvds_mode_set,
404*4882a593Smuzhiyun 	.commit = cdv_intel_lvds_commit,
405*4882a593Smuzhiyun };
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun static const struct drm_connector_helper_funcs
408*4882a593Smuzhiyun 				cdv_intel_lvds_connector_helper_funcs = {
409*4882a593Smuzhiyun 	.get_modes = cdv_intel_lvds_get_modes,
410*4882a593Smuzhiyun 	.mode_valid = cdv_intel_lvds_mode_valid,
411*4882a593Smuzhiyun 	.best_encoder = gma_best_encoder,
412*4882a593Smuzhiyun };
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
415*4882a593Smuzhiyun 	.dpms = drm_helper_connector_dpms,
416*4882a593Smuzhiyun 	.fill_modes = drm_helper_probe_single_connector_modes,
417*4882a593Smuzhiyun 	.set_property = cdv_intel_lvds_set_property,
418*4882a593Smuzhiyun 	.destroy = cdv_intel_lvds_destroy,
419*4882a593Smuzhiyun };
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun /*
422*4882a593Smuzhiyun  * Enumerate the child dev array parsed from VBT to check whether
423*4882a593Smuzhiyun  * the LVDS is present.
424*4882a593Smuzhiyun  * If it is present, return 1.
425*4882a593Smuzhiyun  * If it is not present, return false.
426*4882a593Smuzhiyun  * If no child dev is parsed from VBT, it assumes that the LVDS is present.
427*4882a593Smuzhiyun  */
lvds_is_present_in_vbt(struct drm_device * dev,u8 * i2c_pin)428*4882a593Smuzhiyun static bool lvds_is_present_in_vbt(struct drm_device *dev,
429*4882a593Smuzhiyun 				   u8 *i2c_pin)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
432*4882a593Smuzhiyun 	int i;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	if (!dev_priv->child_dev_num)
435*4882a593Smuzhiyun 		return true;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	for (i = 0; i < dev_priv->child_dev_num; i++) {
438*4882a593Smuzhiyun 		struct child_device_config *child = dev_priv->child_dev + i;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 		/* If the device type is not LFP, continue.
441*4882a593Smuzhiyun 		 * We have to check both the new identifiers as well as the
442*4882a593Smuzhiyun 		 * old for compatibility with some BIOSes.
443*4882a593Smuzhiyun 		 */
444*4882a593Smuzhiyun 		if (child->device_type != DEVICE_TYPE_INT_LFP &&
445*4882a593Smuzhiyun 		    child->device_type != DEVICE_TYPE_LFP)
446*4882a593Smuzhiyun 			continue;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 		if (child->i2c_pin)
449*4882a593Smuzhiyun 		    *i2c_pin = child->i2c_pin;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 		/* However, we cannot trust the BIOS writers to populate
452*4882a593Smuzhiyun 		 * the VBT correctly.  Since LVDS requires additional
453*4882a593Smuzhiyun 		 * information from AIM blocks, a non-zero addin offset is
454*4882a593Smuzhiyun 		 * a good indicator that the LVDS is actually present.
455*4882a593Smuzhiyun 		 */
456*4882a593Smuzhiyun 		if (child->addin_offset)
457*4882a593Smuzhiyun 			return true;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		/* But even then some BIOS writers perform some black magic
460*4882a593Smuzhiyun 		 * and instantiate the device without reference to any
461*4882a593Smuzhiyun 		 * additional data.  Trust that if the VBT was written into
462*4882a593Smuzhiyun 		 * the OpRegion then they have validated the LVDS's existence.
463*4882a593Smuzhiyun 		 */
464*4882a593Smuzhiyun 		if (dev_priv->opregion.vbt)
465*4882a593Smuzhiyun 			return true;
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	return false;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun /**
472*4882a593Smuzhiyun  * cdv_intel_lvds_init - setup LVDS connectors on this device
473*4882a593Smuzhiyun  * @dev: drm device
474*4882a593Smuzhiyun  *
475*4882a593Smuzhiyun  * Create the connector, register the LVDS DDC bus, and try to figure out what
476*4882a593Smuzhiyun  * modes we can display on the LVDS panel (if present).
477*4882a593Smuzhiyun  */
cdv_intel_lvds_init(struct drm_device * dev,struct psb_intel_mode_device * mode_dev)478*4882a593Smuzhiyun void cdv_intel_lvds_init(struct drm_device *dev,
479*4882a593Smuzhiyun 		     struct psb_intel_mode_device *mode_dev)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun 	struct gma_encoder *gma_encoder;
482*4882a593Smuzhiyun 	struct gma_connector *gma_connector;
483*4882a593Smuzhiyun 	struct cdv_intel_lvds_priv *lvds_priv;
484*4882a593Smuzhiyun 	struct drm_connector *connector;
485*4882a593Smuzhiyun 	struct drm_encoder *encoder;
486*4882a593Smuzhiyun 	struct drm_display_mode *scan;
487*4882a593Smuzhiyun 	struct drm_crtc *crtc;
488*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
489*4882a593Smuzhiyun 	u32 lvds;
490*4882a593Smuzhiyun 	int pipe;
491*4882a593Smuzhiyun 	u8 pin;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	if (!dev_priv->lvds_enabled_in_vbt)
494*4882a593Smuzhiyun 		return;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	pin = GMBUS_PORT_PANEL;
497*4882a593Smuzhiyun 	if (!lvds_is_present_in_vbt(dev, &pin)) {
498*4882a593Smuzhiyun 		DRM_DEBUG_KMS("LVDS is not present in VBT\n");
499*4882a593Smuzhiyun 		return;
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	gma_encoder = kzalloc(sizeof(struct gma_encoder),
503*4882a593Smuzhiyun 				    GFP_KERNEL);
504*4882a593Smuzhiyun 	if (!gma_encoder)
505*4882a593Smuzhiyun 		return;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	gma_connector = kzalloc(sizeof(struct gma_connector),
508*4882a593Smuzhiyun 				      GFP_KERNEL);
509*4882a593Smuzhiyun 	if (!gma_connector)
510*4882a593Smuzhiyun 		goto failed_connector;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
513*4882a593Smuzhiyun 	if (!lvds_priv)
514*4882a593Smuzhiyun 		goto failed_lvds_priv;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	gma_encoder->dev_priv = lvds_priv;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	connector = &gma_connector->base;
519*4882a593Smuzhiyun 	gma_connector->save = cdv_intel_lvds_save;
520*4882a593Smuzhiyun 	gma_connector->restore = cdv_intel_lvds_restore;
521*4882a593Smuzhiyun 	encoder = &gma_encoder->base;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	drm_connector_init(dev, connector,
525*4882a593Smuzhiyun 			   &cdv_intel_lvds_connector_funcs,
526*4882a593Smuzhiyun 			   DRM_MODE_CONNECTOR_LVDS);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	gma_connector_attach_encoder(gma_connector, gma_encoder);
531*4882a593Smuzhiyun 	gma_encoder->type = INTEL_OUTPUT_LVDS;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
534*4882a593Smuzhiyun 	drm_connector_helper_add(connector,
535*4882a593Smuzhiyun 				 &cdv_intel_lvds_connector_helper_funcs);
536*4882a593Smuzhiyun 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
537*4882a593Smuzhiyun 	connector->interlace_allowed = false;
538*4882a593Smuzhiyun 	connector->doublescan_allowed = false;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	/*Attach connector properties*/
541*4882a593Smuzhiyun 	drm_object_attach_property(&connector->base,
542*4882a593Smuzhiyun 				      dev->mode_config.scaling_mode_property,
543*4882a593Smuzhiyun 				      DRM_MODE_SCALE_FULLSCREEN);
544*4882a593Smuzhiyun 	drm_object_attach_property(&connector->base,
545*4882a593Smuzhiyun 				      dev_priv->backlight_property,
546*4882a593Smuzhiyun 				      BRIGHTNESS_MAX_LEVEL);
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	/**
549*4882a593Smuzhiyun 	 * Set up I2C bus
550*4882a593Smuzhiyun 	 * FIXME: distroy i2c_bus when exit
551*4882a593Smuzhiyun 	 */
552*4882a593Smuzhiyun 	gma_encoder->i2c_bus = psb_intel_i2c_create(dev,
553*4882a593Smuzhiyun 							 GPIOB,
554*4882a593Smuzhiyun 							 "LVDSBLC_B");
555*4882a593Smuzhiyun 	if (!gma_encoder->i2c_bus) {
556*4882a593Smuzhiyun 		dev_printk(KERN_ERR,
557*4882a593Smuzhiyun 			&dev->pdev->dev, "I2C bus registration failed.\n");
558*4882a593Smuzhiyun 		goto failed_blc_i2c;
559*4882a593Smuzhiyun 	}
560*4882a593Smuzhiyun 	gma_encoder->i2c_bus->slave_addr = 0x2C;
561*4882a593Smuzhiyun 	dev_priv->lvds_i2c_bus = gma_encoder->i2c_bus;
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	/*
564*4882a593Smuzhiyun 	 * LVDS discovery:
565*4882a593Smuzhiyun 	 * 1) check for EDID on DDC
566*4882a593Smuzhiyun 	 * 2) check for VBT data
567*4882a593Smuzhiyun 	 * 3) check to see if LVDS is already on
568*4882a593Smuzhiyun 	 *    if none of the above, no panel
569*4882a593Smuzhiyun 	 * 4) make sure lid is open
570*4882a593Smuzhiyun 	 *    if closed, act like it's not there for now
571*4882a593Smuzhiyun 	 */
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	/* Set up the DDC bus. */
574*4882a593Smuzhiyun 	gma_encoder->ddc_bus = psb_intel_i2c_create(dev,
575*4882a593Smuzhiyun 							 GPIOC,
576*4882a593Smuzhiyun 							 "LVDSDDC_C");
577*4882a593Smuzhiyun 	if (!gma_encoder->ddc_bus) {
578*4882a593Smuzhiyun 		dev_printk(KERN_ERR, &dev->pdev->dev,
579*4882a593Smuzhiyun 			   "DDC bus registration " "failed.\n");
580*4882a593Smuzhiyun 		goto failed_ddc;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	/*
584*4882a593Smuzhiyun 	 * Attempt to get the fixed panel mode from DDC.  Assume that the
585*4882a593Smuzhiyun 	 * preferred mode is the right one.
586*4882a593Smuzhiyun 	 */
587*4882a593Smuzhiyun 	mutex_lock(&dev->mode_config.mutex);
588*4882a593Smuzhiyun 	psb_intel_ddc_get_modes(connector,
589*4882a593Smuzhiyun 				&gma_encoder->ddc_bus->adapter);
590*4882a593Smuzhiyun 	list_for_each_entry(scan, &connector->probed_modes, head) {
591*4882a593Smuzhiyun 		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
592*4882a593Smuzhiyun 			mode_dev->panel_fixed_mode =
593*4882a593Smuzhiyun 			    drm_mode_duplicate(dev, scan);
594*4882a593Smuzhiyun 			goto out;	/* FIXME: check for quirks */
595*4882a593Smuzhiyun 		}
596*4882a593Smuzhiyun 	}
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	/* Failed to get EDID, what about VBT? do we need this?*/
599*4882a593Smuzhiyun 	if (dev_priv->lfp_lvds_vbt_mode) {
600*4882a593Smuzhiyun 		mode_dev->panel_fixed_mode =
601*4882a593Smuzhiyun 			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
602*4882a593Smuzhiyun 		if (mode_dev->panel_fixed_mode) {
603*4882a593Smuzhiyun 			mode_dev->panel_fixed_mode->type |=
604*4882a593Smuzhiyun 				DRM_MODE_TYPE_PREFERRED;
605*4882a593Smuzhiyun 			goto out;	/* FIXME: check for quirks */
606*4882a593Smuzhiyun 		}
607*4882a593Smuzhiyun 	}
608*4882a593Smuzhiyun 	/*
609*4882a593Smuzhiyun 	 * If we didn't get EDID, try checking if the panel is already turned
610*4882a593Smuzhiyun 	 * on.	If so, assume that whatever is currently programmed is the
611*4882a593Smuzhiyun 	 * correct mode.
612*4882a593Smuzhiyun 	 */
613*4882a593Smuzhiyun 	lvds = REG_READ(LVDS);
614*4882a593Smuzhiyun 	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
615*4882a593Smuzhiyun 	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	if (crtc && (lvds & LVDS_PORT_EN)) {
618*4882a593Smuzhiyun 		mode_dev->panel_fixed_mode =
619*4882a593Smuzhiyun 		    cdv_intel_crtc_mode_get(dev, crtc);
620*4882a593Smuzhiyun 		if (mode_dev->panel_fixed_mode) {
621*4882a593Smuzhiyun 			mode_dev->panel_fixed_mode->type |=
622*4882a593Smuzhiyun 			    DRM_MODE_TYPE_PREFERRED;
623*4882a593Smuzhiyun 			goto out;	/* FIXME: check for quirks */
624*4882a593Smuzhiyun 		}
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	/* If we still don't have a mode after all that, give up. */
628*4882a593Smuzhiyun 	if (!mode_dev->panel_fixed_mode) {
629*4882a593Smuzhiyun 		DRM_DEBUG
630*4882a593Smuzhiyun 			("Found no modes on the lvds, ignoring the LVDS\n");
631*4882a593Smuzhiyun 		goto failed_find;
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	/* setup PWM */
635*4882a593Smuzhiyun 	{
636*4882a593Smuzhiyun 		u32 pwm;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 		pwm = REG_READ(BLC_PWM_CTL2);
639*4882a593Smuzhiyun 		if (pipe == 1)
640*4882a593Smuzhiyun 			pwm |= PWM_PIPE_B;
641*4882a593Smuzhiyun 		else
642*4882a593Smuzhiyun 			pwm &= ~PWM_PIPE_B;
643*4882a593Smuzhiyun 		pwm |= PWM_ENABLE;
644*4882a593Smuzhiyun 		REG_WRITE(BLC_PWM_CTL2, pwm);
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun out:
648*4882a593Smuzhiyun 	mutex_unlock(&dev->mode_config.mutex);
649*4882a593Smuzhiyun 	drm_connector_register(connector);
650*4882a593Smuzhiyun 	return;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun failed_find:
653*4882a593Smuzhiyun 	mutex_unlock(&dev->mode_config.mutex);
654*4882a593Smuzhiyun 	pr_err("Failed find\n");
655*4882a593Smuzhiyun 	psb_intel_i2c_destroy(gma_encoder->ddc_bus);
656*4882a593Smuzhiyun failed_ddc:
657*4882a593Smuzhiyun 	pr_err("Failed DDC\n");
658*4882a593Smuzhiyun 	psb_intel_i2c_destroy(gma_encoder->i2c_bus);
659*4882a593Smuzhiyun failed_blc_i2c:
660*4882a593Smuzhiyun 	pr_err("Failed BLC\n");
661*4882a593Smuzhiyun 	drm_encoder_cleanup(encoder);
662*4882a593Smuzhiyun 	drm_connector_cleanup(connector);
663*4882a593Smuzhiyun 	kfree(lvds_priv);
664*4882a593Smuzhiyun failed_lvds_priv:
665*4882a593Smuzhiyun 	kfree(gma_connector);
666*4882a593Smuzhiyun failed_connector:
667*4882a593Smuzhiyun 	kfree(gma_encoder);
668*4882a593Smuzhiyun }
669