From 7cf34db6a9ac4a56282600e6a87c5215beb522aa Mon Sep 17 00:00:00 2001 From: Antti Koskipaa Date: Tue, 31 Jan 2012 17:12:39 +0200 Subject: [PATCH] gfx: drv: Add support for CABC CABC (Content Adaptive Backlight Control) is a power saving technique that is supported by the mfld tablet LCD panel. Signed-off-by: Antti Koskipaa Signed-off-by: Kirill A. Shutemov --- drivers/staging/mrst/drv/mdfld_dsi_output.c | 25 ++------------- drivers/staging/mrst/drv/tc35876x-dsi-lvds.c | 47 ++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/drivers/staging/mrst/drv/mdfld_dsi_output.c b/drivers/staging/mrst/drv/mdfld_dsi_output.c index 6c1d677..148d25f6 100644 --- a/drivers/staging/mrst/drv/mdfld_dsi_output.c +++ b/drivers/staging/mrst/drv/mdfld_dsi_output.c @@ -34,30 +34,12 @@ #include #include -/* 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); } diff --git a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c index 5398dcb..f153c31 100644 --- a/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c +++ b/drivers/staging/mrst/drv/tc35876x-dsi-lvds.c @@ -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) -- 2.7.4