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 "hi35xx_disp.h"
10 #include <securec.h>
11 #include "hdf_base.h"
12 #include "hdf_device_desc.h"
13 #include "hdf_disp.h"
14 #include "hdf_log.h"
15 #include "osal_io.h"
16 #include "pwm_if.h"
17
18 #define TRANSFORM_KILO 1000
19 #define TRANSFORM_MILL 1000000
20
MipiMuxCfg(unsigned long ioCfgBase)21 static void MipiMuxCfg(unsigned long ioCfgBase)
22 {
23 /* config dsi data lane0 */
24 OSAL_WRITEL(0x670, ioCfgBase + 0x0088);
25 OSAL_WRITEL(0x670, ioCfgBase + 0x0084);
26 /* config dsi data lane1 */
27 OSAL_WRITEL(0x470, ioCfgBase + 0x007C);
28 OSAL_WRITEL(0x470, ioCfgBase + 0x0080);
29 /* config dsi data lane2 */
30 OSAL_WRITEL(0x470, ioCfgBase + 0x006C);
31 OSAL_WRITEL(0x470, ioCfgBase + 0x0070);
32 /* config dsi data lane3 */
33 OSAL_WRITEL(0x670, ioCfgBase + 0x0068);
34 OSAL_WRITEL(0x670, ioCfgBase + 0x0064);
35 /* config dsi clock lane */
36 OSAL_WRITEL(0x460, ioCfgBase + 0x0074);
37 OSAL_WRITEL(0x460, ioCfgBase + 0x0078);
38 }
39
Lcd6BitMuxCfg(unsigned long ioCfgBase)40 static void Lcd6BitMuxCfg(unsigned long ioCfgBase)
41 {
42 OSAL_WRITEL(0x4f4, ioCfgBase + 0x0068);
43 OSAL_WRITEL(0x454, ioCfgBase + 0x0084);
44 OSAL_WRITEL(0x474, ioCfgBase + 0x007c);
45 OSAL_WRITEL(0x674, ioCfgBase + 0x0088);
46 OSAL_WRITEL(0x474, ioCfgBase + 0x0080);
47 OSAL_WRITEL(0x474, ioCfgBase + 0x0074);
48 OSAL_WRITEL(0x474, ioCfgBase + 0x0078);
49 OSAL_WRITEL(0x474, ioCfgBase + 0x006C);
50 OSAL_WRITEL(0x474, ioCfgBase + 0x0070);
51 OSAL_WRITEL(0x674, ioCfgBase + 0x0064);
52 }
53
Lcd8BitMuxCfg(unsigned long ioCfgBase)54 static void Lcd8BitMuxCfg(unsigned long ioCfgBase)
55 {
56 OSAL_WRITEL(0x422, ioCfgBase + 0x0034);
57 OSAL_WRITEL(0x462, ioCfgBase + 0x0058);
58 OSAL_WRITEL(0x462, ioCfgBase + 0x004c);
59 OSAL_WRITEL(0x462, ioCfgBase + 0x0054);
60 OSAL_WRITEL(0x422, ioCfgBase + 0x0048);
61 OSAL_WRITEL(0x622, ioCfgBase + 0x0040);
62 OSAL_WRITEL(0x622, ioCfgBase + 0x0044);
63 OSAL_WRITEL(0x622, ioCfgBase + 0x005C);
64 OSAL_WRITEL(0x622, ioCfgBase + 0x003c);
65 OSAL_WRITEL(0x422, ioCfgBase + 0x0038);
66 OSAL_WRITEL(0x622, ioCfgBase + 0x0050);
67 OSAL_WRITEL(0x462, ioCfgBase + 0x0060);
68 }
69
Lcd24BitMuxCfg(unsigned long ioCfgBase)70 static void Lcd24BitMuxCfg(unsigned long ioCfgBase)
71 {
72 OSAL_WRITEL(0x462, ioCfgBase + 0x0034);
73 OSAL_WRITEL(0x432, ioCfgBase + 0x0058);
74 OSAL_WRITEL(0x462, ioCfgBase + 0x004C);
75 OSAL_WRITEL(0x432, ioCfgBase + 0x0054);
76 OSAL_WRITEL(0x432, ioCfgBase + 0x0048);
77 OSAL_WRITEL(0x632, ioCfgBase + 0x0040);
78 OSAL_WRITEL(0x632, ioCfgBase + 0x0044);
79 OSAL_WRITEL(0x632, ioCfgBase + 0x005C);
80 OSAL_WRITEL(0x632, ioCfgBase + 0x003C);
81 OSAL_WRITEL(0x432, ioCfgBase + 0x0038);
82 OSAL_WRITEL(0x632, ioCfgBase + 0x0050);
83 OSAL_WRITEL(0x462, ioCfgBase + 0x0060);
84 OSAL_WRITEL(0x672, ioCfgBase + 0x0084);
85 OSAL_WRITEL(0x672, ioCfgBase + 0x0088);
86 OSAL_WRITEL(0x472, ioCfgBase + 0x007C);
87 OSAL_WRITEL(0x472, ioCfgBase + 0x0080);
88 OSAL_WRITEL(0x472, ioCfgBase + 0x0074);
89 OSAL_WRITEL(0x472, ioCfgBase + 0x0078);
90 OSAL_WRITEL(0x472, ioCfgBase + 0x006C);
91 OSAL_WRITEL(0x462, ioCfgBase + 0x0070);
92 OSAL_WRITEL(0x672, ioCfgBase + 0x0064);
93 OSAL_WRITEL(0x672, ioCfgBase + 0x0068);
94 OSAL_WRITEL(0x532, ioCfgBase + 0x0094);
95 OSAL_WRITEL(0x532, ioCfgBase + 0x0090);
96 OSAL_WRITEL(0x532, ioCfgBase + 0x008C);
97 OSAL_WRITEL(0x632, ioCfgBase + 0x0098);
98 OSAL_WRITEL(0x632, ioCfgBase + 0x009C);
99 OSAL_WRITEL(0x532, ioCfgBase + 0x0030);
100 }
101
LcdPinMuxCfg(uint32_t intf)102 static void LcdPinMuxCfg(uint32_t intf)
103 {
104 unsigned long ioCfgBase;
105
106 ioCfgBase = (unsigned long)OsalIoRemap(IO_CFG2_BASE, IO_CFG_SIZE);
107 if (intf == MIPI_DSI) {
108 MipiMuxCfg(ioCfgBase);
109 } else if (intf == LCD_6BIT) {
110 Lcd6BitMuxCfg(ioCfgBase);
111 } else if (intf == LCD_8BIT) {
112 Lcd8BitMuxCfg(ioCfgBase);
113 } else if (intf == LCD_24BIT) {
114 Lcd24BitMuxCfg(ioCfgBase);
115 } else {
116 HDF_LOGE("%s: not support intf: %d", __func__, intf);
117 }
118 }
119
PwmPinMuxCfg(uint32_t dev)120 static void PwmPinMuxCfg(uint32_t dev)
121 {
122 /* pwm pin config */
123 unsigned long ioCfgBase;
124 ioCfgBase = (unsigned long)OsalIoRemap(IO_CFG1_BASE, IO_CFG_SIZE);
125 switch (dev) {
126 case PWM_DEV0:
127 OSAL_WRITEL(0x601, ioCfgBase + 0x0024);
128 break;
129 case PWM_DEV1:
130 OSAL_WRITEL(0x601, ioCfgBase + 0x0028);
131 break;
132 default:
133 HDF_LOGE("%s: not support pwm dev: %d", __func__, dev);
134 break;
135 }
136 }
137
GetBitsPerPixel(enum DsiOutFormat format)138 static int32_t GetBitsPerPixel(enum DsiOutFormat format)
139 {
140 int32_t bpp;
141
142 switch (format) {
143 case FORMAT_RGB_16_BIT:
144 bpp = 16; // 16 bits per pixel
145 break;
146 case FORMAT_RGB_18_BIT:
147 bpp = 18; // 18 bits per pixel
148 break;
149 case FORMAT_RGB_24_BIT:
150 bpp = 24; // 24 bits per pixel
151 break;
152 default:
153 bpp = 24; // 24 bits per pixel
154 break;
155 }
156 return bpp;
157 }
158
CalcPixelClk(struct PanelInfo * info)159 static uint32_t CalcPixelClk(struct PanelInfo *info)
160 {
161 uint16_t hpixel;
162 uint16_t vline;
163
164 hpixel = info->width + info->hbp + info->hfp + info->hsw;
165 vline = info->height + info->vbp + info->vfp + info->vsw;
166 uint32_t pixNum = hpixel * vline * info->frameRate;
167 if ((pixNum % TRANSFORM_KILO) == 0) {
168 return pixNum / TRANSFORM_KILO;
169 }
170 return (pixNum / TRANSFORM_KILO + 1);
171 }
172
CalcDataRate(struct PanelInfo * info)173 static uint32_t CalcDataRate(struct PanelInfo *info)
174 {
175 uint16_t hpixel;
176 uint16_t vline;
177 uint32_t bitClk;
178
179 hpixel = info->width + info->hbp + info->hfp + info->hsw;
180 vline = info->height + info->vbp + info->vfp + info->vsw;
181 int32_t bpp = GetBitsPerPixel(info->mipi.format);
182 uint32_t bitNum = hpixel * vline * info->frameRate * bpp;
183 if ((bitNum % TRANSFORM_MILL) == 0) {
184 bitClk = bitNum / TRANSFORM_MILL;
185 } else {
186 bitClk = bitNum / TRANSFORM_MILL + 1;
187 }
188 if (!info->mipi.lane) {
189 return HDF_FAILURE;
190 }
191 if ((bitClk % info->mipi.lane) == 0) {
192 return bitClk / info->mipi.lane;
193 }
194 return (bitClk / info->mipi.lane) + 1;
195 }
196
MipiDsiInit(struct PanelInfo * info)197 static int32_t MipiDsiInit(struct PanelInfo *info)
198 {
199 int32_t ret;
200 DevHandle mipiHandle = NULL;
201 struct MipiCfg cfg;
202
203 mipiHandle = MipiDsiOpen(0);
204 if (mipiHandle == NULL) {
205 HDF_LOGE("%s: MipiDsiOpen failed", __func__);
206 return HDF_FAILURE;
207 }
208 cfg.lane = info->mipi.lane;
209 cfg.mode = info->mipi.mode;
210 cfg.format = info->mipi.format;
211 cfg.burstMode = info->mipi.burstMode;
212 cfg.timing.xPixels = info->width;
213 cfg.timing.hsaPixels = info->hsw;
214 cfg.timing.hbpPixels = info->hbp;
215 cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw;
216 cfg.timing.vsaLines = info->vsw;
217 cfg.timing.vbpLines = info->vbp;
218 cfg.timing.vfpLines = info->vfp;
219 cfg.timing.ylines = info->height;
220 /* 0 : no care */
221 cfg.timing.edpiCmdSize = 0;
222 cfg.pixelClk = CalcPixelClk(info);
223 cfg.phyDataRate = CalcDataRate(info);
224 /* config mipi device */
225 ret = MipiDsiSetCfg(mipiHandle, &cfg);
226 if (ret != HDF_SUCCESS) {
227 HDF_LOGE("%s:MipiDsiSetCfg failed", __func__);
228 }
229 MipiDsiClose(mipiHandle);
230 HDF_LOGI("%s:pixelClk = %d, phyDataRate = %u", __func__, cfg.pixelClk, cfg.phyDataRate);
231 return ret;
232 }
233
GetLcdIntfType(enum LcdIntfType type,uint32_t * out)234 static int32_t GetLcdIntfType(enum LcdIntfType type, uint32_t *out)
235 {
236 int32_t ret = HDF_SUCCESS;
237
238 switch (type) {
239 case MIPI_DSI:
240 *out = INTF_MIPI;
241 break;
242 case LCD_6BIT:
243 *out = INTF_LCD_6BIT;
244 break;
245 case LCD_8BIT:
246 *out = INTF_LCD_8BIT;
247 break;
248 case LCD_16BIT:
249 *out = INTF_LCD_16BIT;
250 break;
251 case LCD_18BIT:
252 *out = INTF_LCD_18BIT;
253 break;
254 case LCD_24BIT:
255 *out = INTF_LCD_24BIT;
256 break;
257 default:
258 HDF_LOGE("%s: not support intf: %d", __func__, type);
259 ret = HDF_FAILURE;
260 break;
261 }
262 return ret;
263 }
264
Hi35xxHardWareInit(void)265 static int32_t Hi35xxHardWareInit(void)
266 {
267 int32_t i;
268 int32_t ret;
269 struct PanelManager *panelManager = NULL;
270 struct PanelData *panel = NULL;
271 struct PanelInfo *info = NULL;
272
273 panelManager = GetPanelManager();
274 if (panelManager == NULL) {
275 HDF_LOGE("%s: panelManager is null", __func__);
276 return HDF_FAILURE;
277 }
278 for (i = 0; i < panelManager->panelNum; i++) {
279 panel = panelManager->panel[i];
280 info = panel->info;
281 if (info == NULL) {
282 HDF_LOGE("%s:GetPanelInfo failed", __func__);
283 return HDF_FAILURE;
284 }
285 if (info->blk.type == BLK_PWM) {
286 PwmPinMuxCfg(info->pwm.dev);
287 }
288 /* lcd pin mux config */
289 LcdPinMuxCfg(info->intfType);
290 if (info->intfType == MIPI_DSI) {
291 /* mipi dsi init */
292 ret = MipiDsiInit(info);
293 if (ret) {
294 HDF_LOGE("%s:MipiDsiInit failed", __func__);
295 return HDF_FAILURE;
296 }
297 }
298 if (GetLcdIntfType(info->intfType, &info->intfType) != HDF_SUCCESS) {
299 HDF_LOGE("%s:GetLcdIntfType failed", __func__);
300 return HDF_FAILURE;
301 }
302 if (panel->init != NULL) {
303 if ((panel->init(panel)) != HDF_SUCCESS) {
304 HDF_LOGE("%s:panel[%d] init failed", __func__, i);
305 return HDF_FAILURE;
306 }
307 }
308 }
309 return HDF_SUCCESS;
310 }
311
Hi35xxEntryInit(struct HdfDeviceObject * object)312 static int32_t Hi35xxEntryInit(struct HdfDeviceObject *object)
313 {
314 if (object == NULL) {
315 HDF_LOGE("%s: object is null", __func__);
316 return HDF_FAILURE;
317 }
318 return Hi35xxHardWareInit();
319 }
320
321 struct HdfDriverEntry g_hi35xxDevEntry = {
322 .moduleVersion = 1,
323 .moduleName = "HI351XX_DISP",
324 .Init = Hi35xxEntryInit,
325 };
326
327 HDF_INIT(g_hi35xxDevEntry);
328