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_bl.h"
11 #include "hdf_disp.h"
12 #include "hdf_log.h"
13 #include "mipi_dsi_if.h"
14 #include "osal.h"
15 #include "pwm_if.h"
16
17 #define RESET_GPIO 5
18 #define MIPI_DSI0 0
19 #define BLK_PWM1 1
20 #define PWM_MAX_PERIOD 100000
21 /* backlight setting */
22 #define MIN_LEVEL 0
23 #define MAX_LEVEL 255
24 #define DEFAULT_LEVEL 100
25
26 #define WIDTH 480
27 #define HEIGHT 960
28 #define HORIZONTAL_BACK_PORCH 20
29 #define HORIZONTAL_FRONT_PORCH 20
30 #define HORIZONTAL_SYNC_WIDTH 10
31 #define VERTICAL_BACK_PORCH 14
32 #define VERTICAL_FRONT_PORCH 16
33 #define VERTICAL_SYNC_WIDTH 2
34 #define FRAME_RATE 60
35
36 /* panel on command payload */
37 static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A };
38 static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 };
39 static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B };
40 static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A };
41 static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C };
42 static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C };
43 static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 };
44 static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 };
45 static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 };
46 static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 };
47 static uint8_t g_payLoad10[] = { 0xb7, 0x41 };
48 static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 };
49 static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 };
50 static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 };
51 static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF };
52 static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 };
53 static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 };
54 static uint8_t g_payLoad17[] = { 0xc7, 0x04 };
55 static uint8_t g_payLoad18[] = {
56 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40,
57 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52,
58 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06
59 };
60 static uint8_t g_payLoad19[] = { 0x11 };
61 static uint8_t g_payLoad20[] = { 0x29 };
62
63 struct DsiCmdDesc g_OnCmd[] = {
64 { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 },
65 { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 },
66 { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 },
67 { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 },
68 { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 },
69 { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 },
70 { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 },
71 { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 },
72 { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 },
73 { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 },
74 { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 },
75 { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 },
76 { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 },
77 { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 },
78 { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 },
79 { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 },
80 { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 },
81 { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 },
82 { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 },
83 { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 },
84 { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 },
85 };
86
87 /* panel off command payload */
88 static uint8_t g_offPayLoad0[] = { 0x28 };
89 static uint8_t g_offPayLoad1[] = { 0x10 };
90 struct DsiCmdDesc g_offCmd[] = {
91 { 0x05, 20, sizeof(g_offPayLoad0), g_offPayLoad0 },
92 { 0x05, 120, sizeof(g_offPayLoad1), g_offPayLoad1 },
93 };
94
95 struct Icn9700Dev {
96 struct PanelData panel;
97 DevHandle mipiHandle;
98 uint16_t reset_gpio;
99 uint16_t reset_delay;
100 };
101
LcdResetOn(struct Icn9700Dev * icn9700)102 static int32_t LcdResetOn(struct Icn9700Dev *icn9700)
103 {
104 int32_t ret;
105
106 ret = GpioSetDir(icn9700->reset_gpio, GPIO_DIR_OUT);
107 if (ret != HDF_SUCCESS) {
108 HDF_LOGE("GpioSetDir failed, ret:%d", ret);
109 return HDF_FAILURE;
110 }
111 ret = GpioWrite(icn9700->reset_gpio, GPIO_VAL_HIGH);
112 if (ret != HDF_SUCCESS) {
113 HDF_LOGE("GpioWrite failed, ret:%d", ret);
114 return HDF_FAILURE;
115 }
116 /* delay 20ms */
117 OsalMSleep(icn9700->reset_delay);
118 return HDF_SUCCESS;
119 }
120
LcdResetOff(struct Icn9700Dev * icn9700)121 static int32_t LcdResetOff(struct Icn9700Dev *icn9700)
122 {
123 int32_t ret;
124
125 ret = GpioSetDir(icn9700->reset_gpio, GPIO_DIR_OUT);
126 if (ret != HDF_SUCCESS) {
127 HDF_LOGE("GpioSetDir failed, ret:%d", ret);
128 return HDF_FAILURE;
129 }
130 ret = GpioWrite(icn9700->reset_gpio, GPIO_VAL_LOW);
131 if (ret != HDF_SUCCESS) {
132 HDF_LOGE("GpioWrite failed, ret:%d", ret);
133 return HDF_FAILURE;
134 }
135 /* delay 20ms */
136 OsalMSleep(icn9700->reset_delay);
137 return HDF_SUCCESS;
138 }
139
PanelToIcn9700Dev(const struct PanelData * panel)140 static struct Icn9700Dev *PanelToIcn9700Dev(const struct PanelData *panel)
141 {
142 struct Icn9700Dev *icn9700 = NULL;
143
144 if (panel == NULL) {
145 HDF_LOGE("%s: panel is null", __func__);
146 return NULL;
147 }
148 if (panel->object == NULL) {
149 HDF_LOGE("%s: object is null", __func__);
150 return NULL;
151 }
152 icn9700 = (struct Icn9700Dev *)panel->object->priv;
153 return icn9700;
154 }
155
Icn9700Init(struct PanelData * panel)156 static int32_t Icn9700Init(struct PanelData *panel)
157 {
158 struct Icn9700Dev *icn9700 = NULL;
159
160 icn9700 = PanelToIcn9700Dev(panel);
161 if (icn9700 == NULL) {
162 HDF_LOGE("%s: icn9700 is null", __func__);
163 return HDF_FAILURE;
164 }
165 icn9700->mipiHandle = MipiDsiOpen(MIPI_DSI0);
166 if (icn9700->mipiHandle == NULL) {
167 HDF_LOGE("%s: MipiDsiOpen failed", __func__);
168 return HDF_FAILURE;
169 }
170 return HDF_SUCCESS;
171 }
172
Icn9700On(struct PanelData * panel)173 static int32_t Icn9700On(struct PanelData *panel)
174 {
175 int32_t ret;
176 struct Icn9700Dev *icn9700 = NULL;
177
178 icn9700 = PanelToIcn9700Dev(panel);
179 if (icn9700 == NULL) {
180 HDF_LOGE("%s: icn9700 is null", __func__);
181 return HDF_FAILURE;
182 }
183 /* lcd reset power on */
184 ret = LcdResetOn(icn9700);
185 if (ret != HDF_SUCCESS) {
186 HDF_LOGE("%s: LcdResetOn failed", __func__);
187 return HDF_FAILURE;
188 }
189 if (icn9700->mipiHandle == NULL) {
190 HDF_LOGE("%s: mipiHandle is null", __func__);
191 return HDF_FAILURE;
192 }
193 /* send mipi init code */
194 int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]);
195 int32_t i;
196 /* set mipi to lp mode */
197 MipiDsiSetLpMode(icn9700->mipiHandle);
198 for (i = 0; i < count; i++) {
199 ret = MipiDsiTx(icn9700->mipiHandle, &(g_OnCmd[i]));
200 if (ret != HDF_SUCCESS) {
201 HDF_LOGE("%s: MipiDsiTx failed", __func__);
202 return HDF_FAILURE;
203 }
204 }
205 /* set mipi to hs mode */
206 MipiDsiSetHsMode(icn9700->mipiHandle);
207 return HDF_SUCCESS;
208 }
209
Icn9700Off(struct PanelData * panel)210 static int32_t Icn9700Off(struct PanelData *panel)
211 {
212 int32_t ret;
213 struct Icn9700Dev *icn9700 = NULL;
214
215 icn9700 = PanelToIcn9700Dev(panel);
216 if (icn9700 == NULL) {
217 HDF_LOGE("%s: icn9700 is null", __func__);
218 return HDF_FAILURE;
219 }
220 if (icn9700->mipiHandle == NULL) {
221 HDF_LOGE("%s: mipiHandle is null", __func__);
222 return HDF_FAILURE;
223 }
224 /* send mipi init code */
225 int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]);
226 int32_t i;
227 /* set mipi to lp mode */
228 MipiDsiSetLpMode(icn9700->mipiHandle);
229 for (i = 0; i < count; i++) {
230 ret = MipiDsiTx(icn9700->mipiHandle, &(g_offCmd[i]));
231 if (ret != HDF_SUCCESS) {
232 HDF_LOGE("%s: MipiDsiTx failed", __func__);
233 return HDF_FAILURE;
234 }
235 }
236 /* lcd reset power off */
237 ret = LcdResetOff(icn9700);
238 if (ret != HDF_SUCCESS) {
239 HDF_LOGE("%s: LcdResetOff failed", __func__);
240 return HDF_FAILURE;
241 }
242 return HDF_SUCCESS;
243 }
244
Icn9700EsdCheckFunc(struct PanelData * panel)245 static int32_t Icn9700EsdCheckFunc(struct PanelData *panel)
246 {
247 struct Icn9700Dev *icn9700 = NULL;
248
249 icn9700 = PanelToIcn9700Dev(panel);
250 if (icn9700 == NULL) {
251 HDF_LOGE("%s: icn9700 is null", __func__);
252 return HDF_FAILURE;
253 }
254 HDF_LOGE("%s: enter", __func__);
255 return HDF_SUCCESS;
256 }
257
258 #define OUTPUT_USER 0 /* output timing type */
259 static struct PanelInfo g_panelInfo = {
260 .width = WIDTH, /* width */
261 .height = HEIGHT, /* height */
262 .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */
263 .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */
264 .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */
265 .vbp = VERTICAL_BACK_PORCH, /* vertical back porch */
266 .vfp = VERTICAL_FRONT_PORCH, /* vertical front porch */
267 .vsw = VERTICAL_SYNC_WIDTH, /* vertical sync width */
268 .frameRate = FRAME_RATE, /* frame rate */
269 .intfType = MIPI_DSI, /* panel interface type */
270 .intfSync = OUTPUT_USER,
271 /* mipi config info */
272 .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT },
273 /* backlight config info */
274 .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL },
275 .pwm = { BLK_PWM1, PWM_MAX_PERIOD },
276 };
277
278 static struct PanelEsd g_panelEsd = {
279 .support = false,
280 .checkFunc = Icn9700EsdCheckFunc,
281 };
282
Icn9700PanelInit(struct PanelData * panel)283 static void Icn9700PanelInit(struct PanelData *panel)
284 {
285 panel->info = &g_panelInfo;
286 panel->esd = &g_panelEsd;
287 panel->init = Icn9700Init;
288 panel->on = Icn9700On;
289 panel->off = Icn9700Off;
290 }
291
Icn9700EntryInit(struct HdfDeviceObject * object)292 static int32_t Icn9700EntryInit(struct HdfDeviceObject *object)
293 {
294 struct Icn9700Dev *icn9700 = NULL;
295
296 if (object == NULL) {
297 HDF_LOGE("%s: object is null", __func__);
298 return HDF_FAILURE;
299 }
300 icn9700 = (struct Icn9700Dev *)OsalMemCalloc(sizeof(struct Icn9700Dev));
301 if (icn9700 == NULL) {
302 HDF_LOGE("%s icn9700 malloc fail", __func__);
303 return HDF_FAILURE;
304 }
305 Icn9700PanelInit(&icn9700->panel);
306 icn9700->panel.object = object;
307 icn9700->reset_gpio = RESET_GPIO;
308 icn9700->reset_delay = 20; // delay 20ms
309 object->priv = (void *)icn9700;
310 icn9700->panel.blDev = GetBacklightDev("hdf_pwm");
311 if (icn9700->panel.blDev == NULL) {
312 HDF_LOGE("%s GetBacklightDev fail", __func__);
313 return HDF_FAILURE;
314 }
315 if (RegisterPanel(&icn9700->panel) != HDF_SUCCESS) {
316 HDF_LOGE("%s: RegisterPanel failed", __func__);
317 return HDF_FAILURE;
318 }
319 HDF_LOGI("%s: exit succ", __func__);
320 return HDF_SUCCESS;
321 }
322
323 struct HdfDriverEntry g_icn9700DevEntry = {
324 .moduleVersion = 1,
325 .moduleName = "LCD_ICN9700",
326 .Init = Icn9700EntryInit,
327 };
328
329 HDF_INIT(g_icn9700DevEntry);
330