diff options
-rw-r--r-- | drivers/gpu/drm/gma500/backlight.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_device.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_intel_display.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_intel_dp.c | 468 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_intel_lvds.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/framebuffer.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/intel_bios.c | 101 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/intel_bios.h | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mdfld_dsi_output.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mid_bios.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/opregion.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_lvds.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_reg.h | 38 |
14 files changed, 751 insertions, 61 deletions
diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index 20793951fcac..143eba3309c5 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c | |||
@@ -26,10 +26,55 @@ | |||
26 | #include "intel_bios.h" | 26 | #include "intel_bios.h" |
27 | #include "power.h" | 27 | #include "power.h" |
28 | 28 | ||
29 | static void do_gma_backlight_set(struct drm_device *dev) | ||
30 | { | ||
31 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
32 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
33 | backlight_update_status(dev_priv->backlight_device); | ||
34 | #endif | ||
35 | } | ||
36 | |||
37 | void gma_backlight_enable(struct drm_device *dev) | ||
38 | { | ||
39 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
40 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
41 | dev_priv->backlight_enabled = true; | ||
42 | if (dev_priv->backlight_device) { | ||
43 | dev_priv->backlight_device->props.brightness = dev_priv->backlight_level; | ||
44 | do_gma_backlight_set(dev); | ||
45 | } | ||
46 | #endif | ||
47 | } | ||
48 | |||
49 | void gma_backlight_disable(struct drm_device *dev) | ||
50 | { | ||
51 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
52 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
53 | dev_priv->backlight_enabled = false; | ||
54 | if (dev_priv->backlight_device) { | ||
55 | dev_priv->backlight_device->props.brightness = 0; | ||
56 | do_gma_backlight_set(dev); | ||
57 | } | ||
58 | #endif | ||
59 | } | ||
60 | |||
61 | void gma_backlight_set(struct drm_device *dev, int v) | ||
62 | { | ||
63 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
64 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
65 | dev_priv->backlight_level = v; | ||
66 | if (dev_priv->backlight_device && dev_priv->backlight_enabled) { | ||
67 | dev_priv->backlight_device->props.brightness = v; | ||
68 | do_gma_backlight_set(dev); | ||
69 | } | ||
70 | #endif | ||
71 | } | ||
72 | |||
29 | int gma_backlight_init(struct drm_device *dev) | 73 | int gma_backlight_init(struct drm_device *dev) |
30 | { | 74 | { |
31 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | 75 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE |
32 | struct drm_psb_private *dev_priv = dev->dev_private; | 76 | struct drm_psb_private *dev_priv = dev->dev_private; |
77 | dev_priv->backlight_enabled = true; | ||
33 | return dev_priv->ops->backlight_init(dev); | 78 | return dev_priv->ops->backlight_init(dev); |
34 | #else | 79 | #else |
35 | return 0; | 80 | return 0; |
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 68f100e67135..4882e642eec3 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c | |||
@@ -170,6 +170,7 @@ static int cdv_backlight_init(struct drm_device *dev) | |||
170 | cdv_get_brightness(cdv_backlight_device); | 170 | cdv_get_brightness(cdv_backlight_device); |
171 | backlight_update_status(cdv_backlight_device); | 171 | backlight_update_status(cdv_backlight_device); |
172 | dev_priv->backlight_device = cdv_backlight_device; | 172 | dev_priv->backlight_device = cdv_backlight_device; |
173 | dev_priv->backlight_enabled = true; | ||
173 | return 0; | 174 | return 0; |
174 | } | 175 | } |
175 | 176 | ||
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 3f1106096ad3..bfb056561777 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c | |||
@@ -438,7 +438,8 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, | |||
438 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; | 438 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; |
439 | else | 439 | else |
440 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; | 440 | limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; |
441 | } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { | 441 | } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || |
442 | psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { | ||
442 | if (refclk == 27000) | 443 | if (refclk == 27000) |
443 | limit = &cdv_intel_limits[CDV_LIMIT_DP_27]; | 444 | limit = &cdv_intel_limits[CDV_LIMIT_DP_27]; |
444 | else | 445 | else |
@@ -1045,6 +1046,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1045 | struct drm_connector *connector; | 1046 | struct drm_connector *connector; |
1046 | const struct cdv_intel_limit_t *limit; | 1047 | const struct cdv_intel_limit_t *limit; |
1047 | u32 ddi_select = 0; | 1048 | u32 ddi_select = 0; |
1049 | bool is_edp = false; | ||
1048 | 1050 | ||
1049 | list_for_each_entry(connector, &mode_config->connector_list, head) { | 1051 | list_for_each_entry(connector, &mode_config->connector_list, head) { |
1050 | struct psb_intel_encoder *psb_intel_encoder = | 1052 | struct psb_intel_encoder *psb_intel_encoder = |
@@ -1071,6 +1073,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1071 | case INTEL_OUTPUT_DISPLAYPORT: | 1073 | case INTEL_OUTPUT_DISPLAYPORT: |
1072 | is_dp = true; | 1074 | is_dp = true; |
1073 | break; | 1075 | break; |
1076 | case INTEL_OUTPUT_EDP: | ||
1077 | is_edp = true; | ||
1078 | break; | ||
1074 | default: | 1079 | default: |
1075 | DRM_ERROR("invalid output type.\n"); | 1080 | DRM_ERROR("invalid output type.\n"); |
1076 | return 0; | 1081 | return 0; |
@@ -1083,7 +1088,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1083 | else | 1088 | else |
1084 | /* high-end sku, 27/100 mhz */ | 1089 | /* high-end sku, 27/100 mhz */ |
1085 | refclk = 27000; | 1090 | refclk = 27000; |
1086 | if (is_dp) { | 1091 | if (is_dp || is_edp) { |
1092 | /* | ||
1093 | * Based on the spec the low-end SKU has only CRT/LVDS. So it is | ||
1094 | * unnecessary to consider it for DP/eDP. | ||
1095 | * On the high-end SKU, it will use the 27/100M reference clk | ||
1096 | * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise | ||
1097 | * it will be 27MHz. From the VBIOS code it seems that the pipe A choose | ||
1098 | * 27MHz for DP/eDP while the Pipe B chooses the 100MHz. | ||
1099 | */ | ||
1087 | if (pipe == 0) | 1100 | if (pipe == 0) |
1088 | refclk = 27000; | 1101 | refclk = 27000; |
1089 | else | 1102 | else |
@@ -1133,6 +1146,31 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, | |||
1133 | /* setup pipeconf */ | 1146 | /* setup pipeconf */ |
1134 | pipeconf = REG_READ(map->conf); | 1147 | pipeconf = REG_READ(map->conf); |
1135 | 1148 | ||
1149 | pipeconf &= ~(PIPE_BPC_MASK); | ||
1150 | if (is_edp) { | ||
1151 | switch (dev_priv->edp.bpp) { | ||
1152 | case 24: | ||
1153 | pipeconf |= PIPE_8BPC; | ||
1154 | break; | ||
1155 | case 18: | ||
1156 | pipeconf |= PIPE_6BPC; | ||
1157 | break; | ||
1158 | case 30: | ||
1159 | pipeconf |= PIPE_10BPC; | ||
1160 | break; | ||
1161 | default: | ||
1162 | pipeconf |= PIPE_8BPC; | ||
1163 | break; | ||
1164 | } | ||
1165 | } else if (is_lvds) { | ||
1166 | /* the BPC will be 6 if it is 18-bit LVDS panel */ | ||
1167 | if ((REG_READ(LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) | ||
1168 | pipeconf |= PIPE_8BPC; | ||
1169 | else | ||
1170 | pipeconf |= PIPE_6BPC; | ||
1171 | } else | ||
1172 | pipeconf |= PIPE_8BPC; | ||
1173 | |||
1136 | /* Set up the display plane register */ | 1174 | /* Set up the display plane register */ |
1137 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 1175 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
1138 | 1176 | ||
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index b29b6026b6ef..0571ef9b889b 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c | |||
@@ -36,6 +36,20 @@ | |||
36 | #include "psb_intel_reg.h" | 36 | #include "psb_intel_reg.h" |
37 | #include "drm_dp_helper.h" | 37 | #include "drm_dp_helper.h" |
38 | 38 | ||
39 | #define _wait_for(COND, MS, W) ({ \ | ||
40 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ | ||
41 | int ret__ = 0; \ | ||
42 | while (! (COND)) { \ | ||
43 | if (time_after(jiffies, timeout__)) { \ | ||
44 | ret__ = -ETIMEDOUT; \ | ||
45 | break; \ | ||
46 | } \ | ||
47 | if (W && !in_dbg_master()) msleep(W); \ | ||
48 | } \ | ||
49 | ret__; \ | ||
50 | }) | ||
51 | |||
52 | #define wait_for(COND, MS) _wait_for(COND, MS, 1) | ||
39 | 53 | ||
40 | #define DP_LINK_STATUS_SIZE 6 | 54 | #define DP_LINK_STATUS_SIZE 6 |
41 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | 55 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) |
@@ -59,6 +73,13 @@ struct cdv_intel_dp { | |||
59 | struct i2c_algo_dp_aux_data algo; | 73 | struct i2c_algo_dp_aux_data algo; |
60 | uint8_t train_set[4]; | 74 | uint8_t train_set[4]; |
61 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 75 | uint8_t link_status[DP_LINK_STATUS_SIZE]; |
76 | int panel_power_up_delay; | ||
77 | int panel_power_down_delay; | ||
78 | int panel_power_cycle_delay; | ||
79 | int backlight_on_delay; | ||
80 | int backlight_off_delay; | ||
81 | struct drm_display_mode *panel_fixed_mode; /* for eDP */ | ||
82 | bool panel_on; | ||
62 | }; | 83 | }; |
63 | 84 | ||
64 | struct ddi_regoff { | 85 | struct ddi_regoff { |
@@ -159,31 +180,166 @@ cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes) | |||
159 | return (max_link_clock * max_lanes * 19) / 20; | 180 | return (max_link_clock * max_lanes * 19) / 20; |
160 | } | 181 | } |
161 | 182 | ||
183 | static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder) | ||
184 | { | ||
185 | struct drm_device *dev = intel_encoder->base.dev; | ||
186 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
187 | u32 pp; | ||
188 | |||
189 | if (intel_dp->panel_on) { | ||
190 | DRM_DEBUG_KMS("Skip VDD on because of panel on\n"); | ||
191 | return; | ||
192 | } | ||
193 | DRM_DEBUG_KMS("\n"); | ||
194 | |||
195 | pp = REG_READ(PP_CONTROL); | ||
196 | |||
197 | pp |= EDP_FORCE_VDD; | ||
198 | REG_WRITE(PP_CONTROL, pp); | ||
199 | REG_READ(PP_CONTROL); | ||
200 | msleep(intel_dp->panel_power_up_delay); | ||
201 | } | ||
202 | |||
203 | static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder) | ||
204 | { | ||
205 | struct drm_device *dev = intel_encoder->base.dev; | ||
206 | u32 pp; | ||
207 | |||
208 | DRM_DEBUG_KMS("\n"); | ||
209 | pp = REG_READ(PP_CONTROL); | ||
210 | |||
211 | pp &= ~EDP_FORCE_VDD; | ||
212 | REG_WRITE(PP_CONTROL, pp); | ||
213 | REG_READ(PP_CONTROL); | ||
214 | |||
215 | } | ||
216 | |||
217 | /* Returns true if the panel was already on when called */ | ||
218 | static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder) | ||
219 | { | ||
220 | struct drm_device *dev = intel_encoder->base.dev; | ||
221 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
222 | u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_NONE; | ||
223 | |||
224 | if (intel_dp->panel_on) | ||
225 | return true; | ||
226 | |||
227 | DRM_DEBUG_KMS("\n"); | ||
228 | pp = REG_READ(PP_CONTROL); | ||
229 | pp &= ~PANEL_UNLOCK_MASK; | ||
230 | |||
231 | pp |= (PANEL_UNLOCK_REGS | POWER_TARGET_ON); | ||
232 | REG_WRITE(PP_CONTROL, pp); | ||
233 | REG_READ(PP_CONTROL); | ||
234 | |||
235 | if (wait_for(((REG_READ(PP_STATUS) & idle_on_mask) == idle_on_mask), 1000)) { | ||
236 | DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS)); | ||
237 | intel_dp->panel_on = false; | ||
238 | } else | ||
239 | intel_dp->panel_on = true; | ||
240 | msleep(intel_dp->panel_power_up_delay); | ||
241 | |||
242 | return false; | ||
243 | } | ||
244 | |||
245 | static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder) | ||
246 | { | ||
247 | struct drm_device *dev = intel_encoder->base.dev; | ||
248 | u32 pp, idle_off_mask = PP_ON ; | ||
249 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
250 | |||
251 | DRM_DEBUG_KMS("\n"); | ||
252 | |||
253 | pp = REG_READ(PP_CONTROL); | ||
254 | |||
255 | if ((pp & POWER_TARGET_ON) == 0) | ||
256 | return; | ||
257 | |||
258 | intel_dp->panel_on = false; | ||
259 | pp &= ~PANEL_UNLOCK_MASK; | ||
260 | /* ILK workaround: disable reset around power sequence */ | ||
261 | |||
262 | pp &= ~POWER_TARGET_ON; | ||
263 | pp &= ~EDP_FORCE_VDD; | ||
264 | pp &= ~EDP_BLC_ENABLE; | ||
265 | REG_WRITE(PP_CONTROL, pp); | ||
266 | REG_READ(PP_CONTROL); | ||
267 | DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS)); | ||
268 | |||
269 | if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) { | ||
270 | DRM_DEBUG_KMS("Error in turning off Panel\n"); | ||
271 | } | ||
272 | |||
273 | msleep(intel_dp->panel_power_cycle_delay); | ||
274 | DRM_DEBUG_KMS("Over\n"); | ||
275 | } | ||
276 | |||
277 | static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder) | ||
278 | { | ||
279 | struct drm_device *dev = intel_encoder->base.dev; | ||
280 | u32 pp; | ||
281 | |||
282 | DRM_DEBUG_KMS("\n"); | ||
283 | /* | ||
284 | * If we enable the backlight right away following a panel power | ||
285 | * on, we may see slight flicker as the panel syncs with the eDP | ||
286 | * link. So delay a bit to make sure the image is solid before | ||
287 | * allowing it to appear. | ||
288 | */ | ||
289 | msleep(300); | ||
290 | pp = REG_READ(PP_CONTROL); | ||
291 | |||
292 | pp |= EDP_BLC_ENABLE; | ||
293 | REG_WRITE(PP_CONTROL, pp); | ||
294 | gma_backlight_enable(dev); | ||
295 | } | ||
296 | |||
297 | static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder) | ||
298 | { | ||
299 | struct drm_device *dev = intel_encoder->base.dev; | ||
300 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | ||
301 | u32 pp; | ||
302 | |||
303 | DRM_DEBUG_KMS("\n"); | ||
304 | gma_backlight_disable(dev); | ||
305 | msleep(10); | ||
306 | pp = REG_READ(PP_CONTROL); | ||
307 | |||
308 | pp &= ~EDP_BLC_ENABLE; | ||
309 | REG_WRITE(PP_CONTROL, pp); | ||
310 | msleep(intel_dp->backlight_off_delay); | ||
311 | } | ||
312 | |||
162 | static int | 313 | static int |
163 | cdv_intel_dp_mode_valid(struct drm_connector *connector, | 314 | cdv_intel_dp_mode_valid(struct drm_connector *connector, |
164 | struct drm_display_mode *mode) | 315 | struct drm_display_mode *mode) |
165 | { | 316 | { |
166 | struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); | 317 | struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); |
167 | struct drm_device *dev = connector->dev; | 318 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
168 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
169 | int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); | 319 | int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); |
170 | int max_lanes = cdv_intel_dp_max_lane_count(encoder); | 320 | int max_lanes = cdv_intel_dp_max_lane_count(encoder); |
321 | struct drm_psb_private *dev_priv = connector->dev->dev_private; | ||
171 | 322 | ||
172 | if (is_edp(encoder) && dev_priv->panel_fixed_mode) { | 323 | if (is_edp(encoder) && intel_dp->panel_fixed_mode) { |
173 | if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) | 324 | if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) |
174 | return MODE_PANEL; | 325 | return MODE_PANEL; |
175 | 326 | if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay) | |
176 | if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) | ||
177 | return MODE_PANEL; | 327 | return MODE_PANEL; |
178 | } | 328 | } |
179 | 329 | ||
180 | /* only refuse the mode on non eDP since we have seen some weird eDP panels | 330 | /* only refuse the mode on non eDP since we have seen some weird eDP panels |
181 | which are outside spec tolerances but somehow work by magic */ | 331 | which are outside spec tolerances but somehow work by magic */ |
182 | if (!is_edp(encoder) && | 332 | if (!is_edp(encoder) && |
183 | (cdv_intel_dp_link_required(mode->clock, 24) | 333 | (cdv_intel_dp_link_required(mode->clock, dev_priv->edp.bpp) |
184 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) | 334 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) |
185 | return MODE_CLOCK_HIGH; | 335 | return MODE_CLOCK_HIGH; |
186 | 336 | ||
337 | if (is_edp(encoder)) { | ||
338 | if (cdv_intel_dp_link_required(mode->clock, 24) | ||
339 | > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes)) | ||
340 | return MODE_CLOCK_HIGH; | ||
341 | |||
342 | } | ||
187 | if (mode->clock < 10000) | 343 | if (mode->clock < 10000) |
188 | return MODE_CLOCK_LOW; | 344 | return MODE_CLOCK_LOW; |
189 | 345 | ||
@@ -238,6 +394,8 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder, | |||
238 | aux_clock_divider = 200 / 2; | 394 | aux_clock_divider = 200 / 2; |
239 | 395 | ||
240 | precharge = 4; | 396 | precharge = 4; |
397 | if (is_edp(encoder)) | ||
398 | precharge = 10; | ||
241 | 399 | ||
242 | if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { | 400 | if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { |
243 | DRM_ERROR("dp_aux_ch not started status 0x%08x\n", | 401 | DRM_ERROR("dp_aux_ch not started status 0x%08x\n", |
@@ -492,7 +650,10 @@ static int | |||
492 | cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) | 650 | cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) |
493 | { | 651 | { |
494 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 652 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
653 | int ret; | ||
654 | |||
495 | DRM_DEBUG_KMS("i2c_init %s\n", name); | 655 | DRM_DEBUG_KMS("i2c_init %s\n", name); |
656 | |||
496 | intel_dp->algo.running = false; | 657 | intel_dp->algo.running = false; |
497 | intel_dp->algo.address = 0; | 658 | intel_dp->algo.address = 0; |
498 | intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; | 659 | intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; |
@@ -505,27 +666,58 @@ cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_en | |||
505 | intel_dp->adapter.algo_data = &intel_dp->algo; | 666 | intel_dp->adapter.algo_data = &intel_dp->algo; |
506 | intel_dp->adapter.dev.parent = &connector->base.kdev; | 667 | intel_dp->adapter.dev.parent = &connector->base.kdev; |
507 | 668 | ||
508 | return i2c_dp_aux_add_bus(&intel_dp->adapter); | 669 | if (is_edp(encoder)) |
670 | cdv_intel_edp_panel_vdd_on(encoder); | ||
671 | ret = i2c_dp_aux_add_bus(&intel_dp->adapter); | ||
672 | if (is_edp(encoder)) | ||
673 | cdv_intel_edp_panel_vdd_off(encoder); | ||
674 | |||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | ||
679 | struct drm_display_mode *adjusted_mode) | ||
680 | { | ||
681 | adjusted_mode->hdisplay = fixed_mode->hdisplay; | ||
682 | adjusted_mode->hsync_start = fixed_mode->hsync_start; | ||
683 | adjusted_mode->hsync_end = fixed_mode->hsync_end; | ||
684 | adjusted_mode->htotal = fixed_mode->htotal; | ||
685 | |||
686 | adjusted_mode->vdisplay = fixed_mode->vdisplay; | ||
687 | adjusted_mode->vsync_start = fixed_mode->vsync_start; | ||
688 | adjusted_mode->vsync_end = fixed_mode->vsync_end; | ||
689 | adjusted_mode->vtotal = fixed_mode->vtotal; | ||
690 | |||
691 | adjusted_mode->clock = fixed_mode->clock; | ||
692 | |||
693 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
509 | } | 694 | } |
510 | 695 | ||
511 | static bool | 696 | static bool |
512 | cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, | 697 | cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, |
513 | struct drm_display_mode *adjusted_mode) | 698 | struct drm_display_mode *adjusted_mode) |
514 | { | 699 | { |
700 | struct drm_psb_private *dev_priv = encoder->dev->dev_private; | ||
515 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 701 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
516 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 702 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
517 | int lane_count, clock; | 703 | int lane_count, clock; |
518 | int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); | 704 | int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); |
519 | int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; | 705 | int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; |
520 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | 706 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; |
707 | int refclock = mode->clock; | ||
708 | int bpp = 24; | ||
521 | 709 | ||
710 | if (is_edp(intel_encoder) && intel_dp->panel_fixed_mode) { | ||
711 | cdv_intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); | ||
712 | refclock = intel_dp->panel_fixed_mode->clock; | ||
713 | bpp = dev_priv->edp.bpp; | ||
714 | } | ||
522 | 715 | ||
523 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 716 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
524 | for (clock = max_clock; clock >= 0; clock--) { | 717 | for (clock = max_clock; clock >= 0; clock--) { |
525 | int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); | 718 | int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); |
526 | 719 | ||
527 | if (cdv_intel_dp_link_required(mode->clock, 24) | 720 | if (cdv_intel_dp_link_required(refclock, bpp) <= link_avail) { |
528 | <= link_avail) { | ||
529 | intel_dp->link_bw = bws[clock]; | 721 | intel_dp->link_bw = bws[clock]; |
530 | intel_dp->lane_count = lane_count; | 722 | intel_dp->lane_count = lane_count; |
531 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); | 723 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); |
@@ -537,7 +729,18 @@ cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mo | |||
537 | } | 729 | } |
538 | } | 730 | } |
539 | } | 731 | } |
540 | 732 | if (is_edp(intel_encoder)) { | |
733 | /* okay we failed just pick the highest */ | ||
734 | intel_dp->lane_count = max_lane_count; | ||
735 | intel_dp->link_bw = bws[max_clock]; | ||
736 | adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); | ||
737 | DRM_DEBUG_KMS("Force picking display port link bw %02x lane " | ||
738 | "count %d clock %d\n", | ||
739 | intel_dp->link_bw, intel_dp->lane_count, | ||
740 | adjusted_mode->clock); | ||
741 | |||
742 | return true; | ||
743 | } | ||
541 | return false; | 744 | return false; |
542 | } | 745 | } |
543 | 746 | ||
@@ -550,7 +753,7 @@ struct cdv_intel_dp_m_n { | |||
550 | }; | 753 | }; |
551 | 754 | ||
552 | static void | 755 | static void |
553 | psb_intel_reduce_ratio(uint32_t *num, uint32_t *den) | 756 | cdv_intel_reduce_ratio(uint32_t *num, uint32_t *den) |
554 | { | 757 | { |
555 | /* | 758 | /* |
556 | while (*num > 0xffffff || *den > 0xffffff) { | 759 | while (*num > 0xffffff || *den > 0xffffff) { |
@@ -575,10 +778,10 @@ cdv_intel_dp_compute_m_n(int bpp, | |||
575 | m_n->tu = 64; | 778 | m_n->tu = 64; |
576 | m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; | 779 | m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; |
577 | m_n->gmch_n = link_clock * nlanes; | 780 | m_n->gmch_n = link_clock * nlanes; |
578 | psb_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | 781 | cdv_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); |
579 | m_n->link_m = pixel_clock; | 782 | m_n->link_m = pixel_clock; |
580 | m_n->link_n = link_clock; | 783 | m_n->link_n = link_clock; |
581 | psb_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); | 784 | cdv_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); |
582 | } | 785 | } |
583 | 786 | ||
584 | void | 787 | void |
@@ -586,6 +789,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
586 | struct drm_display_mode *adjusted_mode) | 789 | struct drm_display_mode *adjusted_mode) |
587 | { | 790 | { |
588 | struct drm_device *dev = crtc->dev; | 791 | struct drm_device *dev = crtc->dev; |
792 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
589 | struct drm_mode_config *mode_config = &dev->mode_config; | 793 | struct drm_mode_config *mode_config = &dev->mode_config; |
590 | struct drm_encoder *encoder; | 794 | struct drm_encoder *encoder; |
591 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); | 795 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); |
@@ -610,6 +814,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
610 | break; | 814 | break; |
611 | } else if (is_edp(intel_encoder)) { | 815 | } else if (is_edp(intel_encoder)) { |
612 | lane_count = intel_dp->lane_count; | 816 | lane_count = intel_dp->lane_count; |
817 | bpp = dev_priv->edp.bpp; | ||
613 | break; | 818 | break; |
614 | } | 819 | } |
615 | } | 820 | } |
@@ -640,7 +845,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode | |||
640 | struct drm_crtc *crtc = encoder->crtc; | 845 | struct drm_crtc *crtc = encoder->crtc; |
641 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); | 846 | struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); |
642 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 847 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
643 | 848 | struct drm_device *dev = encoder->dev; | |
644 | 849 | ||
645 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; | 850 | intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; |
646 | intel_dp->DP |= intel_dp->color_range; | 851 | intel_dp->DP |= intel_dp->color_range; |
@@ -683,7 +888,22 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode | |||
683 | if (intel_crtc->pipe == 1) | 888 | if (intel_crtc->pipe == 1) |
684 | intel_dp->DP |= DP_PIPEB_SELECT; | 889 | intel_dp->DP |= DP_PIPEB_SELECT; |
685 | 890 | ||
891 | REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN)); | ||
686 | DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); | 892 | DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); |
893 | if (is_edp(intel_encoder)) { | ||
894 | uint32_t pfit_control; | ||
895 | cdv_intel_edp_panel_on(intel_encoder); | ||
896 | |||
897 | if (mode->hdisplay != adjusted_mode->hdisplay || | ||
898 | mode->vdisplay != adjusted_mode->vdisplay) | ||
899 | pfit_control = PFIT_ENABLE; | ||
900 | else | ||
901 | pfit_control = 0; | ||
902 | |||
903 | pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; | ||
904 | |||
905 | REG_WRITE(PFIT_CONTROL, pfit_control); | ||
906 | } | ||
687 | } | 907 | } |
688 | 908 | ||
689 | 909 | ||
@@ -721,18 +941,31 @@ static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode) | |||
721 | static void cdv_intel_dp_prepare(struct drm_encoder *encoder) | 941 | static void cdv_intel_dp_prepare(struct drm_encoder *encoder) |
722 | { | 942 | { |
723 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 943 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
944 | int edp = is_edp(intel_encoder); | ||
724 | 945 | ||
946 | if (edp) { | ||
947 | cdv_intel_edp_backlight_off(intel_encoder); | ||
948 | cdv_intel_edp_panel_off(intel_encoder); | ||
949 | cdv_intel_edp_panel_vdd_on(intel_encoder); | ||
950 | } | ||
725 | /* Wake up the sink first */ | 951 | /* Wake up the sink first */ |
726 | cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); | 952 | cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); |
727 | cdv_intel_dp_link_down(intel_encoder); | 953 | cdv_intel_dp_link_down(intel_encoder); |
954 | if (edp) | ||
955 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
728 | } | 956 | } |
729 | 957 | ||
730 | static void cdv_intel_dp_commit(struct drm_encoder *encoder) | 958 | static void cdv_intel_dp_commit(struct drm_encoder *encoder) |
731 | { | 959 | { |
732 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); | 960 | struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); |
961 | int edp = is_edp(intel_encoder); | ||
733 | 962 | ||
963 | if (edp) | ||
964 | cdv_intel_edp_panel_on(intel_encoder); | ||
734 | cdv_intel_dp_start_link_train(intel_encoder); | 965 | cdv_intel_dp_start_link_train(intel_encoder); |
735 | cdv_intel_dp_complete_link_train(intel_encoder); | 966 | cdv_intel_dp_complete_link_train(intel_encoder); |
967 | if (edp) | ||
968 | cdv_intel_edp_backlight_on(intel_encoder); | ||
736 | } | 969 | } |
737 | 970 | ||
738 | static void | 971 | static void |
@@ -742,16 +975,29 @@ cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode) | |||
742 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 975 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
743 | struct drm_device *dev = encoder->dev; | 976 | struct drm_device *dev = encoder->dev; |
744 | uint32_t dp_reg = REG_READ(intel_dp->output_reg); | 977 | uint32_t dp_reg = REG_READ(intel_dp->output_reg); |
978 | int edp = is_edp(intel_encoder); | ||
745 | 979 | ||
746 | if (mode != DRM_MODE_DPMS_ON) { | 980 | if (mode != DRM_MODE_DPMS_ON) { |
981 | if (edp) { | ||
982 | cdv_intel_edp_backlight_off(intel_encoder); | ||
983 | cdv_intel_edp_panel_vdd_on(intel_encoder); | ||
984 | } | ||
747 | cdv_intel_dp_sink_dpms(intel_encoder, mode); | 985 | cdv_intel_dp_sink_dpms(intel_encoder, mode); |
748 | cdv_intel_dp_link_down(intel_encoder); | 986 | cdv_intel_dp_link_down(intel_encoder); |
987 | if (edp) { | ||
988 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
989 | cdv_intel_edp_panel_off(intel_encoder); | ||
990 | } | ||
749 | } else { | 991 | } else { |
992 | if (edp) | ||
993 | cdv_intel_edp_panel_on(intel_encoder); | ||
750 | cdv_intel_dp_sink_dpms(intel_encoder, mode); | 994 | cdv_intel_dp_sink_dpms(intel_encoder, mode); |
751 | if (!(dp_reg & DP_PORT_EN)) { | 995 | if (!(dp_reg & DP_PORT_EN)) { |
752 | cdv_intel_dp_start_link_train(intel_encoder); | 996 | cdv_intel_dp_start_link_train(intel_encoder); |
753 | cdv_intel_dp_complete_link_train(intel_encoder); | 997 | cdv_intel_dp_complete_link_train(intel_encoder); |
754 | } | 998 | } |
999 | if (edp) | ||
1000 | cdv_intel_edp_backlight_on(intel_encoder); | ||
755 | } | 1001 | } |
756 | } | 1002 | } |
757 | 1003 | ||
@@ -1090,6 +1336,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) | |||
1090 | 1336 | ||
1091 | for (;;) { | 1337 | for (;;) { |
1092 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ | 1338 | /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ |
1339 | DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", | ||
1340 | intel_dp->train_set[0], | ||
1341 | intel_dp->link_configuration[0], | ||
1342 | intel_dp->link_configuration[1]); | ||
1093 | 1343 | ||
1094 | if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { | 1344 | if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { |
1095 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); | 1345 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); |
@@ -1103,6 +1353,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) | |||
1103 | if (!cdv_intel_dp_get_link_status(encoder)) | 1353 | if (!cdv_intel_dp_get_link_status(encoder)) |
1104 | break; | 1354 | break; |
1105 | 1355 | ||
1356 | DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", | ||
1357 | intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], | ||
1358 | intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); | ||
1359 | |||
1106 | if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1360 | if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1107 | DRM_DEBUG_KMS("PT1 train is done\n"); | 1361 | DRM_DEBUG_KMS("PT1 train is done\n"); |
1108 | clock_recovery = true; | 1362 | clock_recovery = true; |
@@ -1156,7 +1410,13 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) | |||
1156 | reg = DP | DP_LINK_TRAIN_PAT_2; | 1410 | reg = DP | DP_LINK_TRAIN_PAT_2; |
1157 | 1411 | ||
1158 | for (;;) { | 1412 | for (;;) { |
1159 | /* channel eq pattern */ | 1413 | |
1414 | DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", | ||
1415 | intel_dp->train_set[0], | ||
1416 | intel_dp->link_configuration[0], | ||
1417 | intel_dp->link_configuration[1]); | ||
1418 | /* channel eq pattern */ | ||
1419 | |||
1160 | if (!cdv_intel_dp_set_link_train(encoder, reg, | 1420 | if (!cdv_intel_dp_set_link_train(encoder, reg, |
1161 | DP_TRAINING_PATTERN_2)) { | 1421 | DP_TRAINING_PATTERN_2)) { |
1162 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); | 1422 | DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); |
@@ -1177,6 +1437,10 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) | |||
1177 | if (!cdv_intel_dp_get_link_status(encoder)) | 1437 | if (!cdv_intel_dp_get_link_status(encoder)) |
1178 | break; | 1438 | break; |
1179 | 1439 | ||
1440 | DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", | ||
1441 | intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], | ||
1442 | intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); | ||
1443 | |||
1180 | /* Make sure clock is still ok */ | 1444 | /* Make sure clock is still ok */ |
1181 | if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { | 1445 | if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { |
1182 | cdv_intel_dp_start_link_train(encoder); | 1446 | cdv_intel_dp_start_link_train(encoder); |
@@ -1271,12 +1535,18 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) | |||
1271 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 1535 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
1272 | enum drm_connector_status status; | 1536 | enum drm_connector_status status; |
1273 | struct edid *edid = NULL; | 1537 | struct edid *edid = NULL; |
1538 | int edp = is_edp(encoder); | ||
1274 | 1539 | ||
1275 | intel_dp->has_audio = false; | 1540 | intel_dp->has_audio = false; |
1276 | 1541 | ||
1542 | if (edp) | ||
1543 | cdv_intel_edp_panel_vdd_on(encoder); | ||
1277 | status = cdv_dp_detect(encoder); | 1544 | status = cdv_dp_detect(encoder); |
1278 | if (status != connector_status_connected) | 1545 | if (status != connector_status_connected) { |
1546 | if (edp) | ||
1547 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1279 | return status; | 1548 | return status; |
1549 | } | ||
1280 | 1550 | ||
1281 | if (intel_dp->force_audio) { | 1551 | if (intel_dp->force_audio) { |
1282 | intel_dp->has_audio = intel_dp->force_audio > 0; | 1552 | intel_dp->has_audio = intel_dp->force_audio > 0; |
@@ -1288,6 +1558,8 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) | |||
1288 | kfree(edid); | 1558 | kfree(edid); |
1289 | } | 1559 | } |
1290 | } | 1560 | } |
1561 | if (edp) | ||
1562 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1291 | 1563 | ||
1292 | return connector_status_connected; | 1564 | return connector_status_connected; |
1293 | } | 1565 | } |
@@ -1298,6 +1570,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) | |||
1298 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; | 1570 | struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; |
1299 | struct edid *edid = NULL; | 1571 | struct edid *edid = NULL; |
1300 | int ret = 0; | 1572 | int ret = 0; |
1573 | int edp = is_edp(intel_encoder); | ||
1301 | 1574 | ||
1302 | 1575 | ||
1303 | edid = drm_get_edid(connector, &intel_dp->adapter); | 1576 | edid = drm_get_edid(connector, &intel_dp->adapter); |
@@ -1307,6 +1580,42 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) | |||
1307 | kfree(edid); | 1580 | kfree(edid); |
1308 | } | 1581 | } |
1309 | 1582 | ||
1583 | if (is_edp(intel_encoder)) { | ||
1584 | struct drm_device *dev = connector->dev; | ||
1585 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1586 | |||
1587 | cdv_intel_edp_panel_vdd_off(intel_encoder); | ||
1588 | if (ret) { | ||
1589 | if (edp && !intel_dp->panel_fixed_mode) { | ||
1590 | struct drm_display_mode *newmode; | ||
1591 | list_for_each_entry(newmode, &connector->probed_modes, | ||
1592 | head) { | ||
1593 | if (newmode->type & DRM_MODE_TYPE_PREFERRED) { | ||
1594 | intel_dp->panel_fixed_mode = | ||
1595 | drm_mode_duplicate(dev, newmode); | ||
1596 | break; | ||
1597 | } | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | return ret; | ||
1602 | } | ||
1603 | if (!intel_dp->panel_fixed_mode && dev_priv->lfp_lvds_vbt_mode) { | ||
1604 | intel_dp->panel_fixed_mode = | ||
1605 | drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); | ||
1606 | if (intel_dp->panel_fixed_mode) { | ||
1607 | intel_dp->panel_fixed_mode->type |= | ||
1608 | DRM_MODE_TYPE_PREFERRED; | ||
1609 | } | ||
1610 | } | ||
1611 | if (intel_dp->panel_fixed_mode != NULL) { | ||
1612 | struct drm_display_mode *mode; | ||
1613 | mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode); | ||
1614 | drm_mode_probed_add(connector, mode); | ||
1615 | return 1; | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1310 | return ret; | 1619 | return ret; |
1311 | } | 1620 | } |
1312 | 1621 | ||
@@ -1317,6 +1626,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) | |||
1317 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; | 1626 | struct cdv_intel_dp *intel_dp = encoder->dev_priv; |
1318 | struct edid *edid; | 1627 | struct edid *edid; |
1319 | bool has_audio = false; | 1628 | bool has_audio = false; |
1629 | int edp = is_edp(encoder); | ||
1630 | |||
1631 | if (edp) | ||
1632 | cdv_intel_edp_panel_vdd_on(encoder); | ||
1320 | 1633 | ||
1321 | edid = drm_get_edid(connector, &intel_dp->adapter); | 1634 | edid = drm_get_edid(connector, &intel_dp->adapter); |
1322 | if (edid) { | 1635 | if (edid) { |
@@ -1325,6 +1638,8 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) | |||
1325 | connector->display_info.raw_edid = NULL; | 1638 | connector->display_info.raw_edid = NULL; |
1326 | kfree(edid); | 1639 | kfree(edid); |
1327 | } | 1640 | } |
1641 | if (edp) | ||
1642 | cdv_intel_edp_panel_vdd_off(encoder); | ||
1328 | 1643 | ||
1329 | return has_audio; | 1644 | return has_audio; |
1330 | } | 1645 | } |
@@ -1386,12 +1701,19 @@ done: | |||
1386 | } | 1701 | } |
1387 | 1702 | ||
1388 | static void | 1703 | static void |
1389 | cdv_intel_dp_destroy (struct drm_connector *connector) | 1704 | cdv_intel_dp_destroy(struct drm_connector *connector) |
1390 | { | 1705 | { |
1391 | struct psb_intel_encoder *psb_intel_encoder = | 1706 | struct psb_intel_encoder *psb_intel_encoder = |
1392 | psb_intel_attached_encoder(connector); | 1707 | psb_intel_attached_encoder(connector); |
1393 | struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; | 1708 | struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; |
1394 | 1709 | ||
1710 | if (is_edp(psb_intel_encoder)) { | ||
1711 | /* cdv_intel_panel_destroy_backlight(connector->dev); */ | ||
1712 | if (intel_dp->panel_fixed_mode) { | ||
1713 | kfree(intel_dp->panel_fixed_mode); | ||
1714 | intel_dp->panel_fixed_mode = NULL; | ||
1715 | } | ||
1716 | } | ||
1395 | i2c_del_adapter(&intel_dp->adapter); | 1717 | i2c_del_adapter(&intel_dp->adapter); |
1396 | drm_sysfs_connector_remove(connector); | 1718 | drm_sysfs_connector_remove(connector); |
1397 | drm_connector_cleanup(connector); | 1719 | drm_connector_cleanup(connector); |
@@ -1436,6 +1758,26 @@ static void cdv_intel_dp_add_properties(struct drm_connector *connector) | |||
1436 | cdv_intel_attach_broadcast_rgb_property(connector); | 1758 | cdv_intel_attach_broadcast_rgb_property(connector); |
1437 | } | 1759 | } |
1438 | 1760 | ||
1761 | /* check the VBT to see whether the eDP is on DP-D port */ | ||
1762 | static bool cdv_intel_dpc_is_edp(struct drm_device *dev) | ||
1763 | { | ||
1764 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1765 | struct child_device_config *p_child; | ||
1766 | int i; | ||
1767 | |||
1768 | if (!dev_priv->child_dev_num) | ||
1769 | return false; | ||
1770 | |||
1771 | for (i = 0; i < dev_priv->child_dev_num; i++) { | ||
1772 | p_child = dev_priv->child_dev + i; | ||
1773 | |||
1774 | if (p_child->dvo_port == PORT_IDPC && | ||
1775 | p_child->device_type == DEVICE_TYPE_eDP) | ||
1776 | return true; | ||
1777 | } | ||
1778 | return false; | ||
1779 | } | ||
1780 | |||
1439 | void | 1781 | void |
1440 | cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) | 1782 | cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) |
1441 | { | 1783 | { |
@@ -1445,6 +1787,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1445 | struct drm_encoder *encoder; | 1787 | struct drm_encoder *encoder; |
1446 | struct cdv_intel_dp *intel_dp; | 1788 | struct cdv_intel_dp *intel_dp; |
1447 | const char *name = NULL; | 1789 | const char *name = NULL; |
1790 | int type = DRM_MODE_CONNECTOR_DisplayPort; | ||
1448 | 1791 | ||
1449 | psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); | 1792 | psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); |
1450 | if (!psb_intel_encoder) | 1793 | if (!psb_intel_encoder) |
@@ -1456,14 +1799,22 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1456 | if (!intel_dp) | 1799 | if (!intel_dp) |
1457 | goto err_priv; | 1800 | goto err_priv; |
1458 | 1801 | ||
1802 | if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev)) | ||
1803 | type = DRM_MODE_CONNECTOR_eDP; | ||
1804 | |||
1459 | connector = &psb_intel_connector->base; | 1805 | connector = &psb_intel_connector->base; |
1460 | encoder = &psb_intel_encoder->base; | 1806 | encoder = &psb_intel_encoder->base; |
1461 | 1807 | ||
1462 | drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); | 1808 | drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type); |
1463 | drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); | 1809 | drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); |
1464 | 1810 | ||
1465 | psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); | 1811 | psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); |
1466 | psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; | 1812 | |
1813 | if (type == DRM_MODE_CONNECTOR_DisplayPort) | ||
1814 | psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; | ||
1815 | else | ||
1816 | psb_intel_encoder->type = INTEL_OUTPUT_EDP; | ||
1817 | |||
1467 | 1818 | ||
1468 | psb_intel_encoder->dev_priv=intel_dp; | 1819 | psb_intel_encoder->dev_priv=intel_dp; |
1469 | intel_dp->encoder = psb_intel_encoder; | 1820 | intel_dp->encoder = psb_intel_encoder; |
@@ -1493,6 +1844,83 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev | |||
1493 | cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); | 1844 | cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); |
1494 | /* FIXME:fail check */ | 1845 | /* FIXME:fail check */ |
1495 | cdv_intel_dp_add_properties(connector); | 1846 | cdv_intel_dp_add_properties(connector); |
1847 | |||
1848 | if (is_edp(psb_intel_encoder)) { | ||
1849 | int ret; | ||
1850 | struct edp_power_seq cur; | ||
1851 | u32 pp_on, pp_off, pp_div; | ||
1852 | u32 pwm_ctrl; | ||
1853 | |||
1854 | pp_on = REG_READ(PP_CONTROL); | ||
1855 | pp_on &= ~PANEL_UNLOCK_MASK; | ||
1856 | pp_on |= PANEL_UNLOCK_REGS; | ||
1857 | |||
1858 | REG_WRITE(PP_CONTROL, pp_on); | ||
1859 | |||
1860 | pwm_ctrl = REG_READ(BLC_PWM_CTL2); | ||
1861 | pwm_ctrl |= PWM_PIPE_B; | ||
1862 | REG_WRITE(BLC_PWM_CTL2, pwm_ctrl); | ||
1863 | |||
1864 | pp_on = REG_READ(PP_ON_DELAYS); | ||
1865 | pp_off = REG_READ(PP_OFF_DELAYS); | ||
1866 | pp_div = REG_READ(PP_DIVISOR); | ||
1867 | |||
1868 | /* Pull timing values out of registers */ | ||
1869 | cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> | ||
1870 | PANEL_POWER_UP_DELAY_SHIFT; | ||
1871 | |||
1872 | cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> | ||
1873 | PANEL_LIGHT_ON_DELAY_SHIFT; | ||
1874 | |||
1875 | cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> | ||
1876 | PANEL_LIGHT_OFF_DELAY_SHIFT; | ||
1877 | |||
1878 | cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> | ||
1879 | PANEL_POWER_DOWN_DELAY_SHIFT; | ||
1880 | |||
1881 | cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> | ||
1882 | PANEL_POWER_CYCLE_DELAY_SHIFT); | ||
1883 | |||
1884 | DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", | ||
1885 | cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); | ||
1886 | |||
1887 | |||
1888 | intel_dp->panel_power_up_delay = cur.t1_t3 / 10; | ||
1889 | intel_dp->backlight_on_delay = cur.t8 / 10; | ||
1890 | intel_dp->backlight_off_delay = cur.t9 / 10; | ||
1891 | intel_dp->panel_power_down_delay = cur.t10 / 10; | ||
1892 | intel_dp->panel_power_cycle_delay = (cur.t11_t12 - 1) * 100; | ||
1893 | |||
1894 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
1895 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
1896 | intel_dp->panel_power_cycle_delay); | ||
1897 | |||
1898 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
1899 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
1900 | |||
1901 | |||
1902 | cdv_intel_edp_panel_vdd_on(psb_intel_encoder); | ||
1903 | ret = cdv_intel_dp_aux_native_read(psb_intel_encoder, DP_DPCD_REV, | ||
1904 | intel_dp->dpcd, | ||
1905 | sizeof(intel_dp->dpcd)); | ||
1906 | cdv_intel_edp_panel_vdd_off(psb_intel_encoder); | ||
1907 | if (ret == 0) { | ||
1908 | /* if this fails, presume the device is a ghost */ | ||
1909 | DRM_INFO("failed to retrieve link info, disabling eDP\n"); | ||
1910 | cdv_intel_dp_encoder_destroy(encoder); | ||
1911 | cdv_intel_dp_destroy(connector); | ||
1912 | goto err_priv; | ||
1913 | } else { | ||
1914 | DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n", | ||
1915 | intel_dp->dpcd[0], intel_dp->dpcd[1], | ||
1916 | intel_dp->dpcd[2], intel_dp->dpcd[3]); | ||
1917 | |||
1918 | } | ||
1919 | /* The CDV reference driver moves pnale backlight setup into the displays that | ||
1920 | have a backlight: this is a good idea and one we should probably adopt, however | ||
1921 | we need to migrate all the drivers before we can do that */ | ||
1922 | /*cdv_intel_panel_setup_backlight(dev); */ | ||
1923 | } | ||
1496 | return; | 1924 | return; |
1497 | 1925 | ||
1498 | err_priv: | 1926 | err_priv: |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index c7f9468b74ba..b362dd39bf5a 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c | |||
@@ -506,16 +506,8 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector, | |||
506 | property, | 506 | property, |
507 | value)) | 507 | value)) |
508 | return -1; | 508 | return -1; |
509 | else { | 509 | else |
510 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | 510 | gma_backlight_set(encoder->dev, value); |
511 | struct drm_psb_private *dev_priv = | ||
512 | encoder->dev->dev_private; | ||
513 | struct backlight_device *bd = | ||
514 | dev_priv->backlight_device; | ||
515 | bd->props.brightness = value; | ||
516 | backlight_update_status(bd); | ||
517 | #endif | ||
518 | } | ||
519 | } else if (!strcmp(property->name, "DPMS") && encoder) { | 511 | } else if (!strcmp(property->name, "DPMS") && encoder) { |
520 | struct drm_encoder_helper_funcs *helpers = | 512 | struct drm_encoder_helper_funcs *helpers = |
521 | encoder->helper_private; | 513 | encoder->helper_private; |
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 2de6b1fcc135..884ba73ac6ce 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c | |||
@@ -768,6 +768,9 @@ static void psb_setup_outputs(struct drm_device *dev) | |||
768 | crtc_mask = (1 << 0) | (1 << 1); | 768 | crtc_mask = (1 << 0) | (1 << 1); |
769 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | 769 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); |
770 | break; | 770 | break; |
771 | case INTEL_OUTPUT_EDP: | ||
772 | crtc_mask = (1 << 1); | ||
773 | clone_mask = (1 << INTEL_OUTPUT_EDP); | ||
771 | } | 774 | } |
772 | encoder->possible_crtcs = crtc_mask; | 775 | encoder->possible_crtcs = crtc_mask; |
773 | encoder->possible_clones = | 776 | encoder->possible_clones = |
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 8d7caf0f363e..4fb79cf00ed8 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c | |||
@@ -54,6 +54,98 @@ static void *find_section(struct bdb_header *bdb, int section_id) | |||
54 | return NULL; | 54 | return NULL; |
55 | } | 55 | } |
56 | 56 | ||
57 | static void | ||
58 | parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb) | ||
59 | { | ||
60 | struct bdb_edp *edp; | ||
61 | struct edp_power_seq *edp_pps; | ||
62 | struct edp_link_params *edp_link_params; | ||
63 | uint8_t panel_type; | ||
64 | |||
65 | edp = find_section(bdb, BDB_EDP); | ||
66 | |||
67 | dev_priv->edp.bpp = 18; | ||
68 | if (!edp) { | ||
69 | if (dev_priv->edp.support) { | ||
70 | DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported, assume %dbpp panel color depth.\n", | ||
71 | dev_priv->edp.bpp); | ||
72 | } | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | panel_type = dev_priv->panel_type; | ||
77 | switch ((edp->color_depth >> (panel_type * 2)) & 3) { | ||
78 | case EDP_18BPP: | ||
79 | dev_priv->edp.bpp = 18; | ||
80 | break; | ||
81 | case EDP_24BPP: | ||
82 | dev_priv->edp.bpp = 24; | ||
83 | break; | ||
84 | case EDP_30BPP: | ||
85 | dev_priv->edp.bpp = 30; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | /* Get the eDP sequencing and link info */ | ||
90 | edp_pps = &edp->power_seqs[panel_type]; | ||
91 | edp_link_params = &edp->link_params[panel_type]; | ||
92 | |||
93 | dev_priv->edp.pps = *edp_pps; | ||
94 | |||
95 | DRM_DEBUG_KMS("EDP timing in vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", | ||
96 | dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8, | ||
97 | dev_priv->edp.pps.t9, dev_priv->edp.pps.t10, | ||
98 | dev_priv->edp.pps.t11_t12); | ||
99 | |||
100 | dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : | ||
101 | DP_LINK_BW_1_62; | ||
102 | switch (edp_link_params->lanes) { | ||
103 | case 0: | ||
104 | dev_priv->edp.lanes = 1; | ||
105 | break; | ||
106 | case 1: | ||
107 | dev_priv->edp.lanes = 2; | ||
108 | break; | ||
109 | case 3: | ||
110 | default: | ||
111 | dev_priv->edp.lanes = 4; | ||
112 | break; | ||
113 | } | ||
114 | DRM_DEBUG_KMS("VBT reports EDP: Lane_count %d, Lane_rate %d, Bpp %d\n", | ||
115 | dev_priv->edp.lanes, dev_priv->edp.rate, dev_priv->edp.bpp); | ||
116 | |||
117 | switch (edp_link_params->preemphasis) { | ||
118 | case 0: | ||
119 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; | ||
120 | break; | ||
121 | case 1: | ||
122 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; | ||
123 | break; | ||
124 | case 2: | ||
125 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; | ||
126 | break; | ||
127 | case 3: | ||
128 | dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; | ||
129 | break; | ||
130 | } | ||
131 | switch (edp_link_params->vswing) { | ||
132 | case 0: | ||
133 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; | ||
134 | break; | ||
135 | case 1: | ||
136 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; | ||
137 | break; | ||
138 | case 2: | ||
139 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; | ||
140 | break; | ||
141 | case 3: | ||
142 | dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; | ||
143 | break; | ||
144 | } | ||
145 | DRM_DEBUG_KMS("VBT reports EDP: VSwing %d, Preemph %d\n", | ||
146 | dev_priv->edp.vswing, dev_priv->edp.preemphasis); | ||
147 | } | ||
148 | |||
57 | static u16 | 149 | static u16 |
58 | get_blocksize(void *p) | 150 | get_blocksize(void *p) |
59 | { | 151 | { |
@@ -154,6 +246,8 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, | |||
154 | return; | 246 | return; |
155 | 247 | ||
156 | dev_priv->lvds_dither = lvds_options->pixel_dither; | 248 | dev_priv->lvds_dither = lvds_options->pixel_dither; |
249 | dev_priv->panel_type = lvds_options->panel_type; | ||
250 | |||
157 | if (lvds_options->panel_type == 0xff) | 251 | if (lvds_options->panel_type == 0xff) |
158 | return; | 252 | return; |
159 | 253 | ||
@@ -340,6 +434,9 @@ parse_driver_features(struct drm_psb_private *dev_priv, | |||
340 | if (!driver) | 434 | if (!driver) |
341 | return; | 435 | return; |
342 | 436 | ||
437 | if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) | ||
438 | dev_priv->edp.support = 1; | ||
439 | |||
343 | /* This bit means to use 96Mhz for DPLL_A or not */ | 440 | /* This bit means to use 96Mhz for DPLL_A or not */ |
344 | if (driver->primary_lfp_id) | 441 | if (driver->primary_lfp_id) |
345 | dev_priv->dplla_96mhz = true; | 442 | dev_priv->dplla_96mhz = true; |
@@ -437,6 +534,9 @@ int psb_intel_init_bios(struct drm_device *dev) | |||
437 | size_t size; | 534 | size_t size; |
438 | int i; | 535 | int i; |
439 | 536 | ||
537 | |||
538 | dev_priv->panel_type = 0xff; | ||
539 | |||
440 | /* XXX Should this validation be moved to intel_opregion.c? */ | 540 | /* XXX Should this validation be moved to intel_opregion.c? */ |
441 | if (dev_priv->opregion.vbt) { | 541 | if (dev_priv->opregion.vbt) { |
442 | struct vbt_header *vbt = dev_priv->opregion.vbt; | 542 | struct vbt_header *vbt = dev_priv->opregion.vbt; |
@@ -477,6 +577,7 @@ int psb_intel_init_bios(struct drm_device *dev) | |||
477 | parse_sdvo_device_mapping(dev_priv, bdb); | 577 | parse_sdvo_device_mapping(dev_priv, bdb); |
478 | parse_device_mapping(dev_priv, bdb); | 578 | parse_device_mapping(dev_priv, bdb); |
479 | parse_backlight_data(dev_priv, bdb); | 579 | parse_backlight_data(dev_priv, bdb); |
580 | parse_edp(dev_priv, bdb); | ||
480 | 581 | ||
481 | if (bios) | 582 | if (bios) |
482 | pci_unmap_rom(pdev, bios); | 583 | pci_unmap_rom(pdev, bios); |
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 2e95523b84b1..c6267c98c9e7 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define _I830_BIOS_H_ | 23 | #define _I830_BIOS_H_ |
24 | 24 | ||
25 | #include <drm/drmP.h> | 25 | #include <drm/drmP.h> |
26 | #include <drm/drm_dp_helper.h> | ||
26 | 27 | ||
27 | struct vbt_header { | 28 | struct vbt_header { |
28 | u8 signature[20]; /**< Always starts with 'VBT$' */ | 29 | u8 signature[20]; /**< Always starts with 'VBT$' */ |
@@ -93,6 +94,7 @@ struct vbios_data { | |||
93 | #define BDB_SDVO_LVDS_PNP_IDS 24 | 94 | #define BDB_SDVO_LVDS_PNP_IDS 24 |
94 | #define BDB_SDVO_LVDS_POWER_SEQ 25 | 95 | #define BDB_SDVO_LVDS_POWER_SEQ 25 |
95 | #define BDB_TV_OPTIONS 26 | 96 | #define BDB_TV_OPTIONS 26 |
97 | #define BDB_EDP 27 | ||
96 | #define BDB_LVDS_OPTIONS 40 | 98 | #define BDB_LVDS_OPTIONS 40 |
97 | #define BDB_LVDS_LFP_DATA_PTRS 41 | 99 | #define BDB_LVDS_LFP_DATA_PTRS 41 |
98 | #define BDB_LVDS_LFP_DATA 42 | 100 | #define BDB_LVDS_LFP_DATA 42 |
@@ -391,6 +393,11 @@ struct bdb_sdvo_lvds_options { | |||
391 | u8 panel_misc_bits_4; | 393 | u8 panel_misc_bits_4; |
392 | } __attribute__((packed)); | 394 | } __attribute__((packed)); |
393 | 395 | ||
396 | #define BDB_DRIVER_FEATURE_NO_LVDS 0 | ||
397 | #define BDB_DRIVER_FEATURE_INT_LVDS 1 | ||
398 | #define BDB_DRIVER_FEATURE_SDVO_LVDS 2 | ||
399 | #define BDB_DRIVER_FEATURE_EDP 3 | ||
400 | |||
394 | struct bdb_driver_features { | 401 | struct bdb_driver_features { |
395 | u8 boot_dev_algorithm:1; | 402 | u8 boot_dev_algorithm:1; |
396 | u8 block_display_switch:1; | 403 | u8 block_display_switch:1; |
@@ -431,6 +438,45 @@ struct bdb_driver_features { | |||
431 | u8 custom_vbt_version; | 438 | u8 custom_vbt_version; |
432 | } __attribute__((packed)); | 439 | } __attribute__((packed)); |
433 | 440 | ||
441 | #define EDP_18BPP 0 | ||
442 | #define EDP_24BPP 1 | ||
443 | #define EDP_30BPP 2 | ||
444 | #define EDP_RATE_1_62 0 | ||
445 | #define EDP_RATE_2_7 1 | ||
446 | #define EDP_LANE_1 0 | ||
447 | #define EDP_LANE_2 1 | ||
448 | #define EDP_LANE_4 3 | ||
449 | #define EDP_PREEMPHASIS_NONE 0 | ||
450 | #define EDP_PREEMPHASIS_3_5dB 1 | ||
451 | #define EDP_PREEMPHASIS_6dB 2 | ||
452 | #define EDP_PREEMPHASIS_9_5dB 3 | ||
453 | #define EDP_VSWING_0_4V 0 | ||
454 | #define EDP_VSWING_0_6V 1 | ||
455 | #define EDP_VSWING_0_8V 2 | ||
456 | #define EDP_VSWING_1_2V 3 | ||
457 | |||
458 | struct edp_power_seq { | ||
459 | u16 t1_t3; | ||
460 | u16 t8; | ||
461 | u16 t9; | ||
462 | u16 t10; | ||
463 | u16 t11_t12; | ||
464 | } __attribute__ ((packed)); | ||
465 | |||
466 | struct edp_link_params { | ||
467 | u8 rate:4; | ||
468 | u8 lanes:4; | ||
469 | u8 preemphasis:4; | ||
470 | u8 vswing:4; | ||
471 | } __attribute__ ((packed)); | ||
472 | |||
473 | struct bdb_edp { | ||
474 | struct edp_power_seq power_seqs[16]; | ||
475 | u32 color_depth; | ||
476 | u32 sdrrs_msa_timing_delay; | ||
477 | struct edp_link_params link_params[16]; | ||
478 | } __attribute__ ((packed)); | ||
479 | |||
434 | extern int psb_intel_init_bios(struct drm_device *dev); | 480 | extern int psb_intel_init_bios(struct drm_device *dev); |
435 | extern void psb_intel_destroy_bios(struct drm_device *dev); | 481 | extern void psb_intel_destroy_bios(struct drm_device *dev); |
436 | 482 | ||
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index 5675d93b4205..32dba2ab53e1 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c | |||
@@ -299,17 +299,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, | |||
299 | if (drm_connector_property_set_value(connector, property, | 299 | if (drm_connector_property_set_value(connector, property, |
300 | value)) | 300 | value)) |
301 | goto set_prop_error; | 301 | goto set_prop_error; |
302 | else { | 302 | else |
303 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | 303 | gma_backlight_set(encoder->dev, value); |
304 | struct backlight_device *psb_bd; | ||
305 | |||
306 | psb_bd = mdfld_get_backlight_device(); | ||
307 | if (psb_bd) { | ||
308 | psb_bd->props.brightness = value; | ||
309 | mdfld_set_brightness(psb_bd); | ||
310 | } | ||
311 | #endif | ||
312 | } | ||
313 | } | 304 | } |
314 | set_prop_done: | 305 | set_prop_done: |
315 | return 0; | 306 | return 0; |
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index b2a790bd9899..850cd3fbb969 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c | |||
@@ -118,20 +118,20 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv) | |||
118 | dev_priv->platform_rev_id); | 118 | dev_priv->platform_rev_id); |
119 | } | 119 | } |
120 | 120 | ||
121 | struct vbt_header { | 121 | struct mid_vbt_header { |
122 | u32 signature; | 122 | u32 signature; |
123 | u8 revision; | 123 | u8 revision; |
124 | } __packed; | 124 | } __packed; |
125 | 125 | ||
126 | /* The same for r0 and r1 */ | 126 | /* The same for r0 and r1 */ |
127 | struct vbt_r0 { | 127 | struct vbt_r0 { |
128 | struct vbt_header vbt_header; | 128 | struct mid_vbt_header vbt_header; |
129 | u8 size; | 129 | u8 size; |
130 | u8 checksum; | 130 | u8 checksum; |
131 | } __packed; | 131 | } __packed; |
132 | 132 | ||
133 | struct vbt_r10 { | 133 | struct vbt_r10 { |
134 | struct vbt_header vbt_header; | 134 | struct mid_vbt_header vbt_header; |
135 | u8 checksum; | 135 | u8 checksum; |
136 | u16 size; | 136 | u16 size; |
137 | u8 panel_count; | 137 | u8 panel_count; |
@@ -281,7 +281,7 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv) | |||
281 | struct drm_device *dev = dev_priv->dev; | 281 | struct drm_device *dev = dev_priv->dev; |
282 | u32 addr; | 282 | u32 addr; |
283 | u8 __iomem *vbt_virtual; | 283 | u8 __iomem *vbt_virtual; |
284 | struct vbt_header vbt_header; | 284 | struct mid_vbt_header vbt_header; |
285 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | 285 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); |
286 | int ret = -1; | 286 | int ret = -1; |
287 | 287 | ||
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index c430bd424681..ad0d6de938f3 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c | |||
@@ -166,8 +166,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | |||
166 | 166 | ||
167 | if (config_enabled(CONFIG_BACKLIGHT_CLASS_DEVICE)) { | 167 | if (config_enabled(CONFIG_BACKLIGHT_CLASS_DEVICE)) { |
168 | int max = bd->props.max_brightness; | 168 | int max = bd->props.max_brightness; |
169 | bd->props.brightness = bclp * max / 255; | 169 | gma_backlight_set(dev, bclp * max / 255); |
170 | backlight_update_status(bd); | ||
171 | } | 170 | } |
172 | 171 | ||
173 | asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; | 172 | asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; |
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 1bd115ecefe1..4ab6ae7e92b4 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "gma_drm.h" | 28 | #include "gma_drm.h" |
29 | #include "psb_reg.h" | 29 | #include "psb_reg.h" |
30 | #include "psb_intel_drv.h" | 30 | #include "psb_intel_drv.h" |
31 | #include "intel_bios.h" | ||
31 | #include "gtt.h" | 32 | #include "gtt.h" |
32 | #include "power.h" | 33 | #include "power.h" |
33 | #include "opregion.h" | 34 | #include "opregion.h" |
@@ -613,6 +614,8 @@ struct drm_psb_private { | |||
613 | */ | 614 | */ |
614 | struct backlight_device *backlight_device; | 615 | struct backlight_device *backlight_device; |
615 | struct drm_property *backlight_property; | 616 | struct drm_property *backlight_property; |
617 | bool backlight_enabled; | ||
618 | int backlight_level; | ||
616 | uint32_t blc_adj1; | 619 | uint32_t blc_adj1; |
617 | uint32_t blc_adj2; | 620 | uint32_t blc_adj2; |
618 | 621 | ||
@@ -640,6 +643,19 @@ struct drm_psb_private { | |||
640 | int mdfld_panel_id; | 643 | int mdfld_panel_id; |
641 | 644 | ||
642 | bool dplla_96mhz; /* DPLL data from the VBT */ | 645 | bool dplla_96mhz; /* DPLL data from the VBT */ |
646 | |||
647 | struct { | ||
648 | int rate; | ||
649 | int lanes; | ||
650 | int preemphasis; | ||
651 | int vswing; | ||
652 | |||
653 | bool initialized; | ||
654 | bool support; | ||
655 | int bpp; | ||
656 | struct edp_power_seq pps; | ||
657 | } edp; | ||
658 | uint8_t panel_type; | ||
643 | }; | 659 | }; |
644 | 660 | ||
645 | 661 | ||
@@ -796,6 +812,9 @@ extern int psb_fbdev_init(struct drm_device *dev); | |||
796 | /* backlight.c */ | 812 | /* backlight.c */ |
797 | int gma_backlight_init(struct drm_device *dev); | 813 | int gma_backlight_init(struct drm_device *dev); |
798 | void gma_backlight_exit(struct drm_device *dev); | 814 | void gma_backlight_exit(struct drm_device *dev); |
815 | void gma_backlight_disable(struct drm_device *dev); | ||
816 | void gma_backlight_enable(struct drm_device *dev); | ||
817 | void gma_backlight_set(struct drm_device *dev, int v); | ||
799 | 818 | ||
800 | /* oaktrail_crtc.c */ | 819 | /* oaktrail_crtc.c */ |
801 | extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs; | 820 | extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 37adc9edf974..2a4c3a9e33e3 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c | |||
@@ -630,17 +630,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, | |||
630 | property, | 630 | property, |
631 | value)) | 631 | value)) |
632 | goto set_prop_error; | 632 | goto set_prop_error; |
633 | else { | 633 | else |
634 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | 634 | gma_backlight_set(encoder->dev, value); |
635 | struct drm_psb_private *devp = | ||
636 | encoder->dev->dev_private; | ||
637 | struct backlight_device *bd = devp->backlight_device; | ||
638 | if (bd) { | ||
639 | bd->props.brightness = value; | ||
640 | backlight_update_status(bd); | ||
641 | } | ||
642 | #endif | ||
643 | } | ||
644 | } else if (!strcmp(property->name, "DPMS")) { | 635 | } else if (!strcmp(property->name, "DPMS")) { |
645 | struct drm_encoder_helper_funcs *hfuncs | 636 | struct drm_encoder_helper_funcs *hfuncs |
646 | = encoder->helper_private; | 637 | = encoder->helper_private; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h index d3091fc72b9e..389e969e8986 100644 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ b/drivers/gpu/drm/gma500/psb_intel_reg.h | |||
@@ -173,15 +173,46 @@ | |||
173 | #define PP_SEQUENCE_ON (1 << 28) | 173 | #define PP_SEQUENCE_ON (1 << 28) |
174 | #define PP_SEQUENCE_OFF (2 << 28) | 174 | #define PP_SEQUENCE_OFF (2 << 28) |
175 | #define PP_SEQUENCE_MASK 0x30000000 | 175 | #define PP_SEQUENCE_MASK 0x30000000 |
176 | #define PP_CYCLE_DELAY_ACTIVE (1 << 27) | ||
177 | #define PP_SEQUENCE_STATE_ON_IDLE (1 << 3) | ||
178 | #define PP_SEQUENCE_STATE_MASK 0x0000000f | ||
179 | |||
176 | #define PP_CONTROL 0x61204 | 180 | #define PP_CONTROL 0x61204 |
177 | #define POWER_TARGET_ON (1 << 0) | 181 | #define POWER_TARGET_ON (1 << 0) |
178 | 182 | #define PANEL_UNLOCK_REGS (0xabcd << 16) | |
183 | #define PANEL_UNLOCK_MASK (0xffff << 16) | ||
184 | #define EDP_FORCE_VDD (1 << 3) | ||
185 | #define EDP_BLC_ENABLE (1 << 2) | ||
186 | #define PANEL_POWER_RESET (1 << 1) | ||
187 | #define PANEL_POWER_OFF (0 << 0) | ||
188 | #define PANEL_POWER_ON (1 << 0) | ||
189 | |||
190 | /* Poulsbo/Oaktrail */ | ||
179 | #define LVDSPP_ON 0x61208 | 191 | #define LVDSPP_ON 0x61208 |
180 | #define LVDSPP_OFF 0x6120c | 192 | #define LVDSPP_OFF 0x6120c |
181 | #define PP_CYCLE 0x61210 | 193 | #define PP_CYCLE 0x61210 |
182 | 194 | ||
195 | /* Cedartrail */ | ||
183 | #define PP_ON_DELAYS 0x61208 /* Cedartrail */ | 196 | #define PP_ON_DELAYS 0x61208 /* Cedartrail */ |
197 | #define PANEL_PORT_SELECT_MASK (3 << 30) | ||
198 | #define PANEL_PORT_SELECT_LVDS (0 << 30) | ||
199 | #define PANEL_PORT_SELECT_EDP (1 << 30) | ||
200 | #define PANEL_POWER_UP_DELAY_MASK (0x1fff0000) | ||
201 | #define PANEL_POWER_UP_DELAY_SHIFT 16 | ||
202 | #define PANEL_LIGHT_ON_DELAY_MASK (0x1fff) | ||
203 | #define PANEL_LIGHT_ON_DELAY_SHIFT 0 | ||
204 | |||
184 | #define PP_OFF_DELAYS 0x6120c /* Cedartrail */ | 205 | #define PP_OFF_DELAYS 0x6120c /* Cedartrail */ |
206 | #define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000) | ||
207 | #define PANEL_POWER_DOWN_DELAY_SHIFT 16 | ||
208 | #define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff) | ||
209 | #define PANEL_LIGHT_OFF_DELAY_SHIFT 0 | ||
210 | |||
211 | #define PP_DIVISOR 0x61210 /* Cedartrail */ | ||
212 | #define PP_REFERENCE_DIVIDER_MASK (0xffffff00) | ||
213 | #define PP_REFERENCE_DIVIDER_SHIFT 8 | ||
214 | #define PANEL_POWER_CYCLE_DELAY_MASK (0x1f) | ||
215 | #define PANEL_POWER_CYCLE_DELAY_SHIFT 0 | ||
185 | 216 | ||
186 | #define PFIT_CONTROL 0x61230 | 217 | #define PFIT_CONTROL 0x61230 |
187 | #define PFIT_ENABLE (1 << 31) | 218 | #define PFIT_ENABLE (1 << 31) |
@@ -1503,4 +1534,9 @@ No status bits are changed. | |||
1503 | #define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) | 1534 | #define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) |
1504 | #define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) | 1535 | #define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) |
1505 | 1536 | ||
1537 | #define PIPE_BPC_MASK (7 << 5) | ||
1538 | #define PIPE_8BPC (0 << 5) | ||
1539 | #define PIPE_10BPC (1 << 5) | ||
1540 | #define PIPE_6BPC (2 << 5) | ||
1541 | |||
1506 | #endif | 1542 | #endif |