diff options
| author | Shobhit Kumar <shobhit.kumar@intel.com> | 2015-06-26 05:02:10 -0400 |
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-07-21 03:22:48 -0400 |
| commit | b029e66fa8e39ba10dcc47b114be8da8b082493b (patch) | |
| tree | e488953f5d4bd24a9bfa75427f32e1f1f442c389 | |
| parent | fc45e821990781c13dba10e3aef1c9f11af8af08 (diff) | |
drm/i915: Backlight control using CRC PMIC based PWM driver
Use the CRC PWM device in intel_panel.c and add new MIPI backlight
specififc callbacks
v2: Modify to use pwm_config callback
v3: Addressed Jani's comments
- Renamed all function as pwm_* instead of vlv_*
- Call intel_panel_actually_set_backlight in enable function
- Return -ENODEV in case pwm_get fails
- in case pwm_config error return error cdoe from pwm_config
- Cleanup pwm in intel_panel_destroy_backlight
v4: Removed unused #defines and initialized backlight with INVALID_PIPE (Ville)
CC: Samuel Ortiz <sameo@linux.intel.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dsi.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 94 |
3 files changed, 98 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 105928382e21..286127001c43 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -182,6 +182,10 @@ struct intel_panel { | |||
| 182 | bool enabled; | 182 | bool enabled; |
| 183 | bool combination_mode; /* gen 2/4 only */ | 183 | bool combination_mode; /* gen 2/4 only */ |
| 184 | bool active_low_pwm; | 184 | bool active_low_pwm; |
| 185 | |||
| 186 | /* PWM chip */ | ||
| 187 | struct pwm_device *pwm; | ||
| 188 | |||
| 185 | struct backlight_device *device; | 189 | struct backlight_device *device; |
| 186 | } backlight; | 190 | } backlight; |
| 187 | 191 | ||
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index c4db74a5e4e7..892b936e14d4 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c | |||
| @@ -402,6 +402,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder) | |||
| 402 | 402 | ||
| 403 | intel_dsi_port_enable(encoder); | 403 | intel_dsi_port_enable(encoder); |
| 404 | } | 404 | } |
| 405 | |||
| 406 | intel_panel_enable_backlight(intel_dsi->attached_connector); | ||
| 405 | } | 407 | } |
| 406 | 408 | ||
| 407 | static void intel_dsi_pre_enable(struct intel_encoder *encoder) | 409 | static void intel_dsi_pre_enable(struct intel_encoder *encoder) |
| @@ -466,6 +468,8 @@ static void intel_dsi_pre_disable(struct intel_encoder *encoder) | |||
| 466 | 468 | ||
| 467 | DRM_DEBUG_KMS("\n"); | 469 | DRM_DEBUG_KMS("\n"); |
| 468 | 470 | ||
| 471 | intel_panel_disable_backlight(intel_dsi->attached_connector); | ||
| 472 | |||
| 469 | if (is_vid_mode(intel_dsi)) { | 473 | if (is_vid_mode(intel_dsi)) { |
| 470 | /* Send Shutdown command to the panel in LP mode */ | 474 | /* Send Shutdown command to the panel in LP mode */ |
| 471 | for_each_dsi_port(port, intel_dsi->ports) | 475 | for_each_dsi_port(port, intel_dsi->ports) |
| @@ -1132,6 +1136,7 @@ void intel_dsi_init(struct drm_device *dev) | |||
| 1132 | } | 1136 | } |
| 1133 | 1137 | ||
| 1134 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); | 1138 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); |
| 1139 | intel_panel_setup_backlight(connector, INVALID_PIPE); | ||
| 1135 | 1140 | ||
| 1136 | return; | 1141 | return; |
| 1137 | 1142 | ||
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 55aad2322e10..e2ab3f6ed022 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -32,8 +32,11 @@ | |||
| 32 | 32 | ||
| 33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
| 34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
| 35 | #include <linux/pwm.h> | ||
| 35 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
| 36 | 37 | ||
| 38 | #define CRC_PMIC_PWM_PERIOD_NS 21333 | ||
| 39 | |||
| 37 | void | 40 | void |
| 38 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, | 41 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
| 39 | struct drm_display_mode *adjusted_mode) | 42 | struct drm_display_mode *adjusted_mode) |
| @@ -544,6 +547,15 @@ static u32 bxt_get_backlight(struct intel_connector *connector) | |||
| 544 | return I915_READ(BXT_BLC_PWM_DUTY1); | 547 | return I915_READ(BXT_BLC_PWM_DUTY1); |
| 545 | } | 548 | } |
| 546 | 549 | ||
| 550 | static u32 pwm_get_backlight(struct intel_connector *connector) | ||
| 551 | { | ||
| 552 | struct intel_panel *panel = &connector->panel; | ||
| 553 | int duty_ns; | ||
| 554 | |||
| 555 | duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); | ||
| 556 | return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); | ||
| 557 | } | ||
| 558 | |||
| 547 | static u32 intel_panel_get_backlight(struct intel_connector *connector) | 559 | static u32 intel_panel_get_backlight(struct intel_connector *connector) |
| 548 | { | 560 | { |
| 549 | struct drm_device *dev = connector->base.dev; | 561 | struct drm_device *dev = connector->base.dev; |
| @@ -632,6 +644,14 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) | |||
| 632 | I915_WRITE(BXT_BLC_PWM_DUTY1, level); | 644 | I915_WRITE(BXT_BLC_PWM_DUTY1, level); |
| 633 | } | 645 | } |
| 634 | 646 | ||
| 647 | static void pwm_set_backlight(struct intel_connector *connector, u32 level) | ||
| 648 | { | ||
| 649 | struct intel_panel *panel = &connector->panel; | ||
| 650 | int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); | ||
| 651 | |||
| 652 | pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); | ||
| 653 | } | ||
| 654 | |||
| 635 | static void | 655 | static void |
| 636 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) | 656 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
| 637 | { | 657 | { |
| @@ -769,6 +789,16 @@ static void bxt_disable_backlight(struct intel_connector *connector) | |||
| 769 | I915_WRITE(BXT_BLC_PWM_CTL1, tmp & ~BXT_BLC_PWM_ENABLE); | 789 | I915_WRITE(BXT_BLC_PWM_CTL1, tmp & ~BXT_BLC_PWM_ENABLE); |
| 770 | } | 790 | } |
| 771 | 791 | ||
| 792 | static void pwm_disable_backlight(struct intel_connector *connector) | ||
| 793 | { | ||
| 794 | struct intel_panel *panel = &connector->panel; | ||
| 795 | |||
| 796 | /* Disable the backlight */ | ||
| 797 | pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); | ||
| 798 | usleep_range(2000, 3000); | ||
| 799 | pwm_disable(panel->backlight.pwm); | ||
| 800 | } | ||
| 801 | |||
| 772 | void intel_panel_disable_backlight(struct intel_connector *connector) | 802 | void intel_panel_disable_backlight(struct intel_connector *connector) |
| 773 | { | 803 | { |
| 774 | struct drm_device *dev = connector->base.dev; | 804 | struct drm_device *dev = connector->base.dev; |
| @@ -1010,6 +1040,14 @@ static void bxt_enable_backlight(struct intel_connector *connector) | |||
| 1010 | I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); | 1040 | I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); |
| 1011 | } | 1041 | } |
| 1012 | 1042 | ||
| 1043 | static void pwm_enable_backlight(struct intel_connector *connector) | ||
| 1044 | { | ||
| 1045 | struct intel_panel *panel = &connector->panel; | ||
| 1046 | |||
| 1047 | pwm_enable(panel->backlight.pwm); | ||
| 1048 | intel_panel_actually_set_backlight(connector, panel->backlight.level); | ||
| 1049 | } | ||
| 1050 | |||
| 1013 | void intel_panel_enable_backlight(struct intel_connector *connector) | 1051 | void intel_panel_enable_backlight(struct intel_connector *connector) |
| 1014 | { | 1052 | { |
| 1015 | struct drm_device *dev = connector->base.dev; | 1053 | struct drm_device *dev = connector->base.dev; |
| @@ -1386,6 +1424,40 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
| 1386 | return 0; | 1424 | return 0; |
| 1387 | } | 1425 | } |
| 1388 | 1426 | ||
| 1427 | static int pwm_setup_backlight(struct intel_connector *connector, | ||
| 1428 | enum pipe pipe) | ||
| 1429 | { | ||
| 1430 | struct drm_device *dev = connector->base.dev; | ||
| 1431 | struct intel_panel *panel = &connector->panel; | ||
| 1432 | int retval; | ||
| 1433 | |||
| 1434 | /* Get the PWM chip for backlight control */ | ||
| 1435 | panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); | ||
| 1436 | if (IS_ERR(panel->backlight.pwm)) { | ||
| 1437 | DRM_ERROR("Failed to own the pwm chip\n"); | ||
| 1438 | panel->backlight.pwm = NULL; | ||
| 1439 | return -ENODEV; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, | ||
| 1443 | CRC_PMIC_PWM_PERIOD_NS); | ||
| 1444 | if (retval < 0) { | ||
| 1445 | DRM_ERROR("Failed to configure the pwm chip\n"); | ||
| 1446 | pwm_put(panel->backlight.pwm); | ||
| 1447 | panel->backlight.pwm = NULL; | ||
| 1448 | return retval; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | panel->backlight.min = 0; /* 0% */ | ||
| 1452 | panel->backlight.max = 100; /* 100% */ | ||
| 1453 | panel->backlight.level = DIV_ROUND_UP( | ||
| 1454 | pwm_get_duty_cycle(panel->backlight.pwm) * 100, | ||
| 1455 | CRC_PMIC_PWM_PERIOD_NS); | ||
| 1456 | panel->backlight.enabled = panel->backlight.level != 0; | ||
| 1457 | |||
| 1458 | return 0; | ||
| 1459 | } | ||
| 1460 | |||
| 1389 | int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) | 1461 | int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) |
| 1390 | { | 1462 | { |
| 1391 | struct drm_device *dev = connector->dev; | 1463 | struct drm_device *dev = connector->dev; |
| @@ -1429,6 +1501,10 @@ void intel_panel_destroy_backlight(struct drm_connector *connector) | |||
| 1429 | struct intel_connector *intel_connector = to_intel_connector(connector); | 1501 | struct intel_connector *intel_connector = to_intel_connector(connector); |
| 1430 | struct intel_panel *panel = &intel_connector->panel; | 1502 | struct intel_panel *panel = &intel_connector->panel; |
| 1431 | 1503 | ||
| 1504 | /* dispose of the pwm */ | ||
| 1505 | if (panel->backlight.pwm) | ||
| 1506 | pwm_put(panel->backlight.pwm); | ||
| 1507 | |||
| 1432 | panel->backlight.present = false; | 1508 | panel->backlight.present = false; |
| 1433 | } | 1509 | } |
| 1434 | 1510 | ||
| @@ -1456,11 +1532,19 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) | |||
| 1456 | dev_priv->display.set_backlight = pch_set_backlight; | 1532 | dev_priv->display.set_backlight = pch_set_backlight; |
| 1457 | dev_priv->display.get_backlight = pch_get_backlight; | 1533 | dev_priv->display.get_backlight = pch_get_backlight; |
| 1458 | } else if (IS_VALLEYVIEW(dev)) { | 1534 | } else if (IS_VALLEYVIEW(dev)) { |
| 1459 | dev_priv->display.setup_backlight = vlv_setup_backlight; | 1535 | if (dev_priv->vbt.has_mipi) { |
| 1460 | dev_priv->display.enable_backlight = vlv_enable_backlight; | 1536 | dev_priv->display.setup_backlight = pwm_setup_backlight; |
| 1461 | dev_priv->display.disable_backlight = vlv_disable_backlight; | 1537 | dev_priv->display.enable_backlight = pwm_enable_backlight; |
| 1462 | dev_priv->display.set_backlight = vlv_set_backlight; | 1538 | dev_priv->display.disable_backlight = pwm_disable_backlight; |
| 1463 | dev_priv->display.get_backlight = vlv_get_backlight; | 1539 | dev_priv->display.set_backlight = pwm_set_backlight; |
| 1540 | dev_priv->display.get_backlight = pwm_get_backlight; | ||
| 1541 | } else { | ||
| 1542 | dev_priv->display.setup_backlight = vlv_setup_backlight; | ||
| 1543 | dev_priv->display.enable_backlight = vlv_enable_backlight; | ||
| 1544 | dev_priv->display.disable_backlight = vlv_disable_backlight; | ||
| 1545 | dev_priv->display.set_backlight = vlv_set_backlight; | ||
| 1546 | dev_priv->display.get_backlight = vlv_get_backlight; | ||
| 1547 | } | ||
| 1464 | } else if (IS_GEN4(dev)) { | 1548 | } else if (IS_GEN4(dev)) { |
| 1465 | dev_priv->display.setup_backlight = i965_setup_backlight; | 1549 | dev_priv->display.setup_backlight = i965_setup_backlight; |
| 1466 | dev_priv->display.enable_backlight = i965_enable_backlight; | 1550 | dev_priv->display.enable_backlight = i965_enable_backlight; |
