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