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 =%u.", __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 %u 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 %d 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 %d 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 %d 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 %d 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 %d 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
1233 return ret;
1234 }
1235
Hi35xxMipiTxRelease(struct HdfDeviceObject * device)1236 static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device)
1237 {
1238 struct MipiDsiCntlr *cntlr = NULL;
1239
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 HDF_LOGI("%s: unload mipi tx driver successfully!", __func__);
1254 }
1255
1256 struct HdfDriverEntry g_mipiTxDriverEntry = {
1257 .moduleVersion = 1,
1258 .Init = Hi35xxMipiTxInit,
1259 .Release = Hi35xxMipiTxRelease,
1260 .moduleName = "HDF_MIPI_TX",
1261 };
1262 HDF_INIT(g_mipiTxDriverEntry);
1263
1264 #ifdef __cplusplus
1265 #if __cplusplus
1266 }
1267 #endif
1268 #endif /* End of #ifdef __cplusplus */
1269