summaryrefslogtreecommitdiff
path: root/drivers/video/sprdfb/lcd/lcd_hx8369.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sprdfb/lcd/lcd_hx8369.c')
-rw-r--r--drivers/video/sprdfb/lcd/lcd_hx8369.c391
1 files changed, 391 insertions, 0 deletions
diff --git a/drivers/video/sprdfb/lcd/lcd_hx8369.c b/drivers/video/sprdfb/lcd/lcd_hx8369.c
new file mode 100644
index 00000000..5c143a9a
--- /dev/null
+++ b/drivers/video/sprdfb/lcd/lcd_hx8369.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2012 Spreadtrum Communications Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "lcdpanel.h"
+
+static int32_t hx8369_init(struct panel_spec *self)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ /* SET password */
+ send_cmd(0xB9);
+ send_data(0xFF);
+ send_data(0x83);
+ send_data(0x69);
+
+ /* Set Power */
+ send_cmd(0xB1);
+ send_data(0x9D);
+ send_data(0x00);
+ send_data(0x34);
+ send_data(0x07);
+ send_data(0x00);
+ send_data(0x0B);
+ send_data(0x0B);
+ send_data(0x1A);
+ send_data(0x22);
+ send_data(0x3F);
+ send_data(0x3F);
+ send_data(0x01);
+ send_data(0x23);
+ send_data(0x01);
+ send_data(0xE6);
+ send_data(0xE6);
+ send_data(0xE6);
+ send_data(0xE6);
+ send_data(0xE6);
+
+ /* SET Display 480x800 */
+ send_cmd(0xB2);
+ send_data(0x00);
+ send_data(0x20);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x70);
+ send_data(0x00);
+ send_data(0xFF);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x00);
+ send_data(0x01);
+
+ /* SET Display 480x800 */
+ send_cmd(0xB4);
+ send_data(0x00);
+ send_data(0x18);
+ send_data(0x80);
+ send_data(0x06);
+ send_data(0x02);
+
+ /* OSC */
+ send_cmd(0xB0);
+ send_data(0x00);
+ send_data(0x09); /*05 42HZ 07 50HZ 0B 100% 67HZ */
+
+ /* SET VCOM */
+ send_cmd(0xB6);
+ send_data(0x4A);
+ send_data(0x4A);
+
+ /* SET GIP */
+ send_cmd(0xD5);
+ send_data(0x00);
+ send_data(0x03);
+ send_data(0x03);
+ send_data(0x00);
+ send_data(0x01);
+ send_data(0x02);
+
+ send_data(0x28);
+ send_data(0x70);
+ send_data(0x11);
+ send_data(0x13);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x40);
+ send_data(0x06);
+ send_data(0x51);
+ send_data(0x07);
+ send_data(0x00);
+ send_data(0x00);
+ send_data(0x41);
+ send_data(0x06);
+ send_data(0x50);
+ send_data(0x07);
+ send_data(0x07);
+ send_data(0x0F);
+ send_data(0x04);
+ send_data(0x00);
+
+ /* Set Gamma */
+ send_cmd(0xE0);
+ send_data(0x00);
+ send_data(0x01);
+ send_data(0x04);
+ send_data(0x23);
+ send_data(0x22);
+ send_data(0x3F);
+ send_data(0x13);
+ send_data(0x39);
+ send_data(0x06);
+ send_data(0x0B);
+ send_data(0x0E);
+ send_data(0x12);
+ send_data(0x15);
+ send_data(0x13);
+ send_data(0x15);
+ send_data(0x13);
+ send_data(0x1B);
+ send_data(0x00);
+ send_data(0x01);
+ send_data(0x04);
+ send_data(0x23);
+ send_data(0x22);
+ send_data(0x3F);
+ send_data(0x13);
+ send_data(0x39);
+ send_data(0x06);
+ send_data(0x0B);
+ send_data(0x0E);
+ send_data(0x12);
+ send_data(0x15);
+ send_data(0x13);
+ send_data(0x15);
+ send_data(0x13);
+ send_data(0x1B);
+ send_cmd(0x35); /* TE on*/
+ send_data(0x00);
+
+ /* set CSEL */
+ send_cmd(0x3A);
+ send_data(0x07); /* CSEL=0x06, 16bit-color CSEL=0x06, 18bit-color CSEL=0x07, 24bit-color */
+
+ /*24 bit don't need to set 2DH*/
+
+ /* Sleep Out */
+ send_cmd(0x11);
+
+ LCD_DelayMS(120);
+
+ #if 0
+ { /* for test the lcd */
+ int i;
+
+ send_cmd(0x2C); //Write data
+ for (i = 0; i < 480*800/3; i++)
+ send_data(0xff);
+ for (i = 0; i < 480*800/3; i++)
+ send_data(0xff00);
+ for (i = 0; i < 480*800/3; i++)
+ send_data(0xff0000);
+ }
+ #endif
+ /* Display On */
+ send_cmd(0x29);
+
+ LCD_DelayMS (120);
+
+ /* Write data */
+ send_cmd(0x2C);
+
+ return 0;
+}
+
+static int32_t hx8369_set_window(struct panel_spec *self,
+ uint16_t left, uint16_t top, uint16_t right, uint16_t bottom)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ pr_debug("hx8369_set_window:%d, %d, %d, %d\n", left, top, right, bottom);
+
+ /* col */
+ send_cmd(0x2A);
+ send_data((left >> 8));
+ send_data((left & 0xFF));
+ send_data((right >> 8));
+ send_data((right & 0xFF));
+
+ /* row */
+ send_cmd(0x2B);
+ send_data((top >> 8));
+ send_data((top & 0xFF));
+ send_data((bottom >> 8));
+ send_data((bottom & 0xFF));
+
+ /* Write data */
+ send_cmd(0x2C);
+
+ return 0;
+}
+
+
+static int32_t hx8369_invalidate(struct panel_spec *self)
+{
+
+ return self->ops->panel_set_window(self, 0, 0,
+ self->width-1, self->height-1);
+
+}
+
+static int32_t hx8369_invalidate_rect(struct panel_spec *self,
+ uint16_t left, uint16_t top,
+ uint16_t right, uint16_t bottom)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ pr_debug("hx8369_invalidate_rect\n");
+
+ /* TE scanline */
+ send_cmd(0x44);
+ send_data((top >> 8));
+ send_data((top & 0xFF));
+
+ return self->ops->panel_set_window(self, left, top,
+ right, bottom);
+}
+
+static int32_t hx8369_set_direction(struct panel_spec *self, uint16_t direction)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+
+ pr_debug("hx8369_set_direction\n");
+ send_cmd(0x36);
+
+ switch (direction) {
+ case LCD_DIRECT_NORMAL:
+ send_data(0);
+ break;
+ case LCD_DIRECT_ROT_90:
+ send_data(0xA0);
+ break;
+ case LCD_DIRECT_ROT_180:
+ send_data(0x60);
+ break;
+ case LCD_DIRECT_ROT_270:
+ send_data(0xB0);
+ break;
+ case LCD_DIRECT_MIR_H:
+ send_data(0x40);
+ break;
+ case LCD_DIRECT_MIR_V:
+ send_data(0x10);
+ break;
+ case LCD_DIRECT_MIR_HV:
+ send_data(0xE0);
+ break;
+ default:
+ pr_debug("unknown lcd direction!\n");
+ send_data(0x0);
+ direction = LCD_DIRECT_NORMAL;
+ break;
+ }
+
+ self->direction = direction;
+
+ return 0;
+}
+
+static int32_t hx8369_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+
+ if(is_sleep) {
+ /* Sleep In */
+ send_cmd(0x28);
+ LCD_DelayMS(120);
+ send_cmd(0x10);
+ LCD_DelayMS(120);
+ }
+ else {
+#if 1
+ /* Sleep Out */
+ send_cmd(0x11);
+ LCD_DelayMS(120);
+ send_cmd(0x29);
+ LCD_DelayMS(120);
+#else
+ /* re init */
+ se1f->ops->reset(self);
+ se1f->ops->lcd_init(self);
+#endif
+ }
+ return 0;
+}
+
+static uint32_t hx8369_read_id(struct panel_spec *self)
+{
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ send_data_t send_data = self->info.mcu->ops->send_data;
+ read_data_t read_data = self->info.mcu->ops->read_data;
+
+ send_cmd(0xB9);
+ send_data(0xFF);
+ send_data(0x83);
+ send_data(0x69);
+
+ send_cmd(0xF4);
+ read_data();
+ return read_data();
+}
+
+static struct panel_operations lcd_hx8369_operations = {
+ .panel_init = hx8369_init,
+ .panel_set_window = hx8369_set_window,
+ .panel_invalidate = hx8369_invalidate,
+ .panel_invalidate_rect = hx8369_invalidate_rect,
+ .panel_set_direction = hx8369_set_direction,
+ .panel_enter_sleep = hx8369_enter_sleep,
+ .panel_readid = hx8369_read_id,
+};
+
+static struct timing_mcu lcd_hx8369_timing[] = {
+[LCD_REGISTER_TIMING] = { /* read/write register timing (ns) */
+ .rcss = 25, /* 25 ns */
+ .rlpw = 70,
+ .rhpw = 70,
+ .wcss = 10,
+ .wlpw = 50,
+ .whpw = 50,
+ },
+[LCD_GRAM_TIMING] = { /* read/write gram timing (ns) */
+ .rcss = 25,
+ .rlpw = 70,
+ .rhpw = 70,
+ .wcss = 0,
+ .wlpw = 15,
+ .whpw = 24,
+ }
+};
+
+static struct info_mcu lcd_hx8369_info = {
+ .bus_mode = LCD_BUS_8080,
+ .bus_width = 24,
+ .timing = lcd_hx8369_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_hx8369_spec = {
+ .width = 480,
+ .height = 800,
+ .mode = LCD_MODE_MCU,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mcu = &lcd_hx8369_info,
+ },
+ .ops = &lcd_hx8369_operations,
+};
+
+struct panel_cfg lcd_hx8369 = {
+ /* this panel may on both CS0/1 */
+ .lcd_cs = -1,
+ .lcd_id = 0x69,
+ .lcd_name = "lcd_hx8369",
+ .panel = &lcd_hx8369_spec,
+};
+
+static int __init lcd_hx8369_init(void)
+{
+ return sprd_register_panel(&lcd_hx8369);
+}
+
+subsys_initcall(lcd_hx8369_init);