blob: df48326b5755566d206188cae6ce6ad877d62e7b [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#include <common.h>
2#include <malloc.h>
3#include <asm/gpio.h>
4
5/* Only support 3-wire 9bits spi-lcd for now */
6
7#define LCD_SUB_ID_CNT 3
8static u8 sub_id_reg[LCD_SUB_ID_CNT] = {0xDA, 0xDB, 0xDC};
9
10struct lcd_sub_id {
11 u8 val;
12 u8 mask;
13};
14
15struct lcd_info {
16 const char *name;
17 u8 type;
18 struct lcd_sub_id sub_id[LCD_SUB_ID_CNT];
19};
20
21static struct lcd_info lcd_info[] = {
22 {"st7735", 1, {{0x7C, 0x7F}, {0x89, 0xFE}, {0xF0, 0xFF}} },
23};
24
25static inline void SPI_DELAY(u16 a)
26{
27 while (a--)
28 nop();
29}
30
31static inline void SPI_CS(u16 a)
32{
33 gpio_direction_output(CONFIG_SPI_CS_PIN, a);
34}
35
36static inline void SPI_SCL(u16 a)
37{
38 gpio_direction_output(CONFIG_SPI_SCL_PIN, a);
39}
40
41static inline void SPI_TX(u16 a)
42{
43 gpio_direction_output(CONFIG_SPI_TX_PIN, a);
44}
45
46static inline u8 SPI_READ(void)
47{
48 return !!gpio_get_value(CONFIG_SPI_TX_PIN);
49}
50
51static inline void SPI_TX_TO_RX(void)
52{
53 gpio_direction_input(CONFIG_SPI_TX_PIN);
54}
55
56static u8 __lcd_readid(u8 reg)
57{
58 SPI_CS(0);
59 u16 cmd = reg;
60 int i;
61 /* May need to tune this delay for different panel.
62 * For ST7735, this delay can be set to 0.
63 */
64 u16 delay = 0;
65
66 for (i = 0; i < 9; i++)
67 {
68 SPI_TX(cmd & 0x100);
69 SPI_DELAY(delay);
70 SPI_SCL(1);
71 SPI_DELAY(delay);
72 SPI_SCL(0);
73 cmd <<= 1;
74 }
75
76 SPI_TX_TO_RX();
77
78 cmd = 0;
79 for (i = 0; i < 8; i++)
80 {
81 SPI_DELAY(delay);
82 SPI_SCL(1);
83 cmd <<= 1;
84 cmd |= SPI_READ();
85 SPI_SCL(0);
86 }
87
88 SPI_CS(1);
89 printf("LCD ID 0x%x: 0x%x\n", reg, cmd);
90 return cmd;
91}
92
93static void do_lcd_rst(void)
94{
95 gpio_direction_output(CONFIG_LCD_RST_PIN, 1);
96 mdelay(50);
97 gpio_direction_output(CONFIG_LCD_RST_PIN, 0);
98 mdelay(50);
99 gpio_direction_output(CONFIG_LCD_RST_PIN, 1);
100 mdelay(150);
101}
102
103static u8 check_id(u8 id, u8 mask, u8 val)
104{
105 if ((val & mask) == (id & mask))
106 return 0;
107 return 1;
108}
109
110u8 lcd_gettype(void)
111{
112 u32 id = 0;
113 int i;
114 u8 id1, id2, id3;
115 u8 type = 0;
116
117 lcd_readid_pin_config();
118 do_lcd_rst();
119 for (i = 0; i < LCD_SUB_ID_CNT; i++) {
120 id <<= 8;
121 id |= __lcd_readid(sub_id_reg[i]);
122 }
123 lcd_readid_pin_restore();
124
125 id1 = (id & 0xFF0000) >> 16;
126 id2 = (id & 0xFF00) >> 8;
127 id3 = id & 0xFF;
128
129 for (i = 0; i < sizeof(lcd_info) / sizeof(lcd_info[0]); i++) {
130 if (check_id(id1, lcd_info[i].sub_id[0].mask, lcd_info[i].sub_id[0].val) == 0 &&
131 check_id(id2, lcd_info[i].sub_id[1].mask, lcd_info[i].sub_id[1].val) == 0 &&
132 check_id(id3, lcd_info[i].sub_id[2].mask, lcd_info[i].sub_id[2].val) == 0)
133 {
134 printf("LCD Name: %s, ID: 0x%x, Type: %d\n",
135 lcd_info[i].name, id, lcd_info[i].type);
136 type = lcd_info[i].type;
137 goto end;
138 }
139 }
140
141 printf("UNSUPPORTTED LCD ID: 0x%x, Type: 0\n", id);
142end:
143 return type;
144}