drm/i915/dsi: CABC support for Panel PWM backlight control
authorDeepak M <m.deepak@intel.com>
Tue, 26 Apr 2016 13:14:26 +0000 (16:14 +0300)
committerJani Nikula <jani.nikula@intel.com>
Tue, 17 May 2016 13:12:39 +0000 (16:12 +0300)
In CABC (Content Adaptive Brightness Control) content grey level
scale can be increased while simultaneously decreasing
brightness of the backlight to achieve same perceived brightness.

The CABC is not standardized and panel vendors are free to follow
their implementation. The CABC implementaion here assumes that the
panels use standard SW register for control.

CABC is supported only when the PWM source for backlight is
from the panel.

v2 by Jani: rebase, renames, check cabc support earlier, etc.

Signed-off-by: Deepak M <m.deepak@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/883faade74d2e598b143221ccc7df6daf4393a13.1461676337.git.jani.nikula@intel.com
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_dcs_backlight.c

index edb6bea870d6a27e509d9dafd31afbdb0057debe..4009618a5b34e3252c7ed125754a3d59f1d97eaf 100644 (file)
@@ -1489,11 +1489,28 @@ void intel_dsi_init(struct drm_device *dev)
                        intel_dsi->dcs_backlight_ports = BIT(PORT_A) | BIT(PORT_C);
                        break;
                }
+
+               switch (dev_priv->vbt.dsi.config->dl_dcs_cabc_ports) {
+               case DL_DCS_PORT_A:
+                       intel_dsi->dcs_cabc_ports = BIT(PORT_A);
+                       break;
+               case DL_DCS_PORT_C:
+                       intel_dsi->dcs_cabc_ports = BIT(PORT_C);
+                       break;
+               default:
+               case DL_DCS_PORT_A_AND_C:
+                       intel_dsi->dcs_cabc_ports = BIT(PORT_A) | BIT(PORT_C);
+                       break;
+               }
        } else {
                intel_dsi->ports = BIT(port);
                intel_dsi->dcs_backlight_ports = BIT(port);
+               intel_dsi->dcs_cabc_ports = BIT(port);
        }
 
+       if (!dev_priv->vbt.dsi.config->cabc_supported)
+               intel_dsi->dcs_cabc_ports = 0;
+
        /* Create a DSI host (and a device) for each port. */
        for_each_dsi_port(port, intel_dsi->ports) {
                struct intel_dsi_host *host;
index b00fb3fbb0b1c101f5c841c2da15baeffd0dcbd0..5967ea6d60450b55e83de1fd1bfafe183d8b3660 100644 (file)
@@ -80,6 +80,7 @@ struct intel_dsi {
        u8 dual_link;
 
        u16 dcs_backlight_ports;
+       u16 dcs_cabc_ports;
 
        u8 pixel_overlap;
        u32 port_bits;
index 7f9bbffa7f8c8a91efde6275ee282e3330d7d3b4..f0dc427743f869f2ba63c8fef892607b851633d1 100644 (file)
 #define CONTROL_DISPLAY_DD             (1 << 3)
 #define CONTROL_DISPLAY_BL             (1 << 2)
 
+#define POWER_SAVE_OFF                 (0 << 0)
+#define POWER_SAVE_LOW                 (1 << 0)
+#define POWER_SAVE_MEDIUM              (2 << 0)
+#define POWER_SAVE_HIGH                        (3 << 0)
+#define POWER_SAVE_OUTDOOR_MODE                (4 << 0)
+
 #define PANEL_PWM_MAX_VALUE            0xFF
 
 static u32 dcs_get_backlight(struct intel_connector *connector)
@@ -79,6 +85,14 @@ static void dcs_disable_backlight(struct intel_connector *connector)
 
        dcs_set_backlight(connector, 0);
 
+       for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
+               u8 cabc = POWER_SAVE_OFF;
+
+               dsi_device = intel_dsi->dsi_hosts[port]->device;
+               mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
+                                  &cabc, sizeof(cabc));
+       }
+
        for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
                u8 ctrl = 0;
 
@@ -120,6 +134,14 @@ static void dcs_enable_backlight(struct intel_connector *connector)
                                   &ctrl, sizeof(ctrl));
        }
 
+       for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
+               u8 cabc = POWER_SAVE_MEDIUM;
+
+               dsi_device = intel_dsi->dsi_hosts[port]->device;
+               mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
+                                  &cabc, sizeof(cabc));
+       }
+
        dcs_set_backlight(connector, panel->backlight.level);
 }