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