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 "ili9881c_boe.h"
10 #include "gpio_if.h"
11 #include "hdf_disp.h"
12 #include "osal.h"
13
Ili9881cBoeSendCmds(struct mipi_dsi_device * dsi,const struct DsiCmdDesc * cmds,int size)14 static int Ili9881cBoeSendCmds(struct mipi_dsi_device *dsi,
15 const struct DsiCmdDesc *cmds, int size)
16 {
17 int32_t i;
18
19 if (dsi == NULL) {
20 return -EINVAL;
21 }
22
23 for (i = 0; i < size; i++) {
24 mipi_dsi_generic_write(dsi, cmds[i].payload, cmds[i].dataLen);
25 if (cmds[i].delay) {
26 OsalMSleep(cmds[i].delay);
27 }
28 }
29 return HDF_SUCCESS;
30 }
31
ToIli9881cBoeDev(const struct PanelData * panel)32 static struct Ili9881cBoeDev *ToIli9881cBoeDev(const struct PanelData *panel)
33 {
34 return (struct Ili9881cBoeDev *)panel->object->priv;
35 }
36
SetGpioState(uint16_t gpio,uint16_t dir,uint16_t level,uint32_t delay)37 static SetGpioState(uint16_t gpio, uint16_t dir, uint16_t level, uint32_t delay)
38 {
39 int32_t ret;
40
41 ret = GpioSetDir(gpio, dir);
42 if (ret != HDF_SUCCESS) {
43 HDF_LOGE("%s GpioSetDir failed, ret:%d", __func__, ret);
44 return HDF_FAILURE;
45 }
46 ret = GpioWrite(gpio, level);
47 if (ret != HDF_SUCCESS) {
48 HDF_LOGE("%s GpioWrite failed, ret:%d", __func__, ret);
49 return HDF_FAILURE;
50 }
51 OsalMSleep(delay);
52 return HDF_SUCCESS;
53 }
54
Ili9881cBoePrepare(const struct Ili9881cBoeDev * ili9881cBoeDev)55 static int32_t Ili9881cBoePrepare(const struct Ili9881cBoeDev *ili9881cBoeDev)
56 {
57 int32_t i;
58 int32_t ret;
59 int32_t items;
60 struct GpioTiming *timing = NULL;
61
62 HDF_LOGI("%s()", __func__);
63 ret = regulator_enable(ili9881cBoeDev->supply);
64 if (ret < 0) {
65 HDF_LOGE("regulator_enable failed");
66 }
67 ret = SetGpioState(ili9881cBoeDev->avddGpio, GPIO_DIR_OUT, GPIO_VAL_HIGH, 5); /* delay 5ms */
68 if (ret != HDF_SUCCESS) {
69 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->avddGpio);
70 return HDF_FAILURE;
71 }
72 ret = SetGpioState(ili9881cBoeDev->aveeGpio, GPIO_DIR_OUT, GPIO_VAL_HIGH, 5);
73 if (ret != HDF_SUCCESS) {
74 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->aveeGpio);
75 return HDF_FAILURE;
76 }
77 ret = SetGpioState(ili9881cBoeDev->vghlGpio, GPIO_DIR_OUT, GPIO_VAL_HIGH, 5);
78 if (ret != HDF_SUCCESS) {
79 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->vghlGpio);
80 return HDF_FAILURE;
81 }
82 ret = SetGpioState(ili9881cBoeDev->tsrstGpio, GPIO_DIR_OUT, GPIO_VAL_HIGH, 5);
83 if (ret != HDF_SUCCESS) {
84 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->tsrstGpio);
85 return HDF_FAILURE;
86 }
87 ret = GpioSetDir(ili9881cBoeDev->resetGpio, GPIO_DIR_OUT);
88 if (ret != HDF_SUCCESS) {
89 HDF_LOGE("GpioSetDir failed, ret:%d", ret);
90 return HDF_FAILURE;
91 }
92 items = ili9881cBoeDev->rstOnSeq.items;
93 timing = ili9881cBoeDev->rstOnSeq.timing;
94 for (i = 0; i < items; i++) {
95 GpioWrite(ili9881cBoeDev->resetGpio, timing[i].level);
96 OsalMSleep(timing[i].delay);
97 }
98 return HDF_SUCCESS;
99 }
100
Ili9881cBoeUnprepare(const struct Ili9881cBoeDev * ili9881cBoeDev)101 static int32_t Ili9881cBoeUnprepare(const struct Ili9881cBoeDev *ili9881cBoeDev)
102 {
103 int32_t i;
104 int32_t ret;
105 int32_t items;
106 struct GpioTiming *timing = NULL;
107
108 HDF_LOGI("%s()", __func__);
109 ret = SetGpioState(ili9881cBoeDev->avddGpio, GPIO_DIR_OUT, GPIO_VAL_LOW, 5); /* delay 5ms */
110 if (ret != HDF_SUCCESS) {
111 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->avddGpio);
112 return HDF_FAILURE;
113 }
114 ret = SetGpioState(ili9881cBoeDev->aveeGpio, GPIO_DIR_OUT, GPIO_VAL_LOW, 5);
115 if (ret != HDF_SUCCESS) {
116 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->aveeGpio);
117 return HDF_FAILURE;
118 }
119 ret = SetGpioState(ili9881cBoeDev->vghlGpio, GPIO_DIR_OUT, GPIO_VAL_LOW, 5);
120 if (ret != HDF_SUCCESS) {
121 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->vghlGpio);
122 return HDF_FAILURE;
123 }
124 ret = SetGpioState(ili9881cBoeDev->tsrstGpio, GPIO_DIR_OUT, GPIO_VAL_LOW, 5);
125 if (ret != HDF_SUCCESS) {
126 HDF_LOGE("%s SetGpioState failed, gpio:%d", __func__, ili9881cBoeDev->tsrstGpio);
127 return HDF_FAILURE;
128 }
129 ret = GpioSetDir(ili9881cBoeDev->resetGpio, GPIO_DIR_OUT);
130 if (ret != HDF_SUCCESS) {
131 HDF_LOGE("GpioSetDir failed, ret:%d", ret);
132 return HDF_FAILURE;
133 }
134 items = ili9881cBoeDev->rstOffSeq.items;
135 timing = ili9881cBoeDev->rstOffSeq.timing;
136 for (i = 0; i < items; i++) {
137 GpioWrite(ili9881cBoeDev->resetGpio, timing[i].level);
138 OsalMSleep(timing[i].delay);
139 }
140 regulator_disable(ili9881cBoeDev->supply);
141 return HDF_SUCCESS;
142 }
143
Ili9881cBoeOn(struct PanelData * panel)144 static int32_t Ili9881cBoeOn(struct PanelData *panel)
145 {
146 int32_t ret;
147 struct Ili9881cBoeDev *ili9881cBoeDev = NULL;
148
149 HDF_LOGI("%s()", __func__);
150 ili9881cBoeDev = ToIli9881cBoeDev(panel);
151 ret = Ili9881cBoePrepare(ili9881cBoeDev);
152 if (ret != HDF_SUCCESS) {
153 HDF_LOGE("%s Ili9881cBoePrepare failed", __func__);
154 return HDF_FAILURE;
155 }
156 ret = Ili9881cBoeSendCmds(ili9881cBoeDev->dsiDev, g_panelOnCode,
157 sizeof(g_panelOnCode) / sizeof(g_panelOnCode[0]));
158 if (ret != HDF_SUCCESS) {
159 HDF_LOGE("%s Ili9881cBoeSendCmds failed", __func__);
160 return HDF_FAILURE;
161 }
162 return HDF_SUCCESS;
163 }
164
Ili9881cBoeOff(struct PanelData * panel)165 static int32_t Ili9881cBoeOff(struct PanelData *panel)
166 {
167 int32_t ret;
168 struct Ili9881cBoeDev *ili9881cBoeDev = NULL;
169
170 ili9881cBoeDev = ToIli9881cBoeDev(panel);
171 HDF_LOGI(" %s line = %d", __func__, __LINE__);
172 ret = Ili9881cBoeSendCmds(ili9881cBoeDev->dsiDev, g_panelOffCode,
173 sizeof(g_panelOffCode) / sizeof(g_panelOffCode[0]));
174 if (ret != HDF_SUCCESS) {
175 HDF_LOGE("%s Ili9881cBoeSendCmds failed", __func__);
176 return HDF_FAILURE;
177 }
178 ret = Ili9881cBoeUnprepare(ili9881cBoeDev);
179 if (ret != HDF_SUCCESS) {
180 HDF_LOGE("%s Ili9881cBoeUnprepare failed", __func__);
181 return HDF_FAILURE;
182 }
183 return HDF_SUCCESS;
184 }
185
Ili9881cBoeInit(struct PanelData * panel)186 static int32_t Ili9881cBoeInit(struct PanelData *panel)
187 {
188 return 0;
189 }
190
191 #define BLK_PWM_INDEX 2
192 #define PWM_MAX_PERIOD 40000
193 /* backlight setting */
194 #define MIN_LEVEL 0
195 #define MAX_LEVEL 255
196 #define DEFAULT_LEVEL 127
197
198 static struct PanelInfo g_panelInfo = {
199 .width = 800, /* width */
200 .height = 1280, /* height */
201 .hbp = 80, /* horizontal back porch */
202 .hfp = 80, /* horizontal front porch */
203 .hsw = 20, /* horizontal sync width */
204 .vbp = 12, /* vertical back porch */
205 .vfp = 20, /* vertical front porch */
206 .vsw = 4, /* vertical sync width */
207 .clockFreq = 76800000, /* clock */
208 .pWidth = 150, /* physical width */
209 .pHeight = 240, /* physical height */
210 .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL },
211 };
212
213 static struct GpioTiming g_rstOnSeq[] = {
214 {1, 5}, /* high, delay 5ms */
215 {0, 20}, /* low, delay 20ms */
216 {1, 30}, /* high, delay 30ms */
217 };
218
219 static struct GpioTiming g_rstOffSeq = {0, 10}; /* low, delay 10ms */
220
Ili9881cBoeResInit(struct Ili9881cBoeDev * ili9881cBoeDev)221 static void Ili9881cBoeResInit(struct Ili9881cBoeDev *ili9881cBoeDev)
222 {
223 ili9881cBoeDev->avddGpio = AVDD_GPIO;
224 ili9881cBoeDev->aveeGpio = AVEE_GPIO;
225 ili9881cBoeDev->vghlGpio = VGHL_GPIO;
226 ili9881cBoeDev->tsrstGpio = TSRST_GPIO;
227 ili9881cBoeDev->resetGpio = RESET_GPIO;
228 ili9881cBoeDev->rstOnSeq.items = sizeof(g_rstOnSeq) / sizeof(struct GpioTiming);
229 ili9881cBoeDev->rstOnSeq.timing = g_rstOnSeq;
230 ili9881cBoeDev->rstOffSeq.items = 1; /* number of reset off sequence */
231 ili9881cBoeDev->rstOffSeq.timing = &g_rstOffSeq;
232 ili9881cBoeDev->dsiDev->lanes = 4; /* number of active data lanes */
233 ili9881cBoeDev->dsiDev->format = 0; /* pixel format for video mode */
234 ili9881cBoeDev->dsiDev->mode_flags = 3; /* DSI operation mode related flags */
235 ili9881cBoeDev->panel.info = &g_panelInfo;
236 ili9881cBoeDev->panel.init = Ili9881cBoeInit;
237 ili9881cBoeDev->panel.on = Ili9881cBoeOn;
238 ili9881cBoeDev->panel.off = Ili9881cBoeOff;
239 ili9881cBoeDev->panel.priv = ili9881cBoeDev->dsiDev;
240 }
241
Ili9881cBoeEntryInit(struct HdfDeviceObject * object)242 int32_t Ili9881cBoeEntryInit(struct HdfDeviceObject *object)
243 {
244 struct device_node *panelNode = NULL;
245 struct Ili9881cBoeDev *ili9881cBoeDev = NULL;
246
247 ili9881cBoeDev = (struct Ili9881cBoeDev *)OsalMemCalloc(sizeof(struct Ili9881cBoeDev));
248 if (ili9881cBoeDev == NULL) {
249 HDF_LOGE("%s ili9881cBoeDev malloc fail", __func__);
250 return HDF_FAILURE;
251 }
252 panelNode = of_find_compatible_node(NULL, NULL, "sprd,generic-mipi-panel");
253 if (panelNode == NULL) {
254 HDF_LOGE("%s of_find_compatible_node fail", __func__);
255 goto FAIL;
256 }
257 ili9881cBoeDev->dsiDev = of_find_mipi_dsi_device_by_node(panelNode);
258 if (ili9881cBoeDev->dsiDev == NULL) {
259 HDF_LOGE("%s of_find_mipi_dsi_device_by_node fail", __func__);
260 goto FAIL;
261 }
262 ili9881cBoeDev->supply = devm_regulator_get(&ili9881cBoeDev->dsiDev->dev, "power");
263 if (ili9881cBoeDev->supply == NULL) {
264 HDF_LOGE("Get regulator fail");
265 goto FAIL;
266 }
267 Ili9881cBoeResInit(ili9881cBoeDev);
268 ili9881cBoeDev->panel.blDev = GetBacklightDev("hdf_pwm");
269 if (ili9881cBoeDev->panel.blDev == NULL) {
270 HDF_LOGE("%s GetBacklightDev fail", __func__);
271 goto FAIL;
272 }
273 ili9881cBoeDev->panel.object = object;
274 object->priv = ili9881cBoeDev;
275 if (RegisterPanel(&ili9881cBoeDev->panel) == HDF_SUCCESS) {
276 HDF_LOGI("%s success", __func__);
277 return HDF_SUCCESS;
278 }
279
280 FAIL:
281 OsalMemFree(ili9881cBoeDev);
282 return HDF_FAILURE;
283 }
284
285 struct HdfDriverEntry g_ili9881cBoeDevEntry = {
286 .moduleVersion = 1,
287 .moduleName = "LCD_ILI9881CBOE",
288 .Init = Ili9881cBoeEntryInit,
289 };
290
291 HDF_INIT(g_ili9881cBoeDevEntry);
292