1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "gpio_if.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_log.h"
12 #include "osal_mem.h"
13 #include "osal_time.h"
14 #include "spi_if.h"
15 #include "ssp_st7789.h"
16
17 #define WIDTH 240
18 #define HEIGHT 320
19 #define FRAME_RATE 50
20
21 static struct LcdCmd g_onCmd[] = {
22 { LCD_CMD, 0x11, 120 },
23 { LCD_CMD, 0x36, 0 },
24 { LCD_DATA, 0x00, 0 },
25 { LCD_CMD, 0xb2, 0 },
26 { LCD_DATA, 0x00, 0 },
27 { LCD_DATA, 0x00, 0 },
28 { LCD_DATA, 0x00, 0 },
29 { LCD_DATA, 0x33, 0 },
30 { LCD_DATA, 0x33, 0 },
31 { LCD_CMD, 0xb7, 0 },
32 { LCD_DATA, 0x35, 0 },
33 { LCD_CMD, 0xb8, 0 },
34 { LCD_DATA, 0x2f, 0 },
35 { LCD_DATA, 0x2b, 0 },
36 { LCD_DATA, 0x2f, 0 },
37 { LCD_CMD, 0xbb, 0 },
38 { LCD_DATA, 0x24, 0 },
39 { LCD_CMD, 0xc0, 0 },
40 { LCD_DATA, 0x2c, 0 },
41 { LCD_CMD, 0xc3, 0 },
42 { LCD_DATA, 0x20, 0 },
43 { LCD_CMD, 0xc4, 0 },
44 { LCD_DATA, 0x03, 0 },
45 { LCD_CMD, 0xc6, 0 },
46 { LCD_DATA, 0x11, 0 },
47 { LCD_CMD, 0xd0, 0 },
48 { LCD_DATA, 0xa4, 0 },
49 { LCD_DATA, 0xa1, 0 },
50 { LCD_CMD, 0xe8, 0 },
51 { LCD_DATA, 0x03, 0 },
52 { LCD_CMD, 0xe9, 0 },
53 { LCD_DATA, 0x0d, 0 },
54 { LCD_DATA, 0x12, 0 },
55 { LCD_DATA, 0x00, 0 },
56 { LCD_CMD, 0x21, 0 },
57 { LCD_CMD, 0xb0, 0 },
58 { LCD_DATA, 0x11, 0 },
59 { LCD_DATA, 0x04, 0 },
60 { LCD_DATA, 0x00, 0 },
61 { LCD_CMD, 0xb1, 0 },
62 { LCD_DATA, 0xc0, 0 },
63 { LCD_DATA, 0x02, 0 },
64 { LCD_DATA, 0x14, 0 },
65 { LCD_CMD, 0x3a, 0 },
66 { LCD_DATA, 0x66, 0 },
67 { LCD_CMD, 0x11, 0 },
68 { LCD_CMD, 0x29, 0 },
69 { LCD_CMD, 0x2c, 0 },
70 };
71
72 static struct LcdCmd g_offCmd[] = {
73 { LCD_CMD, 0x28, 20 },
74 { LCD_CMD, 0x10, 120 },
75 };
76
77 static DevHandle g_spiHdl = NULL;
78
SpiWrite9Bits(DevHandle spiHandle,uint8_t cmd,uint8_t data)79 static int32_t SpiWrite9Bits(DevHandle spiHandle, uint8_t cmd, uint8_t data)
80 {
81 int32_t ret;
82 uint16_t wbuff[1] = {0};
83
84 wbuff[0] = ((cmd << BITS_PER_BYTE) | data);
85 ret = SpiWrite(spiHandle, (uint8_t *)wbuff, SPI_MSG_SIZE);
86 if (ret != HDF_SUCCESS) {
87 HDF_LOGE("SpiWrite failed, ret:%d", ret);
88 return HDF_FAILURE;
89 }
90 return HDF_SUCCESS;
91 }
92
GetSpiHandle(void)93 static DevHandle GetSpiHandle(void)
94 {
95 int32_t ret;
96 DevHandle spiHandle = NULL;
97 struct SpiDevInfo spiDevinfo;
98 struct SpiCfg cfg;
99
100 spiDevinfo.busNum = 1;
101 spiDevinfo.csNum = 0;
102 spiHandle = SpiOpen(&spiDevinfo);
103 if (spiHandle == NULL) {
104 HDF_LOGE("SpiOpen failed");
105 return NULL;
106 }
107 cfg.mode = SPI_CLK_PHASE | SPI_CLK_POLARITY;
108 cfg.bitsPerWord = BITS_PER_WORD;
109 cfg.maxSpeedHz = SPI_MAX_SPEED;
110 ret = SpiSetCfg(spiHandle, &cfg);
111 if (ret != HDF_SUCCESS) {
112 HDF_LOGE("SpiSetCfg failed, ret:%d", ret);
113 SpiClose(spiHandle);
114 return NULL;
115 }
116 HDF_LOGI("Spi init success!");
117 return spiHandle;
118 }
119
LcdResetOn(void)120 static int32_t LcdResetOn(void)
121 {
122 int32_t ret;
123
124 ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT);
125 if (ret != HDF_SUCCESS) {
126 HDF_LOGE("set lcd reset dir failed, ret:%d", ret);
127 return HDF_FAILURE;
128 }
129 ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH);
130 if (ret != HDF_SUCCESS) {
131 HDF_LOGE("set lcd reset hi failed, ret:%d", ret);
132 return HDF_FAILURE;
133 }
134 ret = GpioWrite(RESET_GPIO, GPIO_VAL_LOW);
135 if (ret != HDF_SUCCESS) {
136 HDF_LOGE("set lcd reset how failed, ret:%d", ret);
137 return HDF_FAILURE;
138 }
139 /* delay 10ms */
140 OsalMSleep(10);
141 ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH);
142 if (ret != HDF_SUCCESS) {
143 HDF_LOGE("set lcd reset hi after delay failed, ret:%d", ret);
144 return HDF_FAILURE;
145 }
146 /* delay 120ms */
147 OsalMSleep(120);
148 return HDF_SUCCESS;
149 }
150
LcdResetOff(void)151 static int32_t LcdResetOff(void)
152 {
153 int32_t ret;
154
155 ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT);
156 if (ret != HDF_SUCCESS) {
157 HDF_LOGE("GpioSetDir failed, ret:%d", ret);
158 return HDF_FAILURE;
159 }
160 ret = GpioWrite(RESET_GPIO, GPIO_VAL_LOW);
161 if (ret != HDF_SUCCESS) {
162 HDF_LOGE("GpioWrite failed, ret:%d", ret);
163 return HDF_FAILURE;
164 }
165 /* delay 20ms */
166 OsalMSleep(20);
167 return HDF_SUCCESS;
168 }
169
St7789Init(void)170 static int32_t St7789Init(void)
171 {
172 g_spiHdl = GetSpiHandle();
173 if (g_spiHdl == NULL) {
174 HDF_LOGE("GetSpiHandle failed");
175 return HDF_FAILURE;
176 }
177 return HDF_SUCCESS;
178 }
179
St7789On(void)180 static int32_t St7789On(void)
181 {
182 int32_t ret;
183 int i;
184
185 /* lcd reset power on */
186 ret = LcdResetOn();
187 if (ret != HDF_SUCCESS) {
188 HDF_LOGE("%s: LcdResetOn failed", __func__);
189 return HDF_FAILURE;
190 }
191 if (g_spiHdl == NULL) {
192 HDF_LOGE("%s: g_spiHdl is null", __func__);
193 return HDF_FAILURE;
194 }
195 int32_t count = sizeof(g_onCmd) / sizeof(g_onCmd[0]);
196 for (i = 0; i < count; i++) {
197 ret = SpiWrite9Bits(g_spiHdl, g_onCmd[i].cmd, g_onCmd[i].data);
198 if (ret != HDF_SUCCESS) {
199 HDF_LOGE("SpiWrite failed");
200 return HDF_FAILURE;
201 }
202 if (g_onCmd[i].delay > 0) {
203 OsalMSleep(g_onCmd[i].delay);
204 }
205 }
206 return HDF_SUCCESS;
207 }
208
St7789Off(void)209 static int32_t St7789Off(void)
210 {
211 int32_t ret;
212 int i;
213
214 if (g_spiHdl == NULL) {
215 HDF_LOGE("%s: g_spiHdl is null", __func__);
216 return HDF_FAILURE;
217 }
218 /* send mipi init code */
219 int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]);
220
221 for (i = 0; i < count; i++) {
222 ret = SpiWrite9Bits(g_spiHdl, g_offCmd[i].cmd, g_offCmd[i].data);
223 if (ret != HDF_SUCCESS) {
224 HDF_LOGE("SpiWrite9Bits failed");
225 return HDF_FAILURE;
226 }
227 if (g_offCmd[i].delay > 0) {
228 OsalMSleep(g_offCmd[i].delay);
229 }
230 }
231 /* lcd reset power off */
232 ret = LcdResetOff();
233 if (ret != HDF_SUCCESS) {
234 HDF_LOGE("%s: LcdResetOff failed", __func__);
235 return HDF_FAILURE;
236 }
237 return HDF_SUCCESS;
238 }
239
St7789SetBacklight(uint32_t level)240 static int32_t St7789SetBacklight(uint32_t level)
241 {
242 (void)level;
243 return HDF_SUCCESS;
244 }
245
246 static struct PanelInfo g_panelInfo = {
247 .width = WIDTH, /* width */
248 .height = HEIGHT, /* height */
249 .frameRate = FRAME_RATE, /* frame rate */
250 .intfType = LCD_6BIT, /* panel interface type */
251 .intfSync = 42, /* Hi3559AV100: For ili9341 at 50 Hz (6bit) */
252 };
253
254 static struct PanelData g_panelData = {
255 .info = &g_panelInfo,
256 .init = St7789Init,
257 .on = St7789On,
258 .off = St7789Off,
259 .setBacklight = St7789SetBacklight,
260 };
261
SspSt7789EntryInit(struct HdfDeviceObject * object)262 static int32_t SspSt7789EntryInit(struct HdfDeviceObject *object)
263 {
264 if (object == NULL) {
265 HDF_LOGE("%s: param is null", __func__);
266 return HDF_FAILURE;
267 }
268 if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) {
269 HDF_LOGE("%s: PanelDataRegister failed", __func__);
270 return HDF_FAILURE;
271 }
272 HDF_LOGI("%s: exit succ", __func__);
273 return HDF_SUCCESS;
274 }
275
276 struct HdfDriverEntry g_st7789DevEntry = {
277 .moduleVersion = 1,
278 .moduleName = "LCD_ST7789",
279 .Init = SspSt7789EntryInit,
280 };
281
282 HDF_INIT(g_st7789DevEntry);
283