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