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