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