1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <common.h>
17#include <linux/types.h>
18#include <linux/errno.h>
19#include <asm/io.h>
20#include <asm/arch/imx-regs.h>
21#include <asm/arch/sys_proto.h>
22#include "ipu.h"
23#include "ipu_regs.h"
24
25enum csc_type_t {
26 RGB2YUV = 0,
27 YUV2RGB,
28 RGB2RGB,
29 YUV2YUV,
30 CSC_NONE,
31 CSC_NUM
32};
33
34struct dp_csc_param_t {
35 int mode;
36 const int (*coeff)[5][3];
37};
38
39#define SYNC_WAVE 0
40
41
42#define DC_DISP_ID_SYNC(di) (di)
43#define DC_DISP_ID_SERIAL 2
44#define DC_DISP_ID_ASYNC 3
45
46int dmfc_type_setup;
47static int dmfc_size_28, dmfc_size_29, dmfc_size_24, dmfc_size_27, dmfc_size_23;
48int g_di1_tvout;
49
50extern struct clk *g_ipu_clk;
51extern struct clk *g_ldb_clk;
52extern struct clk *g_di_clk[2];
53extern struct clk *g_pixel_clk[2];
54
55extern unsigned char g_ipu_clk_enabled;
56extern unsigned char g_dc_di_assignment[];
57
58void ipu_dmfc_init(int dmfc_type, int first)
59{
60 u32 dmfc_wr_chan, dmfc_dp_chan;
61
62 if (first) {
63 if (dmfc_type_setup > dmfc_type)
64 dmfc_type = dmfc_type_setup;
65 else
66 dmfc_type_setup = dmfc_type;
67
68
69 __raw_writel(0x2, DMFC_IC_CTRL);
70 } else if (dmfc_type_setup >= DMFC_HIGH_RESOLUTION_DC) {
71 printf("DMFC high resolution has set, will not change\n");
72 return;
73 } else
74 dmfc_type_setup = dmfc_type;
75
76 if (dmfc_type == DMFC_HIGH_RESOLUTION_DC) {
77
78
79
80
81
82 debug("IPU DMFC DC HIGH RES: 1(0~3), 5B(4,5), 5F(6,7)\n");
83 dmfc_wr_chan = 0x00000088;
84 dmfc_dp_chan = 0x00009694;
85 dmfc_size_28 = 256 * 4;
86 dmfc_size_29 = 0;
87 dmfc_size_24 = 0;
88 dmfc_size_27 = 128 * 4;
89 dmfc_size_23 = 128 * 4;
90 } else if (dmfc_type == DMFC_HIGH_RESOLUTION_DP) {
91
92
93
94
95
96 debug("IPU DMFC DP HIGH RES: 1(0,1), 5B(2~5), 5F(6,7)\n");
97 dmfc_wr_chan = 0x00000090;
98 dmfc_dp_chan = 0x0000968a;
99 dmfc_size_28 = 128 * 4;
100 dmfc_size_29 = 0;
101 dmfc_size_24 = 0;
102 dmfc_size_27 = 128 * 4;
103 dmfc_size_23 = 256 * 4;
104 } else if (dmfc_type == DMFC_HIGH_RESOLUTION_ONLY_DP) {
105
106
107
108
109 debug("IPU DMFC ONLY-DP HIGH RES: 5B(0~3), 5F(4~7)\n");
110 dmfc_wr_chan = 0x00000000;
111 dmfc_dp_chan = 0x00008c88;
112 dmfc_size_28 = 0;
113 dmfc_size_29 = 0;
114 dmfc_size_24 = 0;
115 dmfc_size_27 = 256 * 4;
116 dmfc_size_23 = 256 * 4;
117 } else {
118
119
120
121
122
123 debug("IPU DMFC NORMAL mode: 1(0~1), 5B(4,5), 5F(6,7)\n");
124 dmfc_wr_chan = 0x00000090;
125 dmfc_dp_chan = 0x00009694;
126 dmfc_size_28 = 128 * 4;
127 dmfc_size_29 = 0;
128 dmfc_size_24 = 0;
129 dmfc_size_27 = 128 * 4;
130 dmfc_size_23 = 128 * 4;
131 }
132 __raw_writel(dmfc_wr_chan, DMFC_WR_CHAN);
133 __raw_writel(0x202020F6, DMFC_WR_CHAN_DEF);
134 __raw_writel(dmfc_dp_chan, DMFC_DP_CHAN);
135
136 __raw_writel(0x2020F6F6, DMFC_DP_CHAN_DEF);
137}
138
139void ipu_dmfc_set_wait4eot(int dma_chan, int width)
140{
141 u32 dmfc_gen1 = __raw_readl(DMFC_GENERAL1);
142
143 if (width >= HIGH_RESOLUTION_WIDTH) {
144 if (dma_chan == 23)
145 ipu_dmfc_init(DMFC_HIGH_RESOLUTION_DP, 0);
146 else if (dma_chan == 28)
147 ipu_dmfc_init(DMFC_HIGH_RESOLUTION_DC, 0);
148 }
149
150 if (dma_chan == 23) {
151 if (dmfc_size_23 / width > 3)
152 dmfc_gen1 |= 1UL << 20;
153 else
154 dmfc_gen1 &= ~(1UL << 20);
155 } else if (dma_chan == 24) {
156 if (dmfc_size_24 / width > 1)
157 dmfc_gen1 |= 1UL << 22;
158 else
159 dmfc_gen1 &= ~(1UL << 22);
160 } else if (dma_chan == 27) {
161 if (dmfc_size_27 / width > 2)
162 dmfc_gen1 |= 1UL << 21;
163 else
164 dmfc_gen1 &= ~(1UL << 21);
165 } else if (dma_chan == 28) {
166 if (dmfc_size_28 / width > 2)
167 dmfc_gen1 |= 1UL << 16;
168 else
169 dmfc_gen1 &= ~(1UL << 16);
170 } else if (dma_chan == 29) {
171 if (dmfc_size_29 / width > 1)
172 dmfc_gen1 |= 1UL << 23;
173 else
174 dmfc_gen1 &= ~(1UL << 23);
175 }
176
177 __raw_writel(dmfc_gen1, DMFC_GENERAL1);
178}
179
180static void ipu_di_data_wave_config(int di,
181 int wave_gen,
182 int access_size, int component_size)
183{
184 u32 reg;
185 reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
186 (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
187 __raw_writel(reg, DI_DW_GEN(di, wave_gen));
188}
189
190static void ipu_di_data_pin_config(int di, int wave_gen, int di_pin, int set,
191 int up, int down)
192{
193 u32 reg;
194
195 reg = __raw_readl(DI_DW_GEN(di, wave_gen));
196 reg &= ~(0x3 << (di_pin * 2));
197 reg |= set << (di_pin * 2);
198 __raw_writel(reg, DI_DW_GEN(di, wave_gen));
199
200 __raw_writel((down << 16) | up, DI_DW_SET(di, wave_gen, set));
201}
202
203static void ipu_di_sync_config(int di, int wave_gen,
204 int run_count, int run_src,
205 int offset_count, int offset_src,
206 int repeat_count, int cnt_clr_src,
207 int cnt_polarity_gen_en,
208 int cnt_polarity_clr_src,
209 int cnt_polarity_trigger_src,
210 int cnt_up, int cnt_down)
211{
212 u32 reg;
213
214 if ((run_count >= 0x1000) || (offset_count >= 0x1000) ||
215 (repeat_count >= 0x1000) ||
216 (cnt_up >= 0x400) || (cnt_down >= 0x400)) {
217 printf("DI%d counters out of range.\n", di);
218 return;
219 }
220
221 reg = (run_count << 19) | (++run_src << 16) |
222 (offset_count << 3) | ++offset_src;
223 __raw_writel(reg, DI_SW_GEN0(di, wave_gen));
224 reg = (cnt_polarity_gen_en << 29) | (++cnt_clr_src << 25) |
225 (++cnt_polarity_trigger_src << 12) | (++cnt_polarity_clr_src << 9);
226 reg |= (cnt_down << 16) | cnt_up;
227 if (repeat_count == 0) {
228
229 reg |= 0x10000000;
230 }
231 __raw_writel(reg, DI_SW_GEN1(di, wave_gen));
232 reg = __raw_readl(DI_STP_REP(di, wave_gen));
233 reg &= ~(0xFFFF << (16 * ((wave_gen - 1) & 0x1)));
234 reg |= repeat_count << (16 * ((wave_gen - 1) & 0x1));
235 __raw_writel(reg, DI_STP_REP(di, wave_gen));
236}
237
238static void ipu_dc_map_config(int map, int byte_num, int offset, int mask)
239{
240 int ptr = map * 3 + byte_num;
241 u32 reg;
242
243 reg = __raw_readl(DC_MAP_CONF_VAL(ptr));
244 reg &= ~(0xFFFF << (16 * (ptr & 0x1)));
245 reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
246 __raw_writel(reg, DC_MAP_CONF_VAL(ptr));
247
248 reg = __raw_readl(DC_MAP_CONF_PTR(map));
249 reg &= ~(0x1F << ((16 * (map & 0x1)) + (5 * byte_num)));
250 reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
251 __raw_writel(reg, DC_MAP_CONF_PTR(map));
252}
253
254static void ipu_dc_map_clear(int map)
255{
256 u32 reg = __raw_readl(DC_MAP_CONF_PTR(map));
257 __raw_writel(reg & ~(0xFFFF << (16 * (map & 0x1))),
258 DC_MAP_CONF_PTR(map));
259}
260
261static void ipu_dc_write_tmpl(int word, u32 opcode, u32 operand, int map,
262 int wave, int glue, int sync)
263{
264 u32 reg;
265 int stop = 1;
266
267 reg = sync;
268 reg |= (glue << 4);
269 reg |= (++wave << 11);
270 reg |= (++map << 15);
271 reg |= (operand << 20) & 0xFFF00000;
272 __raw_writel(reg, ipu_dc_tmpl_reg + word * 2);
273
274 reg = (operand >> 12);
275 reg |= opcode << 4;
276 reg |= (stop << 9);
277 __raw_writel(reg, ipu_dc_tmpl_reg + word * 2 + 1);
278}
279
280static void ipu_dc_link_event(int chan, int event, int addr, int priority)
281{
282 u32 reg;
283
284 reg = __raw_readl(DC_RL_CH(chan, event));
285 reg &= ~(0xFFFF << (16 * (event & 0x1)));
286 reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
287 __raw_writel(reg, DC_RL_CH(chan, event));
288}
289
290
291
292
293
294static const int rgb2ycbcr_coeff[5][3] = {
295 {0x4D, 0x96, 0x1D},
296 {0x3D5, 0x3AB, 0x80},
297 {0x80, 0x395, 0x3EB},
298 {0x0000, 0x0200, 0x0200},
299 {0x2, 0x2, 0x2},
300};
301
302
303
304
305
306static const int ycbcr2rgb_coeff[5][3] = {
307 {0x095, 0x000, 0x0CC},
308 {0x095, 0x3CE, 0x398},
309 {0x095, 0x0FF, 0x000},
310 {0x3E42, 0x010A, 0x3DD6},
311 {0x1, 0x1, 0x1},
312};
313
314#define mask_a(a) ((u32)(a) & 0x3FF)
315#define mask_b(b) ((u32)(b) & 0x3FFF)
316
317
318static int rgb_to_yuv(int n, int red, int green, int blue)
319{
320 int c;
321 c = red * rgb2ycbcr_coeff[n][0];
322 c += green * rgb2ycbcr_coeff[n][1];
323 c += blue * rgb2ycbcr_coeff[n][2];
324 c /= 16;
325 c += rgb2ycbcr_coeff[3][n] * 4;
326 c += 8;
327 c /= 16;
328 if (c < 0)
329 c = 0;
330 if (c > 255)
331 c = 255;
332 return c;
333}
334
335
336
337
338
339static struct dp_csc_param_t dp_csc_array[CSC_NUM][CSC_NUM] = {
340 {
341 {DP_COM_CONF_CSC_DEF_BOTH, &rgb2ycbcr_coeff},
342 {0, 0},
343 {0, 0},
344 {DP_COM_CONF_CSC_DEF_BG, &rgb2ycbcr_coeff},
345 {DP_COM_CONF_CSC_DEF_BG, &rgb2ycbcr_coeff}
346 },
347 {
348 {0, 0},
349 {DP_COM_CONF_CSC_DEF_BOTH, &ycbcr2rgb_coeff},
350 {DP_COM_CONF_CSC_DEF_BG, &ycbcr2rgb_coeff},
351 {0, 0},
352 {DP_COM_CONF_CSC_DEF_BG, &ycbcr2rgb_coeff}
353 },
354 {
355 {0, 0},
356 {DP_COM_CONF_CSC_DEF_FG, &ycbcr2rgb_coeff},
357 {0, 0},
358 {0, 0},
359 {0, 0}
360 },
361 {
362 {DP_COM_CONF_CSC_DEF_FG, &rgb2ycbcr_coeff},
363 {0, 0},
364 {0, 0},
365 {0, 0},
366 {0, 0}
367 },
368 {
369 {DP_COM_CONF_CSC_DEF_FG, &rgb2ycbcr_coeff},
370 {DP_COM_CONF_CSC_DEF_FG, &ycbcr2rgb_coeff},
371 {0, 0},
372 {0, 0},
373 {0, 0}
374 }
375};
376
377static enum csc_type_t fg_csc_type = CSC_NONE, bg_csc_type = CSC_NONE;
378static int color_key_4rgb = 1;
379
380static void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
381 unsigned char srm_mode_update)
382{
383 u32 reg;
384 const int (*coeff)[5][3];
385
386 if (dp_csc_param.mode >= 0) {
387 reg = __raw_readl(DP_COM_CONF());
388 reg &= ~DP_COM_CONF_CSC_DEF_MASK;
389 reg |= dp_csc_param.mode;
390 __raw_writel(reg, DP_COM_CONF());
391 }
392
393 coeff = dp_csc_param.coeff;
394
395 if (coeff) {
396 __raw_writel(mask_a((*coeff)[0][0]) |
397 (mask_a((*coeff)[0][1]) << 16), DP_CSC_A_0());
398 __raw_writel(mask_a((*coeff)[0][2]) |
399 (mask_a((*coeff)[1][0]) << 16), DP_CSC_A_1());
400 __raw_writel(mask_a((*coeff)[1][1]) |
401 (mask_a((*coeff)[1][2]) << 16), DP_CSC_A_2());
402 __raw_writel(mask_a((*coeff)[2][0]) |
403 (mask_a((*coeff)[2][1]) << 16), DP_CSC_A_3());
404 __raw_writel(mask_a((*coeff)[2][2]) |
405 (mask_b((*coeff)[3][0]) << 16) |
406 ((*coeff)[4][0] << 30), DP_CSC_0());
407 __raw_writel(mask_b((*coeff)[3][1]) | ((*coeff)[4][1] << 14) |
408 (mask_b((*coeff)[3][2]) << 16) |
409 ((*coeff)[4][2] << 30), DP_CSC_1());
410 }
411
412 if (srm_mode_update) {
413 reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
414 __raw_writel(reg, IPU_SRM_PRI2);
415 }
416}
417
418int ipu_dp_init(ipu_channel_t channel, uint32_t in_pixel_fmt,
419 uint32_t out_pixel_fmt)
420{
421 int in_fmt, out_fmt;
422 int dp;
423 int partial = 0;
424 uint32_t reg;
425
426 if (channel == MEM_FG_SYNC) {
427 dp = DP_SYNC;
428 partial = 1;
429 } else if (channel == MEM_BG_SYNC) {
430 dp = DP_SYNC;
431 partial = 0;
432 } else if (channel == MEM_BG_ASYNC0) {
433 dp = DP_ASYNC0;
434 partial = 0;
435 } else {
436 return -EINVAL;
437 }
438
439 in_fmt = format_to_colorspace(in_pixel_fmt);
440 out_fmt = format_to_colorspace(out_pixel_fmt);
441
442 if (partial) {
443 if (in_fmt == RGB) {
444 if (out_fmt == RGB)
445 fg_csc_type = RGB2RGB;
446 else
447 fg_csc_type = RGB2YUV;
448 } else {
449 if (out_fmt == RGB)
450 fg_csc_type = YUV2RGB;
451 else
452 fg_csc_type = YUV2YUV;
453 }
454 } else {
455 if (in_fmt == RGB) {
456 if (out_fmt == RGB)
457 bg_csc_type = RGB2RGB;
458 else
459 bg_csc_type = RGB2YUV;
460 } else {
461 if (out_fmt == RGB)
462 bg_csc_type = YUV2RGB;
463 else
464 bg_csc_type = YUV2YUV;
465 }
466 }
467
468
469 reg = __raw_readl(DP_COM_CONF());
470 if (color_key_4rgb && (reg & DP_COM_CONF_GWCKE) &&
471 (((fg_csc_type == RGB2YUV) && (bg_csc_type == YUV2YUV)) ||
472 ((fg_csc_type == YUV2YUV) && (bg_csc_type == RGB2YUV)) ||
473 ((fg_csc_type == YUV2YUV) && (bg_csc_type == YUV2YUV)) ||
474 ((fg_csc_type == YUV2RGB) && (bg_csc_type == YUV2RGB)))) {
475 int red, green, blue;
476 int y, u, v;
477 uint32_t color_key = __raw_readl(DP_GRAPH_WIND_CTRL()) &
478 0xFFFFFFL;
479
480 debug("_ipu_dp_init color key 0x%x need change to yuv fmt!\n",
481 color_key);
482
483 red = (color_key >> 16) & 0xFF;
484 green = (color_key >> 8) & 0xFF;
485 blue = color_key & 0xFF;
486
487 y = rgb_to_yuv(0, red, green, blue);
488 u = rgb_to_yuv(1, red, green, blue);
489 v = rgb_to_yuv(2, red, green, blue);
490 color_key = (y << 16) | (u << 8) | v;
491
492 reg = __raw_readl(DP_GRAPH_WIND_CTRL()) & 0xFF000000L;
493 __raw_writel(reg | color_key, DP_GRAPH_WIND_CTRL());
494 color_key_4rgb = 0;
495
496 debug("_ipu_dp_init color key change to yuv fmt 0x%x!\n",
497 color_key);
498 }
499
500 ipu_dp_csc_setup(dp, dp_csc_array[bg_csc_type][fg_csc_type], 1);
501
502 return 0;
503}
504
505void ipu_dp_uninit(ipu_channel_t channel)
506{
507 int dp;
508 int partial = 0;
509
510 if (channel == MEM_FG_SYNC) {
511 dp = DP_SYNC;
512 partial = 1;
513 } else if (channel == MEM_BG_SYNC) {
514 dp = DP_SYNC;
515 partial = 0;
516 } else if (channel == MEM_BG_ASYNC0) {
517 dp = DP_ASYNC0;
518 partial = 0;
519 } else {
520 return;
521 }
522
523 if (partial)
524 fg_csc_type = CSC_NONE;
525 else
526 bg_csc_type = CSC_NONE;
527
528 ipu_dp_csc_setup(dp, dp_csc_array[bg_csc_type][fg_csc_type], 0);
529}
530
531void ipu_dc_init(int dc_chan, int di, unsigned char interlaced)
532{
533 u32 reg = 0;
534
535 if ((dc_chan == 1) || (dc_chan == 5)) {
536 if (interlaced) {
537 ipu_dc_link_event(dc_chan, DC_EVT_NL, 0, 3);
538 ipu_dc_link_event(dc_chan, DC_EVT_EOL, 0, 2);
539 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA, 0, 1);
540 } else {
541 if (di) {
542 ipu_dc_link_event(dc_chan, DC_EVT_NL, 2, 3);
543 ipu_dc_link_event(dc_chan, DC_EVT_EOL, 3, 2);
544 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA,
545 4, 1);
546 } else {
547 ipu_dc_link_event(dc_chan, DC_EVT_NL, 5, 3);
548 ipu_dc_link_event(dc_chan, DC_EVT_EOL, 6, 2);
549 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA,
550 7, 1);
551 }
552 }
553 ipu_dc_link_event(dc_chan, DC_EVT_NF, 0, 0);
554 ipu_dc_link_event(dc_chan, DC_EVT_NFIELD, 0, 0);
555 ipu_dc_link_event(dc_chan, DC_EVT_EOF, 0, 0);
556 ipu_dc_link_event(dc_chan, DC_EVT_EOFIELD, 0, 0);
557 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN, 0, 0);
558 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR, 0, 0);
559
560 reg = 0x2;
561 reg |= DC_DISP_ID_SYNC(di) << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
562 reg |= di << 2;
563 if (interlaced)
564 reg |= DC_WR_CH_CONF_FIELD_MODE;
565 } else if ((dc_chan == 8) || (dc_chan == 9)) {
566
567 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_W_0, 0x64, 1);
568 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_W_1, 0x64, 1);
569
570 reg = 0x3;
571 reg |= DC_DISP_ID_SERIAL << DC_WR_CH_CONF_PROG_DISP_ID_OFFSET;
572 }
573 __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
574
575 __raw_writel(0x00000000, DC_WR_CH_ADDR(dc_chan));
576
577 __raw_writel(0x00000084, DC_GEN);
578}
579
580void ipu_dc_uninit(int dc_chan)
581{
582 if ((dc_chan == 1) || (dc_chan == 5)) {
583 ipu_dc_link_event(dc_chan, DC_EVT_NL, 0, 0);
584 ipu_dc_link_event(dc_chan, DC_EVT_EOL, 0, 0);
585 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA, 0, 0);
586 ipu_dc_link_event(dc_chan, DC_EVT_NF, 0, 0);
587 ipu_dc_link_event(dc_chan, DC_EVT_NFIELD, 0, 0);
588 ipu_dc_link_event(dc_chan, DC_EVT_EOF, 0, 0);
589 ipu_dc_link_event(dc_chan, DC_EVT_EOFIELD, 0, 0);
590 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN, 0, 0);
591 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR, 0, 0);
592 } else if ((dc_chan == 8) || (dc_chan == 9)) {
593 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR_W_0, 0, 0);
594 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR_W_1, 0, 0);
595 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN_W_0, 0, 0);
596 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN_W_1, 0, 0);
597 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_W_0, 0, 0);
598 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_W_1, 0, 0);
599 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR_R_0, 0, 0);
600 ipu_dc_link_event(dc_chan, DC_EVT_NEW_ADDR_R_1, 0, 0);
601 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN_R_0, 0, 0);
602 ipu_dc_link_event(dc_chan, DC_EVT_NEW_CHAN_R_1, 0, 0);
603 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_R_0, 0, 0);
604 ipu_dc_link_event(dc_chan, DC_EVT_NEW_DATA_R_1, 0, 0);
605 }
606}
607
608void ipu_dp_dc_enable(ipu_channel_t channel)
609{
610 int di;
611 uint32_t reg;
612 uint32_t dc_chan;
613
614 if (channel == MEM_DC_SYNC)
615 dc_chan = 1;
616 else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
617 dc_chan = 5;
618 else
619 return;
620
621 if (channel == MEM_FG_SYNC) {
622
623 reg = __raw_readl(DP_COM_CONF());
624 __raw_writel(reg | DP_COM_CONF_FG_EN, DP_COM_CONF());
625
626 reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
627 __raw_writel(reg, IPU_SRM_PRI2);
628 return;
629 }
630
631 di = g_dc_di_assignment[dc_chan];
632
633
634 reg = __raw_readl(DC_WR_CH_CONF(6 - dc_chan));
635 if ((di << 2) == (reg & DC_WR_CH_CONF_PROG_DI_ID)) {
636 reg &= ~DC_WR_CH_CONF_PROG_DI_ID;
637 reg |= di ? 0 : DC_WR_CH_CONF_PROG_DI_ID;
638 __raw_writel(reg, DC_WR_CH_CONF(6 - dc_chan));
639 }
640
641 reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
642 reg |= 4 << DC_WR_CH_CONF_PROG_TYPE_OFFSET;
643 __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
644
645 clk_enable(g_pixel_clk[di]);
646}
647
648static unsigned char dc_swap;
649
650void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap)
651{
652 uint32_t reg;
653 uint32_t csc;
654 uint32_t dc_chan = 0;
655 int timeout = 50;
656 int irq = 0;
657
658 dc_swap = swap;
659
660 if (channel == MEM_DC_SYNC) {
661 dc_chan = 1;
662 irq = IPU_IRQ_DC_FC_1;
663 } else if (channel == MEM_BG_SYNC) {
664 dc_chan = 5;
665 irq = IPU_IRQ_DP_SF_END;
666 } else if (channel == MEM_FG_SYNC) {
667
668 dc_chan = 5;
669
670 reg = __raw_readl(DP_COM_CONF());
671 csc = reg & DP_COM_CONF_CSC_DEF_MASK;
672 if (csc == DP_COM_CONF_CSC_DEF_FG)
673 reg &= ~DP_COM_CONF_CSC_DEF_MASK;
674
675 reg &= ~DP_COM_CONF_FG_EN;
676 __raw_writel(reg, DP_COM_CONF());
677
678 reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
679 __raw_writel(reg, IPU_SRM_PRI2);
680
681 timeout = 50;
682
683
684
685
686
687 if (g_dc_di_assignment[dc_chan] == 0)
688 while ((__raw_readl(DC_STAT) & 0x00000002)
689 != 0x00000002) {
690 udelay(2000);
691 timeout -= 2;
692 if (timeout <= 0)
693 break;
694 }
695 else if (g_dc_di_assignment[dc_chan] == 1)
696 while ((__raw_readl(DC_STAT) & 0x00000020)
697 != 0x00000020) {
698 udelay(2000);
699 timeout -= 2;
700 if (timeout <= 0)
701 break;
702 }
703 return;
704 } else {
705 return;
706 }
707
708 if (dc_swap) {
709
710 reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
711 __raw_writel(reg, DC_WR_CH_CONF(6 - dc_chan));
712 reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
713 reg ^= DC_WR_CH_CONF_PROG_DI_ID;
714 __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
715 } else {
716
717 __raw_writel(IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
718 do {
719 reg = __raw_readl(IPUIRQ_2_STATREG(irq));
720 } while (!(reg & IPUIRQ_2_MASK(irq)));
721
722 reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
723 reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
724 __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
725
726 reg = __raw_readl(IPU_DISP_GEN);
727 if (g_dc_di_assignment[dc_chan])
728 reg &= ~DI1_COUNTER_RELEASE;
729 else
730 reg &= ~DI0_COUNTER_RELEASE;
731 __raw_writel(reg, IPU_DISP_GEN);
732
733
734
735 clk_disable(g_pixel_clk[g_dc_di_assignment[dc_chan]]);
736 }
737}
738
739void ipu_init_dc_mappings(void)
740{
741
742 ipu_dc_map_clear(0);
743 ipu_dc_map_config(0, 0, 7, 0xFF);
744 ipu_dc_map_config(0, 1, 15, 0xFF);
745 ipu_dc_map_config(0, 2, 23, 0xFF);
746
747
748 ipu_dc_map_clear(1);
749 ipu_dc_map_config(1, 0, 5, 0xFC);
750 ipu_dc_map_config(1, 1, 11, 0xFC);
751 ipu_dc_map_config(1, 2, 17, 0xFC);
752
753
754 ipu_dc_map_clear(2);
755 ipu_dc_map_config(2, 0, 15, 0xFF);
756 ipu_dc_map_config(2, 1, 23, 0xFF);
757 ipu_dc_map_config(2, 2, 7, 0xFF);
758
759
760 ipu_dc_map_clear(3);
761 ipu_dc_map_config(3, 0, 4, 0xF8);
762 ipu_dc_map_config(3, 1, 10, 0xFC);
763 ipu_dc_map_config(3, 2, 15, 0xF8);
764
765
766 ipu_dc_map_clear(4);
767 ipu_dc_map_config(4, 0, 5, 0xFC);
768 ipu_dc_map_config(4, 1, 13, 0xFC);
769 ipu_dc_map_config(4, 2, 21, 0xFC);
770}
771
772static int ipu_pixfmt_to_map(uint32_t fmt)
773{
774 switch (fmt) {
775 case IPU_PIX_FMT_GENERIC:
776 case IPU_PIX_FMT_RGB24:
777 return 0;
778 case IPU_PIX_FMT_RGB666:
779 return 1;
780 case IPU_PIX_FMT_YUV444:
781 return 2;
782 case IPU_PIX_FMT_RGB565:
783 return 3;
784 case IPU_PIX_FMT_LVDS666:
785 return 4;
786 }
787
788 return -1;
789}
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
829 uint16_t width, uint16_t height,
830 uint32_t pixel_fmt,
831 uint16_t h_start_width, uint16_t h_sync_width,
832 uint16_t h_end_width, uint16_t v_start_width,
833 uint16_t v_sync_width, uint16_t v_end_width,
834 uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
835{
836 uint32_t reg;
837 uint32_t di_gen, vsync_cnt;
838 uint32_t div, rounded_pixel_clk;
839 uint32_t h_total, v_total;
840 int map;
841 struct clk *di_parent;
842
843 debug("panel size = %d x %d\n", width, height);
844
845 if ((v_sync_width == 0) || (h_sync_width == 0))
846 return -EINVAL;
847
848
849 if (v_end_width < 2) {
850 v_end_width = 2;
851 puts("WARNING: v_end_width (lower_margin) must be >= 2, adjusted\n");
852 }
853
854 h_total = width + h_sync_width + h_start_width + h_end_width;
855 v_total = height + v_sync_width + v_start_width + v_end_width;
856
857
858 debug("pixel clk = %dHz\n", pixel_clk);
859
860 if (sig.ext_clk) {
861 if (!(g_di1_tvout && (disp == 1))) {
862
863
864
865
866 if ((clk_get_usecount(g_pixel_clk[0]) == 0) &&
867 (clk_get_usecount(g_pixel_clk[1]) == 0)) {
868 di_parent = clk_get_parent(g_di_clk[disp]);
869 rounded_pixel_clk =
870 clk_round_rate(g_pixel_clk[disp],
871 pixel_clk);
872 div = clk_get_rate(di_parent) /
873 rounded_pixel_clk;
874 if (div % 2)
875 div++;
876 if (clk_get_rate(di_parent) != div *
877 rounded_pixel_clk)
878 clk_set_rate(di_parent,
879 div * rounded_pixel_clk);
880 udelay(10000);
881 clk_set_rate(g_di_clk[disp],
882 2 * rounded_pixel_clk);
883 udelay(10000);
884 }
885 }
886 clk_set_parent(g_pixel_clk[disp], g_ldb_clk);
887 } else {
888 if (clk_get_usecount(g_pixel_clk[disp]) != 0)
889 clk_set_parent(g_pixel_clk[disp], g_ipu_clk);
890 }
891 rounded_pixel_clk = clk_round_rate(g_pixel_clk[disp], pixel_clk);
892 clk_set_rate(g_pixel_clk[disp], rounded_pixel_clk);
893 udelay(5000);
894
895 div = clk_get_rate(clk_get_parent(g_pixel_clk[disp])) /
896 rounded_pixel_clk;
897
898 ipu_di_data_wave_config(disp, SYNC_WAVE, div - 1, div - 1);
899 ipu_di_data_pin_config(disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
900
901 map = ipu_pixfmt_to_map(pixel_fmt);
902 if (map < 0) {
903 debug("IPU_DISP: No MAP\n");
904 return -EINVAL;
905 }
906
907 di_gen = __raw_readl(DI_GENERAL(disp));
908
909 if (sig.interlaced) {
910
911 ipu_di_sync_config(
912 disp,
913 1,
914 h_total / 2 - 1,
915 DI_SYNC_CLK,
916 0,
917 DI_SYNC_NONE,
918 0,
919 DI_SYNC_NONE,
920 0,
921 DI_SYNC_NONE,
922 DI_SYNC_NONE,
923 0,
924 0
925 );
926
927
928 ipu_di_sync_config(
929 disp,
930 2,
931 h_total - 1,
932 DI_SYNC_CLK,
933 0,
934 DI_SYNC_NONE,
935 0,
936 DI_SYNC_NONE,
937 0,
938 DI_SYNC_NONE,
939 DI_SYNC_NONE,
940 0,
941 4
942 );
943
944
945 ipu_di_sync_config(
946 disp,
947 3,
948 v_total * 2 - 1,
949 DI_SYNC_INT_HSYNC,
950 1,
951 DI_SYNC_INT_HSYNC,
952 0,
953 DI_SYNC_NONE,
954 0,
955 DI_SYNC_NONE,
956 DI_SYNC_NONE,
957 0,
958 4
959 );
960
961
962 ipu_di_sync_config(
963 disp,
964 4,
965 v_total / 2 - 1,
966 DI_SYNC_HSYNC,
967 v_start_width,
968 DI_SYNC_HSYNC,
969 2,
970 DI_SYNC_VSYNC,
971 0,
972 DI_SYNC_NONE,
973 DI_SYNC_NONE,
974 0,
975 0
976 );
977
978
979 ipu_di_sync_config(
980 disp,
981 5,
982 0,
983 DI_SYNC_HSYNC,
984 0,
985 DI_SYNC_NONE,
986 height / 2,
987 4,
988 0,
989 DI_SYNC_NONE,
990 DI_SYNC_NONE,
991 0,
992 0
993 );
994
995
996 ipu_di_sync_config(
997 disp,
998 6,
999 v_total - 1,
1000 DI_SYNC_HSYNC,
1001 0,
1002 DI_SYNC_NONE,
1003 0,
1004 DI_SYNC_NONE,
1005 0,
1006 DI_SYNC_NONE,
1007 DI_SYNC_NONE,
1008 0,
1009 0
1010 );
1011
1012
1013 vsync_cnt = 7;
1014 ipu_di_sync_config(
1015 disp,
1016 7,
1017 v_total / 2 - 1,
1018 DI_SYNC_HSYNC,
1019 9,
1020 DI_SYNC_HSYNC,
1021 2,
1022 DI_SYNC_VSYNC,
1023 0,
1024 DI_SYNC_NONE,
1025 DI_SYNC_NONE,
1026 0,
1027 0
1028 );
1029
1030
1031 ipu_di_sync_config(
1032 disp,
1033 8,
1034 0,
1035 DI_SYNC_CLK,
1036 h_start_width,
1037 DI_SYNC_CLK,
1038 width,
1039 5,
1040 0,
1041 DI_SYNC_NONE,
1042 DI_SYNC_NONE,
1043 0,
1044 0
1045 );
1046
1047 ipu_di_sync_config(
1048 disp,
1049 9,
1050 v_total - 1,
1051 DI_SYNC_INT_HSYNC,
1052 v_total / 2,
1053 DI_SYNC_INT_HSYNC,
1054 0,
1055 DI_SYNC_HSYNC,
1056 0,
1057 DI_SYNC_NONE,
1058 DI_SYNC_NONE,
1059 0,
1060 4
1061 );
1062
1063
1064 reg = __raw_readl(DI_SW_GEN1(disp, 9));
1065 reg &= 0x1FFFFFFF;
1066 reg |= (3 - 1)<<29 | 0x00008000;
1067 __raw_writel(reg, DI_SW_GEN1(disp, 9));
1068
1069 __raw_writel(v_total / 2 - 1, DI_SCR_CONF(disp));
1070
1071
1072 di_gen |= 0x10000000;
1073 di_gen |= DI_GEN_POLARITY_5;
1074 di_gen |= DI_GEN_POLARITY_8;
1075 } else {
1076
1077 ipu_di_sync_config(disp, 1, h_total - 1, DI_SYNC_CLK,
1078 0, DI_SYNC_NONE, 0, DI_SYNC_NONE,
1079 0, DI_SYNC_NONE,
1080 DI_SYNC_NONE, 0, 0);
1081
1082
1083 ipu_di_sync_config(disp, DI_SYNC_HSYNC, h_total - 1,
1084 DI_SYNC_CLK, div * v_to_h_sync, DI_SYNC_CLK,
1085 0, DI_SYNC_NONE, 1, DI_SYNC_NONE,
1086 DI_SYNC_CLK, 0, h_sync_width * 2);
1087
1088 vsync_cnt = DI_SYNC_VSYNC;
1089 ipu_di_sync_config(disp, DI_SYNC_VSYNC, v_total - 1,
1090 DI_SYNC_INT_HSYNC, 0, DI_SYNC_NONE, 0,
1091 DI_SYNC_NONE, 1, DI_SYNC_NONE,
1092 DI_SYNC_INT_HSYNC, 0, v_sync_width * 2);
1093 __raw_writel(v_total - 1, DI_SCR_CONF(disp));
1094
1095
1096 ipu_di_sync_config(disp, 4, 0, DI_SYNC_HSYNC,
1097 v_sync_width + v_start_width, DI_SYNC_HSYNC,
1098 height,
1099 DI_SYNC_VSYNC, 0, DI_SYNC_NONE,
1100 DI_SYNC_NONE, 0, 0);
1101 ipu_di_sync_config(disp, 5, 0, DI_SYNC_CLK,
1102 h_sync_width + h_start_width, DI_SYNC_CLK,
1103 width, 4, 0, DI_SYNC_NONE, DI_SYNC_NONE, 0,
1104 0);
1105
1106
1107 __raw_writel(0, DI_SW_GEN0(disp, 6));
1108 __raw_writel(0, DI_SW_GEN1(disp, 6));
1109 __raw_writel(0, DI_SW_GEN0(disp, 7));
1110 __raw_writel(0, DI_SW_GEN1(disp, 7));
1111 __raw_writel(0, DI_SW_GEN0(disp, 8));
1112 __raw_writel(0, DI_SW_GEN1(disp, 8));
1113 __raw_writel(0, DI_SW_GEN0(disp, 9));
1114 __raw_writel(0, DI_SW_GEN1(disp, 9));
1115
1116 reg = __raw_readl(DI_STP_REP(disp, 6));
1117 reg &= 0x0000FFFF;
1118 __raw_writel(reg, DI_STP_REP(disp, 6));
1119 __raw_writel(0, DI_STP_REP(disp, 7));
1120 __raw_writel(0, DI_STP_REP9(disp));
1121
1122
1123 if (disp) {
1124 ipu_dc_write_tmpl(2, WROD(0), 0, map, SYNC_WAVE, 8, 5);
1125 ipu_dc_write_tmpl(3, WROD(0), 0, map, SYNC_WAVE, 4, 5);
1126 ipu_dc_write_tmpl(4, WROD(0), 0, map, SYNC_WAVE, 0, 5);
1127 } else {
1128 ipu_dc_write_tmpl(5, WROD(0), 0, map, SYNC_WAVE, 8, 5);
1129 ipu_dc_write_tmpl(6, WROD(0), 0, map, SYNC_WAVE, 4, 5);
1130 ipu_dc_write_tmpl(7, WROD(0), 0, map, SYNC_WAVE, 0, 5);
1131 }
1132
1133 if (sig.Hsync_pol)
1134 di_gen |= DI_GEN_POLARITY_2;
1135 if (sig.Vsync_pol)
1136 di_gen |= DI_GEN_POLARITY_3;
1137
1138 if (!sig.clk_pol)
1139 di_gen |= DI_GEN_POL_CLK;
1140
1141 }
1142
1143 __raw_writel(di_gen, DI_GENERAL(disp));
1144
1145 __raw_writel((--vsync_cnt << DI_VSYNC_SEL_OFFSET) |
1146 0x00000002, DI_SYNC_AS_GEN(disp));
1147
1148 reg = __raw_readl(DI_POL(disp));
1149 reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
1150 if (sig.enable_pol)
1151 reg |= DI_POL_DRDY_POLARITY_15;
1152 if (sig.data_pol)
1153 reg |= DI_POL_DRDY_DATA_POLARITY;
1154 __raw_writel(reg, DI_POL(disp));
1155
1156 __raw_writel(width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
1157
1158 return 0;
1159}
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable,
1176 uint8_t alpha)
1177{
1178 uint32_t reg;
1179
1180 unsigned char bg_chan;
1181
1182 if (!((channel == MEM_BG_SYNC || channel == MEM_FG_SYNC) ||
1183 (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0) ||
1184 (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)))
1185 return -EINVAL;
1186
1187 if (channel == MEM_BG_SYNC || channel == MEM_BG_ASYNC0 ||
1188 channel == MEM_BG_ASYNC1)
1189 bg_chan = 1;
1190 else
1191 bg_chan = 0;
1192
1193 if (!g_ipu_clk_enabled)
1194 clk_enable(g_ipu_clk);
1195
1196 if (bg_chan) {
1197 reg = __raw_readl(DP_COM_CONF());
1198 __raw_writel(reg & ~DP_COM_CONF_GWSEL, DP_COM_CONF());
1199 } else {
1200 reg = __raw_readl(DP_COM_CONF());
1201 __raw_writel(reg | DP_COM_CONF_GWSEL, DP_COM_CONF());
1202 }
1203
1204 if (enable) {
1205 reg = __raw_readl(DP_GRAPH_WIND_CTRL()) & 0x00FFFFFFL;
1206 __raw_writel(reg | ((uint32_t) alpha << 24),
1207 DP_GRAPH_WIND_CTRL());
1208
1209 reg = __raw_readl(DP_COM_CONF());
1210 __raw_writel(reg | DP_COM_CONF_GWAM, DP_COM_CONF());
1211 } else {
1212 reg = __raw_readl(DP_COM_CONF());
1213 __raw_writel(reg & ~DP_COM_CONF_GWAM, DP_COM_CONF());
1214 }
1215
1216 reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
1217 __raw_writel(reg, IPU_SRM_PRI2);
1218
1219 if (!g_ipu_clk_enabled)
1220 clk_disable(g_ipu_clk);
1221
1222 return 0;
1223}
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable,
1237 uint32_t color_key)
1238{
1239 uint32_t reg;
1240 int y, u, v;
1241 int red, green, blue;
1242
1243 if (!((channel == MEM_BG_SYNC || channel == MEM_FG_SYNC) ||
1244 (channel == MEM_BG_ASYNC0 || channel == MEM_FG_ASYNC0) ||
1245 (channel == MEM_BG_ASYNC1 || channel == MEM_FG_ASYNC1)))
1246 return -EINVAL;
1247
1248 if (!g_ipu_clk_enabled)
1249 clk_enable(g_ipu_clk);
1250
1251 color_key_4rgb = 1;
1252
1253 if (((fg_csc_type == RGB2YUV) && (bg_csc_type == YUV2YUV)) ||
1254 ((fg_csc_type == YUV2YUV) && (bg_csc_type == RGB2YUV)) ||
1255 ((fg_csc_type == YUV2YUV) && (bg_csc_type == YUV2YUV)) ||
1256 ((fg_csc_type == YUV2RGB) && (bg_csc_type == YUV2RGB))) {
1257
1258 debug("color key 0x%x need change to yuv fmt\n", color_key);
1259
1260 red = (color_key >> 16) & 0xFF;
1261 green = (color_key >> 8) & 0xFF;
1262 blue = color_key & 0xFF;
1263
1264 y = rgb_to_yuv(0, red, green, blue);
1265 u = rgb_to_yuv(1, red, green, blue);
1266 v = rgb_to_yuv(2, red, green, blue);
1267 color_key = (y << 16) | (u << 8) | v;
1268
1269 color_key_4rgb = 0;
1270
1271 debug("color key change to yuv fmt 0x%x\n", color_key);
1272 }
1273
1274 if (enable) {
1275 reg = __raw_readl(DP_GRAPH_WIND_CTRL()) & 0xFF000000L;
1276 __raw_writel(reg | color_key, DP_GRAPH_WIND_CTRL());
1277
1278 reg = __raw_readl(DP_COM_CONF());
1279 __raw_writel(reg | DP_COM_CONF_GWCKE, DP_COM_CONF());
1280 } else {
1281 reg = __raw_readl(DP_COM_CONF());
1282 __raw_writel(reg & ~DP_COM_CONF_GWCKE, DP_COM_CONF());
1283 }
1284
1285 reg = __raw_readl(IPU_SRM_PRI2) | 0x8;
1286 __raw_writel(reg, IPU_SRM_PRI2);
1287
1288 if (!g_ipu_clk_enabled)
1289 clk_disable(g_ipu_clk);
1290
1291 return 0;
1292}
1293