aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_panel.c')
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c346
1 files changed, 233 insertions, 113 deletions
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 293564a2896a..f161ac02c4f6 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -50,23 +50,22 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
50 struct intel_crtc_config *pipe_config, 50 struct intel_crtc_config *pipe_config,
51 int fitting_mode) 51 int fitting_mode)
52{ 52{
53 struct drm_display_mode *mode, *adjusted_mode; 53 struct drm_display_mode *adjusted_mode;
54 int x, y, width, height; 54 int x, y, width, height;
55 55
56 mode = &pipe_config->requested_mode;
57 adjusted_mode = &pipe_config->adjusted_mode; 56 adjusted_mode = &pipe_config->adjusted_mode;
58 57
59 x = y = width = height = 0; 58 x = y = width = height = 0;
60 59
61 /* Native modes don't need fitting */ 60 /* Native modes don't need fitting */
62 if (adjusted_mode->hdisplay == mode->hdisplay && 61 if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
63 adjusted_mode->vdisplay == mode->vdisplay) 62 adjusted_mode->vdisplay == pipe_config->pipe_src_h)
64 goto done; 63 goto done;
65 64
66 switch (fitting_mode) { 65 switch (fitting_mode) {
67 case DRM_MODE_SCALE_CENTER: 66 case DRM_MODE_SCALE_CENTER:
68 width = mode->hdisplay; 67 width = pipe_config->pipe_src_w;
69 height = mode->vdisplay; 68 height = pipe_config->pipe_src_h;
70 x = (adjusted_mode->hdisplay - width + 1)/2; 69 x = (adjusted_mode->hdisplay - width + 1)/2;
71 y = (adjusted_mode->vdisplay - height + 1)/2; 70 y = (adjusted_mode->vdisplay - height + 1)/2;
72 break; 71 break;
@@ -74,17 +73,19 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
74 case DRM_MODE_SCALE_ASPECT: 73 case DRM_MODE_SCALE_ASPECT:
75 /* Scale but preserve the aspect ratio */ 74 /* Scale but preserve the aspect ratio */
76 { 75 {
77 u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; 76 u32 scaled_width = adjusted_mode->hdisplay
78 u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; 77 * pipe_config->pipe_src_h;
78 u32 scaled_height = pipe_config->pipe_src_w
79 * adjusted_mode->vdisplay;
79 if (scaled_width > scaled_height) { /* pillar */ 80 if (scaled_width > scaled_height) { /* pillar */
80 width = scaled_height / mode->vdisplay; 81 width = scaled_height / pipe_config->pipe_src_h;
81 if (width & 1) 82 if (width & 1)
82 width++; 83 width++;
83 x = (adjusted_mode->hdisplay - width + 1) / 2; 84 x = (adjusted_mode->hdisplay - width + 1) / 2;
84 y = 0; 85 y = 0;
85 height = adjusted_mode->vdisplay; 86 height = adjusted_mode->vdisplay;
86 } else if (scaled_width < scaled_height) { /* letter */ 87 } else if (scaled_width < scaled_height) { /* letter */
87 height = scaled_width / mode->hdisplay; 88 height = scaled_width / pipe_config->pipe_src_w;
88 if (height & 1) 89 if (height & 1)
89 height++; 90 height++;
90 y = (adjusted_mode->vdisplay - height + 1) / 2; 91 y = (adjusted_mode->vdisplay - height + 1) / 2;
@@ -171,20 +172,96 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
171 return (FACTOR * ratio + FACTOR/2) / FACTOR; 172 return (FACTOR * ratio + FACTOR/2) / FACTOR;
172} 173}
173 174
175static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
176 u32 *pfit_control)
177{
178 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
179 u32 scaled_width = adjusted_mode->hdisplay *
180 pipe_config->pipe_src_h;
181 u32 scaled_height = pipe_config->pipe_src_w *
182 adjusted_mode->vdisplay;
183
184 /* 965+ is easy, it does everything in hw */
185 if (scaled_width > scaled_height)
186 *pfit_control |= PFIT_ENABLE |
187 PFIT_SCALING_PILLAR;
188 else if (scaled_width < scaled_height)
189 *pfit_control |= PFIT_ENABLE |
190 PFIT_SCALING_LETTER;
191 else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
192 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
193}
194
195static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
196 u32 *pfit_control, u32 *pfit_pgm_ratios,
197 u32 *border)
198{
199 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
200 u32 scaled_width = adjusted_mode->hdisplay *
201 pipe_config->pipe_src_h;
202 u32 scaled_height = pipe_config->pipe_src_w *
203 adjusted_mode->vdisplay;
204 u32 bits;
205
206 /*
207 * For earlier chips we have to calculate the scaling
208 * ratio by hand and program it into the
209 * PFIT_PGM_RATIO register
210 */
211 if (scaled_width > scaled_height) { /* pillar */
212 centre_horizontally(adjusted_mode,
213 scaled_height /
214 pipe_config->pipe_src_h);
215
216 *border = LVDS_BORDER_ENABLE;
217 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
218 bits = panel_fitter_scaling(pipe_config->pipe_src_h,
219 adjusted_mode->vdisplay);
220
221 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
222 bits << PFIT_VERT_SCALE_SHIFT);
223 *pfit_control |= (PFIT_ENABLE |
224 VERT_INTERP_BILINEAR |
225 HORIZ_INTERP_BILINEAR);
226 }
227 } else if (scaled_width < scaled_height) { /* letter */
228 centre_vertically(adjusted_mode,
229 scaled_width /
230 pipe_config->pipe_src_w);
231
232 *border = LVDS_BORDER_ENABLE;
233 if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
234 bits = panel_fitter_scaling(pipe_config->pipe_src_w,
235 adjusted_mode->hdisplay);
236
237 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
238 bits << PFIT_VERT_SCALE_SHIFT);
239 *pfit_control |= (PFIT_ENABLE |
240 VERT_INTERP_BILINEAR |
241 HORIZ_INTERP_BILINEAR);
242 }
243 } else {
244 /* Aspects match, Let hw scale both directions */
245 *pfit_control |= (PFIT_ENABLE |
246 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
247 VERT_INTERP_BILINEAR |
248 HORIZ_INTERP_BILINEAR);
249 }
250}
251
174void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, 252void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
175 struct intel_crtc_config *pipe_config, 253 struct intel_crtc_config *pipe_config,
176 int fitting_mode) 254 int fitting_mode)
177{ 255{
178 struct drm_device *dev = intel_crtc->base.dev; 256 struct drm_device *dev = intel_crtc->base.dev;
179 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; 257 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
180 struct drm_display_mode *mode, *adjusted_mode; 258 struct drm_display_mode *adjusted_mode;
181 259
182 mode = &pipe_config->requested_mode;
183 adjusted_mode = &pipe_config->adjusted_mode; 260 adjusted_mode = &pipe_config->adjusted_mode;
184 261
185 /* Native modes don't need fitting */ 262 /* Native modes don't need fitting */
186 if (adjusted_mode->hdisplay == mode->hdisplay && 263 if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
187 adjusted_mode->vdisplay == mode->vdisplay) 264 adjusted_mode->vdisplay == pipe_config->pipe_src_h)
188 goto out; 265 goto out;
189 266
190 switch (fitting_mode) { 267 switch (fitting_mode) {
@@ -193,81 +270,25 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
193 * For centered modes, we have to calculate border widths & 270 * For centered modes, we have to calculate border widths &
194 * heights and modify the values programmed into the CRTC. 271 * heights and modify the values programmed into the CRTC.
195 */ 272 */
196 centre_horizontally(adjusted_mode, mode->hdisplay); 273 centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
197 centre_vertically(adjusted_mode, mode->vdisplay); 274 centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
198 border = LVDS_BORDER_ENABLE; 275 border = LVDS_BORDER_ENABLE;
199 break; 276 break;
200 case DRM_MODE_SCALE_ASPECT: 277 case DRM_MODE_SCALE_ASPECT:
201 /* Scale but preserve the aspect ratio */ 278 /* Scale but preserve the aspect ratio */
202 if (INTEL_INFO(dev)->gen >= 4) { 279 if (INTEL_INFO(dev)->gen >= 4)
203 u32 scaled_width = adjusted_mode->hdisplay * 280 i965_scale_aspect(pipe_config, &pfit_control);
204 mode->vdisplay; 281 else
205 u32 scaled_height = mode->hdisplay * 282 i9xx_scale_aspect(pipe_config, &pfit_control,
206 adjusted_mode->vdisplay; 283 &pfit_pgm_ratios, &border);
207
208 /* 965+ is easy, it does everything in hw */
209 if (scaled_width > scaled_height)
210 pfit_control |= PFIT_ENABLE |
211 PFIT_SCALING_PILLAR;
212 else if (scaled_width < scaled_height)
213 pfit_control |= PFIT_ENABLE |
214 PFIT_SCALING_LETTER;
215 else if (adjusted_mode->hdisplay != mode->hdisplay)
216 pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
217 } else {
218 u32 scaled_width = adjusted_mode->hdisplay *
219 mode->vdisplay;
220 u32 scaled_height = mode->hdisplay *
221 adjusted_mode->vdisplay;
222 /*
223 * For earlier chips we have to calculate the scaling
224 * ratio by hand and program it into the
225 * PFIT_PGM_RATIO register
226 */
227 if (scaled_width > scaled_height) { /* pillar */
228 centre_horizontally(adjusted_mode,
229 scaled_height /
230 mode->vdisplay);
231
232 border = LVDS_BORDER_ENABLE;
233 if (mode->vdisplay != adjusted_mode->vdisplay) {
234 u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
235 pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
236 bits << PFIT_VERT_SCALE_SHIFT);
237 pfit_control |= (PFIT_ENABLE |
238 VERT_INTERP_BILINEAR |
239 HORIZ_INTERP_BILINEAR);
240 }
241 } else if (scaled_width < scaled_height) { /* letter */
242 centre_vertically(adjusted_mode,
243 scaled_width /
244 mode->hdisplay);
245
246 border = LVDS_BORDER_ENABLE;
247 if (mode->hdisplay != adjusted_mode->hdisplay) {
248 u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
249 pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
250 bits << PFIT_VERT_SCALE_SHIFT);
251 pfit_control |= (PFIT_ENABLE |
252 VERT_INTERP_BILINEAR |
253 HORIZ_INTERP_BILINEAR);
254 }
255 } else {
256 /* Aspects match, Let hw scale both directions */
257 pfit_control |= (PFIT_ENABLE |
258 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
259 VERT_INTERP_BILINEAR |
260 HORIZ_INTERP_BILINEAR);
261 }
262 }
263 break; 284 break;
264 case DRM_MODE_SCALE_FULLSCREEN: 285 case DRM_MODE_SCALE_FULLSCREEN:
265 /* 286 /*
266 * Full scaling, even if it changes the aspect ratio. 287 * Full scaling, even if it changes the aspect ratio.
267 * Fortunately this is all done for us in hw. 288 * Fortunately this is all done for us in hw.
268 */ 289 */
269 if (mode->vdisplay != adjusted_mode->vdisplay || 290 if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
270 mode->hdisplay != adjusted_mode->hdisplay) { 291 pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
271 pfit_control |= PFIT_ENABLE; 292 pfit_control |= PFIT_ENABLE;
272 if (INTEL_INFO(dev)->gen >= 4) 293 if (INTEL_INFO(dev)->gen >= 4)
273 pfit_control |= PFIT_SCALING_AUTO; 294 pfit_control |= PFIT_SCALING_AUTO;
@@ -308,7 +329,7 @@ static int is_backlight_combination_mode(struct drm_device *dev)
308{ 329{
309 struct drm_i915_private *dev_priv = dev->dev_private; 330 struct drm_i915_private *dev_priv = dev->dev_private;
310 331
311 if (INTEL_INFO(dev)->gen >= 4) 332 if (IS_GEN4(dev))
312 return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; 333 return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
313 334
314 if (IS_GEN2(dev)) 335 if (IS_GEN2(dev))
@@ -320,7 +341,7 @@ static int is_backlight_combination_mode(struct drm_device *dev)
320/* XXX: query mode clock or hardware clock and program max PWM appropriately 341/* XXX: query mode clock or hardware clock and program max PWM appropriately
321 * when it's 0. 342 * when it's 0.
322 */ 343 */
323static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) 344static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe)
324{ 345{
325 struct drm_i915_private *dev_priv = dev->dev_private; 346 struct drm_i915_private *dev_priv = dev->dev_private;
326 u32 val; 347 u32 val;
@@ -337,6 +358,21 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
337 val = dev_priv->regfile.saveBLC_PWM_CTL2; 358 val = dev_priv->regfile.saveBLC_PWM_CTL2;
338 I915_WRITE(BLC_PWM_PCH_CTL2, val); 359 I915_WRITE(BLC_PWM_PCH_CTL2, val);
339 } 360 }
361 } else if (IS_VALLEYVIEW(dev)) {
362 val = I915_READ(VLV_BLC_PWM_CTL(pipe));
363 if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
364 dev_priv->regfile.saveBLC_PWM_CTL = val;
365 dev_priv->regfile.saveBLC_PWM_CTL2 =
366 I915_READ(VLV_BLC_PWM_CTL2(pipe));
367 } else if (val == 0) {
368 val = dev_priv->regfile.saveBLC_PWM_CTL;
369 I915_WRITE(VLV_BLC_PWM_CTL(pipe), val);
370 I915_WRITE(VLV_BLC_PWM_CTL2(pipe),
371 dev_priv->regfile.saveBLC_PWM_CTL2);
372 }
373
374 if (!val)
375 val = 0x0f42ffff;
340 } else { 376 } else {
341 val = I915_READ(BLC_PWM_CTL); 377 val = I915_READ(BLC_PWM_CTL);
342 if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { 378 if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
@@ -356,11 +392,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
356 return val; 392 return val;
357} 393}
358 394
359static u32 intel_panel_get_max_backlight(struct drm_device *dev) 395static u32 intel_panel_get_max_backlight(struct drm_device *dev,
396 enum pipe pipe)
360{ 397{
361 u32 max; 398 u32 max;
362 399
363 max = i915_read_blc_pwm_ctl(dev); 400 max = i915_read_blc_pwm_ctl(dev, pipe);
364 401
365 if (HAS_PCH_SPLIT(dev)) { 402 if (HAS_PCH_SPLIT(dev)) {
366 max >>= 16; 403 max >>= 16;
@@ -386,7 +423,8 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
386 "to dri-devel@lists.freedesktop.org, if your machine needs it. " 423 "to dri-devel@lists.freedesktop.org, if your machine needs it. "
387 "It will then be included in an upcoming module version."); 424 "It will then be included in an upcoming module version.");
388module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); 425module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
389static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) 426static u32 intel_panel_compute_brightness(struct drm_device *dev,
427 enum pipe pipe, u32 val)
390{ 428{
391 struct drm_i915_private *dev_priv = dev->dev_private; 429 struct drm_i915_private *dev_priv = dev->dev_private;
392 430
@@ -395,7 +433,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)
395 433
396 if (i915_panel_invert_brightness > 0 || 434 if (i915_panel_invert_brightness > 0 ||
397 dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { 435 dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
398 u32 max = intel_panel_get_max_backlight(dev); 436 u32 max = intel_panel_get_max_backlight(dev, pipe);
399 if (max) 437 if (max)
400 return max - val; 438 return max - val;
401 } 439 }
@@ -403,18 +441,25 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)
403 return val; 441 return val;
404} 442}
405 443
406static u32 intel_panel_get_backlight(struct drm_device *dev) 444static u32 intel_panel_get_backlight(struct drm_device *dev,
445 enum pipe pipe)
407{ 446{
408 struct drm_i915_private *dev_priv = dev->dev_private; 447 struct drm_i915_private *dev_priv = dev->dev_private;
409 u32 val; 448 u32 val;
410 unsigned long flags; 449 unsigned long flags;
450 int reg;
411 451
412 spin_lock_irqsave(&dev_priv->backlight.lock, flags); 452 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
413 453
414 if (HAS_PCH_SPLIT(dev)) { 454 if (HAS_PCH_SPLIT(dev)) {
415 val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; 455 val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
416 } else { 456 } else {
417 val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; 457 if (IS_VALLEYVIEW(dev))
458 reg = VLV_BLC_PWM_CTL(pipe);
459 else
460 reg = BLC_PWM_CTL;
461
462 val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK;
418 if (INTEL_INFO(dev)->gen < 4) 463 if (INTEL_INFO(dev)->gen < 4)
419 val >>= 1; 464 val >>= 1;
420 465
@@ -426,7 +471,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev)
426 } 471 }
427 } 472 }
428 473
429 val = intel_panel_compute_brightness(dev, val); 474 val = intel_panel_compute_brightness(dev, pipe, val);
430 475
431 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); 476 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
432 477
@@ -441,19 +486,21 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
441 I915_WRITE(BLC_PWM_CPU_CTL, val | level); 486 I915_WRITE(BLC_PWM_CPU_CTL, val | level);
442} 487}
443 488
444static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level) 489static void intel_panel_actually_set_backlight(struct drm_device *dev,
490 enum pipe pipe, u32 level)
445{ 491{
446 struct drm_i915_private *dev_priv = dev->dev_private; 492 struct drm_i915_private *dev_priv = dev->dev_private;
447 u32 tmp; 493 u32 tmp;
494 int reg;
448 495
449 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); 496 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
450 level = intel_panel_compute_brightness(dev, level); 497 level = intel_panel_compute_brightness(dev, pipe, level);
451 498
452 if (HAS_PCH_SPLIT(dev)) 499 if (HAS_PCH_SPLIT(dev))
453 return intel_pch_panel_set_backlight(dev, level); 500 return intel_pch_panel_set_backlight(dev, level);
454 501
455 if (is_backlight_combination_mode(dev)) { 502 if (is_backlight_combination_mode(dev)) {
456 u32 max = intel_panel_get_max_backlight(dev); 503 u32 max = intel_panel_get_max_backlight(dev, pipe);
457 u8 lbpc; 504 u8 lbpc;
458 505
459 /* we're screwed, but keep behaviour backwards compatible */ 506 /* we're screwed, but keep behaviour backwards compatible */
@@ -465,23 +512,34 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level
465 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); 512 pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
466 } 513 }
467 514
468 tmp = I915_READ(BLC_PWM_CTL); 515 if (IS_VALLEYVIEW(dev))
516 reg = VLV_BLC_PWM_CTL(pipe);
517 else
518 reg = BLC_PWM_CTL;
519
520 tmp = I915_READ(reg);
469 if (INTEL_INFO(dev)->gen < 4) 521 if (INTEL_INFO(dev)->gen < 4)
470 level <<= 1; 522 level <<= 1;
471 tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; 523 tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
472 I915_WRITE(BLC_PWM_CTL, tmp | level); 524 I915_WRITE(reg, tmp | level);
473} 525}
474 526
475/* set backlight brightness to level in range [0..max] */ 527/* set backlight brightness to level in range [0..max] */
476void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) 528void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
529 u32 max)
477{ 530{
531 struct drm_device *dev = connector->base.dev;
478 struct drm_i915_private *dev_priv = dev->dev_private; 532 struct drm_i915_private *dev_priv = dev->dev_private;
533 enum pipe pipe = intel_get_pipe_from_connector(connector);
479 u32 freq; 534 u32 freq;
480 unsigned long flags; 535 unsigned long flags;
481 536
537 if (pipe == INVALID_PIPE)
538 return;
539
482 spin_lock_irqsave(&dev_priv->backlight.lock, flags); 540 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
483 541
484 freq = intel_panel_get_max_backlight(dev); 542 freq = intel_panel_get_max_backlight(dev, pipe);
485 if (!freq) { 543 if (!freq) {
486 /* we are screwed, bail out */ 544 /* we are screwed, bail out */
487 goto out; 545 goto out;
@@ -498,16 +556,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
498 dev_priv->backlight.device->props.brightness = level; 556 dev_priv->backlight.device->props.brightness = level;
499 557
500 if (dev_priv->backlight.enabled) 558 if (dev_priv->backlight.enabled)
501 intel_panel_actually_set_backlight(dev, level); 559 intel_panel_actually_set_backlight(dev, pipe, level);
502out: 560out:
503 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); 561 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
504} 562}
505 563
506void intel_panel_disable_backlight(struct drm_device *dev) 564void intel_panel_disable_backlight(struct intel_connector *connector)
507{ 565{
566 struct drm_device *dev = connector->base.dev;
508 struct drm_i915_private *dev_priv = dev->dev_private; 567 struct drm_i915_private *dev_priv = dev->dev_private;
568 enum pipe pipe = intel_get_pipe_from_connector(connector);
509 unsigned long flags; 569 unsigned long flags;
510 570
571 if (pipe == INVALID_PIPE)
572 return;
573
511 /* 574 /*
512 * Do not disable backlight on the vgaswitcheroo path. When switching 575 * Do not disable backlight on the vgaswitcheroo path. When switching
513 * away from i915, the other client may depend on i915 to handle the 576 * away from i915, the other client may depend on i915 to handle the
@@ -522,12 +585,17 @@ void intel_panel_disable_backlight(struct drm_device *dev)
522 spin_lock_irqsave(&dev_priv->backlight.lock, flags); 585 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
523 586
524 dev_priv->backlight.enabled = false; 587 dev_priv->backlight.enabled = false;
525 intel_panel_actually_set_backlight(dev, 0); 588 intel_panel_actually_set_backlight(dev, pipe, 0);
526 589
527 if (INTEL_INFO(dev)->gen >= 4) { 590 if (INTEL_INFO(dev)->gen >= 4) {
528 uint32_t reg, tmp; 591 uint32_t reg, tmp;
529 592
530 reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; 593 if (HAS_PCH_SPLIT(dev))
594 reg = BLC_PWM_CPU_CTL2;
595 else if (IS_VALLEYVIEW(dev))
596 reg = VLV_BLC_PWM_CTL2(pipe);
597 else
598 reg = BLC_PWM_CTL2;
531 599
532 I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); 600 I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
533 601
@@ -541,18 +609,25 @@ void intel_panel_disable_backlight(struct drm_device *dev)
541 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); 609 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
542} 610}
543 611
544void intel_panel_enable_backlight(struct drm_device *dev, 612void intel_panel_enable_backlight(struct intel_connector *connector)
545 enum pipe pipe)
546{ 613{
614 struct drm_device *dev = connector->base.dev;
547 struct drm_i915_private *dev_priv = dev->dev_private; 615 struct drm_i915_private *dev_priv = dev->dev_private;
616 enum pipe pipe = intel_get_pipe_from_connector(connector);
548 enum transcoder cpu_transcoder = 617 enum transcoder cpu_transcoder =
549 intel_pipe_to_cpu_transcoder(dev_priv, pipe); 618 intel_pipe_to_cpu_transcoder(dev_priv, pipe);
550 unsigned long flags; 619 unsigned long flags;
551 620
621 if (pipe == INVALID_PIPE)
622 return;
623
624 DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
625
552 spin_lock_irqsave(&dev_priv->backlight.lock, flags); 626 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
553 627
554 if (dev_priv->backlight.level == 0) { 628 if (dev_priv->backlight.level == 0) {
555 dev_priv->backlight.level = intel_panel_get_max_backlight(dev); 629 dev_priv->backlight.level = intel_panel_get_max_backlight(dev,
630 pipe);
556 if (dev_priv->backlight.device) 631 if (dev_priv->backlight.device)
557 dev_priv->backlight.device->props.brightness = 632 dev_priv->backlight.device->props.brightness =
558 dev_priv->backlight.level; 633 dev_priv->backlight.level;
@@ -561,8 +636,12 @@ void intel_panel_enable_backlight(struct drm_device *dev,
561 if (INTEL_INFO(dev)->gen >= 4) { 636 if (INTEL_INFO(dev)->gen >= 4) {
562 uint32_t reg, tmp; 637 uint32_t reg, tmp;
563 638
564 reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; 639 if (HAS_PCH_SPLIT(dev))
565 640 reg = BLC_PWM_CPU_CTL2;
641 else if (IS_VALLEYVIEW(dev))
642 reg = VLV_BLC_PWM_CTL2(pipe);
643 else
644 reg = BLC_PWM_CTL2;
566 645
567 tmp = I915_READ(reg); 646 tmp = I915_READ(reg);
568 647
@@ -602,16 +681,41 @@ set_level:
602 * registers are set. 681 * registers are set.
603 */ 682 */
604 dev_priv->backlight.enabled = true; 683 dev_priv->backlight.enabled = true;
605 intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); 684 intel_panel_actually_set_backlight(dev, pipe,
685 dev_priv->backlight.level);
606 686
607 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); 687 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
608} 688}
609 689
690/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
691static void intel_panel_init_backlight_regs(struct drm_device *dev)
692{
693 struct drm_i915_private *dev_priv = dev->dev_private;
694
695 if (IS_VALLEYVIEW(dev)) {
696 enum pipe pipe;
697
698 for_each_pipe(pipe) {
699 u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
700
701 /* Skip if the modulation freq is already set */
702 if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
703 continue;
704
705 cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
706 I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
707 cur_val);
708 }
709 }
710}
711
610static void intel_panel_init_backlight(struct drm_device *dev) 712static void intel_panel_init_backlight(struct drm_device *dev)
611{ 713{
612 struct drm_i915_private *dev_priv = dev->dev_private; 714 struct drm_i915_private *dev_priv = dev->dev_private;
613 715
614 dev_priv->backlight.level = intel_panel_get_backlight(dev); 716 intel_panel_init_backlight_regs(dev);
717
718 dev_priv->backlight.level = intel_panel_get_backlight(dev, 0);
615 dev_priv->backlight.enabled = dev_priv->backlight.level != 0; 719 dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
616} 720}
617 721
@@ -637,19 +741,34 @@ intel_panel_detect(struct drm_device *dev)
637 } 741 }
638} 742}
639 743
640#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 744#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
641static int intel_panel_update_status(struct backlight_device *bd) 745static int intel_panel_update_status(struct backlight_device *bd)
642{ 746{
643 struct drm_device *dev = bl_get_data(bd); 747 struct intel_connector *connector = bl_get_data(bd);
644 intel_panel_set_backlight(dev, bd->props.brightness, 748 struct drm_device *dev = connector->base.dev;
749
750 mutex_lock(&dev->mode_config.mutex);
751 DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
752 bd->props.brightness, bd->props.max_brightness);
753 intel_panel_set_backlight(connector, bd->props.brightness,
645 bd->props.max_brightness); 754 bd->props.max_brightness);
755 mutex_unlock(&dev->mode_config.mutex);
646 return 0; 756 return 0;
647} 757}
648 758
649static int intel_panel_get_brightness(struct backlight_device *bd) 759static int intel_panel_get_brightness(struct backlight_device *bd)
650{ 760{
651 struct drm_device *dev = bl_get_data(bd); 761 struct intel_connector *connector = bl_get_data(bd);
652 return intel_panel_get_backlight(dev); 762 struct drm_device *dev = connector->base.dev;
763 enum pipe pipe;
764
765 mutex_lock(&dev->mode_config.mutex);
766 pipe = intel_get_pipe_from_connector(connector);
767 mutex_unlock(&dev->mode_config.mutex);
768 if (pipe == INVALID_PIPE)
769 return 0;
770
771 return intel_panel_get_backlight(connector->base.dev, pipe);
653} 772}
654 773
655static const struct backlight_ops intel_panel_bl_ops = { 774static const struct backlight_ops intel_panel_bl_ops = {
@@ -674,7 +793,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
674 props.brightness = dev_priv->backlight.level; 793 props.brightness = dev_priv->backlight.level;
675 794
676 spin_lock_irqsave(&dev_priv->backlight.lock, flags); 795 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
677 props.max_brightness = intel_panel_get_max_backlight(dev); 796 props.max_brightness = intel_panel_get_max_backlight(dev, 0);
678 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); 797 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
679 798
680 if (props.max_brightness == 0) { 799 if (props.max_brightness == 0) {
@@ -683,7 +802,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
683 } 802 }
684 dev_priv->backlight.device = 803 dev_priv->backlight.device =
685 backlight_device_register("intel_backlight", 804 backlight_device_register("intel_backlight",
686 &connector->kdev, dev, 805 connector->kdev,
806 to_intel_connector(connector),
687 &intel_panel_bl_ops, &props); 807 &intel_panel_bl_ops, &props);
688 808
689 if (IS_ERR(dev_priv->backlight.device)) { 809 if (IS_ERR(dev_priv->backlight.device)) {