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