gfx: drv: Add support for CABC
authorAntti Koskipaa <antti.koskipaa@linux.intel.com>
Tue, 31 Jan 2012 15:12:39 +0000 (17:12 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:29:41 +0000 (12:29 +0300)
CABC (Content Adaptive Backlight Control) is a power saving technique
that is supported by the mfld tablet LCD panel.

Signed-off-by: Antti Koskipaa <antti.koskipaa@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/staging/mrst/drv/mdfld_dsi_output.c
drivers/staging/mrst/drv/tc35876x-dsi-lvds.c

index 6c1d677..148d25f 100644 (file)
 #include <linux/pm_runtime.h>
 #include <asm/intel_scu_ipc.h>
 
-/* get the CABC LABC from command line. */
-static int CABC_control = 1;
+/* get the LABC from command line. */
 static int LABC_control = 1;
 
 #ifdef MODULE
-module_param (CABC_control, int, 0644);
 module_param (LABC_control, int, 0644);
 #else
-static int __init parse_CABC_control(char *arg)
-{
-       /* CABC control can be passed in as a cmdline parameter */
-       /* to enable this feature add CABC=1 to cmdline */
-       /* to disable this feature add CABC=0 to cmdline */
-       if (!arg)
-               return -EINVAL;
-
-       if (!strcasecmp(arg, "0"))
-               CABC_control = 0;
-       else if (!strcasecmp (arg, "1"))
-               CABC_control = 1;
-
-       return 0;
-}
-early_param ("CABC", parse_CABC_control);
 
 static int __init parse_LABC_control(char *arg)
 {
@@ -184,7 +166,7 @@ void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
        
        /* Enable backlight or/and LABC */
        gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
-       if (LABC_control == 1 || CABC_control == 1)
+       if (LABC_control == 1)
                gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
 
        if (LABC_control == 1)
@@ -195,9 +177,6 @@ void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
        mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
                                1, true);
 
-       if (CABC_control == 0)
-               return;
-
        mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
 }
 
index 5398dcb..f153c31 100644 (file)
@@ -429,18 +429,30 @@ void tc35876x_brightness_control(struct drm_device *dev, int pipe,
 {
        int ret;
        u8 duty_val;
+       u8 panel_duty_val;
 
        level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
 
        /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
        duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
 
-       printk(KERN_DEBUG "[DISPLAY] %s: level = %d, duty_val = %d\n", __func__,
-              level, duty_val);
+       /* I won't pretend to understand this formula. The panel spec is quite
+        * bad engrish.
+        */
+       panel_duty_val = (2 * level - 100) * 0xA9 /
+                        MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
 
        ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
        if (ret)
                printk(KERN_ERR "[DISPLAY] %s: ipc write fail\n", __func__);
+
+       if (cmi_lcd_i2c_client) {
+               ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
+                                               PANEL_PWM_MAX, panel_duty_val);
+               if (ret < 0)
+                       printk(KERN_ERR "[DISPLAY] %s: i2c write failed\n",
+                              __func__);
+       }
 }
 
 void tc35876x_toshiba_bridge_panel_off(void)
@@ -478,14 +490,31 @@ void tc35876x_toshiba_bridge_panel_on(void)
        }
 
        if (cmi_lcd_i2c_client) {
-               int r;
-
-               dev_dbg(&cmi_lcd_i2c_client->dev, "bypass panel PWM\n");
-
-               r = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, 0x9b, 0x40);
-               if (r < 0)
+               int ret;
+               dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
+               /* Bit 4 is average_saving. Setting it to 1, the brightness is
+                * referenced to the average of the frame content. 0 means
+                * reference to the maximum of frame contents. Bits 3:0 are
+                * allow_distort. When set to a nonzero value, all color values
+                * between 255-allow_distort*2 and 255 are mapped to the
+                * 255-allow_distort*2 value.
+                */
+               ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
+                                               PANEL_ALLOW_DISTORT, 0x10);
+               if (ret < 0)
+                       dev_err(&cmi_lcd_i2c_client->dev,
+                               "i2c write failed (%d)\n", ret);
+               ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
+                                               PANEL_BYPASS_PWMI, 0);
+               if (ret < 0)
+                       dev_err(&cmi_lcd_i2c_client->dev,
+                               "i2c write failed (%d)\n", ret);
+               /* Set minimum brightness value - this is tunable */
+               ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
+                                               PANEL_PWM_MIN, 0x35);
+               if (ret < 0)
                        dev_err(&cmi_lcd_i2c_client->dev,
-                               "i2c write failed (%d)\n", r);
+                               "i2c write failed (%d)\n", ret);
        }
 
        if (pdata->gpio_panel_bl_en != -1)