summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c')
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c395
1 files changed, 57 insertions, 338 deletions
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
index 7afdaa316e..59496f2d24 100644
--- a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
+++ b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
@@ -32,161 +32,76 @@
32#ifdef HAVE_LCD_ENABLE 32#ifdef HAVE_LCD_ENABLE
33static bool lcd_on; 33static bool lcd_on;
34#endif 34#endif
35static unsigned lcd_yuv_options = 0;
36 35
37static void setup_parameters(void) 36static void lcd_write_reg(uint16_t reg, uint16_t data)
38{ 37{
39 imx233_lcdif_reset(); 38 imx233_lcdif_pio_send(false, 1, &reg);
40 imx233_lcdif_set_lcd_databus_width(BV_LCDIF_CTRL_LCD_DATABUS_WIDTH__16_BIT); 39 if(reg != 0x22)
41 imx233_lcdif_set_word_length(BV_LCDIF_CTRL_WORD_LENGTH__16_BIT); 40 imx233_lcdif_pio_send(true, 1, &data);
42 imx233_lcdif_set_timings(2, 2, 3, 3);
43 imx233_lcdif_enable_underflow_recover(true);
44}
45
46static void setup_lcd_pins(bool use_lcdif)
47{
48 /* WARNING
49 * the B1P22 pins is used to gate the speaker! Do NOT drive
50 * them as lcd_dotclk and lcd_hsync or it will break audio */
51 imx233_pinctrl_acquire(1, 18, "lcd reset");
52 imx233_pinctrl_acquire(1, 19, "lcd rs");
53 imx233_pinctrl_acquire(1, 20, "lcd wr");
54 imx233_pinctrl_acquire(1, 21, "lcd cs");
55 imx233_pinctrl_acquire(1, 23, "lcd enable");
56 imx233_pinctrl_acquire(1, 25, "lcd vsync");
57 //imx233_pinctrl_acquire_mask(1, 0x3ffff, "lcd data");
58 if(use_lcdif)
59 {
60 imx233_pinctrl_set_function(1, 25, PINCTRL_FUNCTION_MAIN); /* lcd_vsync */
61 imx233_pinctrl_set_function(1, 21, PINCTRL_FUNCTION_MAIN); /* lcd_cs */
62 imx233_pinctrl_set_function(1, 23, PINCTRL_FUNCTION_MAIN); /* lcd_enable */
63 imx233_pinctrl_set_function(1, 18, PINCTRL_FUNCTION_MAIN); /* lcd_reset */
64 imx233_pinctrl_set_function(1, 19, PINCTRL_FUNCTION_MAIN); /* lcd_rs */
65 imx233_pinctrl_set_function(1, 16, PINCTRL_FUNCTION_MAIN); /* lcd_d16 */
66 imx233_pinctrl_set_function(1, 17, PINCTRL_FUNCTION_MAIN); /* lcd_d17 */
67 imx233_pinctrl_set_function(1, 20, PINCTRL_FUNCTION_MAIN); /* lcd_wr */
68 HW_PINCTRL_MUXSELn_CLR(2) = 0xffffffff; /* lcd_d{0-15} */
69 }
70 else
71 {
72 HW_PINCTRL_MUXSELn_SET(2) = 0xffffffff; /* lcd_d{0-15} */
73 HW_PINCTRL_DOEn_CLR(1) = 0x2bfffff;
74 imx233_pinctrl_set_function(1, 16, PINCTRL_FUNCTION_GPIO); /* lcd_d16 */
75 imx233_pinctrl_set_function(1, 17, PINCTRL_FUNCTION_GPIO); /* lcd_d17 */
76 imx233_pinctrl_set_function(1, 19, PINCTRL_FUNCTION_GPIO); /* lcd_rs */
77 imx233_pinctrl_set_function(1, 20, PINCTRL_FUNCTION_GPIO); /* lcd_wr */
78 imx233_pinctrl_set_function(1, 21, PINCTRL_FUNCTION_GPIO); /* lcd_cs */
79 imx233_pinctrl_set_function(1, 23, PINCTRL_FUNCTION_GPIO); /* lcd_enable */
80 imx233_pinctrl_set_function(1, 25, PINCTRL_FUNCTION_GPIO); /* lcd_vsync */
81 }
82}
83
84static void common_lcd_enable(bool enable)
85{
86 imx233_lcdif_enable(enable);
87 setup_lcd_pins(enable); /* use GPIO pins when disable */
88} 41}
89 42
90static void setup_lcdif(void) 43static void lcd_init_seq(void)
91{ 44{
92 setup_parameters(); 45 lcd_write_reg(1, 0x11c);
93 common_lcd_enable(true); 46 lcd_write_reg(2, 0x100);
94 imx233_lcdif_enable_bus_master(true); 47 lcd_write_reg(3, 0x1030);
48 lcd_write_reg(8, 0x808);
49 lcd_write_reg(0xc, 0);
50 lcd_write_reg(0xf, 0xc01);
51 lcd_write_reg(0x20, 0);
52 lcd_write_reg(0x21, 0);
53 udelay(30);
54 lcd_write_reg(0x10, 0xa00);
55 lcd_write_reg(0x11, 0x1038);
56 udelay(30);
57 lcd_write_reg(0x12, 0x1010);
58 lcd_write_reg(0x13, 0x50);
59 lcd_write_reg(0x14, 0x4f58);
60 lcd_write_reg(0x30, 0);
61 lcd_write_reg(0x31, 0xdb);
62 lcd_write_reg(0x32, 0);
63 lcd_write_reg(0x33, 0);
64 lcd_write_reg(0x34, 0xdb);
65 lcd_write_reg(0x35, 0);
66 lcd_write_reg(0x36, 0xaf);
67 lcd_write_reg(0x37, 0);
68 lcd_write_reg(0x38, 0xdb);
69 lcd_write_reg(0x39, 0);
70 lcd_write_reg(0x50, 0);
71 lcd_write_reg(0x51, 0x705);
72 lcd_write_reg(0x52, 0xe0a);
73 lcd_write_reg(0x53, 0x300);
74 lcd_write_reg(0x54, 0xa0e);
75 lcd_write_reg(0x55, 0x507);
76 lcd_write_reg(0x56, 0);
77 lcd_write_reg(0x57, 3);
78 lcd_write_reg(0x58, 0x90a);
79 lcd_write_reg(0x59, 0xa09);
80 udelay(30);
81 lcd_write_reg(7, 0x1017);
82 udelay(40);
95} 83}
96 84
97static void setup_lcdif_clock(void) 85void lcd_init_device(void)
98{ 86{
99 /* the LCD seems to work at 24Mhz, so use the xtal clock with no divider */ 87 /* the LCD seems to work at 24Mhz, so use the xtal clock with no divider */
100 imx233_clkctrl_enable(CLK_PIX, false); 88 imx233_clkctrl_enable(CLK_PIX, false);
101 imx233_clkctrl_set_div(CLK_PIX, 1); 89 imx233_clkctrl_set_div(CLK_PIX, 1);
102 imx233_clkctrl_set_bypass(CLK_PIX, true); /* use XTAL */ 90 imx233_clkctrl_set_bypass(CLK_PIX, true); /* use XTAL */
103 imx233_clkctrl_enable(CLK_PIX, true); 91 imx233_clkctrl_enable(CLK_PIX, true);
104} 92 imx233_lcdif_init();
105 93 imx233_lcdif_set_lcd_databus_width(16);
106static void lcd_write_reg(uint32_t reg, uint32_t data) 94 imx233_lcdif_set_word_length(16);
107{ 95 imx233_lcdif_set_timings(2, 2, 3, 3);
108 imx233_lcdif_pio_send(false, 2, &reg); 96 imx233_lcdif_enable_underflow_recover(true);
109 if(reg != 0x22) 97 imx233_lcdif_setup_system_pins(16);
110 imx233_lcdif_pio_send(true, 2, &data);
111}
112
113#define REG_UDELAY 0xffffffff
114struct lcd_sequence_entry_t
115{
116 uint32_t reg, data;
117};
118
119static void lcd_send_sequence(struct lcd_sequence_entry_t *seq, unsigned count)
120{
121 for(;count-- > 0; seq++)
122 {
123 if(seq->reg == REG_UDELAY)
124 udelay(seq->data);
125 else
126 lcd_write_reg(seq->reg, seq->data);
127 }
128}
129
130#define _begin_seq() static struct lcd_sequence_entry_t __seq[] = {
131#define _udelay(a) {REG_UDELAY, a},
132#define _lcd_write_reg(a, b) {a, b},
133#define _end_seq() }; lcd_send_sequence(__seq, sizeof(__seq) / sizeof(__seq[0]));
134
135static void lcd_init_seq(void)
136{
137 _begin_seq()
138 _lcd_write_reg(1, 0x11c)
139 _lcd_write_reg(2, 0x100)
140 _lcd_write_reg(3, 0x1030)
141 _lcd_write_reg(8, 0x808)
142 _lcd_write_reg(0xc, 0)
143 _lcd_write_reg(0xf, 0xc01)
144 _lcd_write_reg(0x20, 0)
145 _lcd_write_reg(0x21, 0)
146 _udelay(30)
147 _lcd_write_reg(0x10, 0xa00)
148 _lcd_write_reg(0x11, 0x1038)
149 _udelay(30)
150 _lcd_write_reg(0x12, 0x1010)
151 _lcd_write_reg(0x13, 0x50)
152 _lcd_write_reg(0x14, 0x4f58)
153 _lcd_write_reg(0x30, 0)
154 _lcd_write_reg(0x31, 0xdb)
155 _lcd_write_reg(0x32, 0)
156 _lcd_write_reg(0x33, 0)
157 _lcd_write_reg(0x34, 0xdb)
158 _lcd_write_reg(0x35, 0)
159 _lcd_write_reg(0x36, 0xaf)
160 _lcd_write_reg(0x37, 0)
161 _lcd_write_reg(0x38, 0xdb)
162 _lcd_write_reg(0x39, 0)
163 _lcd_write_reg(0x50, 0)
164 _lcd_write_reg(0x51, 0x705)
165 _lcd_write_reg(0x52, 0xe0a)
166 _lcd_write_reg(0x53, 0x300)
167 _lcd_write_reg(0x54, 0xa0e)
168 _lcd_write_reg(0x55, 0x507)
169 _lcd_write_reg(0x56, 0)
170 _lcd_write_reg(0x57, 3)
171 _lcd_write_reg(0x58, 0x90a)
172 _lcd_write_reg(0x59, 0xa09)
173 _udelay(30)
174 _lcd_write_reg(7, 0x1017)
175 _udelay(40)
176 _end_seq()
177}
178
179void lcd_init_device(void)
180{
181 setup_lcdif();
182 setup_lcdif_clock();
183 98
184 // reset device 99 // reset device
185 BF_SET(LCDIF_CTRL1, RESET); 100 imx233_lcdif_reset_lcd(true);
186 mdelay(50); 101 mdelay(50);
187 BF_CLR(LCDIF_CTRL1, RESET); 102 imx233_lcdif_reset_lcd(false);
188 mdelay(10); 103 mdelay(10);
189 BF_SET(LCDIF_CTRL1, RESET); 104 imx233_lcdif_reset_lcd(true);
190 105
191 lcd_init_seq(); 106 lcd_init_seq();
192#ifdef HAVE_LCD_ENABLE 107#ifdef HAVE_LCD_ENABLE
@@ -204,13 +119,9 @@ static void lcd_enable_seq(bool enable)
204{ 119{
205 if(!enable) 120 if(!enable)
206 { 121 {
207 _begin_seq()
208 _end_seq()
209 } 122 }
210 else 123 else
211 { 124 {
212 _begin_seq()
213 _end_seq()
214 } 125 }
215} 126}
216 127
@@ -220,12 +131,12 @@ void lcd_enable(bool enable)
220 return; 131 return;
221 132
222 lcd_on = enable; 133 lcd_on = enable;
223 134
224 if(enable) 135 if(enable)
225 common_lcd_enable(true); 136 imx233_lcdif_enable(true);
226 lcd_enable_seq(enable); 137 lcd_enable_seq(enable);
227 if(!enable) 138 if(!enable)
228 common_lcd_enable(false); 139 imx233_lcdif_enable(false);
229 else 140 else
230 send_event(LCD_EVENT_ACTIVATION, NULL); 141 send_event(LCD_EVENT_ACTIVATION, NULL);
231} 142}
@@ -258,9 +169,8 @@ void lcd_update_rect(int x, int y, int w, int h)
258 lcd_write_reg(0x22, 0); 169 lcd_write_reg(0x22, 0);
259 170
260 imx233_lcdif_wait_ready(); 171 imx233_lcdif_wait_ready();
261 imx233_lcdif_set_word_length(BV_LCDIF_CTRL_WORD_LENGTH__16_BIT); 172 imx233_lcdif_set_word_length(16);
262 imx233_lcdif_set_byte_packing_format(0xf); /* two pixels per 32-bit word */ 173 imx233_lcdif_set_byte_packing_format(0xf); /* two pixels per 32-bit word */
263 imx233_lcdif_set_data_format(false, false, false); /* RGB565, don't care, don't care */
264 174
265 /* there are two cases here: 175 /* there are two cases here:
266 * - either width = LCD_WIDTH and we can directly memcopy a part of lcd_framebuffer to FRAME 176 * - either width = LCD_WIDTH and we can directly memcopy a part of lcd_framebuffer to FRAME
@@ -306,194 +216,3 @@ void lcd_update_rect(int x, int y, int w, int h)
306 imx233_lcdif_dma_send((void *)FRAME_PHYS_ADDR, w, h); 216 imx233_lcdif_dma_send((void *)FRAME_PHYS_ADDR, w, h);
307} 217}
308 218
309void lcd_yuv_set_options(unsigned options)
310{
311 lcd_yuv_options = options;
312}
313
314#define YFAC (74)
315#define RVFAC (101)
316#define GUFAC (-24)
317#define GVFAC (-51)
318#define BUFAC (128)
319
320static inline int clamp(int val, int min, int max)
321{
322 if (val < min)
323 val = min;
324 else if (val > max)
325 val = max;
326 return val;
327}
328
329void lcd_blit_yuv(unsigned char * const src[3],
330 int src_x, int src_y, int stride,
331 int x, int y, int width, int height)
332{
333 const unsigned char *ysrc, *usrc, *vsrc;
334 int linecounter;
335 fb_data *dst, *row_end;
336 long z;
337
338 /* width and height must be >= 2 and an even number */
339 width &= ~1;
340 linecounter = height >> 1;
341
342 #if LCD_WIDTH >= LCD_HEIGHT
343 dst = FBADDR(x,y);
344 row_end = dst + width;
345 #else
346 dst = FBADDR(LCD_WIDTH - y - 1,x);
347 row_end = dst + LCD_WIDTH * width;
348 #endif
349
350 z = stride * src_y;
351 ysrc = src[0] + z + src_x;
352 usrc = src[1] + (z >> 2) + (src_x >> 1);
353 vsrc = src[2] + (usrc - src[1]);
354
355 /* stride => amount to jump from end of last row to start of next */
356 stride -= width;
357
358 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
359
360 do
361 {
362 do
363 {
364 int y, cb, cr, rv, guv, bu, r, g, b;
365
366 y = YFAC*(*ysrc++ - 16);
367 cb = *usrc++ - 128;
368 cr = *vsrc++ - 128;
369
370 rv = RVFAC*cr;
371 guv = GUFAC*cb + GVFAC*cr;
372 bu = BUFAC*cb;
373
374 r = y + rv;
375 g = y + guv;
376 b = y + bu;
377
378 if ((unsigned)(r | g | b) > 64*256-1)
379 {
380 r = clamp(r, 0, 64*256-1);
381 g = clamp(g, 0, 64*256-1);
382 b = clamp(b, 0, 64*256-1);
383 }
384
385 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
386
387 #if LCD_WIDTH >= LCD_HEIGHT
388 dst++;
389 #else
390 dst += LCD_WIDTH;
391 #endif
392
393 y = YFAC*(*ysrc++ - 16);
394 r = y + rv;
395 g = y + guv;
396 b = y + bu;
397
398 if ((unsigned)(r | g | b) > 64*256-1)
399 {
400 r = clamp(r, 0, 64*256-1);
401 g = clamp(g, 0, 64*256-1);
402 b = clamp(b, 0, 64*256-1);
403 }
404
405 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
406
407 #if LCD_WIDTH >= LCD_HEIGHT
408 dst++;
409 #else
410 dst += LCD_WIDTH;
411 #endif
412 }
413 while (dst < row_end);
414
415 ysrc += stride;
416 usrc -= width >> 1;
417 vsrc -= width >> 1;
418
419 #if LCD_WIDTH >= LCD_HEIGHT
420 row_end += LCD_WIDTH;
421 dst += LCD_WIDTH - width;
422 #else
423 row_end -= 1;
424 dst -= LCD_WIDTH*width + 1;
425 #endif
426
427 do
428 {
429 int y, cb, cr, rv, guv, bu, r, g, b;
430
431 y = YFAC*(*ysrc++ - 16);
432 cb = *usrc++ - 128;
433 cr = *vsrc++ - 128;
434
435 rv = RVFAC*cr;
436 guv = GUFAC*cb + GVFAC*cr;
437 bu = BUFAC*cb;
438
439 r = y + rv;
440 g = y + guv;
441 b = y + bu;
442
443 if ((unsigned)(r | g | b) > 64*256-1)
444 {
445 r = clamp(r, 0, 64*256-1);
446 g = clamp(g, 0, 64*256-1);
447 b = clamp(b, 0, 64*256-1);
448 }
449
450 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
451
452 #if LCD_WIDTH >= LCD_HEIGHT
453 dst++;
454 #else
455 dst += LCD_WIDTH;
456 #endif
457
458 y = YFAC*(*ysrc++ - 16);
459 r = y + rv;
460 g = y + guv;
461 b = y + bu;
462
463 if ((unsigned)(r | g | b) > 64*256-1)
464 {
465 r = clamp(r, 0, 64*256-1);
466 g = clamp(g, 0, 64*256-1);
467 b = clamp(b, 0, 64*256-1);
468 }
469
470 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
471
472 #if LCD_WIDTH >= LCD_HEIGHT
473 dst++;
474 #else
475 dst += LCD_WIDTH;
476 #endif
477 }
478 while (dst < row_end);
479
480 ysrc += stride;
481 usrc += stride >> 1;
482 vsrc += stride >> 1;
483
484 #if LCD_WIDTH >= LCD_HEIGHT
485 row_end += LCD_WIDTH;
486 dst += LCD_WIDTH - width;
487 #else
488 row_end -= 1;
489 dst -= LCD_WIDTH*width + 1;
490 #endif
491 }
492 while (--linecounter > 0);
493
494 #if LCD_WIDTH >= LCD_HEIGHT
495 lcd_update_rect(x, y, width, height);
496 #else
497 lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
498 #endif
499}