1 /*
2 * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
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 #include "cmsis_os2.h"
16 #include "hdf_log.h"
17 #include "lcd_abs_if.h"
18 #include "hdf_device_desc.h"
19 #include "device_resource_if.h"
20 #include "hal_gpio.h"
21 #include "hal_iomux.h"
22
23 #ifdef CONFIG_DISPLAY_ICNA3311
24 #define WIDTH 280
25 #define HEIGHT 456
26
27 static uint8_t g_payLoad0[] = {0xfe, 0x00};
28 static uint8_t g_payLoad1[] = {0x35, 0x00};
29 static uint8_t g_payLoad2[] = {0x36, 0x08};
30 static uint8_t g_payLoad3[] = {0x53, 0x20};
31 static uint8_t g_payLoad4[] = {0x51, 0xff};
32 static uint8_t g_payLoad5[] = {0x63, 0xff};
33 static uint8_t g_payLoad6[] = {0x2a, 0x00, 0x14, 0x01, 0x2B};
34 static uint8_t g_payLoad7[] = {0x2b, 0x00, 0x00, 0x01, 0xC7};
35 static uint8_t g_payLoad8[] = {0x11};
36 static uint8_t g_payLoad9[] = {0x29};
37 static uint8_t g_payLoad10[] = {0x28};
38 static uint8_t g_payLoad11[] = {0x10};
39
40 static struct DsiCmdDesc g_OnCmd[] = {
41 {0x15, 0, sizeof(g_payLoad0), g_payLoad0},
42 {0x15, 0, sizeof(g_payLoad1), g_payLoad1},
43 {0x15, 0, sizeof(g_payLoad2), g_payLoad2},
44 {0x15, 0, sizeof(g_payLoad3), g_payLoad3},
45 {0x15, 0, sizeof(g_payLoad4), g_payLoad4},
46 {0x15, 0, sizeof(g_payLoad5), g_payLoad5},
47 {0x39, 0, sizeof(g_payLoad6), g_payLoad6},
48 {0x39, 0, sizeof(g_payLoad7), g_payLoad7},
49 {0x05, 120, sizeof(g_payLoad8), g_payLoad8},
50 {0x05, 120, sizeof(g_payLoad9), g_payLoad9},
51 };
52
53 static struct DsiCmdDesc g_offCmd[] = {
54 {0x15, 0, sizeof(g_payLoad0), g_payLoad0},
55 {0x05, 20, sizeof(g_payLoad10), g_payLoad10},
56 {0x05, 120, sizeof(g_payLoad11), g_payLoad11},
57 };
58
59 struct PanelDevice {
60 struct PanelData panelData;
61 struct PanelInfo panelInfo;
62 DevHandle mipiHandle;
63 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_rst;
64 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_te;
65 struct HAL_IOMUX_PIN_FUNCTION_MAP pin_vci;
66 };
67
68 static struct PanelDevice priv = {
69 .panelInfo = {
70 .width = WIDTH,
71 .height = HEIGHT,
72 .hbp = 8,
73 .hfp = 8,
74 .hsw = 2,
75 .vbp = 8,
76 .vfp = 8,
77 .vsw = 2,
78 .frameRate = 60,
79 .intfType = MIPI_DSI,
80 .intfSync = OUTPUT_USER,
81 .mipi = {DSI_1_LANES, DSI_CMD_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT},
82 },
83 .pin_rst = {
84 HAL_GPIO_PIN_P0_3,
85 HAL_IOMUX_FUNC_AS_GPIO,
86 HAL_IOMUX_PIN_VOLTAGE_VIO,
87 HAL_IOMUX_PIN_NOPULL,
88 },
89 .pin_te = {
90 HAL_IOMUX_PIN_P2_1,
91 HAL_IOMUX_FUNC_DISPLAY_TE,
92 HAL_IOMUX_PIN_VOLTAGE_VIO,
93 HAL_IOMUX_PIN_NOPULL,
94 },
95 .pin_vci = {
96 HAL_IOMUX_PIN_P0_2,
97 HAL_IOMUX_FUNC_AS_GPIO,
98 HAL_IOMUX_PIN_VOLTAGE_VIO,
99 HAL_IOMUX_PIN_NOPULL,
100 },
101 };
102
PanelInit(struct PanelData * panel)103 static int32_t PanelInit(struct PanelData *panel)
104 {
105 if (panel == NULL || panel->info == NULL) {
106 return HDF_FAILURE;
107 }
108 priv.mipiHandle = MipiDsiOpen(0);
109 if (priv.mipiHandle == NULL) {
110 HDF_LOGE("%s: MipiDsiOpen failed", __func__);
111 return HDF_FAILURE;
112 }
113 HDF_LOGI("%s: width %d, height %d", __func__, WIDTH, HEIGHT);
114
115 struct PanelInfo *panelInfo = panel->info;
116 struct MipiCfg cfg = {0};
117 cfg.lane = panelInfo->mipi.lane;
118 cfg.mode = panelInfo->mipi.mode;
119 cfg.format = panelInfo->mipi.format;
120 cfg.burstMode = panelInfo->mipi.burstMode;
121 cfg.timing.xPixels = panelInfo->width;
122 cfg.timing.hsaPixels = panelInfo->hsw;
123 cfg.timing.hbpPixels = panelInfo->hbp;
124 cfg.timing.hlinePixels = panelInfo->width + panelInfo->hbp + panelInfo->hfp + panelInfo->hsw;
125 cfg.timing.vsaLines = panelInfo->vsw;
126 cfg.timing.vbpLines = panelInfo->vbp;
127 cfg.timing.vfpLines = panelInfo->vfp;
128 cfg.timing.ylines = panelInfo->height;
129
130 cfg.pixelClk = CalcPixelClk(panelInfo);
131 cfg.phyDataRate = CalcDataRate(panelInfo);
132 /* config mipi device */
133 if (MipiDsiSetCfg(priv.mipiHandle, &cfg) != HDF_SUCCESS) {
134 HDF_LOGE("%s: MipiDsiSetCfg failed", __func__);
135 return HDF_FAILURE;
136 }
137 return HDF_SUCCESS;
138 }
139
PanelPowerControl(bool on)140 static void PanelPowerControl(bool on)
141 {
142 if (on) {
143 hal_iomux_init(&priv.pin_vci, 1);
144 hal_iomux_init(&priv.pin_rst, 1);
145 hal_iomux_init(&priv.pin_te, 1);
146 hal_gpio_pin_set_dir(priv.pin_rst.pin, HAL_GPIO_DIR_OUT, 0);
147 hal_gpio_pin_set_dir(priv.pin_vci.pin, HAL_GPIO_DIR_OUT, 0);
148 hal_gpio_pin_set(priv.pin_vci.pin);
149 osDelay(20);
150 hal_gpio_pin_set(priv.pin_rst.pin);
151 osDelay(20);
152 } else {
153 osDelay(120);
154 hal_gpio_pin_clr(priv.pin_rst.pin);
155 osDelay(20);
156 hal_gpio_pin_clr(priv.pin_vci.pin);
157 }
158 }
159
PanelOn(struct PanelData * panel)160 static int32_t PanelOn(struct PanelData *panel)
161 {
162 (void)panel;
163 PanelPowerControl(true);
164 /* send mipi power on code */
165 int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]);
166 int32_t i;
167 for (i = 0; i < count; i++) {
168 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_OnCmd[i]));
169 if (ret != HDF_SUCCESS) {
170 HDF_LOGE("%s: MipiDsiTx failed", __func__);
171 return HDF_FAILURE;
172 }
173 }
174 /* set mipi to hs mode */
175 MipiDsiSetHsMode(priv.mipiHandle);
176 return HDF_SUCCESS;
177 }
178
PanelOff(struct PanelData * panel)179 static int32_t PanelOff(struct PanelData *panel)
180 {
181 (void)panel;
182 /* send mipi power off code */
183 int32_t count = sizeof(g_offCmd) / sizeof(g_offCmd[0]);
184 int32_t i;
185 for (i = 0; i < count; i++) {
186 int32_t ret = MipiDsiTx(priv.mipiHandle, &(g_offCmd[i]));
187 if (ret != HDF_SUCCESS) {
188 HDF_LOGE("%s: MipiDsiTx failed", __func__);
189 return HDF_FAILURE;
190 }
191 }
192 /* set mipi to lp mode */
193 MipiDsiSetLpMode(priv.mipiHandle);
194 PanelPowerControl(false);
195 return HDF_SUCCESS;
196 }
197
PanelSetBacklight(struct PanelData * panel,uint32_t level)198 static int32_t PanelSetBacklight(struct PanelData *panel, uint32_t level)
199 {
200 (void)panel;
201 uint8_t payload[] = {0x51, level & 0xff};
202 struct DsiCmdDesc cmd = {0x15, 0, sizeof(payload), payload};
203 if (MipiDsiTx(priv.mipiHandle, &cmd) != HDF_SUCCESS) {
204 HDF_LOGE("%s: MipiDsiTx failed", __func__);
205 return HDF_FAILURE;
206 }
207 return HDF_SUCCESS;
208 }
209
210 #define REAL_PIN(n) (n / 10 * 8 + n % 10)
PanelGetResource(struct PanelDevice * priv,const struct DeviceResourceNode * resourceNode)211 static uint32_t PanelGetResource(struct PanelDevice *priv, const struct DeviceResourceNode *resourceNode)
212 {
213 struct DeviceResourceIface *res = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
214 if (res == NULL || res->GetUint32 == NULL) {
215 HDF_LOGE("DeviceResourceIface is invalid");
216 return HDF_FAILURE;
217 }
218 uint32_t temp = 0;
219 if (res->GetUint32(resourceNode, "rst_pin", &temp, 0) != HDF_SUCCESS) {
220 HDF_LOGE("%s: failed to get rst_pin", __func__);
221 return HDF_FAILURE;
222 }
223 priv->pin_rst.pin = REAL_PIN(temp);
224 if (res->GetUint32(resourceNode, "te_pin", &temp, 0) != HDF_SUCCESS) {
225 HDF_LOGE("%s: failed to get te_pin", __func__);
226 return HDF_FAILURE;
227 }
228 priv->pin_te.pin = REAL_PIN(temp);
229 if (res->GetUint32(resourceNode, "vci_pin", &temp, 0) != HDF_SUCCESS) {
230 HDF_LOGE("%s: failed to get vci_pin", __func__);
231 return HDF_FAILURE;
232 }
233 priv->pin_vci.pin = REAL_PIN(temp);
234 HDF_LOGD("%s: rst_pin=%d, te_pin=%d, vci_pin=%d", __func__, priv->pin_rst.pin, priv->pin_te.pin, priv->pin_vci.pin);
235 return HDF_SUCCESS;
236 }
237
PanelDriverInit(struct HdfDeviceObject * object)238 static int32_t PanelDriverInit(struct HdfDeviceObject *object)
239 {
240 if (object == NULL) {
241 return HDF_FAILURE;
242 }
243 if (object->property) {
244 if (PanelGetResource(&priv, object->property) != HDF_SUCCESS) {
245 HDF_LOGE("%s: PanelGetResource failed", __func__);
246 return HDF_FAILURE;
247 }
248 }
249 priv.panelData.info = &priv.panelInfo;
250 priv.panelData.init = PanelInit;
251 priv.panelData.on = PanelOn;
252 priv.panelData.off = PanelOff;
253 priv.panelData.setBacklight = PanelSetBacklight;
254 priv.panelData.object = object;
255 if (RegisterPanel(&priv.panelData) != HDF_SUCCESS) {
256 HDF_LOGE("%s: RegisterPanel failed", __func__);
257 return HDF_FAILURE;
258 }
259 return HDF_SUCCESS;
260 }
261
PanelDriverBind(struct HdfDeviceObject * device)262 static int32_t PanelDriverBind(struct HdfDeviceObject *device)
263 {
264 (void)device;
265 return HDF_SUCCESS;
266 }
267
PanelDriverRelease(struct HdfDeviceObject * device)268 static void PanelDriverRelease(struct HdfDeviceObject *device)
269 {
270 (void)device;
271 }
272
273 static struct HdfDriverEntry g_ICNA3311DriverEntry = {
274 .moduleVersion = 1,
275 .moduleName = "HDF_PANEL_ICNA3311",
276 .Bind = PanelDriverBind,
277 .Init = PanelDriverInit,
278 .Release = PanelDriverRelease,
279 };
280
281 HDF_INIT(g_ICNA3311DriverEntry);
282 #endif