1 /*
2 * Copyright (c) 2021 FnLink (hunan) Technologies CO., LIMITED.
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
16 #include "cmsis_os2.h"
17 #include "hdf_log.h"
18 #include "lcd_abs_if.h"
19 #include "hdf_device_desc.h"
20 #include "device_resource_if.h"
21 #include "hal_gpio.h"
22 #include "hal_iomux.h"
23
24 #ifdef CONFIG_DISPLAY_ZZW395
25
26 #define WIDTH 480
27 #define HEIGHT 480
28
29 static uint8_t cmd0[] = {0xFF, 0x77, 0x01, 0x00, 0x00, 0x10};
30 static uint8_t cmd1[] = {0xC0, 0x3B, 0x00};
31 static uint8_t cmd2[] = {0xC1, 0x0D, 0x02};
32 static uint8_t cmd3[] = {0xC2, 0x21, 0x08};
33 static uint8_t cmd4[] = {0xB0, 0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18};
34 static uint8_t cmd5[] = {0xB1, 0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18};
35 static uint8_t cmd6[] = {0xFF, 0x77, 0x01, 0x00, 0x00, 0x11};
36 static uint8_t cmd7[] = {0xB0, 0x60};
37 static uint8_t cmd8[] = {0xB1, 0x30};
38 static uint8_t cmd9[] = {0xB2, 0x87};
39 static uint8_t cmd10[] = {0xB3, 0x80};
40 static uint8_t cmd11[] = {0xB5, 0x49};
41 static uint8_t cmd12[] = {0xB7, 0x85};
42 static uint8_t cmd13[] = {0xB8, 0x21};
43 static uint8_t cmd14[] = {0xC1, 0x78};
44 static uint8_t cmd15[] = {0xC2, 0x78};
45 static uint8_t cmd16[] = {0xE0, 0x00, 0x1B, 0x02};
46 static uint8_t cmd17[] = {0xE1, 0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44};
47 static uint8_t cmd18[] = {0xE2, 0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00};
48 static uint8_t cmd19[] = {0xE3, 0x00, 0x00, 0x11, 0x11};
49 static uint8_t cmd20[] = {0xE4, 0x44, 0x44};
50 static uint8_t cmd21[] = {0xE5, 0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0,};
51 static uint8_t cmd22[] = {0xE6, 0x00, 0x00, 0x11, 0x11};
52 static uint8_t cmd23[] = {0xE7, 0x44, 0x44};
53 static uint8_t cmd24[] = {0xE8, 0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0};
54 static uint8_t cmd25[] = {0xEB, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40};
55 static uint8_t cmd26[] = {0xEC, 0x3C, 0x00};
56 static uint8_t cmd27[] = {0xED, 0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA};
57 static uint8_t cmd28[] = {0xFF, 0x77, 0x01, 0x00, 0x00, 0x00};
58 static uint8_t cmd29[] = {0x36, 0x00, 0x77, 0x01, 0x00, 0x00,0x12};
59 static uint8_t cmd30[] = {0xd1, 0x81};
60 static uint8_t cmd31[] = {0xd2, 0x08};
61 static uint8_t cmd32[] = {0x11};
62 static uint8_t cmd33[] = {0x29};
63 static uint8_t cmd34[] = {0x28};
64 static uint8_t cmd35[] = {0x10};
65
66 static struct DsiCmdDesc g_OnCmd[] = {
67 {0x39, 0, sizeof(cmd0), cmd0},
68 {0x39, 0, sizeof(cmd1), cmd1},
69 {0x39, 0, sizeof(cmd2), cmd2},
70 {0x39, 0, sizeof(cmd3), cmd3},
71 {0x39, 0, sizeof(cmd4), cmd4},
72 {0x39, 0, sizeof(cmd5), cmd5},
73 {0x39, 0, sizeof(cmd6), cmd6},
74 {0x15, 0, sizeof(cmd7), cmd7},
75 {0x15, 0, sizeof(cmd8), cmd8},
76 {0x15, 0, sizeof(cmd9), cmd9},
77 {0x15, 0, sizeof(cmd10), cmd10},
78 {0x15, 0, sizeof(cmd11), cmd11},
79 {0x15, 0, sizeof(cmd12), cmd12},
80 {0x15, 0, sizeof(cmd13), cmd13},
81 {0x15, 0, sizeof(cmd14), cmd14},
82 {0x15, 20, sizeof(cmd15), cmd15},
83 {0x39, 0, sizeof(cmd16), cmd16},
84 {0x39, 0, sizeof(cmd17), cmd17},
85 {0x39, 0, sizeof(cmd18), cmd18},
86 {0x39, 0, sizeof(cmd19), cmd19},
87 {0x39, 0, sizeof(cmd20), cmd20},
88 {0x39, 0, sizeof(cmd21), cmd21},
89 {0x39, 0, sizeof(cmd22), cmd22},
90 {0x39, 0, sizeof(cmd23), cmd23},
91 {0x39, 0, sizeof(cmd24), cmd24},
92 {0x39, 0, sizeof(cmd25), cmd25},
93 {0x39, 0, sizeof(cmd26), cmd26},
94 {0x39, 0, sizeof(cmd27), cmd27},
95 {0x39, 0, sizeof(cmd28), cmd28},
96 {0x39, 0, sizeof(cmd29), cmd29},
97 {0x15, 0, sizeof(cmd30), cmd30},
98 {0x15, 0, sizeof(cmd31), cmd31},
99 {0x05, 120, sizeof(cmd32), cmd32},
100 {0x05, 20, sizeof(cmd33), cmd33},
101 };
102
103 static struct DsiCmdDesc g_offCmd[] = {
104 {0x05, 20, sizeof(cmd34), cmd34},
105 {0x05, 120, sizeof(cmd35), cmd35},
106 };
107
108 struct PanelDevice {
109 struct PanelData panelData;
110 struct PanelInfo panelInfo;
111 DevHandle mipiHandle;
112 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_rst;
113 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_te;
114 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_led;
115 };
116
117 static struct PanelDevice priv = {
118 .panelInfo = {
119 .width = WIDTH,
120 .height = HEIGHT,
121 .hbp = 80,
122 .hfp = 80,
123 .hsw = 8,
124 .vbp = 30,
125 .vfp = 18,
126 .vsw = 2,
127 .frameRate = 60,
128 .intfType = MIPI_DSI,
129 .intfSync = OUTPUT_USER,
130 .mipi = {DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT},
131 },
132 .pin_rst = {
133 HAL_GPIO_PIN_P0_3,
134 HAL_IOMUX_FUNC_AS_GPIO,
135 HAL_IOMUX_PIN_VOLTAGE_VIO,
136 HAL_IOMUX_PIN_NOPULL,
137 },
138 .pin_te = {
139 HAL_IOMUX_PIN_P2_1,
140 HAL_IOMUX_FUNC_DISPLAY_TE,
141 HAL_IOMUX_PIN_VOLTAGE_VIO,
142 HAL_IOMUX_PIN_NOPULL,
143 },
144 .pin_led = {
145 HAL_IOMUX_PIN_P2_6,
146 HAL_IOMUX_FUNC_AS_GPIO,
147 HAL_IOMUX_PIN_VOLTAGE_VIO,
148 HAL_IOMUX_PIN_NOPULL,
149 },
150 };
151
PanelInit(struct PanelData * panel)152 static int32_t PanelInit(struct PanelData *panel)
153 {
154 if (panel == NULL || panel->info == NULL) {
155 return HDF_FAILURE;
156 }
157 priv.mipiHandle = MipiDsiOpen(0);
158 if (priv.mipiHandle == NULL) {
159 HDF_LOGE("%s: MipiDsiOpen failed", __func__);
160 return HDF_FAILURE;
161 }
162 HDF_LOGI("%s: width %d, height %d", __func__, WIDTH, HEIGHT);
163
164 struct PanelInfo *panelInfo = panel->info;
165 struct MipiCfg cfg = {0};
166 cfg.lane = panelInfo->mipi.lane;
167 cfg.mode = panelInfo->mipi.mode;
168 cfg.format = panelInfo->mipi.format;
169 cfg.burstMode = panelInfo->mipi.burstMode;
170 cfg.timing.xPixels = panelInfo->width;
171 cfg.timing.hsaPixels = panelInfo->hsw;
172 cfg.timing.hbpPixels = panelInfo->hbp;
173 cfg.timing.hlinePixels = panelInfo->width + panelInfo->hbp + panelInfo->hfp + panelInfo->hsw;
174 cfg.timing.vsaLines = panelInfo->vsw;
175 cfg.timing.vbpLines = panelInfo->vbp;
176 cfg.timing.vfpLines = panelInfo->vfp;
177 cfg.timing.ylines = panelInfo->height;
178
179 cfg.pixelClk = CalcPixelClk(panelInfo);
180 cfg.phyDataRate = CalcDataRate(panelInfo);
181 /* config mipi device */
182 if (MipiDsiSetCfg(priv.mipiHandle, &cfg) != HDF_SUCCESS) {
183 HDF_LOGE("%s: MipiDsiSetCfg failed", __func__);
184 return HDF_FAILURE;
185 }
186 return HDF_SUCCESS;
187 }
188
PanelPowerControl(bool on)189 static void PanelPowerControl(bool on)
190 {
191 if (on) {
192 hal_iomux_init(&priv.pin_led, 1);
193 hal_iomux_init(&priv.pin_rst, 1);
194 hal_iomux_init(&priv.pin_te, 1);
195 hal_gpio_pin_set_dir(priv.pin_rst.pin, HAL_GPIO_DIR_OUT, 1);
196 osDelay(10);
197 hal_gpio_pin_clr(priv.pin_rst.pin);
198 osDelay(10);
199 hal_gpio_pin_set(priv.pin_rst.pin);
200 osDelay(10);
201 } else {
202 osDelay(20);
203 hal_gpio_pin_clr(priv.pin_rst.pin);
204 osDelay(120);
205 hal_gpio_pin_clr(priv.pin_led.pin);
206 }
207 }
208
PanelReadId()209 static int32_t PanelReadId()
210 {
211 uint8_t read_id[3] = {0};
212 uint8_t payload[] = {0x04};
213 struct DsiCmdDesc cmd = {0x06, 0, sizeof(payload), &payload};
214 int32_t ret = MipiDsiRx(priv.mipiHandle, &cmd, 3, read_id);
215 if (ret != HDF_SUCCESS) {
216 HDF_LOGE("%s: MipiDsiRx failed", __func__);
217 return HDF_FAILURE;
218 }
219 HDF_LOGI("%s: read id %02X-%02X-%02X", __func__, read_id[0], read_id[1], read_id[2]);
220 return HDF_SUCCESS;
221 }
222
PanelOn(struct PanelData * panel)223 static int32_t PanelOn(struct PanelData *panel)
224 {
225 (void)panel;
226 PanelPowerControl(true);
227 if (PanelReadId() != HDF_SUCCESS) {
228 return HDF_FAILURE;
229 }
230 /* send mipi power on code */
231 int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]);
232 int32_t i;
233 for (i = 0; i < count; i++) {
234 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_OnCmd[i]));
235 if (ret != HDF_SUCCESS) {
236 HDF_LOGE("%s: MipiDsiTx failed", __func__);
237 return HDF_FAILURE;
238 }
239 }
240 /* set mipi to hs mode */
241 MipiDsiSetHsMode(priv.mipiHandle);
242 hal_gpio_pin_set_dir(priv.pin_led.pin, HAL_GPIO_DIR_OUT, 1);
243 osDelay(20);
244 return HDF_SUCCESS;
245 }
246
PanelOff(struct PanelData * panel)247 static int32_t PanelOff(struct PanelData *panel)
248 {
249 (void)panel;
250 /* send mipi power off code */
251 int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]);
252 int32_t i;
253 for (i = 0; i < count; i++) {
254 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_offCmd[i]));
255 if (ret != HDF_SUCCESS) {
256 HDF_LOGE("%s: MipiDsiTx failed", __func__);
257 return HDF_FAILURE;
258 }
259 }
260 /* set mipi to lp mode */
261 MipiDsiSetLpMode(priv.mipiHandle);
262 PanelPowerControl(false);
263 return HDF_SUCCESS;
264 }
265
PanelSetBacklight(struct PanelData * panel,uint32_t level)266 static int32_t PanelSetBacklight(struct PanelData *panel, uint32_t level)
267 {
268 (void)panel;
269 uint8_t payload[] = {0x51, level & 0xff};
270 struct DsiCmdDesc cmd = {0x15, 0, sizeof(payload), payload};
271 if (MipiDsiTx(priv.mipiHandle, &cmd) != HDF_SUCCESS) {
272 HDF_LOGE("%s: MipiDsiTx failed", __func__);
273 return HDF_FAILURE;
274 }
275 return HDF_SUCCESS;
276 }
277
278 #define REAL_PIN(n) (n / 10 * 8 + n % 10)
PanelGetResource(struct PanelDevice * priv,const struct DeviceResourceNode * resourceNode)279 static uint32_t PanelGetResource(struct PanelDevice *priv, const struct DeviceResourceNode *resourceNode)
280 {
281 struct DeviceResourceIface *res = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
282 if (res == NULL || res->GetUint32 == NULL) {
283 HDF_LOGE("DeviceResourceIface is invalid");
284 return HDF_FAILURE;
285 }
286 uint32_t temp = 0;
287 if (res->GetUint32(resourceNode, "rst_pin", &temp, 0) != HDF_SUCCESS) {
288 HDF_LOGE("%s: failed to get rst_pin", __func__);
289 return HDF_FAILURE;
290 }
291 priv->pin_rst.pin = REAL_PIN(temp);
292 if (res->GetUint32(resourceNode, "te_pin", &temp, 0) != HDF_SUCCESS) {
293 HDF_LOGE("%s: failed to get te_pin", __func__);
294 return HDF_FAILURE;
295 }
296 priv->pin_te.pin = REAL_PIN(temp);
297 if (res->GetUint32(resourceNode, "led_pin", &temp, 0) != HDF_SUCCESS) {
298 HDF_LOGE("%s: failed to get led_pin", __func__);
299 return HDF_FAILURE;
300 }
301 priv->pin_led.pin = REAL_PIN(temp);
302 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);
303 return HDF_SUCCESS;
304 }
305
PanelDriverInit(struct HdfDeviceObject * object)306 static int32_t PanelDriverInit(struct HdfDeviceObject *object)
307 {
308 if (object == NULL) {
309 return HDF_FAILURE;
310 }
311 HDF_LOGD("%s entry !!!", __func__);
312 if (object->property) {
313 if (PanelGetResource(&priv, object->property) != HDF_SUCCESS) {
314 HDF_LOGE("%s: PanelGetResource failed", __func__);
315 return HDF_FAILURE;
316 }
317 }
318 priv.panelData.info = &priv.panelInfo;
319 priv.panelData.init = PanelInit;
320 priv.panelData.on = PanelOn;
321 priv.panelData.off = PanelOff;
322 priv.panelData.setBacklight = PanelSetBacklight;
323 priv.panelData.object = object;
324 if (RegisterPanel(&priv.panelData) != HDF_SUCCESS) {
325 HDF_LOGE("%s: RegisterPanel failed", __func__);
326 return HDF_FAILURE;
327 }
328 return HDF_SUCCESS;
329 }
330
PanelDriverBind(struct HdfDeviceObject * device)331 static int32_t PanelDriverBind(struct HdfDeviceObject *device)
332 {
333 (void)device;
334 return HDF_SUCCESS;
335 }
336
PanelDriverRelease(struct HdfDeviceObject * device)337 static void PanelDriverRelease(struct HdfDeviceObject *device)
338 {
339 (void)device;
340 }
341
342 static struct HdfDriverEntry g_ZZW395DriverEntry = {
343 .moduleVersion = 1,
344 .moduleName = "HDF_PANEL_ZZW395",
345 .Bind = PanelDriverBind,
346 .Init = PanelDriverInit,
347 .Release = PanelDriverRelease,
348 };
349
350 HDF_INIT(g_ZZW395DriverEntry);
351 #endif