1 /*
2 * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "cmsis_os2.h"
16 #include "hdf_log.h"
17 #include "lcd_abs_if.h"
18 #include "hdf_device_desc.h"
19 #include "hal_gpio.h"
20 #include "hal_iomux.h"
21 #include "hal_dsi.h"
22 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
23 #include "hcs_macro.h"
24 #include "hdf_config_macro.h"
25 #else
26 #include "device_resource_if.h"
27 #endif
28
29 #ifdef CONFIG_DISPLAY_ILI9488
30 #define WIDTH 320
31 #define HEIGHT 480
32
33 static void PanelPowerControl(bool on);
34 static int32_t PanelCheckStatus(struct PanelData *panel);
35 static int32_t PanelReadId();
36
37 static uint8_t cmd0[] = {0xE0, 0x00, 0x13, 0x18, 0x04, 0x0F, 0x06, 0x3A, 0x56, 0x4D, 0x03, 0x0A, 0x06, 0x30, 0x3E, 0x0F};
38 static uint8_t cmd1[] = {0xE1, 0x00, 0x13, 0x18, 0x01, 0x11, 0x06, 0x38, 0x34, 0x4D, 0x06, 0x0D, 0x0B, 0x31, 0x37, 0x0F};
39 static uint8_t cmd2[] = {0x35, 0x00};
40 static uint8_t cmd3[] = {0XC0, 0x18, 0x17}; // Power Control 1
41 static uint8_t cmd4[] = {0xC1, 0x41}; // Power Control 2
42 static uint8_t cmd5[] = {0xC5, 0x00, 0x1A, 0x80}; // Power Control 3
43 static uint8_t cmd6[] = {0x36, 0x48};
44 static uint8_t cmd7[] = {0x3A, 0x66}; // Interface Pixel Format //18bit
45 static uint8_t cmd8[] = {0XB0, 0x00};
46 static uint8_t cmd9[] = {0xB1, 0xA0}; // Frame rate 60HZ
47 static uint8_t cmd10[] = {0xB4, 0x02}; // Display Inversion Control //2-dot
48 static uint8_t cmd11[] = {0xB6, 0x02, 0x02}; // RGB/MCU Interface Control //MCU //Source,Gate scan dieection
49 static uint8_t cmd12[] = {0xE9, 0x00}; // Set Image Function,0x00 disable 24 bit data input
50 static uint8_t cmd13[] = {0xF7, 0xA9, 0x51, 0x2C, 0x82}; // Adjust Control
51 static uint8_t cmd14[] = {0x21}; // Normal Black
52 static uint8_t cmd15[] = {0x11}; // Sleep out
53 static uint8_t cmd16[] = {0x29}; // Display on
54 static uint8_t cmd17[] = {0x28};
55 static uint8_t cmd18[] = {0x10};
56
57 static struct DsiCmdDesc g_OnCmd[] = {
58 {0x39, 0, sizeof(cmd0), cmd0},
59 {0x39, 0, sizeof(cmd1), cmd1},
60 {0x15, 0, sizeof(cmd2), cmd2},
61 {0x39, 0, sizeof(cmd3), cmd3},
62 {0x15, 0, sizeof(cmd4), cmd4},
63 {0x39, 0, sizeof(cmd5), cmd5},
64 {0x15, 0, sizeof(cmd6), cmd6},
65 {0x15, 0, sizeof(cmd7), cmd7},
66 {0x15, 0, sizeof(cmd8), cmd8},
67 {0x15, 0, sizeof(cmd9), cmd9},
68 {0x15, 0, sizeof(cmd10), cmd10},
69 {0x39, 0, sizeof(cmd11), cmd11},
70 {0x15, 0, sizeof(cmd12), cmd12},
71 {0x39, 0, sizeof(cmd13), cmd13},
72 {0x05, 0, sizeof(cmd14), cmd14},
73 {0x05, 150, sizeof(cmd15), cmd15},
74 {0x05, 50, sizeof(cmd16), cmd16},
75 };
76
77 struct DsiCmdDesc g_offCmd[] = {
78 {0x05, 150, sizeof(cmd17), cmd17},
79 {0x05, 50, sizeof(cmd18), cmd18},
80 };
81
82 struct PanelDevice {
83 struct PanelData panelData;
84 struct PanelInfo panelInfo;
85 struct PanelEsd panelEsd;
86 DevHandle mipiHandle;
87 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_rst;
88 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_te;
89 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_led;
90 };
91
92 static struct PanelDevice priv = {
93 .panelInfo = {
94 .width = WIDTH,
95 .height = HEIGHT,
96 .hbp = 15,
97 .hfp = 15,
98 .hsw = 5,
99 .vbp = 8,
100 .vfp = 8,
101 .vsw = 4,
102 .frameRate = 60,
103 .intfType = MIPI_DSI,
104 .intfSync = OUTPUT_USER,
105 .mipi = {DSI_1_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT},
106 },
107 .panelEsd = {
108 .support = true,
109 .interval = 30 * 1000,
110 .recoveryNum = 5,
111 .checkFunc = PanelCheckStatus,
112 },
113 .pin_rst = {
114 HAL_GPIO_PIN_P2_0,
115 HAL_IOMUX_FUNC_AS_GPIO,
116 HAL_IOMUX_PIN_VOLTAGE_VIO,
117 HAL_IOMUX_PIN_NOPULL,
118 },
119 .pin_te = {
120 HAL_IOMUX_PIN_P2_1,
121 HAL_IOMUX_FUNC_DISPLAY_TE,
122 HAL_IOMUX_PIN_VOLTAGE_VIO,
123 HAL_IOMUX_PIN_NOPULL,
124 },
125 .pin_led = {
126 HAL_IOMUX_PIN_P0_3,
127 HAL_IOMUX_FUNC_AS_GPIO,
128 HAL_IOMUX_PIN_VOLTAGE_VIO,
129 HAL_IOMUX_PIN_NOPULL,
130 },
131 };
132
PanelInit(struct PanelData * panel)133 static int32_t PanelInit(struct PanelData *panel)
134 {
135 if (panel == NULL || panel->info == NULL) {
136 return HDF_FAILURE;
137 }
138 priv.mipiHandle = MipiDsiOpen(0);
139 if (priv.mipiHandle == NULL) {
140 HDF_LOGE("%s: MipiDsiOpen failed", __func__);
141 return HDF_FAILURE;
142 }
143 HDF_LOGI("%s: width %d, height %d", __func__, WIDTH, HEIGHT);
144 PanelPowerControl(true);
145
146 struct PanelInfo *panelInfo = panel->info;
147 struct MipiCfg cfg = {0};
148 cfg.lane = panelInfo->mipi.lane;
149 cfg.mode = panelInfo->mipi.mode;
150 cfg.format = panelInfo->mipi.format;
151 cfg.burstMode = panelInfo->mipi.burstMode;
152 cfg.timing.xPixels = panelInfo->width;
153 cfg.timing.hsaPixels = panelInfo->hsw;
154 cfg.timing.hbpPixels = panelInfo->hbp;
155 cfg.timing.hlinePixels = panelInfo->width + panelInfo->hbp + panelInfo->hfp + panelInfo->hsw;
156 cfg.timing.vsaLines = panelInfo->vsw;
157 cfg.timing.vbpLines = panelInfo->vbp;
158 cfg.timing.vfpLines = panelInfo->vfp;
159 cfg.timing.ylines = panelInfo->height;
160
161 cfg.pixelClk = CalcPixelClk(panelInfo);
162 cfg.phyDataRate = CalcDataRate(panelInfo);
163 /* config mipi device */
164 if (MipiDsiSetCfg(priv.mipiHandle, &cfg) != HDF_SUCCESS) {
165 HDF_LOGE("%s: MipiDsiSetCfg failed", __func__);
166 return HDF_FAILURE;
167 }
168 PanelReadId();
169 return HDF_SUCCESS;
170 }
171
PanelPowerControl(bool on)172 static void PanelPowerControl(bool on)
173 {
174 if (on) {
175 hal_iomux_init(&priv.pin_led, 1);
176 hal_iomux_init(&priv.pin_rst, 1);
177 hal_iomux_init(&priv.pin_te, 1);
178 hal_gpio_pin_set_dir(priv.pin_rst.pin, HAL_GPIO_DIR_OUT, 1);
179 osDelay(10);
180 hal_gpio_pin_clr(priv.pin_rst.pin);
181 osDelay(50);
182 hal_gpio_pin_set(priv.pin_rst.pin);
183 osDelay(150);
184 } else {
185 osDelay(50);
186 hal_gpio_pin_clr(priv.pin_rst.pin);
187 osDelay(150);
188 hal_gpio_pin_clr(priv.pin_led.pin);
189 }
190 }
191
PanelReadId()192 static int32_t PanelReadId()
193 {
194 uint8_t read_id[3] = {0};
195 uint8_t payload[] = {0x04};
196 struct DsiCmdDesc cmd = {0x06, 0, sizeof(payload), payload};
197 int32_t ret = MipiDsiRx(priv.mipiHandle, &cmd, 3, read_id);
198 if (ret != HDF_SUCCESS) {
199 HDF_LOGE("%s: MipiDsiRx failed", __func__);
200 return HDF_FAILURE;
201 }
202 HDF_LOGI("%s: read id %02X-%02X-%02X", __func__, read_id[0], read_id[1], read_id[2]);
203 return HDF_SUCCESS;
204 }
205 #define DSI_INIT_DELAY 100
PanelCheckStatus(struct PanelData * panel)206 static int32_t PanelCheckStatus(struct PanelData *panel)
207 {
208 uint8_t powerMode = 0;
209 uint8_t payload[] = {0x0A};
210 struct DsiCmdDesc cmd = {0x06, 0, sizeof(payload), payload};
211 int64_t cnt = panel->esd->recoveryNum;
212 do {
213 int32_t ret = MipiDsiRx(priv.mipiHandle, &cmd, 1, &powerMode);
214 if (ret == HDF_SUCCESS) {
215 HDF_LOGD("%s: powerMode 0x%x ok", __func__, powerMode);
216 break;
217 }
218 HDF_LOGE("%s: reset", __func__);
219 hal_dsi_init(WIDTH, priv.panelInfo.mipi.lane);
220 osDelay(DSI_INIT_DELAY);
221 for (int32_t i = 0; i < sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); i++) {
222 ret = MipiDsiTx(priv.mipiHandle, &(g_OnCmd[i]));
223 if (ret != HDF_SUCCESS) {
224 HDF_LOGE("%s: MipiDsiTx failed", __func__);
225 return HDF_FAILURE;
226 }
227 }
228 } while (--cnt > 0);
229 if (cnt < panel->esd->recoveryNum) {
230 hal_dsi_start();
231 }
232 return HDF_SUCCESS;
233 }
234
PanelOn(struct PanelData * panel)235 static int32_t PanelOn(struct PanelData *panel)
236 {
237 /* send mipi power on code */
238 int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]);
239 int32_t i;
240 for (i = 0; i < count; i++) {
241 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_OnCmd[i]));
242 if (ret != HDF_SUCCESS) {
243 HDF_LOGE("%s: MipiDsiTx failed", __func__);
244 return HDF_FAILURE;
245 }
246 }
247 /* set mipi to hs mode */
248 MipiDsiSetHsMode(priv.mipiHandle);
249 PanelCheckStatus(panel);
250 hal_gpio_pin_set_dir(priv.pin_led.pin, HAL_GPIO_DIR_OUT, 1);
251 osDelay(100);
252 return HDF_SUCCESS;
253 }
254
PanelOff(struct PanelData * panel)255 static int32_t PanelOff(struct PanelData *panel)
256 {
257 /* send mipi power off code */
258 int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]);
259 int32_t i;
260 for (i = 0; i < count; i++) {
261 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_offCmd[i]));
262 if (ret != HDF_SUCCESS) {
263 HDF_LOGE("%s: MipiDsiTx failed", __func__);
264 return HDF_FAILURE;
265 }
266 }
267 /* set mipi to lp mode */
268 MipiDsiSetLpMode(priv.mipiHandle);
269 return HDF_SUCCESS;
270 }
271
PanelSetBacklight(struct PanelData * panel,uint32_t level)272 static int32_t PanelSetBacklight(struct PanelData *panel, uint32_t level)
273 {
274 (void)panel;
275 uint8_t payload[] = {0x51, level & 0xff};
276 struct DsiCmdDesc cmd = {0x15, 0, sizeof(payload), payload};
277 if (MipiDsiTx(priv.mipiHandle, &cmd) != HDF_SUCCESS) {
278 HDF_LOGE("%s: MipiDsiTx failed", __func__);
279 return HDF_FAILURE;
280 }
281 PanelCheckStatus(panel);
282 return HDF_SUCCESS;
283 }
284 #define REAL_PIN(n) (n / 10 * 8 + n % 10)
285 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
286 #define DISPLAY_PANEL_CONFIG HCS_NODE(HCS_NODE(HCS_NODE(HCS_ROOT, display), panel_config), a064_config)
PanelGetResource(struct PanelDevice * priv)287 static uint32_t PanelGetResource(struct PanelDevice *priv)
288 {
289 uint32_t temp;
290 temp = HCS_PROP(DISPLAY_PANEL_CONFIG, rst_pin);
291 priv->pin_rst.pin = REAL_PIN(temp);
292
293 temp = HCS_PROP(DISPLAY_PANEL_CONFIG, te_pin);
294 priv->pin_te.pin = REAL_PIN(temp);
295
296 temp = HCS_PROP(DISPLAY_PANEL_CONFIG, led_pin);
297 priv->pin_led.pin = REAL_PIN(temp);
298
299 HDF_LOGD("%s: rst_pin=%d, te_pin=%d, led_pin=%d", __func__, priv->pin_rst.pin, priv->pin_te.pin, priv->pin_led.pin);
300 return HDF_SUCCESS;
301 }
302 #else
PanelGetResource(struct PanelDevice * priv,const struct DeviceResourceNode * resourceNode)303 static uint32_t PanelGetResource(struct PanelDevice *priv, const struct DeviceResourceNode *resourceNode)
304 {
305 struct DeviceResourceIface *res = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
306 if (res == NULL || res->GetUint32 == NULL) {
307 HDF_LOGE("DeviceResourceIface is invalid");
308 return HDF_FAILURE;
309 }
310 uint32_t temp = 0;
311 if (res->GetUint32(resourceNode, "rst_pin", &temp, 0) != HDF_SUCCESS) {
312 HDF_LOGE("%s: failed to get rst_pin", __func__);
313 return HDF_FAILURE;
314 }
315 priv->pin_rst.pin = REAL_PIN(temp);
316 if (res->GetUint32(resourceNode, "te_pin", &temp, 0) != HDF_SUCCESS) {
317 HDF_LOGE("%s: failed to get te_pin", __func__);
318 return HDF_FAILURE;
319 }
320 priv->pin_te.pin = REAL_PIN(temp);
321 if (res->GetUint32(resourceNode, "led_pin", &temp, 0) != HDF_SUCCESS) {
322 HDF_LOGE("%s: failed to get led_pin", __func__);
323 return HDF_FAILURE;
324 }
325 priv->pin_led.pin = REAL_PIN(temp);
326 HDF_LOGD("%s: rst_pin=%d, te_pin=%d, led_pin=%d", __func__, priv->pin_rst.pin, priv->pin_te.pin, priv->pin_led.pin);
327 return HDF_SUCCESS;
328 }
329 #endif
PanelDriverInit(struct HdfDeviceObject * object)330 static int32_t PanelDriverInit(struct HdfDeviceObject *object)
331 {
332 if (object == NULL) {
333 return HDF_FAILURE;
334 }
335 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
336 if (PanelGetResource(&priv) != HDF_SUCCESS) {
337 HDF_LOGE("%s: PanelGetResource failed", __func__);
338 return HDF_FAILURE;
339 }
340 #else
341 if (object->property) {
342 if (PanelGetResource(&priv, object->property) != HDF_SUCCESS) {
343 HDF_LOGE("%s: PanelGetResource failed", __func__);
344 return HDF_FAILURE;
345 }
346 }
347 #endif
348 priv.panelData.info = &priv.panelInfo;
349 priv.panelData.esd = &priv.panelEsd;
350 priv.panelData.init = PanelInit;
351 priv.panelData.on = PanelOn;
352 priv.panelData.off = PanelOff;
353 priv.panelData.setBacklight = PanelSetBacklight;
354 priv.panelData.object = object;
355 if (RegisterPanel(&priv.panelData) != HDF_SUCCESS) {
356 HDF_LOGE("%s: RegisterPanel failed", __func__);
357 return HDF_FAILURE;
358 }
359 return HDF_SUCCESS;
360 }
361
PanelDriverBind(struct HdfDeviceObject * device)362 static int32_t PanelDriverBind(struct HdfDeviceObject *device)
363 {
364 (void)device;
365 return HDF_SUCCESS;
366 }
367
PanelDriverRelease(struct HdfDeviceObject * device)368 static void PanelDriverRelease(struct HdfDeviceObject *device)
369 {
370 (void)device;
371 }
372
373 static struct HdfDriverEntry g_ili9488DriverEntry = {
374 .moduleVersion = 1,
375 .moduleName = "HDF_PANEL_ILI9488",
376 .Bind = PanelDriverBind,
377 .Init = PanelDriverInit,
378 .Release = PanelDriverRelease,
379 };
380
381 HDF_INIT(g_ili9488DriverEntry);
382 #endif