aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Chiang <roy_chiang@htc.com>2010-06-10 14:29:52 -0700
committerDima Zavin <dima@android.com>2011-01-04 18:10:15 -0800
commit434a9ebdd8acb63d9fe314b77be1cf8cbb36ecc7 (patch)
tree4d334dd771545bc20d76e96b1061c3d4e8948d69
parentc314fe2244c246801188595bd6c0e700b8bcf07c (diff)
downloadexperimental-434a9ebdd8acb63d9fe314b77be1cf8cbb36ecc7.tar.gz
[ARM] mahimahi: add support for Sony TFT panel
Signed-off-by: Iliyan Malchev <malchev@google.com>
-rw-r--r--arch/arm/mach-msm/board-mahimahi-panel.c354
-rw-r--r--arch/arm/mach-msm/board-mahimahi.h27
2 files changed, 370 insertions, 11 deletions
diff --git a/arch/arm/mach-msm/board-mahimahi-panel.c b/arch/arm/mach-msm/board-mahimahi-panel.c
index a7dadcad2f2..64b66b7a37d 100644
--- a/arch/arm/mach-msm/board-mahimahi-panel.c
+++ b/arch/arm/mach-msm/board-mahimahi-panel.c
@@ -29,6 +29,8 @@
#include <mach/msm_fb.h>
#include <mach/msm_iomap.h>
+#include <mach/vreg.h>
+#include "proc_comm.h"
#include "board-mahimahi.h"
#include "devices.h"
@@ -43,6 +45,8 @@
static void __iomem *spi_base;
static struct clk *spi_clk ;
+static struct vreg *vreg_lcm_rftx_2v6;
+static struct vreg *vreg_lcm_aux_2v6;
static int qspi_send(uint32_t id, uint8_t data)
{
@@ -62,6 +66,24 @@ static int qspi_send(uint32_t id, uint8_t data)
return 0;
}
+static int qspi_send_9bit(uint32_t id, uint8_t data)
+{
+ uint32_t err;
+
+ while (readl(spi_base + SPI_OPERATIONAL) & (1<<5)) {
+ err = readl(spi_base + SPI_ERROR_FLAGS);
+ if (err) {
+ pr_err("%s: ERROR: SPI_ERROR_FLAGS=0x%08x\n", __func__,
+ err);
+ return -EIO;
+ }
+ }
+ writel(((id << 8) | data) << 23, spi_base + SPI_OUTPUT_FIFO);
+ udelay(100);
+
+ return 0;
+}
+
static int lcm_writeb(uint8_t reg, uint8_t val)
{
qspi_send(0x0, reg);
@@ -397,6 +419,15 @@ static struct lcm_tbl samsung_oled_gamma_table[][OLED_GAMMA_TABLE_SIZE] = {
SAMSUNG_OLED_MIN_VAL) / \
(SAMSUNG_OLED_NUM_LEVELS - 1))
+
+#define SONY_TFT_DEF_USER_VAL 102
+#define SONY_TFT_MIN_USER_VAL 30
+#define SONY_TFT_MAX_USER_VAL 255
+#define SONY_TFT_DEF_PANEL_VAL 155
+#define SONY_TFT_MIN_PANEL_VAL 26
+#define SONY_TFT_MAX_PANEL_VAL 255
+
+
static DEFINE_MUTEX(panel_lock);
static struct work_struct brightness_delayed_work;
static DEFINE_SPINLOCK(brightness_lock);
@@ -404,6 +435,8 @@ static uint8_t new_val = SAMSUNG_OLED_DEFAULT_VAL;
static uint8_t last_val = SAMSUNG_OLED_DEFAULT_VAL;
static uint8_t table_sel_vals[] = { 0x43, 0x34 };
static int table_sel_idx = 0;
+static uint8_t tft_panel_on;
+
static void gamma_table_bank_select(void)
{
lcm_writeb(0x39, table_sel_vals[table_sel_idx]);
@@ -514,13 +547,252 @@ static int samsung_oled_panel_blank(struct msm_lcdc_panel_ops *ops)
return 0;
}
-static struct msm_lcdc_panel_ops mahimahi_lcdc_panel_ops = {
+struct lcm_cmd {
+ int reg;
+ uint32_t val;
+ unsigned delay;
+};
+
+#define LCM_GPIO_CFG(gpio, func, str) \
+ PCOM_GPIO_CFG(gpio, func, GPIO_OUTPUT, GPIO_NO_PULL, str)
+
+static uint32_t sony_tft_display_on_gpio_table[] = {
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R1, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R2, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R3, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R4, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R5, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G0, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G1, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G2, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G3, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G4, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G5, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B1, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B2, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B3, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B4, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B5, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_PCLK, 1, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_VSYNC, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_HSYNC, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_DE, 1, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_CLK, 1, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_DO, 1, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_CSz, 1, GPIO_4MA),
+};
+
+static uint32_t sony_tft_display_off_gpio_table[] = {
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R1, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R2, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R3, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R4, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_R5, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G0, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G1, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G2, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G3, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G4, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_G5, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B1, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B2, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B3, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B4, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_B5, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_PCLK, 0, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_VSYNC, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_HSYNC, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_DE, 0, GPIO_8MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_CLK, 0, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_DO, 0, GPIO_4MA),
+ LCM_GPIO_CFG(MAHIMAHI_LCD_SPI_CSz, 0, GPIO_4MA),
+};
+
+#undef LCM_GPIO_CFG
+
+#define SONY_TFT_DEF_PANEL_DELTA \
+ (SONY_TFT_DEF_PANEL_VAL - SONY_TFT_MIN_PANEL_VAL)
+#define SONY_TFT_DEF_USER_DELTA \
+ (SONY_TFT_DEF_USER_VAL - SONY_TFT_MIN_USER_VAL)
+
+static void sony_tft_set_pwm_val(int val)
+{
+ pr_info("%s: %d\n", __func__, val);
+
+ last_val = val;
+
+ if (!tft_panel_on)
+ return;
+
+ if (val <= SONY_TFT_DEF_USER_VAL) {
+ if (val <= SONY_TFT_MIN_USER_VAL)
+ val = SONY_TFT_MIN_PANEL_VAL;
+ else
+ val = SONY_TFT_DEF_PANEL_DELTA *
+ (val - SONY_TFT_MIN_USER_VAL) /
+ SONY_TFT_DEF_USER_DELTA +
+ SONY_TFT_MIN_PANEL_VAL;
+ } else
+ val = (SONY_TFT_MAX_PANEL_VAL - SONY_TFT_DEF_PANEL_VAL) *
+ (val - SONY_TFT_DEF_USER_VAL) /
+ (SONY_TFT_MAX_USER_VAL - SONY_TFT_DEF_USER_VAL) +
+ SONY_TFT_DEF_PANEL_VAL;
+
+ clk_enable(spi_clk);
+ qspi_send_9bit(0x0, 0x51);
+ qspi_send_9bit(0x1, val);
+ qspi_send_9bit(0x0, 0x53);
+ qspi_send_9bit(0x1, 0x24);
+ clk_disable(spi_clk);
+}
+
+#undef SONY_TFT_DEF_PANEL_DELTA
+#undef SONY_TFT_DEF_USER_DELTA
+
+static void sony_tft_panel_config_gpio_table(uint32_t *table, int len)
+{
+ int n;
+ unsigned id;
+ for (n = 0; n < len; n++) {
+ id = table[n];
+ msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0);
+ }
+}
+
+
+static int sony_tft_panel_power(int on)
+{
+ unsigned id, on_off;
+
+ if (on) {
+ on_off = 0;
+
+ vreg_enable(vreg_lcm_aux_2v6);
+ vreg_enable(vreg_lcm_rftx_2v6);
+
+ id = PM_VREG_PDOWN_AUX_ID;
+ msm_proc_comm(PCOM_VREG_PULLDOWN, &on_off, &id);
+
+ id = PM_VREG_PDOWN_RFTX_ID;
+ msm_proc_comm(PCOM_VREG_PULLDOWN, &on_off, &id);
+ mdelay(10);
+ gpio_set_value(MAHIMAHI_GPIO_LCD_RST_N, 1);
+ mdelay(10);
+ gpio_set_value(MAHIMAHI_GPIO_LCD_RST_N, 0);
+ udelay(500);
+ gpio_set_value(MAHIMAHI_GPIO_LCD_RST_N, 1);
+ mdelay(10);
+ sony_tft_panel_config_gpio_table(
+ sony_tft_display_on_gpio_table,
+ ARRAY_SIZE(sony_tft_display_on_gpio_table));
+ } else {
+ on_off = 1;
+
+ gpio_set_value(MAHIMAHI_GPIO_LCD_RST_N, 0);
+
+ mdelay(120);
+
+ vreg_disable(vreg_lcm_rftx_2v6);
+ vreg_disable(vreg_lcm_aux_2v6);
+
+ id = PM_VREG_PDOWN_RFTX_ID;
+ msm_proc_comm(PCOM_VREG_PULLDOWN, &on_off, &id);
+
+ id = PM_VREG_PDOWN_AUX_ID;
+ msm_proc_comm(PCOM_VREG_PULLDOWN, &on_off, &id);
+ sony_tft_panel_config_gpio_table(
+ sony_tft_display_off_gpio_table,
+ ARRAY_SIZE(sony_tft_display_off_gpio_table));
+ }
+ return 0;
+}
+
+static int sony_tft_panel_init(struct msm_lcdc_panel_ops *ops)
+{
+ return 0;
+}
+
+static int sony_tft_panel_unblank(struct msm_lcdc_panel_ops *ops)
+{
+ pr_info("%s: +()\n", __func__);
+
+ mutex_lock(&panel_lock);
+
+ if (tft_panel_on) {
+ pr_info("%s: -() already unblanked\n", __func__);
+ goto done;
+ }
+
+ sony_tft_panel_power(1);
+ msleep(45);
+
+ clk_enable(spi_clk);
+ qspi_send_9bit(0x0, 0x11);
+ msleep(5);
+ qspi_send_9bit(0x0, 0x3a);
+ qspi_send_9bit(0x1, 0x05);
+ msleep(100);
+ qspi_send_9bit(0x0, 0x29);
+ /* unlock register page for pwm setting */
+ qspi_send_9bit(0x0, 0xf0);
+ qspi_send_9bit(0x1, 0x5a);
+ qspi_send_9bit(0x1, 0x5a);
+ qspi_send_9bit(0x0, 0xf1);
+ qspi_send_9bit(0x1, 0x5a);
+ qspi_send_9bit(0x1, 0x5a);
+ qspi_send_9bit(0x0, 0xd0);
+ qspi_send_9bit(0x1, 0x5a);
+ qspi_send_9bit(0x1, 0x5a);
+
+ qspi_send_9bit(0x0, 0xc2);
+ qspi_send_9bit(0x1, 0x53);
+ qspi_send_9bit(0x1, 0x12);
+ clk_disable(spi_clk);
+ msleep(100);
+ tft_panel_on = 1;
+ sony_tft_set_pwm_val(last_val);
+
+ pr_info("%s: -()\n", __func__);
+done:
+ mutex_unlock(&panel_lock);
+ return 0;
+}
+
+static int sony_tft_panel_blank(struct msm_lcdc_panel_ops *ops)
+{
+ pr_info("%s: +()\n", __func__);
+
+ mutex_lock(&panel_lock);
+
+ clk_enable(spi_clk);
+ qspi_send_9bit(0x0, 0x28);
+ qspi_send_9bit(0x0, 0x10);
+ clk_disable(spi_clk);
+
+ msleep(40);
+ sony_tft_panel_power(0);
+ tft_panel_on = 0;
+
+ mutex_unlock(&panel_lock);
+
+ pr_info("%s: -()\n", __func__);
+ return 0;
+}
+
+static struct msm_lcdc_panel_ops mahimahi_lcdc_amoled_panel_ops = {
.init = samsung_oled_panel_init,
.blank = samsung_oled_panel_blank,
.unblank = samsung_oled_panel_unblank,
};
-static struct msm_lcdc_timing mahimahi_lcdc_timing = {
+static struct msm_lcdc_panel_ops mahimahi_lcdc_tft_panel_ops = {
+ .init = sony_tft_panel_init,
+ .blank = sony_tft_panel_blank,
+ .unblank = sony_tft_panel_unblank,
+};
+
+
+static struct msm_lcdc_timing mahimahi_lcdc_amoled_timing = {
.clk_rate = 24576000,
.hsync_pulse_width = 4,
.hsync_back_porch = 8,
@@ -534,6 +806,20 @@ static struct msm_lcdc_timing mahimahi_lcdc_timing = {
.den_act_low = 1,
};
+static struct msm_lcdc_timing mahimahi_lcdc_tft_timing = {
+ .clk_rate = 24576000,
+ .hsync_pulse_width = 2,
+ .hsync_back_porch = 20,
+ .hsync_front_porch = 20,
+ .hsync_skew = 0,
+ .vsync_pulse_width = 2,
+ .vsync_back_porch = 6,
+ .vsync_front_porch = 4,
+ .vsync_act_low = 1,
+ .hsync_act_low = 1,
+ .den_act_low = 0,
+};
+
static struct msm_fb_data mahimahi_lcdc_fb_data = {
.xres = 480,
.yres = 800,
@@ -542,19 +828,35 @@ static struct msm_fb_data mahimahi_lcdc_fb_data = {
.output_format = MSM_MDP_OUT_IF_FMT_RGB565,
};
-static struct msm_lcdc_platform_data mahimahi_lcdc_platform_data = {
- .panel_ops = &mahimahi_lcdc_panel_ops,
- .timing = &mahimahi_lcdc_timing,
+static struct msm_lcdc_platform_data mahimahi_lcdc_amoled_platform_data = {
+ .panel_ops = &mahimahi_lcdc_amoled_panel_ops,
+ .timing = &mahimahi_lcdc_amoled_timing,
+ .fb_id = 0,
+ .fb_data = &mahimahi_lcdc_fb_data,
+ .fb_resource = &resources_msm_fb[0],
+};
+
+static struct msm_lcdc_platform_data mahimahi_lcdc_tft_platform_data = {
+ .panel_ops = &mahimahi_lcdc_tft_panel_ops,
+ .timing = &mahimahi_lcdc_tft_timing,
.fb_id = 0,
.fb_data = &mahimahi_lcdc_fb_data,
.fb_resource = &resources_msm_fb[0],
};
-static struct platform_device mahimahi_lcdc_device = {
+static struct platform_device mahimahi_lcdc_amoled_device = {
+ .name = "msm_mdp_lcdc",
+ .id = -1,
+ .dev = {
+ .platform_data = &mahimahi_lcdc_amoled_platform_data,
+ },
+};
+
+static struct platform_device mahimahi_lcdc_tft_device = {
.name = "msm_mdp_lcdc",
.id = -1,
.dev = {
- .platform_data = &mahimahi_lcdc_platform_data,
+ .platform_data = &mahimahi_lcdc_tft_platform_data,
},
};
@@ -604,7 +906,7 @@ static void mahimahi_brightness_set(struct led_classdev *led_cdev,
schedule_work(&brightness_delayed_work);
}
-static void mahimahi_brightness_set_work(struct work_struct *work_ptr)
+static void mahimahi_brightness_amoled_set_work(struct work_struct *work_ptr)
{
unsigned long flags;
uint8_t val;
@@ -618,6 +920,20 @@ static void mahimahi_brightness_set_work(struct work_struct *work_ptr)
mutex_unlock(&panel_lock);
}
+static void mahimahi_brightness_tft_set_work(struct work_struct *work_ptr)
+{
+ unsigned long flags;
+ uint8_t val;
+
+ spin_lock_irqsave(&brightness_lock, flags);
+ val = new_val;
+ spin_unlock_irqrestore(&brightness_lock, flags);
+
+ mutex_lock(&panel_lock);
+ sony_tft_set_pwm_val(val);
+ mutex_unlock(&panel_lock);
+}
+
static struct led_classdev mahimahi_brightness_led = {
.name = "lcd-backlight",
.brightness = LED_FULL,
@@ -646,9 +962,27 @@ int __init mahimahi_init_panel(void)
if (ret != 0)
return ret;
- INIT_WORK(&brightness_delayed_work, mahimahi_brightness_set_work);
+ if (gpio_get_value(MAHIMAHI_GPIO_LCD_ID0)) {
+ pr_info("%s: tft panel\n", __func__);
+ vreg_lcm_rftx_2v6 = vreg_get(0, "rftx");
+ if (IS_ERR(vreg_lcm_rftx_2v6))
+ return PTR_ERR(vreg_lcm_rftx_2v6);
+ vreg_set_level(vreg_lcm_rftx_2v6, 2600);
+
+ vreg_lcm_aux_2v6 = vreg_get(0, "gp4");
+ if (IS_ERR(vreg_lcm_aux_2v6))
+ return PTR_ERR(vreg_lcm_aux_2v6);
+
+ if (gpio_get_value(MAHIMAHI_GPIO_LCD_RST_N))
+ tft_panel_on = 1;
+ ret = platform_device_register(&mahimahi_lcdc_tft_device);
+ INIT_WORK(&brightness_delayed_work, mahimahi_brightness_tft_set_work);
+ } else {
+ pr_info("%s: amoled panel\n", __func__);
+ ret = platform_device_register(&mahimahi_lcdc_amoled_device);
+ INIT_WORK(&brightness_delayed_work, mahimahi_brightness_amoled_set_work);
+ }
- ret = platform_device_register(&mahimahi_lcdc_device);
if (ret != 0)
return ret;
diff --git a/arch/arm/mach-msm/board-mahimahi.h b/arch/arm/mach-msm/board-mahimahi.h
index db810129a5a..9696a47c400 100644
--- a/arch/arm/mach-msm/board-mahimahi.h
+++ b/arch/arm/mach-msm/board-mahimahi.h
@@ -126,6 +126,7 @@
#define MAHIMAHI_GPIO_LED_3V3_EN 85
#define MAHIMAHI_GPIO_LCD_RST_N 29
+#define MAHIMAHI_GPIO_LCD_ID0 147
/* 3.5mm remote control key interrupt shutdown signal */
#define MAHIMAHI_GPIO_35MM_KEY_INT_SHUTDOWN 19
@@ -144,7 +145,31 @@
#define MAHIMAHI_CDMA_SD_2V85_EN 100
#define MAHIMAHI_CDMA_JOG_2V6_EN 150
-
+/* display relative */
+#define MAHIMAHI_LCD_SPI_CLK (17)
+#define MAHIMAHI_LCD_SPI_DO (18)
+#define MAHIMAHI_LCD_SPI_CSz (20)
+#define MAHIMAHI_LCD_RSTz (29)
+#define MAHIMAHI_LCD_R1 (114)
+#define MAHIMAHI_LCD_R2 (115)
+#define MAHIMAHI_LCD_R3 (116)
+#define MAHIMAHI_LCD_R4 (117)
+#define MAHIMAHI_LCD_R5 (118)
+#define MAHIMAHI_LCD_G0 (121)
+#define MAHIMAHI_LCD_G1 (122)
+#define MAHIMAHI_LCD_G2 (123)
+#define MAHIMAHI_LCD_G3 (124)
+#define MAHIMAHI_LCD_G4 (125)
+#define MAHIMAHI_LCD_G5 (126)
+#define MAHIMAHI_LCD_B1 (130)
+#define MAHIMAHI_LCD_B2 (131)
+#define MAHIMAHI_LCD_B3 (132)
+#define MAHIMAHI_LCD_B4 (133)
+#define MAHIMAHI_LCD_B5 (134)
+#define MAHIMAHI_LCD_PCLK (135)
+#define MAHIMAHI_LCD_VSYNC (136)
+#define MAHIMAHI_LCD_HSYNC (137)
+#define MAHIMAHI_LCD_DE (138)
#define is_cdma_version(rev) (((rev) & 0xF0) == 0xC0)
#endif /* __ARCH_ARM_MACH_MSM_BOARD_MAHIMAHI_H */