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