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