diff options
author | Roy Chiang <roy_chiang@htc.com> | 2010-06-10 14:29:52 -0700 |
---|---|---|
committer | Dima Zavin <dima@android.com> | 2011-01-04 18:10:15 -0800 |
commit | 434a9ebdd8acb63d9fe314b77be1cf8cbb36ecc7 (patch) | |
tree | 4d334dd771545bc20d76e96b1061c3d4e8948d69 | |
parent | c314fe2244c246801188595bd6c0e700b8bcf07c (diff) | |
download | experimental-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.c | 354 | ||||
-rw-r--r-- | arch/arm/mach-msm/board-mahimahi.h | 27 |
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 */ |