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