summaryrefslogtreecommitdiff
path: root/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c')
-rw-r--r--drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c b/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c
new file mode 100644
index 00000000..f9538e90
--- /dev/null
+++ b/drivers/video/sprdfb/lcd/lcd_st7789v_mcu.c
@@ -0,0 +1,336 @@
+/* drivers/video/sprdfb/lcd_st7789v.c
+ *
+ * Support for st7789v LCD device
+ *
+ * Copyright (C) 2010 Spreadtrum
+ *
+ * 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 "../sprdfb_panel.h"
+
+#define ST7789V_BUS_WIDTH_8BIT // bus_width = 8
+
+static int32_t st7789v_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;
+
+ pr_debug("st7789v_init\n");
+ //Power setting sequence
+ send_cmd(0x11);
+ mdelay(120);
+
+#if defined(ST7789V_BUS_WIDTH_8BIT)
+ send_cmd(0xDF);
+ send_data(0x5A69);
+ send_data(0x0201);
+
+ send_cmd(0x36);
+ send_data(0x0000);
+
+ send_cmd(0x3a);
+ send_data(0x0500);
+
+ send_cmd(0x35);
+ send_data(0x0000);
+
+ send_cmd(0xd2);
+ send_data(0x4c00);
+
+ send_cmd(0xb2);
+ send_data(0x0404);
+ send_data(0x0033);
+ send_data(0x3300);
+
+ send_cmd(0xC6);
+ send_data(0x0A00);
+
+ send_cmd(0xb8);
+ send_data(0x2A2B);
+ send_data(0x0575);
+
+ send_cmd(0xb7);
+ send_data(0x7500);
+
+ send_cmd(0xbb);
+ send_data(0x1B00);
+
+ send_cmd(0xC2);
+ send_data(0x0100);
+
+ send_cmd(0xC3);
+ send_data(0x0b00);
+
+ send_cmd(0xC4);
+ send_data(0x2000);
+
+ send_cmd(0xd0);
+ send_data(0xa4a1);
+
+ send_cmd(0xE8);
+ send_data(0x8300);
+
+ send_cmd(0xE9);
+ send_data(0x0909);
+ send_data(0x0500);
+
+ send_cmd(0xC0);
+ send_data(0x2500);
+
+ send_cmd(0xb0);
+ send_data(0x00d0);
+
+ send_cmd(0xE0);
+ send_data(0xd00E);
+ send_data(0x1810);
+ send_data(0x0E2A);
+ send_data(0x3E54);
+ send_data(0x4C2B);
+ send_data(0x1716);
+ send_data(0x1D21);
+
+ send_cmd(0XE1);
+ send_data(0xd00E);
+ send_data(0x1710);
+ send_data(0x0E29);
+ send_data(0x3C44);
+ send_data(0x4D2C);
+ send_data(0x1615);
+ send_data(0x1E22);
+
+ send_cmd(0x29);
+#else // 16/18/24bit
+ send_cmd(0xB7); send_data(0x35);
+ send_cmd(0xBB); send_data(0x1A);
+ send_cmd(0xC2); send_data(0x01);
+ send_cmd(0xC3); send_data(0x0B);
+ send_cmd(0xC4); send_data(0x20);
+ send_cmd(0xD0); send_data(0xA4);send_data(0xA1);
+ send_cmd(0xE8); send_data(0x83);
+ send_cmd(0xE9); send_data(0x09);send_data(0x09);send_data(0x08);
+
+ //Init setting
+ send_cmd(0x36); send_data(0x00);
+ send_cmd(0x35); send_data(0x00);
+ send_cmd(0x3A); send_data(0x05);//0x06: 262k 0x05:65k
+ send_cmd(0xD2); send_data(0x4C);
+ send_cmd(0xB2);send_data(0x0C);send_data(0x0C);send_data(0x00);send_data(0x33);send_data(0x33);
+ send_cmd(0xC6); send_data(0x09);
+
+ //Gamma setting
+ send_cmd(0xE0);
+ send_data(0xD0);
+ send_data(0x02);
+ send_data(0x11);
+ send_data(0x12);
+ send_data(0x12);
+ send_data(0x2A);
+ send_data(0x3D);
+ send_data(0x44);
+ send_data(0x4C);
+ send_data(0x2B);
+ send_data(0x16);
+ send_data(0x14);
+ send_data(0x1E);
+ send_data(0x21);
+
+ send_cmd(0xE1);
+ send_data(0xD0);
+ send_data(0x02);
+ send_data(0x11);
+ send_data(0x11);
+ send_data(0x12);
+ send_data(0x2A);
+ send_data(0x3B);
+ send_data(0x44);
+ send_data(0x4C);
+ send_data(0x2B);
+ send_data(0x16);
+ send_data(0x15);
+ send_data(0x1E);
+ send_data(0x21);
+
+ send_cmd(0x29); //Display On
+#endif
+ return 0;
+}
+
+
+static int32_t st7789v_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("st7789v_set_window\n");
+
+#if defined(ST7789V_BUS_WIDTH_8BIT)
+ send_cmd(0x002A); // col
+ send_data(left);
+ send_data(right);
+
+ send_cmd(0x002B); // row
+ send_data(top);
+ send_data(bottom);
+ send_cmd(0x002C);
+#else // 16/18/24bit
+ send_cmd(0x2A); // col
+ send_data((left >> 8));
+ send_data((left & 0xFF));
+ send_data((right >> 8));
+ send_data((right & 0xFF));
+
+ send_cmd(0x2B); // row
+ send_data((top >> 8));
+ send_data((top & 0xFF));
+ send_data((bottom >> 8));
+ send_data((bottom & 0xFF));
+ send_cmd(0x2C);
+#endif
+
+ return 0;
+}
+
+
+static int32_t st7789v_invalidate(struct panel_spec *self)
+{
+ pr_debug("st7789v_invalidate\n");
+
+ return self->ops->panel_set_window(self, 0, 0,
+ self->width-1, self->height-1);
+}
+
+static int32_t st7789v_invalidate_rect(struct panel_spec *self,
+ uint16_t left, uint16_t top,
+ uint16_t right, uint16_t bottom)
+{
+
+ pr_debug("st7789v_invalidate_rect : (%d, %d, %d, %d)\n",left, top, right, bottom);
+
+ return self->ops->panel_set_window(self, left, top,
+ right, bottom);
+}
+
+static int32_t st7789v_set_direction(struct panel_spec *self, uint16_t direction)
+{
+
+ pr_debug("st7789v_set_direction\n");
+ return 0;
+}
+
+static int32_t st7789v_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
+{
+ //send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+
+ if(is_sleep) {
+ //send_cmd(0x10);
+ mdelay(120);
+ }
+ else {
+ //send_cmd(0x11);
+ mdelay(120);
+ }
+ return 0;
+}
+
+#define LCD_MTP_ID 0x51a0f0
+static uint32_t st7789v_read_id(struct panel_spec *self)
+{
+ int32_t read_value = 0;
+
+ send_data_t send_cmd = self->info.mcu->ops->send_cmd;
+ read_data_t read_data = self->info.mcu->ops->read_data;
+
+ send_cmd(0x04);
+
+#if defined(ST7789V_BUS_WIDTH_8BIT)
+ read_value += (read_data() &0xff)<<16;
+ read_value += read_data();
+#else
+ read_data();
+ read_value += read_data()<< 16;
+ read_value += read_data()<< 8;
+ read_value += read_data();
+#endif
+ pr_debug("st7789v_read_id=%x\n",read_value);
+
+ if(read_value == LCD_MTP_ID)
+ read_value = 0x7789;
+
+ return read_value;
+}
+
+static struct panel_operations lcd_st7789v_operations = {
+ .panel_init = st7789v_init,
+ .panel_set_window = st7789v_set_window,
+ .panel_invalidate = st7789v_invalidate,
+ //.lcd_invalidate_rect = st7789v_invalidate_rect,
+ .panel_set_direction = st7789v_set_direction,
+ .panel_enter_sleep = st7789v_enter_sleep,
+ .panel_readid = st7789v_read_id,
+};
+
+static struct timing_mcu lcd_st7789v_timing[] = {
+ [MCU_LCD_REGISTER_TIMING] = {
+ .rcss = 45,
+ .rlpw = 60,
+ .rhpw = 100,
+ .wcss = 10,
+ .wlpw = 28,
+ .whpw = 28,
+ },
+ [MCU_LCD_GRAM_TIMING] = {
+ .rcss = 25, /* 25 ns */
+ .rlpw = 70,
+ .rhpw = 70,
+ .wcss = 10,
+ .wlpw = 28,
+ .whpw = 28,
+ }
+};
+
+
+static struct info_mcu lcd_st7789v_info = {
+ .bus_mode = LCD_BUS_8080,
+ .bus_width = 8, //16,
+ .bpp = 16, /*RGB565*/
+ .timing = &lcd_st7789v_timing,
+ .ops = NULL,
+};
+
+struct panel_spec lcd_panel_st7789v = {
+ .width = 240,
+ .height = 320,
+ .fps = 60,
+ .type = LCD_MODE_MCU,
+ .direction = LCD_DIRECT_NORMAL,
+ .info = {
+ .mcu = &lcd_st7789v_info
+ },
+ .ops = &lcd_st7789v_operations,
+};
+
+struct panel_cfg lcd_st7789v = {
+ /* this panel may on both CS0/1 */
+ .dev_id = SPRDFB_MAINLCD_ID,
+ .lcd_id = 0x7789,
+ .lcd_name = "lcd_st7789v",
+ .panel = &lcd_panel_st7789v,
+};
+
+static int __init lcd_st7789v_init(void)
+{
+ return sprdfb_panel_register(&lcd_st7789v);
+}
+
+subsys_initcall(lcd_st7789v_init); \ No newline at end of file