1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 
16 #include "mipi_tx_hi35xx.h"
17 #include "hdf_log.h"
18 #include "osal_io.h"
19 #include "osal_mem.h"
20 #include "osal_time.h"
21 #include "mipi_dsi_define.h"
22 #include "mipi_dsi_core.h"
23 #include "mipi_tx_reg.h"
24 #include "platform_dumper.h"
25 
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif /* End of #ifdef __cplusplus */
31 
32 #define HDF_LOG_TAG mipi_tx_hi35xx
33 
34 volatile  MipiTxRegsTypeTag *g_mipiTxRegsVa = NULL;
35 unsigned int g_mipiTxIrqNum = MIPI_TX_IRQ;
36 unsigned int g_actualPhyDataRate;
37 static unsigned int g_regMapFlag;
38 /**
39  * @brief g_enCfg is the flag that the controller parameters have been set, which is independent of the high
40  * and low speed modes. The program design requires setting parameters before operating the controller,
41  * otherwise it will directly return to failure.
42  */
43 static bool g_enCfg = false;
44 
WriteReg32(unsigned long *addr, unsigned int value, unsigned int mask)45 static void WriteReg32(unsigned long *addr, unsigned int value, unsigned int mask)
46 {
47     unsigned int t;
48 
49     t = OSAL_READL(addr);
50     t &= ~mask;
51     t |= value & mask;
52     OSAL_WRITEL(t, addr);
53 }
54 
OsalIsb(void)55 static void OsalIsb(void)
56 {
57     __asm__ __volatile__("isb" : : : "memory");
58 }
59 
OsalDsb(void)60 static void OsalDsb(void)
61 {
62     __asm__ __volatile__("dsb" : : : "memory");
63 }
64 
OsalDmb(void)65 static void OsalDmb(void)
66 {
67     __asm__ __volatile__("dmb" : : : "memory");
68 }
69 
HdfIsbDsbDmb(void)70 static void HdfIsbDsbDmb(void)
71 {
72     OsalIsb();
73     OsalDsb();
74     OsalDmb();
75 }
76 
SetPhyReg(unsigned int addr, unsigned char value)77 static void SetPhyReg(unsigned int addr, unsigned char value)
78 {
79     HdfIsbDsbDmb();
80     g_mipiTxRegsVa->PHY_TST_CTRL1.u32 = (0x10000 + addr);
81     HdfIsbDsbDmb();
82     g_mipiTxRegsVa->PHY_TST_CTRL0.u32 = 0x2;
83     HdfIsbDsbDmb();
84     g_mipiTxRegsVa->PHY_TST_CTRL0.u32 = 0x0;
85     HdfIsbDsbDmb();
86     g_mipiTxRegsVa->PHY_TST_CTRL1.u32 = value;
87     HdfIsbDsbDmb();
88     g_mipiTxRegsVa->PHY_TST_CTRL0.u32 = 0x2;
89     HdfIsbDsbDmb();
90     g_mipiTxRegsVa->PHY_TST_CTRL0.u32 = 0x0;
91     HdfIsbDsbDmb();
92 }
93 
MipiTxDrvGetPhyPllSet0(unsigned int phyDataRate)94 static unsigned char MipiTxDrvGetPhyPllSet0(unsigned int phyDataRate)
95 {
96     unsigned char pllSet0;
97 
98     /* to get pllSet0, the parameters come from algorithm */
99     if (phyDataRate > 750) {          /* 750: mipi clk */
100         pllSet0 = 0x0;
101     } else if (phyDataRate > 375) {   /* 375: mipi clk */
102         pllSet0 = 0x8;
103     } else if (phyDataRate > 188) {   /* 188: mipi clk */
104         pllSet0 = 0xa;
105     } else if (phyDataRate > 94) {    /* 94: mipi clk */
106         pllSet0 = 0xc;
107     } else {
108         pllSet0 = 0xe;
109     }
110     return pllSet0;
111 }
112 
MipiTxDrvGetPhyPllSet1Set5(unsigned int phyDataRate, unsigned char pllSet0, unsigned char *pllSet1, unsigned char *pllSet5)113 static void MipiTxDrvGetPhyPllSet1Set5(unsigned int phyDataRate,
114     unsigned char pllSet0,
115     unsigned char *pllSet1,
116     unsigned char *pllSet5)
117 {
118     int dataRateClk;
119     int pllRef;
120 
121     dataRateClk = (phyDataRate + MIPI_TX_REF_CLK - 1) / MIPI_TX_REF_CLK;
122 
123     /* to get pllSet1 and pllSet5, the parameters come from algorithm */
124     if (pllSet0 / 2 == 4) {           /* 2: pll, 4: pll sel */
125         pllRef = 2;                   /* 2: pll set */
126     } else if (pllSet0 / 2 == 5) {    /* 2: pll, 5: pllSet5 */
127         pllRef = 4;                   /* 4: pll set */
128     } else if (pllSet0 / 2 == 6) {    /* 2: pll, 6: pll sel */
129         pllRef = 8;                   /* 8: pll set */
130     } else if (pllSet0 / 2 == 7) {    /* 2: pll, 7: pll sel */
131         pllRef = 16;                  /* 16: pll set */
132     } else {
133         pllRef = 1;
134     }
135     if ((dataRateClk * pllRef) % 2) { /* 2: pll */
136         *pllSet1 = 0x10;
137         *pllSet5 = (dataRateClk * pllRef - 1) / 2; /* 2: pllRef sel */
138     } else {
139         *pllSet1 = 0x20;
140         *pllSet5 = dataRateClk * pllRef / 2 - 1;   /* 2: pllRef sel */
141     }
142 
143     return;
144 }
145 
MipiTxDrvSetPhyPllSetX(unsigned int phyDataRate)146 static void MipiTxDrvSetPhyPllSetX(unsigned int phyDataRate)
147 {
148     unsigned char pllSet0;
149     unsigned char pllSet1;
150     unsigned char pllSet2;
151 #ifdef HI_FPGA
152     unsigned char pllSet3;
153 #endif
154     unsigned char pllSet4;
155     unsigned char pllSet5;
156 
157     /* pllSet0 */
158     pllSet0 = MipiTxDrvGetPhyPllSet0(phyDataRate);
159     SetPhyReg(PLL_SET0, pllSet0);
160     /* pllSet1 */
161     MipiTxDrvGetPhyPllSet1Set5(phyDataRate, pllSet0, &pllSet1, &pllSet5);
162     SetPhyReg(PLL_SET1, pllSet1);
163     /* pllSet2 */
164     pllSet2 = 0x2;
165     SetPhyReg(PLL_SET2, pllSet2);
166     /* pllSet4 */
167     pllSet4 = 0x0;
168     SetPhyReg(PLL_SET4, pllSet4);
169 
170 #ifdef HI_FPGA
171     pllSet3 = 0x1;
172     SetPhyReg(PLL_SET3, pllSet3);
173 #endif
174     /* pllSet5 */
175     SetPhyReg(PLL_SET5, pllSet5);
176 
177 #ifdef MIPI_TX_DEBUG
178     HDF_LOGI("%s: \n==========phy pll info=======", __func__);
179     HDF_LOGI("pllSet0(0x14): 0x%x", pllSet0);
180     HDF_LOGI("pllSet1(0x15): 0x%x", pllSet1);
181     HDF_LOGI("pllSet2(0x16): 0x%x", pllSet2);
182 #ifdef HI_FPGA
183     HDF_LOGI("pllSet3(0x17): 0x%x", pllSet3);
184 #endif
185     HDF_LOGI("pllSet4(0x1e): 0x%x", pllSet4);
186     HDF_LOGI("=========================\n");
187 #endif
188 }
189 
MipiTxDrvGetPhyClkPrepare(unsigned char *clkPrepare)190 static void MipiTxDrvGetPhyClkPrepare(unsigned char *clkPrepare)
191 {
192     unsigned char temp0;
193     unsigned char temp1;
194 
195     temp0 = ((g_actualPhyDataRate * TCLK_PREPARE + ROUNDUP_VALUE) / INNER_PEROID - 1 +
196             ((g_actualPhyDataRate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID) -
197             ((((g_actualPhyDataRate * TCLK_PREPARE + ROUNDUP_VALUE) / INNER_PEROID +
198             ((g_actualPhyDataRate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID)) * INNER_PEROID -
199             PREPARE_COMPENSATE * g_actualPhyDataRate - TCLK_PREPARE * g_actualPhyDataRate) / INNER_PEROID));
200     if (temp0 > 0) { /* 0 is the minimum */
201         temp1 = temp0;
202     } else {
203         temp1 = 0; /* 0 is the minimum */
204     }
205 
206     if (((temp1 + 1) * INNER_PEROID - PREPARE_COMPENSATE * g_actualPhyDataRate) > /* temp + 1 is next level period */
207         94 * g_actualPhyDataRate) { /* 94 is the  maximum in mipi protocol */
208         if (temp0 > 0) {
209             *clkPrepare = temp0 - 1;
210         } else {
211             *clkPrepare = 255; /* set 255 will easy to found mistake */
212             HDF_LOGE("%s: err when calc phy timing.", __func__);
213         }
214     } else {
215         if (temp0 > 0) { /* 0 is the minimum */
216             *clkPrepare = temp0;
217         } else {
218             *clkPrepare = 0; /* 0 is the minimum */
219         }
220     }
221 }
222 
MipiTxDrvGetPhyDataPrepare(unsigned char *dataPrepare)223 static void MipiTxDrvGetPhyDataPrepare(unsigned char *dataPrepare)
224 {
225     unsigned char temp0;
226     unsigned char temp1;
227 
228     /* DATA_THS_PREPARE */
229     temp0 = ((g_actualPhyDataRate * THS_PREPARE + ROUNDUP_VALUE) / INNER_PEROID - 1 +
230             ((g_actualPhyDataRate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID) -
231             ((((g_actualPhyDataRate * THS_PREPARE + ROUNDUP_VALUE) / INNER_PEROID +
232             ((g_actualPhyDataRate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID)) * INNER_PEROID -
233             PREPARE_COMPENSATE * g_actualPhyDataRate - THS_PREPARE * g_actualPhyDataRate) / INNER_PEROID));
234     if (temp0 > 0) {
235         temp1 = temp0;
236     } else {
237         temp1 = 0;
238     }
239 
240     if ((g_actualPhyDataRate > 105) && /* bigger than 105 */
241         (((temp1 + 1) * INNER_PEROID - PREPARE_COMPENSATE * g_actualPhyDataRate) >
242         (85 * g_actualPhyDataRate + 6 * 1000))) { /* 85 + 6 * 1000 is the  maximum in mipi protocol */
243         if (temp0 > 0) {
244             *dataPrepare = temp0 - 1;
245         } else {
246             *dataPrepare = 255; /* set 255 will easy to found mistake */
247             HDF_LOGE("%s: err when calc phy timing.", __func__);
248         }
249     } else {
250         if (temp0 > 0) {
251             *dataPrepare = temp0;
252         } else {
253             *dataPrepare = 0;
254         }
255     }
256 }
257 
258 /* get global operation timing parameters. */
MipiTxDrvGetPhyTimingParam(MipiTxPhyTimingParamTag *tp)259 static void MipiTxDrvGetPhyTimingParam(MipiTxPhyTimingParamTag *tp)
260 {
261     /* DATA0~3 TPRE-DELAY */
262     /* 1: compensate */
263     tp->dataTpreDelay = (g_actualPhyDataRate * TPRE_DELAY + ROUNDUP_VALUE) / INNER_PEROID - 1;
264     /* CLK_TLPX */
265     tp->clkTlpx = (g_actualPhyDataRate * TLPX + ROUNDUP_VALUE) / INNER_PEROID - 1; /* 1 is compensate */
266     /* CLK_TCLK_PREPARE */
267     MipiTxDrvGetPhyClkPrepare(&tp->clkTclkPrepare);
268     /* CLK_TCLK_ZERO */
269     if ((g_actualPhyDataRate * TCLK_ZERO + ROUNDUP_VALUE) / INNER_PEROID > 4) {    /* 4 is compensate */
270         tp->clkTclkZero = (g_actualPhyDataRate * TCLK_ZERO + ROUNDUP_VALUE) / INNER_PEROID - 4;
271     } else {
272         tp->clkTclkZero = 0;       /* 0 is minimum */
273     }
274     /* CLK_TCLK_TRAIL */
275     tp->clkTclkTrail = (g_actualPhyDataRate * TCLK_TRAIL + ROUNDUP_VALUE) / INNER_PEROID;
276     /* DATA_TLPX */
277     tp->dataTlpx = (g_actualPhyDataRate * TLPX + ROUNDUP_VALUE) / INNER_PEROID - 1; /* 1 is compensate */
278     /* DATA_THS_PREPARE */
279     MipiTxDrvGetPhyDataPrepare(&tp->dataThsPrepare);
280     /* DATA_THS_ZERO */
281     if ((g_actualPhyDataRate * THS_ZERO + ROUNDUP_VALUE) / INNER_PEROID > 4) {      /* 4 is compensate */
282         tp->dataThsZero = (g_actualPhyDataRate * THS_ZERO + ROUNDUP_VALUE) / INNER_PEROID - 4;
283     } else {
284         tp->dataThsZero = 0;       /* 0 is minimum */
285     }
286     /* DATA_THS_TRAIL */
287     tp->dataThsTrail = (g_actualPhyDataRate * THS_TRAIL + ROUNDUP_VALUE) / INNER_PEROID + 1; /* 1 is compensate */
288 }
289 
290 /* set global operation timing parameters. */
MipiTxDrvSetPhyTimingParam(const MipiTxPhyTimingParamTag *tp)291 static void MipiTxDrvSetPhyTimingParam(const MipiTxPhyTimingParamTag *tp)
292 {
293     /* DATA0~3 TPRE-DELAY */
294     SetPhyReg(DATA0_TPRE_DELAY, tp->dataTpreDelay);
295     SetPhyReg(DATA1_TPRE_DELAY, tp->dataTpreDelay);
296     SetPhyReg(DATA2_TPRE_DELAY, tp->dataTpreDelay);
297     SetPhyReg(DATA3_TPRE_DELAY, tp->dataTpreDelay);
298 
299     /* CLK_TLPX */
300     SetPhyReg(CLK_TLPX, tp->clkTlpx);
301     /* CLK_TCLK_PREPARE */
302     SetPhyReg(CLK_TCLK_PREPARE, tp->clkTclkPrepare);
303     /* CLK_TCLK_ZERO */
304     SetPhyReg(CLK_TCLK_ZERO, tp->clkTclkZero);
305     /* CLK_TCLK_TRAIL */
306     SetPhyReg(CLK_TCLK_TRAIL, tp->clkTclkTrail);
307 
308     /*
309      * DATA_TLPX
310      * DATA_THS_PREPARE
311      * DATA_THS_ZERO
312      * DATA_THS_TRAIL
313      */
314     SetPhyReg(DATA0_TLPX, tp->dataTlpx);
315     SetPhyReg(DATA0_THS_PREPARE, tp->dataThsPrepare);
316     SetPhyReg(DATA0_THS_ZERO, tp->dataThsZero);
317     SetPhyReg(DATA0_THS_TRAIL, tp->dataThsTrail);
318     SetPhyReg(DATA1_TLPX, tp->dataTlpx);
319     SetPhyReg(DATA1_THS_PREPARE, tp->dataThsPrepare);
320     SetPhyReg(DATA1_THS_ZERO, tp->dataThsZero);
321     SetPhyReg(DATA1_THS_TRAIL, tp->dataThsTrail);
322     SetPhyReg(DATA2_TLPX, tp->dataTlpx);
323     SetPhyReg(DATA2_THS_PREPARE, tp->dataThsPrepare);
324     SetPhyReg(DATA2_THS_ZERO, tp->dataThsZero);
325     SetPhyReg(DATA2_THS_TRAIL, tp->dataThsTrail);
326     SetPhyReg(DATA3_TLPX, tp->dataTlpx);
327     SetPhyReg(DATA3_THS_PREPARE, tp->dataThsPrepare);
328     SetPhyReg(DATA3_THS_ZERO, tp->dataThsZero);
329     SetPhyReg(DATA3_THS_TRAIL, tp->dataThsTrail);
330 
331 #ifdef MIPI_TX_DEBUG
332     HDF_LOGI("%s:\n==========phy timing parameters=======", __func__);
333     HDF_LOGI("data_tpre_delay(0x30/40/50/60): 0x%x", tp->dataTpreDelay);
334     HDF_LOGI("clk_tlpx(0x22): 0x%x", tp->clkTlpx);
335     HDF_LOGI("clk_tclk_prepare(0x23): 0x%x", tp->clkTclkPrepare);
336     HDF_LOGI("clk_tclk_zero(0x24): 0x%x", tp->clkTclkZero);
337     HDF_LOGI("clk_tclk_trail(0x25): 0x%x", tp->clkTclkTrail);
338     HDF_LOGI("data_tlpx(0x32/42/52/62): 0x%x", tp->dataTlpx);
339     HDF_LOGI("data_ths_prepare(0x33/43/53/63): 0x%x", tp->dataThsPrepare);
340     HDF_LOGI("data_ths_zero(0x34/44/54/64): 0x%x", tp->dataThsZero);
341     HDF_LOGI("data_ths_trail(0x35/45/55/65): 0x%x", tp->dataThsTrail);
342     HDF_LOGI("=========================\n");
343 #endif
344 }
345 
346 /*
347  * set data lp2hs,hs2lp time
348  * set clk lp2hs,hs2lp time
349  * unit: hsclk
350  */
MipiTxDrvSetPhyHsLpSwitchTime(const MipiTxPhyTimingParamTag *tp)351 static void MipiTxDrvSetPhyHsLpSwitchTime(const MipiTxPhyTimingParamTag *tp)
352 {
353     /* data lp2hs,hs2lp time */
354     g_mipiTxRegsVa->PHY_TMR_CFG.u32 = ((tp->dataThsTrail - 1) << 16) +  /* 16 set register */
355         tp->dataTpreDelay + tp->dataTlpx + tp->dataThsPrepare + tp->dataThsZero + 7; /* 7 from algorithm */
356     /* clk lp2hs,hs2lp time */
357     g_mipiTxRegsVa->PHY_TMR_LPCLK_CFG.u32 = ((31 + tp->dataThsTrail) << 16) + /* 31 from algorithm, 16 set register */
358         tp->clkTlpx + tp->clkTclkPrepare + tp->clkTclkZero + 6; /* 6 from algorithm */
359 #ifdef MIPI_TX_DEBUG
360     HDF_LOGI("%s: PHY_TMR_CFG(0x9C): 0x%x", __func__, g_mipiTxRegsVa->PHY_TMR_CFG.u32);
361     HDF_LOGI("%s: PHY_TMR_LPCLK_CFG(0x98): 0x%x", __func__, g_mipiTxRegsVa->PHY_TMR_LPCLK_CFG.u32);
362 #endif
363 }
364 
MipiTxDrvSetPhyCfg(const ComboDevCfgTag *cfg)365 static void MipiTxDrvSetPhyCfg(const ComboDevCfgTag *cfg)
366 {
367     MipiTxPhyTimingParamTag tp = {0};
368 
369     if (cfg == NULL) {
370         HDF_LOGE("%s: cfg is NULL!", __func__);
371         return;
372     }
373 
374     /* set phy pll parameters setx */
375     MipiTxDrvSetPhyPllSetX(cfg->phyDataRate);
376     /* get global operation timing parameters */
377     MipiTxDrvGetPhyTimingParam(&tp);
378     /* set global operation timing parameters */
379     MipiTxDrvSetPhyTimingParam(&tp);
380     /* set hs switch to lp and lp switch to hs time  */
381     MipiTxDrvSetPhyHsLpSwitchTime(&tp);
382     /* edpi_cmd_size */
383     g_mipiTxRegsVa->EDPI_CMD_SIZE.u32 = 0xF0;
384     /* phy enable */
385     g_mipiTxRegsVa->PHY_RSTZ.u32 = 0xf;
386     if (cfg->outputMode == OUTPUT_MODE_CSI) {
387         if (cfg->outputFormat == OUT_FORMAT_YUV420_8_BIT_NORMAL) {
388             g_mipiTxRegsVa->DATATYPE0.u32 = 0x10218;
389             g_mipiTxRegsVa->CSI_CTRL.u32 = 0x1111;
390         } else if (cfg->outputFormat == OUT_FORMAT_YUV422_8_BIT) {
391             g_mipiTxRegsVa->DATATYPE0.u32 = 0x1021E;
392             g_mipiTxRegsVa->CSI_CTRL.u32 = 0x1111;
393         }
394     } else {
395         if (cfg->outputFormat == OUT_FORMAT_RGB_16_BIT) {
396             g_mipiTxRegsVa->DATATYPE0.u32 = 0x111213D;
397             g_mipiTxRegsVa->CSI_CTRL.u32 = 0x10100;
398         } else if (cfg->outputFormat == OUT_FORMAT_RGB_18_BIT) {
399             g_mipiTxRegsVa->DATATYPE0.u32 = 0x111213D;
400             g_mipiTxRegsVa->CSI_CTRL.u32 = 0x10100;
401         } else if (cfg->outputFormat == OUT_FORMAT_RGB_24_BIT) {
402             g_mipiTxRegsVa->DATATYPE0.u32 = 0x111213D;
403             g_mipiTxRegsVa->CSI_CTRL.u32 = 0x10100;
404         }
405     }
406     g_mipiTxRegsVa->PHY_RSTZ.u32 = 0XF;
407     OsalMSleep(1);
408     g_mipiTxRegsVa->LPCLK_CTRL.u32 = 0x0;
409 }
410 
MipiTxDrvGetDevStatus(MipiTxDevPhyTag *phyCtx)411 void MipiTxDrvGetDevStatus(MipiTxDevPhyTag *phyCtx)
412 {
413     if (phyCtx == NULL) {
414         HDF_LOGE("%s: phyCtx is NULL!", __func__);
415         return;
416     }
417     phyCtx->hactDet = g_mipiTxRegsVa->HORI0_DET.bits.hact_det;
418     phyCtx->hallDet = g_mipiTxRegsVa->HORI0_DET.bits.hline_det;
419     phyCtx->hbpDet  = g_mipiTxRegsVa->HORI1_DET.bits.hbp_det;
420     phyCtx->hsaDet  = g_mipiTxRegsVa->HORI1_DET.bits.hsa_det;
421     phyCtx->vactDet = g_mipiTxRegsVa->VERT_DET.bits.vact_det;
422     phyCtx->vallDet = g_mipiTxRegsVa->VERT_DET.bits.vall_det;
423     phyCtx->vsaDet  = g_mipiTxRegsVa->VSA_DET.bits.vsa_det;
424 }
425 
SetOutputFormat(const ComboDevCfgTag *cfg)426 static void SetOutputFormat(const ComboDevCfgTag *cfg)
427 {
428     int colorCoding = 0;
429 
430     if (cfg->outputMode == OUTPUT_MODE_CSI) {
431         if (cfg->outputFormat == OUT_FORMAT_YUV420_8_BIT_NORMAL) {
432             colorCoding = 0xd;
433         } else if (cfg->outputFormat == OUT_FORMAT_YUV422_8_BIT) {
434             colorCoding = 0x1;
435         }
436     } else {
437         if (cfg->outputFormat == OUT_FORMAT_RGB_16_BIT) {
438             colorCoding = 0x0;
439         } else if (cfg->outputFormat == OUT_FORMAT_RGB_18_BIT) {
440             colorCoding = 0x3;
441         } else if (cfg->outputFormat == OUT_FORMAT_RGB_24_BIT) {
442             colorCoding = 0x5;
443         }
444     }
445     g_mipiTxRegsVa->COLOR_CODING.u32 = colorCoding;
446 #ifdef MIPI_TX_DEBUG
447     HDF_LOGI("%s: SetOutputFormat: 0x%x", __func__, colorCoding);
448 #endif
449 }
450 
SetVideoModeCfg(const ComboDevCfgTag *cfg)451 static void SetVideoModeCfg(const ComboDevCfgTag *cfg)
452 {
453     int videoMode;
454 
455     if (cfg->videoMode == NON_BURST_MODE_SYNC_PULSES) {
456         videoMode = 0;
457     } else if (cfg->videoMode == NON_BURST_MODE_SYNC_EVENTS) {
458         videoMode = 1;
459     } else {
460         videoMode = 2; /* 2 register value */
461     }
462     if ((cfg->outputMode == OUTPUT_MODE_CSI) || (cfg->outputMode == OUTPUT_MODE_DSI_CMD)) {
463         videoMode = 2; /* 2 register value */
464     }
465     g_mipiTxRegsVa->VID_MODE_CFG.u32 = 0x3f00 + videoMode;
466 }
467 
SetTimingConfig(const ComboDevCfgTag *cfg)468 static void SetTimingConfig(const ComboDevCfgTag *cfg)
469 {
470     unsigned int hsa;
471     unsigned int hbp;
472     unsigned int hline;
473 
474     if (cfg->pixelClk == 0) {
475         HDF_LOGE("%s: cfg->pixelClk is 0, illegal.", __func__);
476         return;
477     }
478     /* 125 from algorithm */
479     hsa = g_actualPhyDataRate * cfg->syncInfo.vidHsaPixels * 125 / cfg->pixelClk;
480     /* 125 from algorithm */
481     hbp = g_actualPhyDataRate * cfg->syncInfo.vidHbpPixels * 125 / cfg->pixelClk;
482     /* 125 from algorithm */
483     hline = g_actualPhyDataRate * cfg->syncInfo.vidHlinePixels * 125 / cfg->pixelClk;
484     g_mipiTxRegsVa->VID_HSA_TIME.u32 = hsa;
485     g_mipiTxRegsVa->VID_HBP_TIME.u32 = hbp;
486     g_mipiTxRegsVa->VID_HLINE_TIME.u32 = hline;
487     g_mipiTxRegsVa->VID_VSA_LINES.u32 = cfg->syncInfo.vidVsaLines;
488     g_mipiTxRegsVa->VID_VBP_LINES.u32 = cfg->syncInfo.vidVbpLines;
489     g_mipiTxRegsVa->VID_VFP_LINES.u32 = cfg->syncInfo.vidVfpLines;
490     g_mipiTxRegsVa->VID_VACTIVE_LINES.u32 = cfg->syncInfo.vidActiveLines;
491 #ifdef MIPI_TX_DEBUG
492     HDF_LOGI("%s:\n==========Set Timing Config=======", __func__);
493     HDF_LOGI("VID_HSA_TIME(0x48): 0x%x", hsa);
494     HDF_LOGI("VID_HBP_TIME(0x4c): 0x%x", hbp);
495     HDF_LOGI("VID_HLINE_TIME(0x50): 0x%x", hline);
496     HDF_LOGI("VID_VSA_LINES(0x54): 0x%x", cfg->syncInfo.vidVsaLines);
497     HDF_LOGI("VID_VBP_LINES(0x58): 0x%x", cfg->syncInfo.vidVbpLines);
498     HDF_LOGI("VID_VFP_LINES(0x5c): 0x%x", cfg->syncInfo.vidVfpLines);
499     HDF_LOGI("VID_VACTIVE_LINES(0x60): 0x%x", cfg->syncInfo.vidActiveLines);
500     HDF_LOGI("=========================\n");
501 #endif
502 }
503 
SetLaneConfig(const short laneId[], int len)504 static void SetLaneConfig(const short laneId[], int len)
505 {
506     int num = 0;
507     int i;
508 
509     for (i = 0; i < len; i++) {
510         if (-1 != laneId[i]) {
511             num++;
512         }
513     }
514     g_mipiTxRegsVa->PHY_IF_CFG.u32 = num - 1;
515 }
516 
MipiTxDrvSetClkMgrCfg(void)517 static void MipiTxDrvSetClkMgrCfg(void)
518 {
519     if (g_actualPhyDataRate / 160 < 2) { /* 160 cal div, should not smaller than 2 */
520         g_mipiTxRegsVa->CLKMGR_CFG.u32 = 0x102;
521     } else {
522         g_mipiTxRegsVa->CLKMGR_CFG.u32 = 0x100 + (g_actualPhyDataRate + 159) / 160; /* 159 160 cal div */
523     }
524 }
525 
MipiTxDrvSetControllerCfg(const ComboDevCfgTag *cfg)526 static void MipiTxDrvSetControllerCfg(const ComboDevCfgTag *cfg)
527 {
528     if (cfg == NULL) {
529         HDF_LOGE("%s: cfg is NULL!", __func__);
530         return;
531     }
532     /* disable input */
533     g_mipiTxRegsVa->OPERATION_MODE.u32 = 0x0;
534     /* vc_id */
535     g_mipiTxRegsVa->VCID.u32 = 0x0;
536     /* output format,color coding */
537     SetOutputFormat(cfg);
538     /* txescclk,timeout */
539     g_actualPhyDataRate = ((cfg->phyDataRate + MIPI_TX_REF_CLK - 1) / MIPI_TX_REF_CLK) * MIPI_TX_REF_CLK;
540     MipiTxDrvSetClkMgrCfg();
541     /* cmd transmission mode */
542     g_mipiTxRegsVa->CMD_MODE_CFG.u32 = 0xffffff00;
543     /* crc,ecc,eotp tran */
544     g_mipiTxRegsVa->PCKHDL_CFG.u32 = 0x1c;
545     /* gen_vcid_rx */
546     g_mipiTxRegsVa->GEN_VCID.u32 = 0x0;
547     /* mode config */
548     g_mipiTxRegsVa->MODE_CFG.u32 = 0x1;
549     /* video mode cfg */
550     SetVideoModeCfg(cfg);
551     if ((cfg->outputMode == OUTPUT_MODE_DSI_VIDEO) || (cfg->outputMode == OUTPUT_MODE_CSI)) {
552         g_mipiTxRegsVa->VID_PKT_SIZE.u32 = cfg->syncInfo.vidPktSize;
553     } else {
554         g_mipiTxRegsVa->EDPI_CMD_SIZE.u32 = cfg->syncInfo.edpiCmdSize;
555     }
556     /* num_chunks/null_size */
557     g_mipiTxRegsVa->VID_NUM_CHUNKS.u32 = 0x0;
558     g_mipiTxRegsVa->VID_NULL_SIZE.u32 = 0x0;
559     /* timing config */
560     SetTimingConfig(cfg);
561     /* invact,outvact time */
562     g_mipiTxRegsVa->LP_CMD_TIM.u32 = 0x0;
563     g_mipiTxRegsVa->PHY_TMR_CFG.u32 = 0x9002D;
564     g_mipiTxRegsVa->PHY_TMR_LPCLK_CFG.u32 = 0x29002E;
565     g_mipiTxRegsVa->EDPI_CMD_SIZE.u32 = 0xF0;
566     /* lp_wr_to_cnt */
567     g_mipiTxRegsVa->LP_WR_TO_CNT.u32 = 0x0;
568     /* bta_to_cnt */
569     g_mipiTxRegsVa->BTA_TO_CNT.u32 = 0x0;
570     /* lanes */
571     SetLaneConfig(cfg->laneId, LANE_MAX_NUM);
572     /* phy_tx requlpsclk */
573     g_mipiTxRegsVa->PHY_ULPS_CTRL.u32 = 0x0;
574     /* int msk0 */
575     g_mipiTxRegsVa->INT_MSK0.u32 = 0x0;
576     /* pwr_up unreset */
577     g_mipiTxRegsVa->PWR_UP.u32 = 0x0;
578     g_mipiTxRegsVa->PWR_UP.u32 = 0xf;
579 }
580 
GetDevCfg(struct MipiDsiCntlr *cntlr)581 static ComboDevCfgTag *GetDevCfg(struct MipiDsiCntlr *cntlr)
582 {
583     static ComboDevCfgTag dev;
584     int i;
585 
586     if (cntlr == NULL) {
587         HDF_LOGE("%s: cntlr is NULL!", __func__);
588         return NULL;
589     }
590     dev.devno = cntlr->devNo;
591     dev.outputMode = (OutPutModeTag)cntlr->cfg.mode;
592     dev.videoMode = (VideoModeTag)cntlr->cfg.burstMode;
593     dev.outputFormat = (OutputFormatTag)cntlr->cfg.format;
594     dev.syncInfo.vidPktSize = cntlr->cfg.timing.xPixels;
595     dev.syncInfo.vidHsaPixels = cntlr->cfg.timing.hsaPixels;
596     dev.syncInfo.vidHbpPixels = cntlr->cfg.timing.hbpPixels;
597     dev.syncInfo.vidHlinePixels = cntlr->cfg.timing.hlinePixels;
598     dev.syncInfo.vidVsaLines = cntlr->cfg.timing.vsaLines;
599     dev.syncInfo.vidVbpLines = cntlr->cfg.timing.vbpLines;
600     dev.syncInfo.vidVfpLines = cntlr->cfg.timing.vfpLines;
601     dev.syncInfo.vidActiveLines = cntlr->cfg.timing.ylines;
602     dev.syncInfo.edpiCmdSize = cntlr->cfg.timing.edpiCmdSize;
603     dev.phyDataRate = cntlr->cfg.phyDataRate;
604     dev.pixelClk = cntlr->cfg.pixelClk;
605     for (i = 0; i < LANE_MAX_NUM; i++) {
606         dev.laneId[i] = -1;   /* -1 : not use */
607     }
608     for (i = 0; i < cntlr->cfg.lane; i++) {
609         dev.laneId[i] = i;
610     }
611     return &dev;
612 }
613 
614 static struct MipiDsiCntlr g_mipiTx = {
615     .devNo = 0
616 };
617 
MipiTxDumperCreate(void)618 static int32_t MipiTxDumperCreate(void)
619 {
620     struct PlatformDumper *dumper = NULL;
621     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
622     char *name = NULL;
623 
624     name = (char *)OsalMemCalloc(MIPI_TX_DUMPER_NAME_LEN);
625     if (name == NULL) {
626         HDF_LOGE("%s: alloc name fail", __func__);
627         return HDF_ERR_MALLOC_FAIL;
628     }
629 
630     if (snprintf_s(name, MIPI_TX_DUMPER_NAME_LEN, MIPI_TX_DUMPER_NAME_LEN - 1, "%s%d",
631         MIPI_TX_DUMPER_NAME_PREFIX, g_mipiTx.devNo) < 0) {
632         HDF_LOGE("%s: snprintf_s name fail!", __func__);
633         OsalMemFree(name);
634         return HDF_ERR_IO;
635     }
636     dumper = PlatformDumperCreate(name);
637     if (dumper == NULL) {
638         HDF_LOGE("%s: get dumper for %s fail!", __func__, name);
639         OsalMemFree(name);
640         return HDF_ERR_IO;
641     }
642     dev->dumper = dumper;
643     dev->dumperName = name;
644 
645     return HDF_SUCCESS;
646 }
647 
MipiTxDumperDump(struct PlatformDumper *dumper)648 static void MipiTxDumperDump(struct PlatformDumper *dumper)
649 {
650     int32_t ret;
651     struct PlatformDumperData datas[] = {
652         {"PWR_UP", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_PWR_UP)},
653         {"CLKMGR_CFG", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_CLKMGR_CFG)},
654         {"VCID", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VCID)},
655         {"COLOR_CODING", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_COLOR_CODING)},
656         {"MIPI_TX_LP_CMD_TIM", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_LP_CMD_TIM)},
657         {"MIPI_TX_GEN_VCID", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_GEN_VCID)},
658         {"MIPI_TX_VID_HSA_TIME", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_HSA_TIME)},
659         {"MIPI_TX_VID_HBP_TIME", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_HBP_TIME)},
660         {"MIPI_TX_VID_HLINE_TIME", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_HLINE_TIME)},
661         {"MIPI_TX_VID_VSA_LINES", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_VSA_LINES)},
662         {"MIPI_TX_VID_VBP_LINES", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_VBP_LINES)},
663         {"MIPI_TX_VID_VFP_LINES", PLATFORM_DUMPER_REGISTERL, (void *)(g_mipiTxRegsVa + MIPI_TX_VID_VFP_LINES)},
664     };
665 
666     if (dumper == NULL) {
667         HDF_LOGE("%s: mipitxRegsVa dumper is NULL!", __func__);
668         return;
669     }
670     ret = PlatformDumperAddDatas(dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
671     if (ret != HDF_SUCCESS) {
672         return;
673     }
674     (void)PlatformDumperDump(dumper);
675     (void)PlatformDumperClearDatas(dumper);
676 }
677 
MipiTxWaitCmdFifoEmpty(void)678 static int MipiTxWaitCmdFifoEmpty(void)
679 {
680     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
681     U_CMD_PKT_STATUS cmdPktStatus;
682     unsigned int waitCnt;
683 
684     waitCnt = 0;
685     do {
686         cmdPktStatus.u32 = g_mipiTxRegsVa->CMD_PKT_STATUS.u32;
687         waitCnt++;
688         OsalUDelay(1);
689         if (waitCnt >  MIPI_TX_READ_TIMEOUT_CNT) {
690             HDF_LOGW("%s: timeout when send cmd buffer.", __func__);
691             MipiTxDumperDump(dev->dumper);
692             return HDF_ERR_TIMEOUT;
693         }
694     } while (cmdPktStatus.bits.gen_cmd_empty == 0);
695     return HDF_SUCCESS;
696 }
697 
MipiTxWaitWriteFifoEmpty(void)698 static int MipiTxWaitWriteFifoEmpty(void)
699 {
700     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
701     U_CMD_PKT_STATUS cmdPktStatus;
702     unsigned int waitCnt;
703 
704     waitCnt = 0;
705     do {
706         cmdPktStatus.u32 = g_mipiTxRegsVa->CMD_PKT_STATUS.u32;
707         waitCnt++;
708         OsalUDelay(1);
709         if (waitCnt >  MIPI_TX_READ_TIMEOUT_CNT) {
710             HDF_LOGW("%s: timeout when send data buffer.", __func__);
711             MipiTxDumperDump(dev->dumper);
712             return HDF_ERR_TIMEOUT;
713         }
714     } while (cmdPktStatus.bits.gen_pld_w_empty == 0);
715     return HDF_SUCCESS;
716 }
717 
MipiTxWaitWriteFifoNotFull(void)718 static int MipiTxWaitWriteFifoNotFull(void)
719 {
720     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
721     U_CMD_PKT_STATUS cmdPktStatus;
722     unsigned int waitCnt;
723 
724     waitCnt = 0;
725     do {
726         cmdPktStatus.u32 = g_mipiTxRegsVa->CMD_PKT_STATUS.u32;
727         if (waitCnt > 0) {
728             OsalUDelay(1);
729             HDF_LOGW("%s: write fifo full happened wait count = %u.", __func__, waitCnt);
730         }
731         if (waitCnt >  MIPI_TX_READ_TIMEOUT_CNT) {
732             HDF_LOGW("%s: timeout when wait write fifo not full buffer.", __func__);
733             MipiTxDumperDump(dev->dumper);
734             return HDF_ERR_TIMEOUT;
735         }
736         waitCnt++;
737     } while (cmdPktStatus.bits.gen_pld_w_full == 1);
738     return HDF_SUCCESS;
739 }
740 
741 /*
742  * set payloads data by writing register
743  * each 4 bytes in cmd corresponds to one register
744  */
MipiTxDrvSetPayloadData(const unsigned char *cmd, unsigned short cmdSize)745 static void MipiTxDrvSetPayloadData(const unsigned char *cmd, unsigned short cmdSize)
746 {
747     int32_t ret;
748     U_GEN_PLD_DATA genPldData;
749     int i, j;
750 
751     genPldData.u32 = g_mipiTxRegsVa->GEN_PLD_DATA.u32;
752 
753     for (i = 0; i < (cmdSize / 4); i++) { /* 4 cmd once */
754         genPldData.bits.gen_pld_b1 = cmd[i * 4]; /* 0 in 4 */
755         genPldData.bits.gen_pld_b2 = cmd[i * 4 + 1]; /* 1 in 4 */
756         genPldData.bits.gen_pld_b3 = cmd[i * 4 + 2]; /* 2 in 4 */
757         genPldData.bits.gen_pld_b4 = cmd[i * 4 + 3]; /* 3 in 4 */
758         ret = MipiTxWaitWriteFifoNotFull();
759         if (ret != HDF_SUCCESS) {
760             HDF_LOGE("%s: [MipiTxWaitWriteFifoNotFull] failed.", __func__);
761             return;
762         }
763         g_mipiTxRegsVa->GEN_PLD_DATA.u32 = genPldData.u32;
764     }
765     j = cmdSize % 4; /* remainder of 4 */
766     if (j != 0) {
767         if (j > 0) {
768             genPldData.bits.gen_pld_b1 = cmd[i * 4]; /* 0 in 4 */
769         }
770         if (j > 1) {
771             genPldData.bits.gen_pld_b2 = cmd[i * 4 + 1]; /* 1 in 4 */
772         }
773         if (j > 2) { /* bigger than 2 */
774             genPldData.bits.gen_pld_b3 = cmd[i * 4 + 2]; /* 2 in 4 */
775         }
776         ret = MipiTxWaitWriteFifoNotFull();
777         if (ret != HDF_SUCCESS) {
778             HDF_LOGE("%s: [MipiTxWaitWriteFifoNotFull] failed.", __func__);
779             return;
780         }
781         g_mipiTxRegsVa->GEN_PLD_DATA.u32 = genPldData.u32;
782     }
783 #ifdef MIPI_TX_DEBUG
784     HDF_LOGI("%s: \n=====set cmd=======", __func__);
785     HDF_LOGI("GEN_PLD_DATA(0x70): 0x%x", genPldData);
786 #endif
787 }
788 
MipiTxDrvSetCmdInfo(const CmdInfoTag *cmdInfo)789 static int MipiTxDrvSetCmdInfo(const CmdInfoTag *cmdInfo)
790 {
791     int32_t ret;
792     U_GEN_HDR genHdr;
793     unsigned char *cmd = NULL;
794     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
795 
796     if (cmdInfo == NULL) {
797         HDF_LOGE("%s: cmdInfo is NULL.", __func__);
798         return HDF_ERR_INVALID_OBJECT;
799     }
800     genHdr.u32 = g_mipiTxRegsVa->GEN_HDR.u32;
801     if (cmdInfo->cmd != NULL) {
802         if ((cmdInfo->cmdSize > 200) || (cmdInfo->cmdSize == 0)) { /* 200 is max cmd size */
803             HDF_LOGE("%s: set cmd size illegal, size =%hu.", __func__, cmdInfo->cmdSize);
804             return HDF_ERR_INVALID_PARAM;
805         }
806         cmd = (unsigned char *)OsalMemCalloc(cmdInfo->cmdSize);
807         if (cmd == NULL) {
808             HDF_LOGE("%s: OsalMemCalloc fail,please check,need %hu bytes.", __func__, cmdInfo->cmdSize);
809             return HDF_ERR_MALLOC_FAIL;
810         }
811         if (LOS_CopyToKernel(cmd, cmdInfo->cmdSize, cmdInfo->cmd, cmdInfo->cmdSize) != 0) {
812             OsalMemFree(cmd);
813             cmd = NULL;
814             HDF_LOGE("%s: [CopyFromUser] failed.", __func__);
815             MipiTxDumperDump(dev->dumper);
816             return HDF_ERR_IO;
817         }
818         MipiTxDrvSetPayloadData(cmd, cmdInfo->cmdSize);
819         OsalMemFree(cmd);
820         cmd = NULL;
821     }
822     genHdr.bits.gen_dt = cmdInfo->dataType;
823     genHdr.bits.gen_wc_lsbyte = cmdInfo->cmdSize & 0xff;
824     genHdr.bits.gen_wc_msbyte = (cmdInfo->cmdSize & 0xff00) >> 8; /* height 8 bits */
825     g_mipiTxRegsVa->GEN_HDR.u32 = genHdr.u32;
826     OsalUDelay(350);  /* wait 350 us transfer end */
827     ret = MipiTxWaitCmdFifoEmpty();
828     if (ret != HDF_SUCCESS) {
829         HDF_LOGE("%s: [MipiTxWaitCmdFifoEmpty] failed.", __func__);
830         return HDF_FAILURE;
831     }
832     ret = MipiTxWaitWriteFifoEmpty();
833     if (ret != HDF_SUCCESS) {
834         HDF_LOGE("%s: [MipiTxWaitWriteFifoEmpty] failed.", __func__);
835         return HDF_FAILURE;
836     }
837     return HDF_SUCCESS;
838 }
839 
MipiTxWaitReadFifoNotEmpty(void)840 static int MipiTxWaitReadFifoNotEmpty(void)
841 {
842     U_INT_ST0 intSt0;
843     U_INT_ST1 intSt1;
844     unsigned int waitCnt;
845     U_CMD_PKT_STATUS cmdPktStatus;
846 
847     waitCnt = 0;
848     do {
849         intSt1.u32 =  g_mipiTxRegsVa->INT_ST1.u32;
850         intSt0.u32 =  g_mipiTxRegsVa->INT_ST0.u32;
851         if ((intSt1.u32 & 0x3e) != 0) {
852             HDF_LOGE("%s: err happened when read data, int_st1 = 0x%x,int_st0 = %x.",
853                 __func__, intSt1.u32, intSt0.u32);
854             return HDF_FAILURE;
855         }
856         if (waitCnt >  MIPI_TX_READ_TIMEOUT_CNT) {
857             HDF_LOGW("%s: timeout when read data.", __func__);
858             return HDF_ERR_TIMEOUT;
859         }
860         waitCnt++;
861         OsalUDelay(1);
862         cmdPktStatus.u32 = g_mipiTxRegsVa->CMD_PKT_STATUS.u32;
863     } while (cmdPktStatus.bits.gen_pld_r_empty == 0x1);
864     return HDF_SUCCESS;
865 }
866 
MipiTxWaitReadFifoEmpty(void)867 static int MipiTxWaitReadFifoEmpty(void)
868 {
869     U_GEN_PLD_DATA pldData;
870     U_INT_ST1 intSt1;
871     unsigned int waitCnt;
872 
873     waitCnt = 0;
874     do {
875         intSt1.u32 = g_mipiTxRegsVa->INT_ST1.u32;
876         if ((intSt1.bits.gen_pld_rd_err) == 0x0) {
877             pldData.u32 = g_mipiTxRegsVa->GEN_PLD_DATA.u32;
878         }
879         waitCnt++;
880         OsalUDelay(1);
881         if (waitCnt >  MIPI_TX_READ_TIMEOUT_CNT) {
882             HDF_LOGW("%s: timeout when clear data buffer, the last read data is 0x%x.", __func__, pldData.u32);
883             return HDF_ERR_TIMEOUT;
884         }
885     } while ((intSt1.bits.gen_pld_rd_err) == 0x0);
886     return HDF_SUCCESS;
887 }
888 
MipiTxSendShortPacket(unsigned char virtualChannel, short unsigned dataType, unsigned short dataParam)889 static int MipiTxSendShortPacket(unsigned char virtualChannel,
890     short unsigned dataType, unsigned short  dataParam)
891 {
892     U_GEN_HDR genHdr;
893 
894     genHdr.bits.gen_vc = virtualChannel;
895     genHdr.bits.gen_dt = dataType;
896     genHdr.bits.gen_wc_lsbyte = (dataParam & 0xff);
897     genHdr.bits.gen_wc_msbyte = (dataParam & 0xff00) >> 8; /* height 8 bits */
898     g_mipiTxRegsVa->GEN_HDR.u32 = genHdr.u32;
899     if (MipiTxWaitCmdFifoEmpty() != HDF_SUCCESS) {
900         HDF_LOGE("%s: [MipiTxWaitCmdFifoEmpty] failed!", __func__);
901         return HDF_FAILURE;
902     }
903     return HDF_SUCCESS;
904 }
905 
MipiTxGetReadFifoData(unsigned int getDataSize, unsigned char *dataBuf)906 static int MipiTxGetReadFifoData(unsigned int getDataSize, unsigned char *dataBuf)
907 {
908     U_GEN_PLD_DATA pldData;
909     unsigned int i, j;
910 
911     for (i = 0; i < getDataSize / 4; i++) {   /* 4byte once */
912         if (MipiTxWaitReadFifoNotEmpty() != HDF_SUCCESS) {
913             HDF_LOGE("%s: [MipiTxWaitReadFifoNotEmpty] failed at first!", __func__);
914             return HDF_FAILURE;
915         }
916         pldData.u32 = g_mipiTxRegsVa->GEN_PLD_DATA.u32;
917         dataBuf[i * 4] = pldData.bits.gen_pld_b1;     /* 0 in 4 */
918         dataBuf[i * 4 + 1] = pldData.bits.gen_pld_b2; /* 1 in 4 */
919         dataBuf[i * 4 + 2] = pldData.bits.gen_pld_b3; /* 2 in 4 */
920         dataBuf[i * 4 + 3] = pldData.bits.gen_pld_b4; /* 3 in 4 */
921     }
922 
923     j = getDataSize % 4; /* remainder of 4 */
924 
925     if (j != 0) {
926         if (MipiTxWaitReadFifoNotEmpty() != HDF_SUCCESS) {
927             HDF_LOGE("%s: [MipiTxWaitReadFifoNotEmpty] failed at second!", __func__);
928             return HDF_FAILURE;
929         }
930         pldData.u32 = g_mipiTxRegsVa->GEN_PLD_DATA.u32;
931         if (j > 0) {
932             dataBuf[i * 4] = pldData.bits.gen_pld_b1; /* 0 in 4 */
933         }
934         if (j > 1) {
935             dataBuf[i * 4 + 1] = pldData.bits.gen_pld_b2; /* 1 in 4 */
936         }
937         if (j > 2) { /* bigger than 2 */
938             dataBuf[i * 4 + 2] = pldData.bits.gen_pld_b3; /* 2 in 4 */
939         }
940     }
941     return HDF_SUCCESS;
942 }
943 
MipiTxReset(void)944 static void MipiTxReset(void)
945 {
946     g_mipiTxRegsVa->PWR_UP.u32 = 0x0;
947     g_mipiTxRegsVa->PHY_RSTZ.u32 = 0xd;
948     OsalUDelay(1);
949     g_mipiTxRegsVa->PWR_UP.u32 = 0x1;
950     g_mipiTxRegsVa->PHY_RSTZ.u32 = 0xf;
951     OsalUDelay(1);
952     return;
953 }
954 
MipiTxDrvGetCmdInfo(GetCmdInfoTag *getCmdInfo)955 static int MipiTxDrvGetCmdInfo(GetCmdInfoTag *getCmdInfo)
956 {
957     unsigned char *dataBuf = NULL;
958 
959     dataBuf = (unsigned char*)OsalMemAlloc(getCmdInfo->getDataSize);
960     if (dataBuf == NULL) {
961         HDF_LOGE("%s: dataBuf is NULL!", __func__);
962         return HDF_ERR_MALLOC_FAIL;
963     }
964     if (MipiTxWaitReadFifoEmpty() != HDF_SUCCESS) {
965         HDF_LOGE("%s: [MipiTxWaitReadFifoEmpty] failed!", __func__);
966         goto fail0;
967     }
968     if (MipiTxSendShortPacket(0, getCmdInfo->dataType, getCmdInfo->dataParam) != HDF_SUCCESS) {
969         HDF_LOGE("%s: [MipiTxSendShortPacket] failed!", __func__);
970         goto fail0;
971     }
972     if (MipiTxGetReadFifoData(getCmdInfo->getDataSize, dataBuf) != HDF_SUCCESS) {
973         /* fail will block mipi data lane, so need reset */
974         MipiTxReset();
975         HDF_LOGE("%s: [MipiTxGetReadFifoData] failed!", __func__);
976         goto fail0;
977     }
978     LOS_CopyFromKernel(getCmdInfo->getData, getCmdInfo->getDataSize, dataBuf, getCmdInfo->getDataSize);
979     OsalMemFree(dataBuf);
980     dataBuf = NULL;
981 
982     return HDF_SUCCESS;
983 
984 fail0:
985     OsalMemFree(dataBuf);
986     dataBuf = NULL;
987     return HDF_FAILURE;
988 }
989 
MipiTxDrvEnableInput(const OutPutModeTag outputMode)990 static void MipiTxDrvEnableInput(const OutPutModeTag outputMode)
991 {
992     if ((outputMode == OUTPUT_MODE_DSI_VIDEO) || (outputMode == OUTPUT_MODE_CSI)) {
993         g_mipiTxRegsVa->MODE_CFG.u32 = 0x0;
994     }
995     if (outputMode == OUTPUT_MODE_DSI_CMD) {
996         g_mipiTxRegsVa->CMD_MODE_CFG.u32 = 0x0;
997     }
998     /* enable input */
999     g_mipiTxRegsVa->OPERATION_MODE.u32 = 0x80150000;
1000     g_mipiTxRegsVa->LPCLK_CTRL.u32 = 0x1;
1001     MipiTxReset();
1002 }
1003 
MipiTxDrvDisableInput(void)1004 static void MipiTxDrvDisableInput(void)
1005 {
1006     /* disable input */
1007     g_mipiTxRegsVa->OPERATION_MODE.u32 = 0x0;
1008     g_mipiTxRegsVa->CMD_MODE_CFG.u32 = 0xffffff00;
1009     /* command mode */
1010     g_mipiTxRegsVa->MODE_CFG.u32 = 0x1;
1011     g_mipiTxRegsVa->LPCLK_CTRL.u32 = 0x0;
1012     MipiTxReset();
1013 }
1014 
MipiTxDrvRegInit(void)1015 static int MipiTxDrvRegInit(void)
1016 {
1017     int32_t ret;
1018     if (!g_mipiTxRegsVa) {
1019         g_mipiTxRegsVa = (MipiTxRegsTypeTag *)OsalIoRemap(MIPI_TX_REGS_ADDR, (unsigned int)MIPI_TX_REGS_SIZE);
1020         if (g_mipiTxRegsVa == NULL) {
1021             HDF_LOGE("%s: remap mipi_tx reg addr fail.", __func__);
1022             return HDF_FAILURE;
1023         }
1024         g_regMapFlag = 1;
1025     }
1026     ret = MipiTxDumperCreate();
1027     if (ret != HDF_SUCCESS) {
1028         HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
1029         return ret;
1030     }
1031 
1032     return HDF_SUCCESS;
1033 }
1034 
MipiTxDrvRegExit(void)1035 static void MipiTxDrvRegExit(void)
1036 {
1037     ComboDevCfgTag *dev = GetDevCfg(&g_mipiTx);
1038 
1039     if (g_regMapFlag == 1) {
1040         if (g_mipiTxRegsVa != NULL) {
1041             OsalIoUnmap((void *)g_mipiTxRegsVa);
1042             g_mipiTxRegsVa = NULL;
1043         }
1044         g_regMapFlag = 0;
1045     }
1046     PlatformDumperDestroy(dev->dumper);
1047     OsalMemFree(dev->dumperName);
1048 }
1049 
MipiTxDrvHwInit(int smooth)1050 static void MipiTxDrvHwInit(int smooth)
1051 {
1052     unsigned long *mipiTxCrgAddr;
1053 
1054     mipiTxCrgAddr = (unsigned long *)OsalIoRemap(MIPI_TX_CRG, (unsigned long)0x4);
1055     /* mipi_tx gate clk enable */
1056     WriteReg32(mipiTxCrgAddr, 1, 0x1);
1057     /* reset */
1058     if (smooth == 0) {
1059         WriteReg32(mipiTxCrgAddr, 1 << 1, 0x1 << 1);
1060     }
1061     /* unreset */
1062     WriteReg32(mipiTxCrgAddr, 0 << 1, 0x1 << 1);
1063     /* ref clk */
1064     WriteReg32(mipiTxCrgAddr, 1 << 2, 0x1 << 2); /* 2 clk bit */
1065     OsalIoUnmap((void *)mipiTxCrgAddr);
1066 }
1067 
MipiTxDrvInit(int smooth)1068 static int MipiTxDrvInit(int smooth)
1069 {
1070     int32_t ret;
1071 
1072     ret = MipiTxDrvRegInit();
1073     if (ret != HDF_SUCCESS) {
1074         HDF_LOGE("%s: MipiTxDrvRegInit fail!", __func__);
1075         return ret;
1076     }
1077     MipiTxDrvHwInit(smooth);
1078     return ret;
1079 }
1080 
MipiTxDrvExit(void)1081 static void MipiTxDrvExit(void)
1082 {
1083     MipiTxDrvRegExit();
1084 }
1085 
MipiTxCheckCombDevCfg(const ComboDevCfgTag *devCfg)1086 static int MipiTxCheckCombDevCfg(const ComboDevCfgTag *devCfg)
1087 {
1088     int i;
1089     int validLaneId[LANE_MAX_NUM] = {0, 1, 2, 3};
1090 
1091     if (devCfg->devno != 0) {
1092         HDF_LOGE("%s: mipi_tx dev devno err!", __func__);
1093         return HDF_ERR_INVALID_PARAM;
1094     }
1095     for (i = 0; i < LANE_MAX_NUM; i++) {
1096         if ((devCfg->laneId[i] != validLaneId[i]) && (devCfg->laneId[i] != MIPI_TX_DISABLE_LANE_ID)) {
1097             HDF_LOGE("%s: mipi_tx dev laneId %hd err!", __func__, devCfg->laneId[i]);
1098             return HDF_ERR_INVALID_PARAM;
1099         }
1100     }
1101     if ((devCfg->outputMode != OUTPUT_MODE_CSI) && (devCfg->outputMode != OUTPUT_MODE_DSI_VIDEO) &&
1102         (devCfg->outputMode != OUTPUT_MODE_DSI_CMD)) {
1103         HDF_LOGE("%s: mipi_tx dev outputMode %d err!", __func__, devCfg->outputMode);
1104         return HDF_ERR_INVALID_PARAM;
1105     }
1106     if ((devCfg->videoMode != BURST_MODE) && (devCfg->videoMode != NON_BURST_MODE_SYNC_PULSES) &&
1107         (devCfg->videoMode != NON_BURST_MODE_SYNC_EVENTS)) {
1108         HDF_LOGE("%s: mipi_tx dev videoMode %d err!", __func__, devCfg->videoMode);
1109         return HDF_ERR_INVALID_PARAM;
1110     }
1111     if ((devCfg->outputFormat != OUT_FORMAT_RGB_16_BIT) && (devCfg->outputFormat != OUT_FORMAT_RGB_18_BIT) &&
1112         (devCfg->outputFormat != OUT_FORMAT_RGB_24_BIT) && (devCfg->outputFormat !=
1113         OUT_FORMAT_YUV420_8_BIT_NORMAL) && (devCfg->outputFormat != OUT_FORMAT_YUV420_8_BIT_LEGACY) &&
1114         (devCfg->outputFormat != OUT_FORMAT_YUV422_8_BIT)) {
1115         HDF_LOGE("%s: mipi_tx dev outputFormat %d err!", __func__, devCfg->outputFormat);
1116         return HDF_ERR_INVALID_PARAM;
1117     }
1118 
1119     return HDF_SUCCESS;
1120 }
1121 
MipiTxSetComboDevCfg(const ComboDevCfgTag *devCfg)1122 static int MipiTxSetComboDevCfg(const ComboDevCfgTag *devCfg)
1123 {
1124     int32_t ret = MipiTxCheckCombDevCfg(devCfg);
1125     if (ret != HDF_SUCCESS) {
1126         HDF_LOGE("%s: mipi_tx check combo_dev config failed!", __func__);
1127         return ret;
1128     }
1129     /* set controler config */
1130     MipiTxDrvSetControllerCfg(devCfg);
1131     /* set phy config */
1132     MipiTxDrvSetPhyCfg(devCfg);
1133     g_enCfg = true;
1134     return ret;
1135 }
1136 
Hi35xxSetCntlrCfg(struct MipiDsiCntlr *cntlr)1137 static int32_t Hi35xxSetCntlrCfg(struct MipiDsiCntlr *cntlr)
1138 {
1139     ComboDevCfgTag *dev = GetDevCfg(cntlr);
1140 
1141     if (dev == NULL) {
1142         HDF_LOGE("%s: dev is NULL!", __func__);
1143         return HDF_ERR_INVALID_OBJECT;
1144     }
1145     return MipiTxSetComboDevCfg(dev);
1146 }
1147 
MipiTxCheckSetCmdInfo(const CmdInfoTag *cmdInfo)1148 static int MipiTxCheckSetCmdInfo(const CmdInfoTag *cmdInfo)
1149 {
1150     if (!g_enCfg) {
1151         HDF_LOGE("%s: mipi_tx dev has not config!", __func__);
1152         return HDF_FAILURE;
1153     }
1154     if (cmdInfo->devno != 0) {
1155         HDF_LOGE("%s: mipi_tx devno %u err!", __func__, cmdInfo->devno);
1156         return HDF_ERR_INVALID_PARAM;
1157     }
1158     /* When cmd is not NULL, cmd_size means the length of cmd or it means cmd and addr */
1159     if (cmdInfo->cmd != NULL) {
1160         if (cmdInfo->cmdSize > MIPI_TX_SET_DATA_SIZE) {
1161             HDF_LOGE("%s: mipi_tx dev cmd_size %hu err!", __func__, cmdInfo->cmdSize);
1162             return HDF_ERR_INVALID_PARAM;
1163         }
1164     }
1165     return HDF_SUCCESS;
1166 }
1167 
MipiTxSetCmd(const CmdInfoTag *cmdInfo)1168 static int MipiTxSetCmd(const CmdInfoTag *cmdInfo)
1169 {
1170     int32_t ret;
1171     if (cmdInfo == NULL) {
1172         HDF_LOGE("%s: cmdInfo is NULL!", __func__);
1173         return HDF_ERR_INVALID_OBJECT;
1174     }
1175     ret = MipiTxCheckSetCmdInfo(cmdInfo);
1176     if (ret != HDF_SUCCESS) {
1177         HDF_LOGE("%s: mipi_tx check combo_dev config failed!", __func__);
1178         return ret;
1179     }
1180     return MipiTxDrvSetCmdInfo(cmdInfo);
1181 }
1182 
Hi35xxSetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd)1183 static int32_t Hi35xxSetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd)
1184 {
1185     CmdInfoTag cmdInfo;
1186 
1187     (void)cntlr;
1188     if (cmd == NULL) {
1189         HDF_LOGE("%s: cmd is NULL!", __func__);
1190         return HDF_ERR_INVALID_OBJECT;
1191     }
1192     cmdInfo.devno = 0;
1193     if (cmd->dataLen > 2) {                     /* 2: use long data type */
1194         cmdInfo.cmdSize = cmd->dataLen;
1195         cmdInfo.dataType = cmd->dataType;       /* 0x29: long data type */
1196         cmdInfo.cmd = cmd->payload;
1197     } else if (cmd->dataLen == 2) {             /* 2: use short data type */
1198         uint16_t tmp = cmd->payload[1];         /* 3: payload */
1199         tmp = (tmp & 0x00ff) << 8;              /* 0x00ff , 8: payload to high */
1200         tmp = 0xff00 & tmp;
1201         tmp = tmp | cmd->payload[0];            /* 2: reg addr */
1202         cmdInfo.cmdSize = tmp;
1203         cmdInfo.dataType = cmd->dataType;       /* 0x23: short data type */
1204         cmdInfo.cmd = NULL;
1205     } else if (cmd->dataLen == 1) {
1206         cmdInfo.cmdSize = cmd->payload[0];      /* 2: reg addr */
1207         cmdInfo.dataType = cmd->dataType;       /* 0x05: short data type */
1208         cmdInfo.cmd = NULL;
1209     } else {
1210         HDF_LOGE("%s: dataLen error!", __func__);
1211         return HDF_ERR_INVALID_PARAM;
1212     }
1213     return MipiTxSetCmd(&cmdInfo);
1214 }
1215 
MipiTxCheckGetCmdInfo(const GetCmdInfoTag *getCmdInfo)1216 static int MipiTxCheckGetCmdInfo(const GetCmdInfoTag *getCmdInfo)
1217 {
1218     if (!g_enCfg) {
1219         HDF_LOGE("%s: mipi_tx dev has not config!", __func__);
1220         return HDF_FAILURE;
1221     }
1222     if (getCmdInfo->devno != 0) {
1223         HDF_LOGE("%s: mipi_tx dev devno %u err!", __func__, getCmdInfo->devno);
1224         return HDF_ERR_INVALID_PARAM;
1225     }
1226     if ((getCmdInfo->getDataSize == 0) || (getCmdInfo->getDataSize > MIPI_TX_GET_DATA_SIZE)) {
1227         HDF_LOGE("%s: mipi_tx dev getDataSize %hu err!", __func__, getCmdInfo->getDataSize);
1228         return HDF_ERR_INVALID_PARAM;
1229     }
1230     if (getCmdInfo->getData == NULL) {
1231         HDF_LOGE("%s: mipi_tx dev getData is null!", __func__);
1232         return HDF_ERR_INVALID_OBJECT;
1233     }
1234     return HDF_SUCCESS;
1235 }
1236 
MipiTxGetCmd(GetCmdInfoTag *getCmdInfo)1237 static int MipiTxGetCmd(GetCmdInfoTag *getCmdInfo)
1238 {
1239     int32_t ret;
1240 
1241     ret = MipiTxCheckGetCmdInfo(getCmdInfo);
1242     if (ret != HDF_SUCCESS) {
1243         HDF_LOGE("%s: [MipiTxCheckGetCmdInfo] failed!", __func__);
1244         return ret;
1245     }
1246     return MipiTxDrvGetCmdInfo(getCmdInfo);
1247 }
1248 
Hi35xxGetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out)1249 static int32_t Hi35xxGetCmd(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out)
1250 {
1251     GetCmdInfoTag cmdInfo;
1252 
1253     (void)cntlr;
1254     if (cmd == NULL || out == NULL) {
1255         HDF_LOGE("%s: cmd or out is NULL!", __func__);
1256         return HDF_ERR_INVALID_OBJECT;
1257     }
1258     cmdInfo.devno = 0;
1259     cmdInfo.dataType = cmd->dataType;
1260     cmdInfo.dataParam = cmd->payload[0];
1261     cmdInfo.getDataSize = readLen;
1262     cmdInfo.getData = out;
1263     return MipiTxGetCmd(&cmdInfo);
1264 }
1265 
Hi35xxToLp(struct MipiDsiCntlr *cntlr)1266 static void Hi35xxToLp(struct MipiDsiCntlr *cntlr)
1267 {
1268     (void)cntlr;
1269     MipiTxDrvDisableInput();
1270 }
1271 
Hi35xxToHs(struct MipiDsiCntlr *cntlr)1272 static void Hi35xxToHs(struct MipiDsiCntlr *cntlr)
1273 {
1274     ComboDevCfgTag *dev = GetDevCfg(cntlr);
1275 
1276     if (dev == NULL) {
1277         HDF_LOGE("%s: dev is NULL.", __func__);
1278         return;
1279     }
1280     MipiTxDrvEnableInput(dev->outputMode);
1281 }
1282 
1283 static struct MipiDsiCntlrMethod g_method = {
1284     .setCntlrCfg = Hi35xxSetCntlrCfg,
1285     .setCmd = Hi35xxSetCmd,
1286     .getCmd = Hi35xxGetCmd,
1287     .toHs = Hi35xxToHs,
1288     .toLp = Hi35xxToLp
1289 };
1290 
Hi35xxMipiTxInit(struct HdfDeviceObject *device)1291 static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device)
1292 {
1293     int32_t ret;
1294 
1295     g_mipiTx.priv = NULL;
1296     g_mipiTx.ops = &g_method;
1297     ret = MipiDsiRegisterCntlr(&g_mipiTx, device);
1298     if (ret != HDF_SUCCESS) {
1299         HDF_LOGE("%s: [MipiDsiRegisterCntlr] failed!", __func__);
1300         return ret;
1301     }
1302 
1303     ret = MipiTxDrvInit(0);
1304     if (ret != HDF_SUCCESS) {
1305         HDF_LOGE("%s: [MipiTxDrvInit] failed.", __func__);
1306         return ret;
1307     }
1308     HDF_LOGI("%s: load mipi tx driver successfully!", __func__);
1309     return ret;
1310 }
1311 
Hi35xxMipiTxRelease(struct HdfDeviceObject *device)1312 static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device)
1313 {
1314     struct MipiDsiCntlr *cntlr = NULL;
1315 
1316     HDF_LOGI("%s: enter", __func__);
1317     if (device == NULL) {
1318         HDF_LOGE("%s: device is NULL.", __func__);
1319         return;
1320     }
1321     cntlr = MipiDsiCntlrFromDevice(device);
1322     if (cntlr == NULL) {
1323         HDF_LOGE("%s: cntlr is NULL.", __func__);
1324         return;
1325     }
1326 
1327     MipiTxDrvExit();
1328     MipiDsiUnregisterCntlr(&g_mipiTx);
1329     g_mipiTx.priv = NULL;
1330 }
1331 
1332 struct HdfDriverEntry g_mipiTxDriverEntry = {
1333     .moduleVersion = 1,
1334     .Init = Hi35xxMipiTxInit,
1335     .Release = Hi35xxMipiTxRelease,
1336     .moduleName = "HDF_MIPI_TX",
1337 };
1338 HDF_INIT(g_mipiTxDriverEntry);
1339 
1340 #ifdef __cplusplus
1341 #if __cplusplus
1342 }
1343 #endif
1344 #endif /* End of #ifdef __cplusplus */
1345