1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "mipi_tx_hal.h"
20 #include "hi_osal.h"
21 #include "type.h"
22 #include "mipi_tx.h"
23 #include "mipi_tx_reg.h"
24
25 #ifdef __cplusplus
26 #if __cplusplus
27 extern "C" {
28 #endif
29 #endif /* End of #ifdef __cplusplus */
30
31 #define MIPI_TX_REGS_ADDR 0x11270000
32 #define MIPI_TX_REGS_SIZE 0x10000
33
34 #define MIPI_TX_IRQ 120
35
36 #define MIPI_TX_CRG 0x1201010C
37
38 #define MIPI_TX_REF_CLK 27
39
40 #define TLPX 60
41 #define TCLK_PREPARE 60
42 #define TCLK_ZERO 250
43 #define TCLK_TRAIL 80
44 #define TPRE_DELAY 100
45 #define THS_PREPARE 80
46 #define THS_ZERO 180
47 #define THS_TRAIL 110
48
49 /* phy addr */
50 #define PLL_SET0 0x60
51 #define PLL_SET1 0x64
52 #define PLL_SET2 0x65
53 #ifdef HI_FPGA
54 #define PLL_SET3 0x17
55 #endif
56 #define PLL_SET4 0x66
57 #define PLL_SET5 0x67
58
59 #define DATA0_TPRE_DELAY 0x28
60 #define DATA1_TPRE_DELAY 0x38
61 #define DATA2_TPRE_DELAY 0x48
62 #define DATA3_TPRE_DELAY 0x58
63
64 #define CLK_TLPX 0x10
65 #define CLK_TCLK_PREPARE 0x11
66 #define CLK_TCLK_ZERO 0x12
67 #define CLK_TCLK_TRAIL 0x13
68
69 #define DATA0_TLPX 0x20
70 #define DATA0_THS_PREPARE 0x21
71 #define DATA0_THS_ZERO 0x22
72 #define DATA0_THS_TRAIL 0x23
73 #define DATA1_TLPX 0x30
74 #define DATA1_THS_PREPARE 0x31
75 #define DATA1_THS_ZERO 0x32
76 #define DATA1_THS_TRAIL 0x33
77 #define DATA2_TLPX 0x40
78 #define DATA2_THS_PREPARE 0x41
79 #define DATA2_THS_ZERO 0x42
80 #define DATA2_THS_TRAIL 0x43
81 #define DATA3_TLPX 0x50
82 #define DATA3_THS_PREPARE 0x51
83 #define DATA3_THS_ZERO 0x52
84 #define DATA3_THS_TRAIL 0x53
85
86 #define MIPI_TX_READ_TIMEOUT_CNT 1000
87
88 #define PREPARE_COMPENSATE 10
89 #define ROUNDUP_VALUE 7999
90 #define INNER_PEROID 8000 /* 8 * 1000 ,1000 is 1us = 1000ns, 8 is division ratio */
91
92 typedef struct {
93 unsigned char data_tpre_delay;
94 unsigned char clk_tlpx;
95 unsigned char clk_tclk_prepare;
96 unsigned char clk_tclk_zero;
97 unsigned char clk_tclk_trail;
98 unsigned char data_tlpx;
99 unsigned char data_ths_prepare;
100 unsigned char data_ths_zero;
101 unsigned char data_ths_trail;
102 } mipi_tx_phy_timing_parameters;
103
104 volatile mipi_tx_regs_type_t *g_mipi_tx_regs_va = NULL;
105
106 unsigned int g_mipi_tx_irq_num = MIPI_TX_IRQ;
107
108 unsigned int g_actual_phy_data_rate;
109
110 static unsigned int g_reg_map_flag = 0;
111
write_reg32(unsigned long addr,unsigned int value,unsigned int mask)112 static void write_reg32(unsigned long addr, unsigned int value, unsigned int mask)
113 {
114 unsigned int t;
115
116 t = osal_readl(addr);
117 t &= ~mask;
118 t |= value & mask;
119 osal_writel(t, addr);
120 }
121
set_phy_reg(unsigned int addr,unsigned char value)122 static void set_phy_reg(unsigned int addr, unsigned char value)
123 {
124 osal_isb();
125 osal_dsb();
126 osal_dmb();
127 g_mipi_tx_regs_va->PHY_TST_CTRL1.u32 = (0x10000 + addr);
128 osal_isb();
129 osal_dsb();
130 osal_dmb();
131 g_mipi_tx_regs_va->PHY_TST_CTRL0.u32 = 0x2;
132 osal_isb();
133 osal_dsb();
134 osal_dmb();
135 g_mipi_tx_regs_va->PHY_TST_CTRL0.u32 = 0x0;
136 osal_isb();
137 osal_dsb();
138 osal_dmb();
139 g_mipi_tx_regs_va->PHY_TST_CTRL1.u32 = value;
140 osal_isb();
141 osal_dsb();
142 osal_dmb();
143 g_mipi_tx_regs_va->PHY_TST_CTRL0.u32 = 0x2;
144 osal_isb();
145 osal_dsb();
146 osal_dmb();
147 g_mipi_tx_regs_va->PHY_TST_CTRL0.u32 = 0x0;
148 osal_isb();
149 osal_dsb();
150 osal_dmb();
151 }
152
mipi_tx_drv_get_phy_pll_set0(unsigned int phy_data_rate)153 static unsigned char mipi_tx_drv_get_phy_pll_set0(unsigned int phy_data_rate)
154 {
155 unsigned char pll_set0;
156
157 /* to get pll_set0, the parameters come from algorithm */
158 if (phy_data_rate > 750) { // 750 is data rate value, Different values correspond to different pll_set.
159 pll_set0 = 0x0;
160 } else if (phy_data_rate > 375) { // 375 is data rate value, Different values correspond to different pll_set.
161 pll_set0 = 0x8;
162 } else if (phy_data_rate > 188) { // 188 is data rate value, Different values correspond to different pll_set.
163 pll_set0 = 0xa;
164 } else if (phy_data_rate > 94) { // 94 is data rate value, Different values correspond to different pll_set.
165 pll_set0 = 0xc;
166 } else {
167 pll_set0 = 0xe;
168 }
169 return pll_set0;
170 }
171
mipi_tx_drv_get_phy_pll_set1_set5(unsigned int phy_data_rate,unsigned char pll_set0,unsigned char * pll_set1,unsigned char * pll_set5)172 static void mipi_tx_drv_get_phy_pll_set1_set5(unsigned int phy_data_rate,
173 unsigned char pll_set0,
174 unsigned char *pll_set1,
175 unsigned char *pll_set5)
176 {
177 int datarate_clk;
178 int pll_ref;
179
180 datarate_clk = (phy_data_rate + MIPI_TX_REF_CLK - 1) / MIPI_TX_REF_CLK;
181
182 /* to get pll_set1 and pll_set5, the parameters come from algorithm */
183 if (pll_set0 / 2 == 4) {
184 pll_ref = 2;
185 } else if (pll_set0 / 2 == 5) {
186 pll_ref = 4;
187 } else if (pll_set0 / 2 == 6) {
188 pll_ref = 8;
189 } else if (pll_set0 / 2 == 7) {
190 pll_ref = 16;
191 } else {
192 pll_ref = 1;
193 }
194 if ((datarate_clk * pll_ref) % 2) {
195 *pll_set1 = 0x10;
196 *pll_set5 = (datarate_clk * pll_ref - 1) / 2;
197 } else {
198 *pll_set1 = 0x20;
199 *pll_set5 = datarate_clk * pll_ref / 2 - 1;
200 }
201
202 return;
203 }
204
mipi_tx_drv_set_phy_pll_setx(unsigned int phy_data_rate)205 static void mipi_tx_drv_set_phy_pll_setx(unsigned int phy_data_rate)
206 {
207 unsigned char pll_set0;
208 unsigned char pll_set1;
209 unsigned char pll_set2;
210 #ifdef HI_FPGA
211 unsigned char pll_set3;
212 #endif
213 unsigned char pll_set4;
214 unsigned char pll_set5;
215
216 /* pll_set0 */
217 pll_set0 = mipi_tx_drv_get_phy_pll_set0(phy_data_rate);
218 set_phy_reg(PLL_SET0, pll_set0);
219
220 /* pll_set1 */
221 mipi_tx_drv_get_phy_pll_set1_set5(phy_data_rate, pll_set0, &pll_set1, &pll_set5);
222 set_phy_reg(PLL_SET1, pll_set1);
223
224 /* pll_set2 */
225 pll_set2 = 0x2;
226 set_phy_reg(PLL_SET2, pll_set2);
227
228 /* pll_set4 */
229 pll_set4 = 0x0;
230 set_phy_reg(PLL_SET4, pll_set4);
231
232 #ifdef HI_FPGA
233 pll_set3 = 0x1;
234 set_phy_reg(PLL_SET3, pll_set3);
235 #endif
236
237 /* pll_set5 */
238 set_phy_reg(PLL_SET5, pll_set5);
239
240 #ifdef MIPI_TX_DEBUG
241 osal_printk("\n==========phy pll info=======\n");
242 osal_printk("pll_set0(0x14): 0x%x\n", pll_set0);
243 osal_printk("pll_set1(0x15): 0x%x\n", pll_set1);
244 osal_printk("pll_set2(0x16): 0x%x\n", pll_set2);
245 #ifdef HI_FPGA
246 osal_printk("pll_set3(0x17): 0x%x\n", pll_set3);
247 #endif
248 osal_printk("pll_set4(0x1e): 0x%x\n", pll_set4);
249 osal_printk("=========================\n");
250 #endif
251 }
252
mipi_tx_drv_get_phy_clk_prepare(unsigned char * clk_prepare)253 static void mipi_tx_drv_get_phy_clk_prepare(unsigned char *clk_prepare)
254 {
255 unsigned char temp0;
256 unsigned char temp1;
257
258 temp0 = ((g_actual_phy_data_rate * TCLK_PREPARE + ROUNDUP_VALUE) / INNER_PEROID - 1 +
259 ((g_actual_phy_data_rate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID) -
260 ((((g_actual_phy_data_rate * TCLK_PREPARE + ROUNDUP_VALUE) / INNER_PEROID +
261 ((g_actual_phy_data_rate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID)) * INNER_PEROID -
262 PREPARE_COMPENSATE * g_actual_phy_data_rate - TCLK_PREPARE * g_actual_phy_data_rate) / INNER_PEROID));
263 if (temp0 > 0) { /* 0 is the minimum */
264 temp1 = temp0;
265 } else {
266 temp1 = 0; /* 0 is the minimum */
267 }
268
269 if (((temp1 + 1) * INNER_PEROID - PREPARE_COMPENSATE * g_actual_phy_data_rate) /* temp + 1 is next level period */
270 > 94 * g_actual_phy_data_rate) { /* 94 is the maximum in mipi protocol */
271 if (temp0 > 0) {
272 *clk_prepare = temp0 - 1;
273 } else {
274 *clk_prepare = 255; /* set 255 will easy to found mistake */
275 hi_mipi_tx_err("err when calc phy timing \n");
276 }
277 } else {
278 if (temp0 > 0) { /* 0 is the minimum */
279 *clk_prepare = temp0;
280 } else {
281 *clk_prepare = 0; /* 0 is the minimum */
282 }
283 }
284 }
285
mipi_tx_drv_get_phy_data_prepare(unsigned char * data_prepare)286 static void mipi_tx_drv_get_phy_data_prepare(unsigned char *data_prepare)
287 {
288 unsigned char temp0;
289 unsigned char temp1;
290
291 /* DATA_THS_PREPARE */
292 temp0 = ((g_actual_phy_data_rate * THS_PREPARE + ROUNDUP_VALUE) / INNER_PEROID - 1 +
293 ((g_actual_phy_data_rate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID) -
294 ((((g_actual_phy_data_rate * THS_PREPARE + ROUNDUP_VALUE) / INNER_PEROID +
295 ((g_actual_phy_data_rate * PREPARE_COMPENSATE + ROUNDUP_VALUE) / INNER_PEROID)) * INNER_PEROID -
296 PREPARE_COMPENSATE * g_actual_phy_data_rate - THS_PREPARE * g_actual_phy_data_rate) / INNER_PEROID));
297 if (temp0 > 0) {
298 temp1 = temp0;
299 } else {
300 temp1 = 0;
301 }
302
303 if ((g_actual_phy_data_rate > 105) && /* bigger than 105 */
304 (((temp1 + 1) * INNER_PEROID - PREPARE_COMPENSATE * g_actual_phy_data_rate) >
305 (85 * g_actual_phy_data_rate + 6 * 1000))) { /* 85 + 6 * 1000 is the maximum in mipi protocol */
306 if (temp0 > 0) {
307 *data_prepare = temp0 - 1;
308 } else {
309 *data_prepare = 255; /* set 255 will easy to found mistake */
310 hi_mipi_tx_err("err when calc phy timing \n");
311 }
312 } else {
313 if (temp0 > 0) {
314 *data_prepare = temp0;
315 } else {
316 *data_prepare = 0;
317 }
318 }
319 }
320
321 /* get global operation timing parameters. */
mipi_tx_drv_get_phy_timing_parameters(mipi_tx_phy_timing_parameters * tp)322 static void mipi_tx_drv_get_phy_timing_parameters(mipi_tx_phy_timing_parameters *tp)
323 {
324 /* DATA0~3 TPRE-DELAY */
325 tp->data_tpre_delay = (g_actual_phy_data_rate * TPRE_DELAY + ROUNDUP_VALUE) /
326 INNER_PEROID - 1; /* 1 is compensate */
327 /* CLK_TLPX */
328 tp->clk_tlpx = (g_actual_phy_data_rate * TLPX + ROUNDUP_VALUE) / INNER_PEROID - 1; /* 1 is compensate */
329 /* CLK_TCLK_PREPARE */
330 mipi_tx_drv_get_phy_clk_prepare(&tp->clk_tclk_prepare);
331
332 /* CLK_TCLK_ZERO */
333 if ((g_actual_phy_data_rate * TCLK_ZERO + ROUNDUP_VALUE) / INNER_PEROID > 4) { /* 4 is compensate */
334 tp->clk_tclk_zero = (g_actual_phy_data_rate * TCLK_ZERO + ROUNDUP_VALUE) / INNER_PEROID - 4;
335 } else {
336 tp->clk_tclk_zero = 0; /* 0 is minimum */
337 }
338
339 /* CLK_TCLK_TRAIL */
340 tp->clk_tclk_trail = (g_actual_phy_data_rate * TCLK_TRAIL + ROUNDUP_VALUE) / INNER_PEROID;
341
342 /* DATA_TLPX */
343 tp->data_tlpx = (g_actual_phy_data_rate * TLPX + ROUNDUP_VALUE) / INNER_PEROID - 1; /* 1 is compensate */
344
345 /* DATA_THS_PREPARE */
346 mipi_tx_drv_get_phy_data_prepare(&tp->data_ths_prepare);
347
348 /* DATA_THS_ZERO */
349 if ((g_actual_phy_data_rate * THS_ZERO + ROUNDUP_VALUE) / INNER_PEROID > 4) { /* 4 is compensate */
350 tp->data_ths_zero = (g_actual_phy_data_rate * THS_ZERO + ROUNDUP_VALUE) / INNER_PEROID - 4;
351 } else {
352 tp->data_ths_zero = 0; /* 0 is minimum */
353 }
354
355 /* DATA_THS_TRAIL */
356 tp->data_ths_trail = (g_actual_phy_data_rate * THS_TRAIL + ROUNDUP_VALUE) /
357 INNER_PEROID + 1; /* 1 is compensate */
358 }
359
360 /* set global operation timing parameters. */
mipi_tx_drv_set_phy_timing_parameters(const mipi_tx_phy_timing_parameters * tp)361 static void mipi_tx_drv_set_phy_timing_parameters(const mipi_tx_phy_timing_parameters *tp)
362 {
363 unsigned char data_tpre_delay = tp->data_tpre_delay;
364 unsigned char clk_tlpx = tp->clk_tlpx;
365 unsigned char clk_tclk_prepare = tp->clk_tclk_prepare;
366 unsigned char clk_tclk_zero = tp->clk_tclk_zero;
367 unsigned char clk_tclk_trail = tp->clk_tclk_trail;
368 unsigned char data_tlpx = tp->data_tlpx;
369 unsigned char data_ths_prepare = tp->data_ths_prepare;
370 unsigned char data_ths_zero = tp->data_ths_zero;
371 unsigned char data_ths_trail = tp->data_ths_trail;
372
373 /* DATA0~3 TPRE-DELAY */
374 set_phy_reg(DATA0_TPRE_DELAY, data_tpre_delay);
375 set_phy_reg(DATA1_TPRE_DELAY, data_tpre_delay);
376 set_phy_reg(DATA2_TPRE_DELAY, data_tpre_delay);
377 set_phy_reg(DATA3_TPRE_DELAY, data_tpre_delay);
378
379 /* CLK_TLPX */
380 set_phy_reg(CLK_TLPX, clk_tlpx);
381
382 /* CLK_TCLK_PREPARE */
383 set_phy_reg(CLK_TCLK_PREPARE, clk_tclk_prepare);
384
385 /* CLK_TCLK_ZERO */
386 set_phy_reg(CLK_TCLK_ZERO, clk_tclk_zero);
387
388 /* CLK_TCLK_TRAIL */
389 set_phy_reg(CLK_TCLK_TRAIL, clk_tclk_trail);
390
391 /*
392 * DATA_TLPX
393 * DATA_THS_PREPARE
394 * DATA_THS_ZERO
395 * DATA_THS_TRAIL
396 */
397 set_phy_reg(DATA0_TLPX, data_tlpx);
398 set_phy_reg(DATA0_THS_PREPARE, data_ths_prepare);
399 set_phy_reg(DATA0_THS_ZERO, data_ths_zero);
400 set_phy_reg(DATA0_THS_TRAIL, data_ths_trail);
401 set_phy_reg(DATA1_TLPX, data_tlpx);
402 set_phy_reg(DATA1_THS_PREPARE, data_ths_prepare);
403 set_phy_reg(DATA1_THS_ZERO, data_ths_zero);
404 set_phy_reg(DATA1_THS_TRAIL, data_ths_trail);
405 set_phy_reg(DATA2_TLPX, data_tlpx);
406 set_phy_reg(DATA2_THS_PREPARE, data_ths_prepare);
407 set_phy_reg(DATA2_THS_ZERO, data_ths_zero);
408 set_phy_reg(DATA2_THS_TRAIL, data_ths_trail);
409 set_phy_reg(DATA3_TLPX, data_tlpx);
410 set_phy_reg(DATA3_THS_PREPARE, data_ths_prepare);
411 set_phy_reg(DATA3_THS_ZERO, data_ths_zero);
412 set_phy_reg(DATA3_THS_TRAIL, data_ths_trail);
413
414 #ifdef MIPI_TX_DEBUG
415 osal_printk("\n==========phy timing parameters=======\n");
416 osal_printk("data_tpre_delay(0x30/40/50/60): 0x%x\n", data_tpre_delay);
417 osal_printk("clk_tlpx(0x22): 0x%x\n", clk_tlpx);
418 osal_printk("clk_tclk_prepare(0x23): 0x%x\n", clk_tclk_prepare);
419 osal_printk("clk_tclk_zero(0x24): 0x%x\n", clk_tclk_zero);
420 osal_printk("clk_tclk_trail(0x25): 0x%x\n", clk_tclk_trail);
421 osal_printk("data_tlpx(0x32/42/52/62): 0x%x\n", data_tlpx);
422 osal_printk("data_ths_prepare(0x33/43/53/63): 0x%x\n", data_ths_prepare);
423 osal_printk("data_ths_zero(0x34/44/54/64): 0x%x\n", data_ths_zero);
424 osal_printk("data_ths_trail(0x35/45/55/65): 0x%x\n", data_ths_trail);
425 osal_printk("=========================\n");
426 #endif
427 }
428
429 /*
430 * set data lp2hs,hs2lp time
431 * set clk lp2hs,hs2lp time
432 * unit: hsclk
433 */
mipi_tx_drv_set_phy_hs_lp_switch_time(const mipi_tx_phy_timing_parameters * tp)434 static void mipi_tx_drv_set_phy_hs_lp_switch_time(const mipi_tx_phy_timing_parameters *tp)
435 {
436 unsigned char data_tpre_delay = tp->data_tpre_delay;
437 unsigned char clk_tlpx = tp->clk_tlpx;
438 unsigned char clk_tclk_prepare = tp->clk_tclk_prepare;
439 unsigned char clk_tclk_zero = tp->clk_tclk_zero;
440 unsigned char data_tlpx = tp->data_tlpx;
441 unsigned char data_ths_prepare = tp->data_ths_prepare;
442 unsigned char data_ths_zero = tp->data_ths_zero;
443 unsigned char data_ths_trail = tp->data_ths_trail;
444
445 /* data lp2hs,hs2lp time */
446 g_mipi_tx_regs_va->PHY_TMR_CFG.u32 = ((data_ths_trail - 1) << 16) + /* 16 set register */
447 data_tpre_delay + data_tlpx + data_ths_prepare + data_ths_zero + 7; /* 7 from algorithm */
448 /* clk lp2hs,hs2lp time */
449 g_mipi_tx_regs_va->PHY_TMR_LPCLK_CFG.u32 = ((31 + data_ths_trail) << 16) + /* 31 from algorithm, 16 set register */
450 clk_tlpx + clk_tclk_prepare + clk_tclk_zero + 6; /* 6 from algorithm */
451
452 #ifdef MIPI_TX_DEBUG
453 osal_printk("PHY_TMR_CFG(0x9C): 0x%x\n", g_mipi_tx_regs_va->PHY_TMR_CFG.u32);
454 osal_printk("PHY_TMR_LPCLK_CFG(0x98): 0x%x\n", g_mipi_tx_regs_va->PHY_TMR_LPCLK_CFG.u32);
455 #endif
456 }
457
mipi_tx_drv_set_phy_cfg(const combo_dev_cfg_t * dev_cfg)458 void mipi_tx_drv_set_phy_cfg(const combo_dev_cfg_t *dev_cfg)
459 {
460 mipi_tx_phy_timing_parameters tp = {0};
461
462 /* set phy pll parameters setx */
463 mipi_tx_drv_set_phy_pll_setx(dev_cfg->phy_data_rate);
464
465 /* get global operation timing parameters */
466 mipi_tx_drv_get_phy_timing_parameters(&tp);
467
468 /* set global operation timing parameters */
469 mipi_tx_drv_set_phy_timing_parameters(&tp);
470
471 /* set hs switch to lp and lp switch to hs time */
472 mipi_tx_drv_set_phy_hs_lp_switch_time(&tp);
473
474 /* edpi_cmd_size */
475 g_mipi_tx_regs_va->EDPI_CMD_SIZE.u32 = 0xF0;
476
477 /* phy enable */
478 g_mipi_tx_regs_va->PHY_RSTZ.u32 = 0xf;
479
480 if (dev_cfg->output_mode == OUTPUT_MODE_CSI) {
481 if (dev_cfg->output_format == OUT_FORMAT_YUV420_8_BIT_NORMAL) {
482 g_mipi_tx_regs_va->DATATYPE0.u32 = 0x10218;
483 g_mipi_tx_regs_va->CSI_CTRL.u32 = 0x1111;
484 } else if (dev_cfg->output_format == OUT_FORMAT_YUV422_8_BIT) {
485 g_mipi_tx_regs_va->DATATYPE0.u32 = 0x1021E;
486 g_mipi_tx_regs_va->CSI_CTRL.u32 = 0x1111;
487 }
488 } else {
489 if (dev_cfg->output_format == OUT_FORMAT_RGB_16_BIT) {
490 g_mipi_tx_regs_va->DATATYPE0.u32 = 0x111213D;
491 g_mipi_tx_regs_va->CSI_CTRL.u32 = 0x10100;
492 } else if (dev_cfg->output_format == OUT_FORMAT_RGB_18_BIT) {
493 g_mipi_tx_regs_va->DATATYPE0.u32 = 0x111213D;
494 g_mipi_tx_regs_va->CSI_CTRL.u32 = 0x10100;
495 } else if (dev_cfg->output_format == OUT_FORMAT_RGB_24_BIT) {
496 g_mipi_tx_regs_va->DATATYPE0.u32 = 0x111213D;
497 g_mipi_tx_regs_va->CSI_CTRL.u32 = 0x10100;
498 }
499 }
500
501 g_mipi_tx_regs_va->PHY_RSTZ.u32 = 0XF;
502
503 osal_msleep(1);
504
505 g_mipi_tx_regs_va->LPCLK_CTRL.u32 = 0x0;
506 }
507
mipi_tx_drv_get_dev_status(mipi_tx_dev_phy_t * mipi_tx_phy_ctx)508 void mipi_tx_drv_get_dev_status(mipi_tx_dev_phy_t *mipi_tx_phy_ctx)
509 {
510 mipi_tx_phy_ctx->hact_det = g_mipi_tx_regs_va->HORI0_DET.bits.hact_det;
511 mipi_tx_phy_ctx->hall_det = g_mipi_tx_regs_va->HORI0_DET.bits.hline_det;
512 mipi_tx_phy_ctx->hbp_det = g_mipi_tx_regs_va->HORI1_DET.bits.hbp_det;
513 mipi_tx_phy_ctx->hsa_det = g_mipi_tx_regs_va->HORI1_DET.bits.hsa_det;
514
515 mipi_tx_phy_ctx->vact_det = g_mipi_tx_regs_va->VERT_DET.bits.vact_det;
516 mipi_tx_phy_ctx->vall_det = g_mipi_tx_regs_va->VERT_DET.bits.vall_det;
517 mipi_tx_phy_ctx->vsa_det = g_mipi_tx_regs_va->VSA_DET.bits.vsa_det;
518 }
519
set_output_format(const combo_dev_cfg_t * dev_cfg)520 static void set_output_format(const combo_dev_cfg_t *dev_cfg)
521 {
522 int color_coding = 0;
523
524 if (dev_cfg->output_mode == OUTPUT_MODE_CSI) {
525 if (dev_cfg->output_format == OUT_FORMAT_YUV420_8_BIT_NORMAL) {
526 color_coding = 0xd;
527 } else if (dev_cfg->output_format == OUT_FORMAT_YUV422_8_BIT) {
528 color_coding = 0x1;
529 }
530 } else {
531 if (dev_cfg->output_format == OUT_FORMAT_RGB_16_BIT) {
532 color_coding = 0x0;
533 } else if (dev_cfg->output_format == OUT_FORMAT_RGB_18_BIT) {
534 color_coding = 0x3;
535 } else if (dev_cfg->output_format == OUT_FORMAT_RGB_24_BIT) {
536 color_coding = 0x5;
537 }
538 }
539
540 g_mipi_tx_regs_va->COLOR_CODING.u32 = color_coding;
541 #ifdef MIPI_TX_DEBUG
542 osal_printk("set_output_format: 0x%x\n", color_coding);
543 #endif
544 }
545
set_video_mode_cfg(const combo_dev_cfg_t * dev_cfg)546 static void set_video_mode_cfg(const combo_dev_cfg_t *dev_cfg)
547 {
548 int video_mode;
549
550 if (dev_cfg->video_mode == NON_BURST_MODE_SYNC_PULSES) {
551 video_mode = 0;
552 } else if (dev_cfg->video_mode == NON_BURST_MODE_SYNC_EVENTS) {
553 video_mode = 1;
554 } else {
555 video_mode = 2; /* 2 register value */
556 }
557
558 if ((dev_cfg->output_mode == OUTPUT_MODE_CSI) || (dev_cfg->output_mode == OUTPUT_MODE_DSI_CMD)) {
559 video_mode = 2; /* 2 register value */
560 }
561
562 g_mipi_tx_regs_va->VID_MODE_CFG.u32 = 0x3f00 + video_mode;
563 }
564
set_timing_config(const combo_dev_cfg_t * dev_cfg)565 static void set_timing_config(const combo_dev_cfg_t *dev_cfg)
566 {
567 unsigned int hsa_time;
568 unsigned int hbp_time;
569 unsigned int hline_time;
570
571 if (dev_cfg->pixel_clk == 0) {
572 osal_printk("dev_cfg->pixel_clk is 0, illegal.\n");
573 return;
574 }
575
576 hsa_time = g_actual_phy_data_rate * dev_cfg->sync_info.vid_hsa_pixels * 125 / /* 125 from algorithm */
577 dev_cfg->pixel_clk;
578 hbp_time = g_actual_phy_data_rate * dev_cfg->sync_info.vid_hbp_pixels * 125 / /* 125 from algorithm */
579 dev_cfg->pixel_clk;
580 hline_time = g_actual_phy_data_rate * dev_cfg->sync_info.vid_hline_pixels * 125 / /* 125 from algorithm */
581 dev_cfg->pixel_clk;
582
583 g_mipi_tx_regs_va->VID_HSA_TIME.u32 = hsa_time;
584 g_mipi_tx_regs_va->VID_HBP_TIME.u32 = hbp_time;
585 g_mipi_tx_regs_va->VID_HLINE_TIME.u32 = hline_time;
586
587 g_mipi_tx_regs_va->VID_VSA_LINES.u32 = dev_cfg->sync_info.vid_vsa_lines;
588 g_mipi_tx_regs_va->VID_VBP_LINES.u32 = dev_cfg->sync_info.vid_vbp_lines;
589 g_mipi_tx_regs_va->VID_VFP_LINES.u32 = dev_cfg->sync_info.vid_vfp_lines;
590 g_mipi_tx_regs_va->VID_VACTIVE_LINES.u32 = dev_cfg->sync_info.vid_active_lines;
591
592 #ifdef MIPI_TX_DEBUG
593 osal_printk("VID_HSA_TIME(0x48): 0x%x\n", hsa_time);
594 osal_printk("VID_HBP_TIME(0x4c): 0x%x\n", hbp_time);
595 osal_printk("VID_HLINE_TIME(0x50): 0x%x\n", hline_time);
596 osal_printk("VID_VSA_LINES(0x54): 0x%x\n", dev_cfg->sync_info.vid_vsa_lines);
597 osal_printk("VID_VBP_LINES(0x58): 0x%x\n", dev_cfg->sync_info.vid_vbp_lines);
598 osal_printk("VID_VFP_LINES(0x5c): 0x%x\n", dev_cfg->sync_info.vid_vfp_lines);
599 osal_printk("VID_VACTIVE_LINES(0x60): 0x%x\n", dev_cfg->sync_info.vid_active_lines);
600 #endif
601 }
602
set_lane_config(const short lane_id[])603 void set_lane_config(const short lane_id[])
604 {
605 int lane_num = 0;
606 int i;
607
608 for (i = 0; i < LANE_MAX_NUM; i++) {
609 if (-1 != lane_id[i]) {
610 lane_num++;
611 }
612 }
613
614 g_mipi_tx_regs_va->PHY_IF_CFG.u32 = lane_num - 1;
615 }
616
mipi_tx_drv_set_clkmgr_cfg(void)617 void mipi_tx_drv_set_clkmgr_cfg(void)
618 {
619 if (g_actual_phy_data_rate / 160 < 2) { /* 160 cal div, should not smaller than 2 */
620 g_mipi_tx_regs_va->CLKMGR_CFG.u32 = 0x102;
621 } else {
622 g_mipi_tx_regs_va->CLKMGR_CFG.u32 = 0x100 + (g_actual_phy_data_rate + 159) / 160; /* 159 160 cal div */
623 }
624 }
625
mipi_tx_drv_set_controller_cfg(const combo_dev_cfg_t * dev_cfg)626 void mipi_tx_drv_set_controller_cfg(const combo_dev_cfg_t *dev_cfg)
627 {
628 if (dev_cfg == NULL) {
629 hi_mipi_tx_err("para check failed \n");
630 return;
631 }
632 /* disable input */
633 g_mipi_tx_regs_va->OPERATION_MODE.u32 = 0x0;
634
635 /* vc_id */
636 g_mipi_tx_regs_va->VCID.u32 = 0x0;
637
638 /* output format,color coding */
639 set_output_format(dev_cfg);
640
641 /* txescclk,timeout */
642 g_actual_phy_data_rate = ((dev_cfg->phy_data_rate + MIPI_TX_REF_CLK - 1) / MIPI_TX_REF_CLK) * MIPI_TX_REF_CLK;
643 mipi_tx_drv_set_clkmgr_cfg();
644
645 /* cmd transmission mode */
646 g_mipi_tx_regs_va->CMD_MODE_CFG.u32 = 0xffffff00;
647
648 /* crc,ecc,eotp tran */
649 g_mipi_tx_regs_va->PCKHDL_CFG.u32 = 0x1c;
650 /* gen_vcid_rx */
651 g_mipi_tx_regs_va->GEN_VCID.u32 = 0x0;
652
653 /* mode config */
654 g_mipi_tx_regs_va->MODE_CFG.u32 = 0x1;
655
656 /* video mode cfg */
657 set_video_mode_cfg(dev_cfg);
658 if ((dev_cfg->output_mode == OUTPUT_MODE_DSI_VIDEO) || (dev_cfg->output_mode == OUTPUT_MODE_CSI)) {
659 g_mipi_tx_regs_va->VID_PKT_SIZE.u32 = dev_cfg->sync_info.vid_pkt_size;
660 } else {
661 g_mipi_tx_regs_va->EDPI_CMD_SIZE.u32 = dev_cfg->sync_info.edpi_cmd_size;
662 }
663
664 /* num_chunks/null_size */
665 g_mipi_tx_regs_va->VID_NUM_CHUNKS.u32 = 0x0;
666 g_mipi_tx_regs_va->VID_NULL_SIZE.u32 = 0x0;
667
668 /* timing config */
669 set_timing_config(dev_cfg);
670
671 /* invact,outvact time */
672 g_mipi_tx_regs_va->LP_CMD_TIM.u32 = 0x0;
673
674 g_mipi_tx_regs_va->PHY_TMR_CFG.u32 = 0x9002D;
675
676 g_mipi_tx_regs_va->PHY_TMR_LPCLK_CFG.u32 = 0x29002E;
677
678 g_mipi_tx_regs_va->EDPI_CMD_SIZE.u32 = 0xF0;
679
680 /* lp_wr_to_cnt */
681 g_mipi_tx_regs_va->LP_WR_TO_CNT.u32 = 0x0;
682 /* bta_to_cnt */
683 g_mipi_tx_regs_va->BTA_TO_CNT.u32 = 0x0;
684
685 /* lanes */
686 set_lane_config(dev_cfg->lane_id);
687
688 /* phy_tx requlpsclk */
689 g_mipi_tx_regs_va->PHY_ULPS_CTRL.u32 = 0x0;
690
691 /* int msk0 */
692 g_mipi_tx_regs_va->INT_MSK0.u32 = 0x0;
693
694 /* pwr_up unreset */
695 g_mipi_tx_regs_va->PWR_UP.u32 = 0x0;
696 g_mipi_tx_regs_va->PWR_UP.u32 = 0xf;
697 }
698
mipi_tx_wait_cmd_fifo_empty(void)699 static int mipi_tx_wait_cmd_fifo_empty(void)
700 {
701 U_CMD_PKT_STATUS cmd_pkt_status;
702 unsigned int wait_count;
703
704 wait_count = 0;
705 do {
706 cmd_pkt_status.u32 = g_mipi_tx_regs_va->CMD_PKT_STATUS.u32;
707
708 wait_count++;
709
710 osal_udelay(1);
711
712 if (wait_count > MIPI_TX_READ_TIMEOUT_CNT) {
713 hi_mipi_tx_err("timeout when send cmd buffer \n");
714 return -1;
715 }
716 } while (cmd_pkt_status.bits.gen_cmd_empty == 0);
717
718 return 0;
719 }
720
mipi_tx_wait_write_fifo_empty(void)721 static int mipi_tx_wait_write_fifo_empty(void)
722 {
723 U_CMD_PKT_STATUS cmd_pkt_status;
724 unsigned int wait_count;
725
726 wait_count = 0;
727 do {
728 cmd_pkt_status.u32 = g_mipi_tx_regs_va->CMD_PKT_STATUS.u32;
729
730 wait_count++;
731
732 osal_udelay(1);
733
734 if (wait_count > MIPI_TX_READ_TIMEOUT_CNT) {
735 hi_mipi_tx_err("timeout when send data buffer \n");
736 return -1;
737 }
738 } while (cmd_pkt_status.bits.gen_pld_w_empty == 0);
739
740 return 0;
741 }
742
mipi_tx_wait_write_fifo_not_full(void)743 static int mipi_tx_wait_write_fifo_not_full(void)
744 {
745 U_CMD_PKT_STATUS cmd_pkt_status;
746 unsigned int wait_count;
747
748 wait_count = 0;
749 do {
750 cmd_pkt_status.u32 = g_mipi_tx_regs_va->CMD_PKT_STATUS.u32;
751 if (wait_count > 0) {
752 osal_udelay(1);
753 hi_mipi_tx_err("write fifo full happened wait count = %d\n", wait_count);
754 }
755 if (wait_count > MIPI_TX_READ_TIMEOUT_CNT) {
756 hi_mipi_tx_err("timeout when wait write fifo not full buffer \n");
757 return -1;
758 }
759 wait_count++;
760 } while (cmd_pkt_status.bits.gen_pld_w_full == 1);
761
762 return 0;
763 }
764
765 /*
766 * set payloads data by writing register
767 * each 4 bytes in cmd corresponds to one register
768 */
mipi_tx_drv_set_payload_data(const unsigned char * cmd,unsigned short cmd_size)769 static void mipi_tx_drv_set_payload_data(const unsigned char *cmd, unsigned short cmd_size)
770 {
771 U_GEN_PLD_DATA gen_pld_data;
772 int i, j;
773
774 gen_pld_data.u32 = g_mipi_tx_regs_va->GEN_PLD_DATA.u32;
775
776 for (i = 0; i < (cmd_size / 4); i++) { /* 4 cmd once */
777 gen_pld_data.bits.gen_pld_b1 = cmd[i * 4]; /* 0 in 4 */
778 gen_pld_data.bits.gen_pld_b2 = cmd[i * 4 + 1]; /* 1 in 4 */
779 gen_pld_data.bits.gen_pld_b3 = cmd[i * 4 + 2]; /* 2 in 4 */
780 gen_pld_data.bits.gen_pld_b4 = cmd[i * 4 + 3]; /* 3 in 4 */
781
782 mipi_tx_wait_write_fifo_not_full();
783 g_mipi_tx_regs_va->GEN_PLD_DATA.u32 = gen_pld_data.u32;
784 }
785
786 j = cmd_size % 4; /* remainder of 4 */
787 if (j != 0) {
788 if (j > 0) {
789 gen_pld_data.bits.gen_pld_b1 = cmd[i * 4]; /* 0 in 4 */
790 }
791 if (j > 1) {
792 gen_pld_data.bits.gen_pld_b2 = cmd[i * 4 + 1]; /* 1 in 4 */
793 }
794 if (j > 2) { /* bigger than 2 */
795 gen_pld_data.bits.gen_pld_b3 = cmd[i * 4 + 2]; /* 2 in 4 */
796 }
797
798 mipi_tx_wait_write_fifo_not_full();
799 g_mipi_tx_regs_va->GEN_PLD_DATA.u32 = gen_pld_data.u32;
800 }
801
802 #ifdef MIPI_TX_DEBUG
803 osal_printk("\n=====set cmd=======\n");
804 osal_printk("GEN_PLD_DATA(0x70): 0x%x\n", gen_pld_data);
805 #endif
806
807 return;
808 }
809
mipi_tx_drv_set_cmd_info(const cmd_info_t * cmd_info)810 int mipi_tx_drv_set_cmd_info(const cmd_info_t *cmd_info)
811 {
812 U_GEN_HDR gen_hdr;
813 unsigned char *cmd = NULL;
814
815 gen_hdr.u32 = g_mipi_tx_regs_va->GEN_HDR.u32;
816
817 if (cmd_info->cmd != NULL) {
818 if (cmd_info->cmd_size > 200 || cmd_info->cmd_size == 0) { /* 200 is max cmd size */
819 hi_mipi_tx_err("set cmd size illegal, size =%d\n", cmd_info->cmd_size);
820 return -1;
821 }
822
823 cmd = (unsigned char *)osal_kmalloc(cmd_info->cmd_size, osal_gfp_kernel);
824 if (cmd == NULL) {
825 hi_mipi_tx_err("kmalloc fail,please check,need %d bytes\n", cmd_info->cmd_size);
826 return -1;
827 }
828
829 if (osal_copy_from_user(cmd, cmd_info->cmd, cmd_info->cmd_size)) {
830 osal_kfree(cmd);
831 cmd = NULL;
832 return -1;
833 }
834
835 mipi_tx_drv_set_payload_data(cmd, cmd_info->cmd_size);
836
837 osal_kfree(cmd);
838 cmd = NULL;
839 }
840
841 gen_hdr.bits.gen_dt = cmd_info->data_type;
842 gen_hdr.bits.gen_wc_lsbyte = cmd_info->cmd_size & 0xff;
843 gen_hdr.bits.gen_wc_msbyte = (cmd_info->cmd_size & 0xff00) >> 8; /* height 8 bits */
844 g_mipi_tx_regs_va->GEN_HDR.u32 = gen_hdr.u32;
845
846 osal_udelay(350); /* wait 350 us transfer end */
847
848 mipi_tx_wait_cmd_fifo_empty();
849 mipi_tx_wait_write_fifo_empty();
850
851 #ifdef MIPI_TX_DEBUG
852 osal_printk("\n=====set cmd=======\n");
853 osal_printk("cmd_info->cmd_size: 0x%x\n", cmd_info->cmd_size);
854 osal_printk("cmd_info->data_type: 0x%x\n", cmd_info->data_type);
855 osal_printk("GEN_HDR(0x6C): 0x%x\n", gen_hdr);
856 #endif
857
858 return 0;
859 }
860
mipi_tx_wait_read_fifo_not_empty(void)861 static int mipi_tx_wait_read_fifo_not_empty(void)
862 {
863 U_INT_ST0 int_st0;
864 U_INT_ST1 int_st1;
865 unsigned int wait_count;
866 U_CMD_PKT_STATUS cmd_pkt_status;
867
868 wait_count = 0;
869 do {
870 int_st1.u32 = g_mipi_tx_regs_va->INT_ST1.u32;
871 int_st0.u32 = g_mipi_tx_regs_va->INT_ST0.u32;
872
873 if ((int_st1.u32 & 0x3e) != 0) {
874 hi_mipi_tx_err("err happened when read data, int_st1 = 0x%x,int_st0 = %x\n", int_st1.u32, int_st0.u32);
875 return -1;
876 }
877
878 if (wait_count > MIPI_TX_READ_TIMEOUT_CNT) {
879 hi_mipi_tx_err("timeout when read data\n");
880 return -1;
881 }
882
883 wait_count++;
884
885 osal_udelay(1);
886
887 cmd_pkt_status.u32 = g_mipi_tx_regs_va->CMD_PKT_STATUS.u32;
888 } while (cmd_pkt_status.bits.gen_pld_r_empty == 0x1);
889
890 return 0;
891 }
892
mipi_tx_wait_read_fifo_empty(void)893 static int mipi_tx_wait_read_fifo_empty(void)
894 {
895 U_GEN_PLD_DATA pld_data;
896 U_INT_ST1 int_st1;
897 unsigned int wait_count;
898
899 wait_count = 0;
900 do {
901 int_st1.u32 = g_mipi_tx_regs_va->INT_ST1.u32;
902 if ((int_st1.bits.gen_pld_rd_err) == 0x0) {
903 pld_data.u32 = g_mipi_tx_regs_va->GEN_PLD_DATA.u32;
904 }
905 wait_count++;
906 osal_udelay(1);
907 if (wait_count > MIPI_TX_READ_TIMEOUT_CNT) {
908 hi_mipi_tx_err("timeout when clear data buffer, the last read data is 0x%x \n", pld_data.u32);
909 return -1;
910 }
911 } while ((int_st1.bits.gen_pld_rd_err) == 0x0);
912
913 return 0;
914 }
915
mipi_tx_send_short_packet(unsigned char virtual_channel,short unsigned data_type,unsigned short data_param)916 static int mipi_tx_send_short_packet(unsigned char virtual_channel,
917 short unsigned data_type, unsigned short data_param)
918 {
919 U_GEN_HDR gen_hdr;
920
921 gen_hdr.bits.gen_vc = virtual_channel;
922 gen_hdr.bits.gen_dt = data_type;
923 gen_hdr.bits.gen_wc_lsbyte = (data_param & 0xff);
924 gen_hdr.bits.gen_wc_msbyte = (data_param & 0xff00) >> 8; /* height 8 bits */
925 g_mipi_tx_regs_va->GEN_HDR.u32 = gen_hdr.u32;
926
927 if (mipi_tx_wait_cmd_fifo_empty() != 0) {
928 return -1;
929 }
930
931 return 0;
932 }
933
mipi_tx_get_read_fifo_data(unsigned int get_data_size,unsigned char * data_buf)934 static int mipi_tx_get_read_fifo_data(unsigned int get_data_size, unsigned char *data_buf)
935 {
936 U_GEN_PLD_DATA pld_data;
937 unsigned int i, j;
938
939 for (i = 0; i < get_data_size / 4; i++) { /* 4byte once */
940 if (mipi_tx_wait_read_fifo_not_empty() != 0) {
941 return -1;
942 }
943 pld_data.u32 = g_mipi_tx_regs_va->GEN_PLD_DATA.u32;
944 data_buf[i * 4] = pld_data.bits.gen_pld_b1; /* 0 in 4 */
945 data_buf[i * 4 + 1] = pld_data.bits.gen_pld_b2; /* 1 in 4 */
946 data_buf[i * 4 + 2] = pld_data.bits.gen_pld_b3; /* 2 in 4 */
947 data_buf[i * 4 + 3] = pld_data.bits.gen_pld_b4; /* 3 in 4 */
948 }
949
950 j = get_data_size % 4; /* remainder of 4 */
951
952 if (j != 0) {
953 if (mipi_tx_wait_read_fifo_not_empty() != 0) {
954 return -1;
955 }
956 pld_data.u32 = g_mipi_tx_regs_va->GEN_PLD_DATA.u32;
957 if (j > 0) {
958 data_buf[i * 4] = pld_data.bits.gen_pld_b1; /* 0 in 4 */
959 }
960 if (j > 1) {
961 data_buf[i * 4 + 1] = pld_data.bits.gen_pld_b2; /* 1 in 4 */
962 }
963 if (j > 2) { /* bigger than 2 */
964 data_buf[i * 4 + 2] = pld_data.bits.gen_pld_b3; /* 2 in 4 */
965 }
966 }
967
968 return 0;
969 }
970
mipi_tx_reset(void)971 void mipi_tx_reset(void)
972 {
973 g_mipi_tx_regs_va->PWR_UP.u32 = 0x0;
974 g_mipi_tx_regs_va->PHY_RSTZ.u32 = 0xd;
975 osal_udelay(1);
976 g_mipi_tx_regs_va->PWR_UP.u32 = 0x1;
977 g_mipi_tx_regs_va->PHY_RSTZ.u32 = 0xf;
978 osal_udelay(1);
979 return;
980 }
981
mipi_tx_drv_get_cmd_info(get_cmd_info_t * get_cmd_info)982 int mipi_tx_drv_get_cmd_info(get_cmd_info_t *get_cmd_info)
983 {
984 unsigned char* data_buf = NULL;
985
986 data_buf = (unsigned char*)osal_kmalloc(get_cmd_info->get_data_size, osal_gfp_kernel);
987 if (data_buf == NULL) {
988 return -1;
989 }
990
991 if (mipi_tx_wait_read_fifo_empty() != 0) {
992 goto fail0;
993 }
994
995 if (mipi_tx_send_short_packet(0, get_cmd_info->data_type, get_cmd_info->data_param) != 0) {
996 goto fail0;
997 }
998
999 if (mipi_tx_get_read_fifo_data(get_cmd_info->get_data_size, data_buf) != 0) {
1000 /* fail will block mipi data lane ,so need reset */
1001 mipi_tx_reset();
1002 goto fail0;
1003 }
1004
1005 osal_copy_to_user(get_cmd_info->get_data, data_buf, get_cmd_info->get_data_size);
1006
1007 osal_kfree(data_buf);
1008 data_buf = NULL;
1009
1010 return 0;
1011
1012 fail0:
1013 osal_kfree(data_buf);
1014 data_buf = NULL;
1015 return -1;
1016 }
1017
mipi_tx_drv_enable_input(const output_mode_t output_mode)1018 void mipi_tx_drv_enable_input(const output_mode_t output_mode)
1019 {
1020 if ((output_mode == OUTPUT_MODE_DSI_VIDEO) || (output_mode == OUTPUT_MODE_CSI)) {
1021 g_mipi_tx_regs_va->MODE_CFG.u32 = 0x0;
1022 }
1023
1024 if (output_mode == OUTPUT_MODE_DSI_CMD) {
1025 g_mipi_tx_regs_va->CMD_MODE_CFG.u32 = 0x0;
1026 }
1027
1028 /* enable input */
1029 g_mipi_tx_regs_va->OPERATION_MODE.u32 = 0x80150000;
1030
1031 g_mipi_tx_regs_va->LPCLK_CTRL.u32 = 0x1;
1032
1033 mipi_tx_reset();
1034 }
1035
mipi_tx_drv_disable_input(void)1036 void mipi_tx_drv_disable_input(void)
1037 {
1038 /* disable input */
1039 g_mipi_tx_regs_va->OPERATION_MODE.u32 = 0x0;
1040
1041 g_mipi_tx_regs_va->CMD_MODE_CFG.u32 = 0xffffff00;
1042
1043 /* command mode */
1044 g_mipi_tx_regs_va->MODE_CFG.u32 = 0x1;
1045
1046 g_mipi_tx_regs_va->LPCLK_CTRL.u32 = 0x0;
1047
1048 mipi_tx_reset();
1049 }
1050
mipi_tx_drv_reg_init(void)1051 static int mipi_tx_drv_reg_init(void)
1052 {
1053 if (g_mipi_tx_regs_va == NULL) {
1054 g_mipi_tx_regs_va = (mipi_tx_regs_type_t *)osal_ioremap(MIPI_TX_REGS_ADDR, (unsigned int)MIPI_TX_REGS_SIZE);
1055 if (g_mipi_tx_regs_va == NULL) {
1056 hi_mipi_tx_err("remap mipi_tx reg addr fail\n");
1057 return -1;
1058 }
1059 g_reg_map_flag = 1;
1060 }
1061
1062 return 0;
1063 }
1064
mipi_tx_drv_reg_exit(void)1065 static void mipi_tx_drv_reg_exit(void)
1066 {
1067 if (g_reg_map_flag == 1) {
1068 if (g_mipi_tx_regs_va != NULL) {
1069 osal_iounmap((void *)g_mipi_tx_regs_va, (unsigned int)MIPI_TX_REGS_SIZE);
1070 g_mipi_tx_regs_va = NULL;
1071 }
1072 g_reg_map_flag = 0;
1073 }
1074 }
1075
mipi_tx_drv_hw_init(int smooth)1076 static void mipi_tx_drv_hw_init(int smooth)
1077 {
1078 unsigned long mipi_tx_crg_addr;
1079
1080 mipi_tx_crg_addr = (unsigned long)osal_ioremap(MIPI_TX_CRG, (unsigned long)0x4);
1081
1082 /* mipi_tx gate clk enable */
1083 write_reg32(mipi_tx_crg_addr, 1, 0x1);
1084
1085 /* reset */
1086 if (smooth == FALSE) {
1087 write_reg32(mipi_tx_crg_addr, 1 << 1, 0x1 << 1);
1088 }
1089
1090 /* unreset */
1091 write_reg32(mipi_tx_crg_addr, 0 << 1, 0x1 << 1);
1092
1093 /* ref clk */
1094 write_reg32(mipi_tx_crg_addr, 1 << 2, 0x1 << 2); /* 2 clk bit */
1095
1096 osal_iounmap((void *)mipi_tx_crg_addr, (unsigned long)0x4);
1097 }
1098
mipi_tx_drv_init(int smooth)1099 int mipi_tx_drv_init(int smooth)
1100 {
1101 int ret;
1102
1103 ret = mipi_tx_drv_reg_init();
1104 if (ret < 0) {
1105 hi_mipi_tx_err("mipi_tx_drv_reg_init fail!\n");
1106 goto fail0;
1107 }
1108
1109 mipi_tx_drv_hw_init(smooth);
1110
1111 return 0;
1112
1113 fail0:
1114 return -1;
1115 }
1116
mipi_tx_drv_exit(void)1117 void mipi_tx_drv_exit(void)
1118 {
1119 mipi_tx_drv_reg_exit();
1120 }
1121
1122 #ifdef __cplusplus
1123 #if __cplusplus
1124 }
1125
1126 #endif
1127 #endif /* End of #ifdef __cplusplus */
1128