From ebad1765542d63fd873d62fb52ca9e150c9b6291 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 14 Aug 2013 11:27:40 -0500 Subject: [PATCH] rtd2132: implement full configuration It has been disseminated that the RTD2132 chip needs to be fully programmed for settings to take affect. Most of the settings are note documented very well and present themselves as magic values. Also, the wait time for starting the sequence needs to be bumped from 2ms to 60ms. Lastly, expose all the known settings through devicetree. Change-Id: I9eeea9c4a13ec20b8ce1c5297e43c4dd793d90e5 Signed-off-by: Aaron Durbin Reviewed-on: https://gerrit.chromium.org/gerrit/65857 Reviewed-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/4471 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/drivers/i2c/rtd2132/chip.h | 22 +++++ src/drivers/i2c/rtd2132/rtd2132.c | 158 ++++++++++++++++++++++++++---- 2 files changed, 159 insertions(+), 21 deletions(-) diff --git a/src/drivers/i2c/rtd2132/chip.h b/src/drivers/i2c/rtd2132/chip.h index 34ae91a3fe..2cf08270d3 100644 --- a/src/drivers/i2c/rtd2132/chip.h +++ b/src/drivers/i2c/rtd2132/chip.h @@ -18,6 +18,28 @@ */ struct drivers_i2c_rtd2132_config { + /* Panel Power Sequencing. All units in ms. */ + u16 t1; /* Delay from panel Vcc enable to LVDS output enable. */ + u16 t2; /* Delay from LVDS output enable to PWM output enable. */ + u16 t3; /* Delay from PWM output enable to backlight output enable. */ + u16 t4; /* Delay from backlight output disable to PWM output disable. */ + u16 t5; /* Delay from PWM output disable to LVDS output disable. */ + u16 t6; /* Delay from LVDS output disable to panel Vcc disable. */ + u16 t7; /* Delay between tweo panel power on/off sequence. */ + + /* + * LVDS swap. + * 0x00 - Normal + * 0x01 - Mirror + * 0x02 - P/N + * 0x03 - Mirror + P/N + * 0x04 - R/L + * + * Dual Support or in bit 7: + * 0x80 - Dual Swap + */ + u8 lvds_swap; + /* * LVDS Spread Spectrum Clock * 0x00 = DISABLED diff --git a/src/drivers/i2c/rtd2132/rtd2132.c b/src/drivers/i2c/rtd2132/rtd2132.c index a3470b0453..22a9f03108 100644 --- a/src/drivers/i2c/rtd2132/rtd2132.c +++ b/src/drivers/i2c/rtd2132/rtd2132.c @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ +#include #include #include #include @@ -31,6 +32,15 @@ #define RTD2132_FIRMWARE_START 0x00 #define RTD2132_FIRMWARE_STOP 0x01 +/* Panel Power Sequence Timing Registers. */ +#define RTD2132_COMMAND_PWR_SEQ_T1 0x32 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T2 0x33 /* 4ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T3 0x34 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T4 0x35 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T5 0x36 /* 4ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T6 0x37 /* 1ms units. */ +#define RTD2132_COMMAND_PWR_SEQ_T7 0x38 /* 4ms units. */ + /* Spread spectrum configuration */ #define RTD2132_COMMAND_SSCG_CONFIG_0 0x39 #define RTD2132_SSCG_ENABLE 0xa0 @@ -41,16 +51,42 @@ #define RTD2132_SSCG_CONFIG_1_0 0x0f /* 1.0% */ #define RTD2132_SSCG_CONFIG_1_5 0x16 /* 1.5% */ +/* LVDS Swap */ +#define RTD2132_COMMAND_LVDS_SWAP 0x3b +#define RTD2132_LVDS_SWAP_DUAL 0x80 +#define RTD2132_LVDS_SWAP_NORMAL 0x04 +#define RTD2132_LVDS_SWAP_MIRROR 0x14 +#define RTD2132_LVDS_SWAP_P_N 0x24 +#define RTD2132_LVDS_SWAP_MIRROR_P_N 0x34 +#define RTD2132_LVDS_SWAP_R_L 0x0c + /* Configuration values from devicetree */ #define RTD2132_SSCG_PERCENT_0_0 0x00 /* DISABLED */ #define RTD2132_SSCG_PERCENT_0_5 0x05 /* 0.5% */ #define RTD2132_SSCG_PERCENT_1_0 0x10 /* 1.0% */ #define RTD2132_SSCG_PERCENT_1_5 0x15 /* 1.5% */ +#define RTD2132_LVDS_SWAP_CFG_DUAL 0x80 +#define RTD2132_LVDS_SWAP_CFG_NORMAL 0x00 +#define RTD2132_LVDS_SWAP_CFG_MIRROR 0x01 +#define RTD2132_LVDS_SWAP_CFG_P_N 0x02 +#define RTD2132_LVDS_SWAP_CFG_MIRROR_P_N 0x03 +#define RTD2132_LVDS_SWAP_CFG_R_L 0x04 + +#define RTD2132_DEBUG_REG 0 + +static void rtd2132_write_reg(device_t dev, u8 reg, u8 value) +{ + if (RTD2132_DEBUG_REG) + printk(BIOS_DEBUG, "RTD2132 0x%02x <- 0x%02x\n", reg, value); + smbus_write_byte(dev, RTD2132_COMMAND, reg); + smbus_write_byte(dev, RTD2132_DATA, value); +} + static void rtd2132_firmware_stop(device_t dev) { smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_STOP); - mdelay(2); + mdelay(60); } static void rtd2132_firmware_start(device_t dev) @@ -58,40 +94,42 @@ static void rtd2132_firmware_start(device_t dev) smbus_write_byte(dev, RTD2132_FIRMWARE, RTD2132_FIRMWARE_START); } +static void rtd2132_pps(device_t dev, struct drivers_i2c_rtd2132_config *cfg) +{ + /* T2, T5, and T7 register values are in units of 4ms. */ + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T1, cfg->t1); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T2, cfg->t2 / 4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T3, cfg->t3); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T4, cfg->t4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T5, cfg->t5 / 4); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T6, cfg->t6); + rtd2132_write_reg(dev, RTD2132_COMMAND_PWR_SEQ_T7, cfg->t7 / 4); +} + static void rtd2132_sscg_enable(device_t dev, u8 sscg_percent) { /* SSCG_Config_0 */ - smbus_write_byte(dev, RTD2132_COMMAND, RTD2132_COMMAND_SSCG_CONFIG_0); - smbus_write_byte(dev, RTD2132_DATA, RTD2132_SSCG_ENABLE); + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0, + RTD2132_SSCG_ENABLE); /* SSCG_Config_1 */ - smbus_write_byte(dev, RTD2132_COMMAND, RTD2132_COMMAND_SSCG_CONFIG_1); - smbus_write_byte(dev, RTD2132_DATA, sscg_percent); + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1, sscg_percent); } static void rtd2132_sscg_disable(device_t dev) { /* SSCG_Config_0 */ - smbus_write_byte(dev, RTD2132_COMMAND, RTD2132_COMMAND_SSCG_CONFIG_0); - smbus_write_byte(dev, RTD2132_DATA, RTD2132_SSCG_DISABLE); + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_0, + RTD2132_SSCG_DISABLE); /* SSCG_Config_1 */ - smbus_write_byte(dev, RTD2132_COMMAND, RTD2132_COMMAND_SSCG_CONFIG_1); - smbus_write_byte(dev, RTD2132_DATA, RTD2132_SSCG_CONFIG_DISABLED); + rtd2132_write_reg(dev, RTD2132_COMMAND_SSCG_CONFIG_1, + RTD2132_SSCG_CONFIG_DISABLED); } -static void rtd2132_setup(device_t dev) +static void rtd2132_sscg(device_t dev, struct drivers_i2c_rtd2132_config *cfg) { - struct drivers_i2c_rtd2132_config *config = dev->chip_info; - - if (!config) - return; - - /* Stop running firmware */ - rtd2132_firmware_stop(dev); - - /* Spread spectrum configuration */ - switch (config->sscg_percent) { + switch (cfg->sscg_percent) { case RTD2132_SSCG_PERCENT_0_0: printk(BIOS_INFO, "RTD2132: Disable Spread Spectrum\n"); rtd2132_sscg_disable(dev); @@ -110,8 +148,86 @@ static void rtd2132_setup(device_t dev) break; default: printk(BIOS_ERR, "RTD2132: Invalid Spread Spectrum 0x%02x\n", - config->sscg_percent); + cfg->sscg_percent); } +} + +static void rtd2132_lvds_swap(device_t dev, + struct drivers_i2c_rtd2132_config *cfg) +{ + u8 swap_value = RTD2132_LVDS_SWAP_NORMAL; + + switch (cfg->lvds_swap & ~RTD2132_LVDS_SWAP_CFG_DUAL) { + case RTD2132_LVDS_SWAP_CFG_NORMAL: + swap_value = RTD2132_LVDS_SWAP_NORMAL; + break; + case RTD2132_LVDS_SWAP_CFG_MIRROR: + swap_value = RTD2132_LVDS_SWAP_MIRROR; + break; + case RTD2132_LVDS_SWAP_CFG_P_N: + swap_value = RTD2132_LVDS_SWAP_P_N; + break; + case RTD2132_LVDS_SWAP_CFG_MIRROR_P_N: + swap_value = RTD2132_LVDS_SWAP_MIRROR_P_N; + break; + case RTD2132_LVDS_SWAP_CFG_R_L: + swap_value = RTD2132_LVDS_SWAP_R_L; + break; + default: + printk(BIOS_ERR, "RTD2132: Invalid LVDS swap value 0x%02x\n", + cfg->lvds_swap); + } + + if (cfg->lvds_swap & RTD2132_LVDS_SWAP_CFG_DUAL) + swap_value |= RTD2132_LVDS_SWAP_DUAL; + + printk(BIOS_INFO, "RTD2132: LVDS Swap 0x%02x\n", swap_value);; + + rtd2132_write_reg(dev, RTD2132_COMMAND_LVDS_SWAP, swap_value); +} + +static void rtd2132_defaults(device_t dev) +{ + static const struct def_setting { + u8 reg; + u8 value; + } def_settings[] = { + { 0x3c, 0x06 }, + { 0x3d, 0x38 }, + { 0x3e, 0x73 }, + { 0x3f, 0x33 }, + { 0x06, 0x90 }, + { 0x06, 0xb0 }, + { 0x06, 0x80 }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(def_settings); i++) + rtd2132_write_reg(dev, def_settings[i].reg, + def_settings[i].value); +} + +static void rtd2132_setup(device_t dev) +{ + struct drivers_i2c_rtd2132_config *config = dev->chip_info; + + if (!config) + return; + + /* Stop running firmware */ + rtd2132_firmware_stop(dev); + + /* Panel Power Sequencing Settings. */ + rtd2132_pps(dev, config); + + /* Spread spectrum configuration */ + rtd2132_sscg(dev, config); + + /* LVDS Swap Setting. */ + rtd2132_lvds_swap(dev, config); + + /* Default settings. */ + rtd2132_defaults(dev); /* Start firmware */ rtd2132_firmware_start(dev);