• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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