• 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_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