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