summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/i2c/rtd2132/chip.h22
-rw-r--r--src/drivers/i2c/rtd2132/rtd2132.c158
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 <stdlib.h>
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
@@ -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,9 +148,87 @@ 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);
}