diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2013-10-31 12:55:49 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-11-06 11:56:28 -0500 |
commit | 752aa88a1e784c22d514db3b440e49427b58259e (patch) | |
tree | 755926ad23793496c41b601a9cbb42950a57416e | |
parent | 91a60f20712179e56b7a6c3d332a5f6f9a54aa11 (diff) |
drm/i915: make backlight functions take a connector
On VLV/BYT, backlight controls a per-pipe, so when adjusting the
backlight we need to pass the correct info. So make the externally
visible backlight functions take a connector argument, which can be used
internally to figure out the pipe backlight to adjust.
v2: make connector pipe lookup check for NULL crtc (Jani)
fixup connector check in ASLE code (Jani)
v3: make sure we take the mode config lock around lookups (Daniel)
v4: fix double unlock in panel_get_brightness (Daniel)
v5: push ASLE work into a work queue (Daniel)
v6: separate ASLE work to a prep patch, rebase (Jani)
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 86 |
7 files changed, 122 insertions, 37 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b37b3531c27..b2023d7c1d6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define DRIVER_DATE "20080730" | 54 | #define DRIVER_DATE "20080730" |
55 | 55 | ||
56 | enum pipe { | 56 | enum pipe { |
57 | INVALID_PIPE = -1, | ||
57 | PIPE_A = 0, | 58 | PIPE_A = 0, |
58 | PIPE_B, | 59 | PIPE_B, |
59 | PIPE_C, | 60 | PIPE_C, |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e31a740e1663..73f036bddb6f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -9874,6 +9874,18 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
9874 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); | 9874 | drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); |
9875 | } | 9875 | } |
9876 | 9876 | ||
9877 | enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) | ||
9878 | { | ||
9879 | struct drm_encoder *encoder = connector->base.encoder; | ||
9880 | |||
9881 | WARN_ON(!mutex_is_locked(&connector->base.dev->mode_config.mutex)); | ||
9882 | |||
9883 | if (!encoder) | ||
9884 | return INVALID_PIPE; | ||
9885 | |||
9886 | return to_intel_crtc(encoder->crtc)->pipe; | ||
9887 | } | ||
9888 | |||
9877 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 9889 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
9878 | struct drm_file *file) | 9890 | struct drm_file *file) |
9879 | { | 9891 | { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d58fbb6b5ffd..4609eedf52aa 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1249,7 +1249,6 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) | |||
1249 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 1249 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
1250 | struct drm_device *dev = intel_dig_port->base.base.dev; | 1250 | struct drm_device *dev = intel_dig_port->base.base.dev; |
1251 | struct drm_i915_private *dev_priv = dev->dev_private; | 1251 | struct drm_i915_private *dev_priv = dev->dev_private; |
1252 | int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe; | ||
1253 | u32 pp; | 1252 | u32 pp; |
1254 | u32 pp_ctrl_reg; | 1253 | u32 pp_ctrl_reg; |
1255 | 1254 | ||
@@ -1272,7 +1271,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) | |||
1272 | I915_WRITE(pp_ctrl_reg, pp); | 1271 | I915_WRITE(pp_ctrl_reg, pp); |
1273 | POSTING_READ(pp_ctrl_reg); | 1272 | POSTING_READ(pp_ctrl_reg); |
1274 | 1273 | ||
1275 | intel_panel_enable_backlight(dev, pipe); | 1274 | intel_panel_enable_backlight(intel_dp->attached_connector); |
1276 | } | 1275 | } |
1277 | 1276 | ||
1278 | void ironlake_edp_backlight_off(struct intel_dp *intel_dp) | 1277 | void ironlake_edp_backlight_off(struct intel_dp *intel_dp) |
@@ -1285,7 +1284,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp) | |||
1285 | if (!is_edp(intel_dp)) | 1284 | if (!is_edp(intel_dp)) |
1286 | return; | 1285 | return; |
1287 | 1286 | ||
1288 | intel_panel_disable_backlight(dev); | 1287 | intel_panel_disable_backlight(intel_dp->attached_connector); |
1289 | 1288 | ||
1290 | DRM_DEBUG_KMS("\n"); | 1289 | DRM_DEBUG_KMS("\n"); |
1291 | pp = ironlake_get_pp_control(intel_dp); | 1290 | pp = ironlake_get_pp_control(intel_dp); |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9d2624fd92c2..1e49aa8f5377 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -630,6 +630,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector, | |||
630 | struct drm_encoder *intel_best_encoder(struct drm_connector *connector); | 630 | struct drm_encoder *intel_best_encoder(struct drm_connector *connector); |
631 | struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, | 631 | struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, |
632 | struct drm_crtc *crtc); | 632 | struct drm_crtc *crtc); |
633 | enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); | ||
633 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 634 | int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
634 | struct drm_file *file_priv); | 635 | struct drm_file *file_priv); |
635 | enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, | 636 | enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, |
@@ -802,10 +803,11 @@ void intel_pch_panel_fitting(struct intel_crtc *crtc, | |||
802 | void intel_gmch_panel_fitting(struct intel_crtc *crtc, | 803 | void intel_gmch_panel_fitting(struct intel_crtc *crtc, |
803 | struct intel_crtc_config *pipe_config, | 804 | struct intel_crtc_config *pipe_config, |
804 | int fitting_mode); | 805 | int fitting_mode); |
805 | void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max); | 806 | void intel_panel_set_backlight(struct intel_connector *connector, u32 level, |
807 | u32 max); | ||
806 | int intel_panel_setup_backlight(struct drm_connector *connector); | 808 | int intel_panel_setup_backlight(struct drm_connector *connector); |
807 | void intel_panel_enable_backlight(struct drm_device *dev, enum pipe pipe); | 809 | void intel_panel_enable_backlight(struct intel_connector *connector); |
808 | void intel_panel_disable_backlight(struct drm_device *dev); | 810 | void intel_panel_disable_backlight(struct intel_connector *connector); |
809 | void intel_panel_destroy_backlight(struct drm_device *dev); | 811 | void intel_panel_destroy_backlight(struct drm_device *dev); |
810 | enum drm_connector_status intel_panel_detect(struct drm_device *dev); | 812 | enum drm_connector_status intel_panel_detect(struct drm_device *dev); |
811 | 813 | ||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b0ef55833087..c3b4da7895ed 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -206,7 +206,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder) | |||
206 | { | 206 | { |
207 | struct drm_device *dev = encoder->base.dev; | 207 | struct drm_device *dev = encoder->base.dev; |
208 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); | 208 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); |
209 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | 209 | struct intel_connector *intel_connector = |
210 | &lvds_encoder->attached_connector->base; | ||
210 | struct drm_i915_private *dev_priv = dev->dev_private; | 211 | struct drm_i915_private *dev_priv = dev->dev_private; |
211 | u32 ctl_reg, stat_reg; | 212 | u32 ctl_reg, stat_reg; |
212 | 213 | ||
@@ -225,13 +226,15 @@ static void intel_enable_lvds(struct intel_encoder *encoder) | |||
225 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) | 226 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) |
226 | DRM_ERROR("timed out waiting for panel to power on\n"); | 227 | DRM_ERROR("timed out waiting for panel to power on\n"); |
227 | 228 | ||
228 | intel_panel_enable_backlight(dev, intel_crtc->pipe); | 229 | intel_panel_enable_backlight(intel_connector); |
229 | } | 230 | } |
230 | 231 | ||
231 | static void intel_disable_lvds(struct intel_encoder *encoder) | 232 | static void intel_disable_lvds(struct intel_encoder *encoder) |
232 | { | 233 | { |
233 | struct drm_device *dev = encoder->base.dev; | 234 | struct drm_device *dev = encoder->base.dev; |
234 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); | 235 | struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); |
236 | struct intel_connector *intel_connector = | ||
237 | &lvds_encoder->attached_connector->base; | ||
235 | struct drm_i915_private *dev_priv = dev->dev_private; | 238 | struct drm_i915_private *dev_priv = dev->dev_private; |
236 | u32 ctl_reg, stat_reg; | 239 | u32 ctl_reg, stat_reg; |
237 | 240 | ||
@@ -243,7 +246,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder) | |||
243 | stat_reg = PP_STATUS; | 246 | stat_reg = PP_STATUS; |
244 | } | 247 | } |
245 | 248 | ||
246 | intel_panel_disable_backlight(dev); | 249 | intel_panel_disable_backlight(intel_connector); |
247 | 250 | ||
248 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); | 251 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); |
249 | if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000)) | 252 | if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000)) |
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 892d520175d8..91b68dca0641 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -396,7 +396,13 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) | |||
396 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | 396 | static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) |
397 | { | 397 | { |
398 | struct drm_i915_private *dev_priv = dev->dev_private; | 398 | struct drm_i915_private *dev_priv = dev->dev_private; |
399 | struct drm_encoder *encoder; | ||
400 | struct drm_connector *connector; | ||
401 | struct intel_connector *intel_connector = NULL; | ||
402 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; | ||
399 | struct opregion_asle __iomem *asle = dev_priv->opregion.asle; | 403 | struct opregion_asle __iomem *asle = dev_priv->opregion.asle; |
404 | u32 ret = 0; | ||
405 | bool found = false; | ||
400 | 406 | ||
401 | DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); | 407 | DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); |
402 | 408 | ||
@@ -407,11 +413,39 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | |||
407 | if (bclp > 255) | 413 | if (bclp > 255) |
408 | return ASLC_BACKLIGHT_FAILED; | 414 | return ASLC_BACKLIGHT_FAILED; |
409 | 415 | ||
416 | mutex_lock(&dev->mode_config.mutex); | ||
417 | /* | ||
418 | * Could match the OpRegion connector here instead, but we'd also need | ||
419 | * to verify the connector could handle a backlight call. | ||
420 | */ | ||
421 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | ||
422 | if (encoder->crtc == crtc) { | ||
423 | found = true; | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | if (!found) { | ||
428 | ret = ASLC_BACKLIGHT_FAILED; | ||
429 | goto out; | ||
430 | } | ||
431 | |||
432 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
433 | if (connector->encoder == encoder) | ||
434 | intel_connector = to_intel_connector(connector); | ||
435 | |||
436 | if (!intel_connector) { | ||
437 | ret = ASLC_BACKLIGHT_FAILED; | ||
438 | goto out; | ||
439 | } | ||
440 | |||
410 | DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); | 441 | DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); |
411 | intel_panel_set_backlight(dev, bclp, 255); | 442 | intel_panel_set_backlight(intel_connector, bclp, 255); |
412 | iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); | 443 | iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); |
413 | 444 | ||
414 | return 0; | 445 | out: |
446 | mutex_unlock(&dev->mode_config.mutex); | ||
447 | |||
448 | return ret; | ||
415 | } | 449 | } |
416 | 450 | ||
417 | static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) | 451 | static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index de1518614827..17ddcb00bd26 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -341,7 +341,7 @@ static int is_backlight_combination_mode(struct drm_device *dev) | |||
341 | /* 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 |
342 | * when it's 0. | 342 | * when it's 0. |
343 | */ | 343 | */ |
344 | static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) | 344 | static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) |
345 | { | 345 | { |
346 | struct drm_i915_private *dev_priv = dev->dev_private; | 346 | struct drm_i915_private *dev_priv = dev->dev_private; |
347 | u32 val; | 347 | u32 val; |
@@ -380,11 +380,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) | |||
380 | return val; | 380 | return val; |
381 | } | 381 | } |
382 | 382 | ||
383 | static u32 intel_panel_get_max_backlight(struct drm_device *dev) | 383 | static u32 intel_panel_get_max_backlight(struct drm_device *dev, |
384 | enum pipe pipe) | ||
384 | { | 385 | { |
385 | u32 max; | 386 | u32 max; |
386 | 387 | ||
387 | max = i915_read_blc_pwm_ctl(dev); | 388 | max = i915_read_blc_pwm_ctl(dev, pipe); |
388 | 389 | ||
389 | if (HAS_PCH_SPLIT(dev)) { | 390 | if (HAS_PCH_SPLIT(dev)) { |
390 | max >>= 16; | 391 | max >>= 16; |
@@ -410,7 +411,8 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " | |||
410 | "to dri-devel@lists.freedesktop.org, if your machine needs it. " | 411 | "to dri-devel@lists.freedesktop.org, if your machine needs it. " |
411 | "It will then be included in an upcoming module version."); | 412 | "It will then be included in an upcoming module version."); |
412 | module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); | 413 | module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
413 | static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) | 414 | static u32 intel_panel_compute_brightness(struct drm_device *dev, |
415 | enum pipe pipe, u32 val) | ||
414 | { | 416 | { |
415 | struct drm_i915_private *dev_priv = dev->dev_private; | 417 | struct drm_i915_private *dev_priv = dev->dev_private; |
416 | 418 | ||
@@ -419,7 +421,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) | |||
419 | 421 | ||
420 | if (i915_panel_invert_brightness > 0 || | 422 | if (i915_panel_invert_brightness > 0 || |
421 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { | 423 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
422 | u32 max = intel_panel_get_max_backlight(dev); | 424 | u32 max = intel_panel_get_max_backlight(dev, pipe); |
423 | if (max) | 425 | if (max) |
424 | return max - val; | 426 | return max - val; |
425 | } | 427 | } |
@@ -427,7 +429,8 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) | |||
427 | return val; | 429 | return val; |
428 | } | 430 | } |
429 | 431 | ||
430 | static u32 intel_panel_get_backlight(struct drm_device *dev) | 432 | static u32 intel_panel_get_backlight(struct drm_device *dev, |
433 | enum pipe pipe) | ||
431 | { | 434 | { |
432 | struct drm_i915_private *dev_priv = dev->dev_private; | 435 | struct drm_i915_private *dev_priv = dev->dev_private; |
433 | u32 val; | 436 | u32 val; |
@@ -450,7 +453,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev) | |||
450 | } | 453 | } |
451 | } | 454 | } |
452 | 455 | ||
453 | val = intel_panel_compute_brightness(dev, val); | 456 | val = intel_panel_compute_brightness(dev, pipe, val); |
454 | 457 | ||
455 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); | 458 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
456 | 459 | ||
@@ -466,19 +469,19 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) | |||
466 | } | 469 | } |
467 | 470 | ||
468 | static void intel_panel_actually_set_backlight(struct drm_device *dev, | 471 | static void intel_panel_actually_set_backlight(struct drm_device *dev, |
469 | u32 level) | 472 | enum pipe pipe, u32 level) |
470 | { | 473 | { |
471 | struct drm_i915_private *dev_priv = dev->dev_private; | 474 | struct drm_i915_private *dev_priv = dev->dev_private; |
472 | u32 tmp; | 475 | u32 tmp; |
473 | 476 | ||
474 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); | 477 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
475 | level = intel_panel_compute_brightness(dev, level); | 478 | level = intel_panel_compute_brightness(dev, pipe, level); |
476 | 479 | ||
477 | if (HAS_PCH_SPLIT(dev)) | 480 | if (HAS_PCH_SPLIT(dev)) |
478 | return intel_pch_panel_set_backlight(dev, level); | 481 | return intel_pch_panel_set_backlight(dev, level); |
479 | 482 | ||
480 | if (is_backlight_combination_mode(dev)) { | 483 | if (is_backlight_combination_mode(dev)) { |
481 | u32 max = intel_panel_get_max_backlight(dev); | 484 | u32 max = intel_panel_get_max_backlight(dev, pipe); |
482 | u8 lbpc; | 485 | u8 lbpc; |
483 | 486 | ||
484 | /* we're screwed, but keep behaviour backwards compatible */ | 487 | /* we're screwed, but keep behaviour backwards compatible */ |
@@ -498,15 +501,21 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, | |||
498 | } | 501 | } |
499 | 502 | ||
500 | /* set backlight brightness to level in range [0..max] */ | 503 | /* set backlight brightness to level in range [0..max] */ |
501 | void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) | 504 | void intel_panel_set_backlight(struct intel_connector *connector, u32 level, |
505 | u32 max) | ||
502 | { | 506 | { |
507 | struct drm_device *dev = connector->base.dev; | ||
503 | struct drm_i915_private *dev_priv = dev->dev_private; | 508 | struct drm_i915_private *dev_priv = dev->dev_private; |
509 | enum pipe pipe = intel_get_pipe_from_connector(connector); | ||
504 | u32 freq; | 510 | u32 freq; |
505 | unsigned long flags; | 511 | unsigned long flags; |
506 | 512 | ||
513 | if (pipe == INVALID_PIPE) | ||
514 | return; | ||
515 | |||
507 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); | 516 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
508 | 517 | ||
509 | freq = intel_panel_get_max_backlight(dev); | 518 | freq = intel_panel_get_max_backlight(dev, pipe); |
510 | if (!freq) { | 519 | if (!freq) { |
511 | /* we are screwed, bail out */ | 520 | /* we are screwed, bail out */ |
512 | goto out; | 521 | goto out; |
@@ -523,16 +532,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) | |||
523 | dev_priv->backlight.device->props.brightness = level; | 532 | dev_priv->backlight.device->props.brightness = level; |
524 | 533 | ||
525 | if (dev_priv->backlight.enabled) | 534 | if (dev_priv->backlight.enabled) |
526 | intel_panel_actually_set_backlight(dev, level); | 535 | intel_panel_actually_set_backlight(dev, pipe, level); |
527 | out: | 536 | out: |
528 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); | 537 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
529 | } | 538 | } |
530 | 539 | ||
531 | void intel_panel_disable_backlight(struct drm_device *dev) | 540 | void intel_panel_disable_backlight(struct intel_connector *connector) |
532 | { | 541 | { |
542 | struct drm_device *dev = connector->base.dev; | ||
533 | struct drm_i915_private *dev_priv = dev->dev_private; | 543 | struct drm_i915_private *dev_priv = dev->dev_private; |
544 | enum pipe pipe = intel_get_pipe_from_connector(connector); | ||
534 | unsigned long flags; | 545 | unsigned long flags; |
535 | 546 | ||
547 | if (pipe == INVALID_PIPE) | ||
548 | return; | ||
549 | |||
536 | /* | 550 | /* |
537 | * Do not disable backlight on the vgaswitcheroo path. When switching | 551 | * Do not disable backlight on the vgaswitcheroo path. When switching |
538 | * away from i915, the other client may depend on i915 to handle the | 552 | * away from i915, the other client may depend on i915 to handle the |
@@ -547,7 +561,7 @@ void intel_panel_disable_backlight(struct drm_device *dev) | |||
547 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); | 561 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
548 | 562 | ||
549 | dev_priv->backlight.enabled = false; | 563 | dev_priv->backlight.enabled = false; |
550 | intel_panel_actually_set_backlight(dev, 0); | 564 | intel_panel_actually_set_backlight(dev, pipe, 0); |
551 | 565 | ||
552 | if (INTEL_INFO(dev)->gen >= 4) { | 566 | if (INTEL_INFO(dev)->gen >= 4) { |
553 | uint32_t reg, tmp; | 567 | uint32_t reg, tmp; |
@@ -566,20 +580,25 @@ void intel_panel_disable_backlight(struct drm_device *dev) | |||
566 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); | 580 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
567 | } | 581 | } |
568 | 582 | ||
569 | void intel_panel_enable_backlight(struct drm_device *dev, | 583 | void intel_panel_enable_backlight(struct intel_connector *connector) |
570 | enum pipe pipe) | ||
571 | { | 584 | { |
585 | struct drm_device *dev = connector->base.dev; | ||
572 | struct drm_i915_private *dev_priv = dev->dev_private; | 586 | struct drm_i915_private *dev_priv = dev->dev_private; |
587 | enum pipe pipe = intel_get_pipe_from_connector(connector); | ||
573 | enum transcoder cpu_transcoder = | 588 | enum transcoder cpu_transcoder = |
574 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); | 589 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
575 | unsigned long flags; | 590 | unsigned long flags; |
576 | 591 | ||
592 | if (pipe == INVALID_PIPE) | ||
593 | return; | ||
594 | |||
577 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); | 595 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
578 | 596 | ||
579 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); | 597 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
580 | 598 | ||
581 | if (dev_priv->backlight.level == 0) { | 599 | if (dev_priv->backlight.level == 0) { |
582 | dev_priv->backlight.level = intel_panel_get_max_backlight(dev); | 600 | dev_priv->backlight.level = intel_panel_get_max_backlight(dev, |
601 | pipe); | ||
583 | if (dev_priv->backlight.device) | 602 | if (dev_priv->backlight.device) |
584 | dev_priv->backlight.device->props.brightness = | 603 | dev_priv->backlight.device->props.brightness = |
585 | dev_priv->backlight.level; | 604 | dev_priv->backlight.level; |
@@ -629,7 +648,8 @@ set_level: | |||
629 | * registers are set. | 648 | * registers are set. |
630 | */ | 649 | */ |
631 | dev_priv->backlight.enabled = true; | 650 | dev_priv->backlight.enabled = true; |
632 | intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); | 651 | intel_panel_actually_set_backlight(dev, pipe, |
652 | dev_priv->backlight.level); | ||
633 | 653 | ||
634 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); | 654 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
635 | } | 655 | } |
@@ -652,7 +672,7 @@ static void intel_panel_init_backlight(struct drm_device *dev) | |||
652 | 672 | ||
653 | intel_panel_init_backlight_regs(dev); | 673 | intel_panel_init_backlight_regs(dev); |
654 | 674 | ||
655 | dev_priv->backlight.level = intel_panel_get_backlight(dev); | 675 | dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); |
656 | dev_priv->backlight.enabled = dev_priv->backlight.level != 0; | 676 | dev_priv->backlight.enabled = dev_priv->backlight.level != 0; |
657 | } | 677 | } |
658 | 678 | ||
@@ -681,18 +701,31 @@ intel_panel_detect(struct drm_device *dev) | |||
681 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) | 701 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
682 | static int intel_panel_update_status(struct backlight_device *bd) | 702 | static int intel_panel_update_status(struct backlight_device *bd) |
683 | { | 703 | { |
684 | struct drm_device *dev = bl_get_data(bd); | 704 | struct intel_connector *connector = bl_get_data(bd); |
705 | struct drm_device *dev = connector->base.dev; | ||
706 | |||
707 | mutex_lock(&dev->mode_config.mutex); | ||
685 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", | 708 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
686 | bd->props.brightness, bd->props.max_brightness); | 709 | bd->props.brightness, bd->props.max_brightness); |
687 | intel_panel_set_backlight(dev, bd->props.brightness, | 710 | intel_panel_set_backlight(connector, bd->props.brightness, |
688 | bd->props.max_brightness); | 711 | bd->props.max_brightness); |
712 | mutex_unlock(&dev->mode_config.mutex); | ||
689 | return 0; | 713 | return 0; |
690 | } | 714 | } |
691 | 715 | ||
692 | static int intel_panel_get_brightness(struct backlight_device *bd) | 716 | static int intel_panel_get_brightness(struct backlight_device *bd) |
693 | { | 717 | { |
694 | struct drm_device *dev = bl_get_data(bd); | 718 | struct intel_connector *connector = bl_get_data(bd); |
695 | return intel_panel_get_backlight(dev); | 719 | struct drm_device *dev = connector->base.dev; |
720 | enum pipe pipe; | ||
721 | |||
722 | mutex_lock(&dev->mode_config.mutex); | ||
723 | pipe = intel_get_pipe_from_connector(connector); | ||
724 | mutex_unlock(&dev->mode_config.mutex); | ||
725 | if (pipe == INVALID_PIPE) | ||
726 | return 0; | ||
727 | |||
728 | return intel_panel_get_backlight(connector->base.dev, pipe); | ||
696 | } | 729 | } |
697 | 730 | ||
698 | static const struct backlight_ops intel_panel_bl_ops = { | 731 | static const struct backlight_ops intel_panel_bl_ops = { |
@@ -717,7 +750,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector) | |||
717 | props.brightness = dev_priv->backlight.level; | 750 | props.brightness = dev_priv->backlight.level; |
718 | 751 | ||
719 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); | 752 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
720 | props.max_brightness = intel_panel_get_max_backlight(dev); | 753 | props.max_brightness = intel_panel_get_max_backlight(dev, 0); |
721 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); | 754 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
722 | 755 | ||
723 | if (props.max_brightness == 0) { | 756 | if (props.max_brightness == 0) { |
@@ -726,7 +759,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector) | |||
726 | } | 759 | } |
727 | dev_priv->backlight.device = | 760 | dev_priv->backlight.device = |
728 | backlight_device_register("intel_backlight", | 761 | backlight_device_register("intel_backlight", |
729 | &connector->kdev, dev, | 762 | &connector->kdev, |
763 | to_intel_connector(connector), | ||
730 | &intel_panel_bl_ops, &props); | 764 | &intel_panel_bl_ops, &props); |
731 | 765 | ||
732 | if (IS_ERR(dev_priv->backlight.device)) { | 766 | if (IS_ERR(dev_priv->backlight.device)) { |