diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c | 158 |
1 files changed, 110 insertions, 48 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c index 0446fb2cce..47b646be34 100644 --- a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c +++ b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2016 by Roman Stolyarov | 10 | * Copyright (C) 2016 by Roman Stolyarov |
11 | * Copyright (C) 2020 by William Wilgus | ||
11 | * | 12 | * |
12 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 14 | * modify it under the terms of the GNU General Public License |
@@ -44,6 +45,13 @@ | |||
44 | #define PIN_LCD_RES (32*2+18) | 45 | #define PIN_LCD_RES (32*2+18) |
45 | #define PIN_LCD_WR (32*2+19) | 46 | #define PIN_LCD_WR (32*2+19) |
46 | 47 | ||
48 | /* LCD_PINS_MASK D0-D7 RD DC CS RES WR */ | ||
49 | #define LCD_PINS_MASK 0x000C73FC | ||
50 | /* LCD_DATA_MASK D0-D7 */ | ||
51 | #define LCD_DATA_MASK 0x000030FC | ||
52 | /* FRAMEBUF_TO_LCD_DATA -- translate data to match LCD data pins */ | ||
53 | #define FRAMEBUF_TO_LCD_DATA(b) (((b & 0xC0) << 6) | ((b & 0x3F) << 2)) | ||
54 | |||
47 | /* LCD setup codes */ | 55 | /* LCD setup codes */ |
48 | #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) | 56 | #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) |
49 | #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) | 57 | #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) |
@@ -82,35 +90,37 @@ | |||
82 | 90 | ||
83 | #define LCD_COL_OFFSET 2 /* column offset */ | 91 | #define LCD_COL_OFFSET 2 /* column offset */ |
84 | 92 | ||
85 | static inline void bitdelay(void) | 93 | #define BITDELAY() \ |
86 | { | 94 | do { \ |
87 | unsigned int i = 15; | 95 | volatile unsigned int i = 12; \ |
88 | __asm__ __volatile__ ( | 96 | __asm__ __volatile__ ( \ |
89 | ".set noreorder \n" | 97 | ".set noreorder \n" \ |
90 | "1: \n" | 98 | "1: \n" \ |
91 | "bne %0, $0, 1b \n" | 99 | "bne %0, $0, 1b \n" \ |
92 | "addi %0, %0, -1 \n" | 100 | "addi %0, %0, -1 \n" \ |
93 | ".set reorder \n" | 101 | ".set reorder \n" \ |
94 | : "=r" (i) | 102 | : "=r" (i) \ |
95 | : "0" (i) | 103 | : "0" (i) \ |
96 | ); | 104 | ); \ |
97 | } | 105 | } while (0) |
98 | 106 | ||
99 | void lcd_hw_init(void) | 107 | void lcd_hw_init(void) |
100 | { | 108 | { |
101 | REG_GPIO_PXFUNC(2) = 0x000C73FC; /* D0-D7 RD DC CS RES WR -- GPIO/INTERRUPT */ | 109 | REG_GPIO_PXFUNC(2) = LCD_PINS_MASK; /* GPIO/INTERRUPT */ |
102 | REG_GPIO_PXSELC(2) = 0x000C73FC; /* GPIO */ | 110 | REG_GPIO_PXSELC(2) = LCD_PINS_MASK; /* GPIO */ |
103 | 111 | ||
104 | REG_GPIO_PXPEC(2) = 0x000C73FC; /* ENABLE PULLUP*/ | 112 | REG_GPIO_PXPEC(2) = LCD_PINS_MASK; /* ENABLE PULLUP*/ |
113 | REG_GPIO_PXDIRS(2) = LCD_PINS_MASK; /* OUTPUT */ | ||
105 | 114 | ||
106 | REG_GPIO_PXDIRS(2) = 0x000C73FC; /* OUTPUT */ | 115 | REG_GPIO_PXDATS(2) = LCD_PINS_MASK; /* SET BIT */ |
107 | REG_GPIO_PXDATS(2) = 0x000C73FC; /* D0-D7 RD DC CS RES WR -- SET BIT */ | 116 | REG_GPIO_PXSLS(2) = LCD_PINS_MASK; /* slew -- fast rate */ |
108 | 117 | ||
109 | REG_GPIO_PXSLC(2) = 0x000C73FC; /* slew -- slow rate */ | 118 | REG_GPIO_PXDS0C(2) = LCD_PINS_MASK; /* Low pin drive strength */ |
119 | REG_GPIO_PXDS1C(2) = LCD_PINS_MASK; | ||
120 | REG_GPIO_PXDS2C(2) = LCD_PINS_MASK; | ||
110 | 121 | ||
111 | REG_GPIO_PXDS0C(2) = 0x000C73FC; /* Low pin drive strength */ | 122 | __gpio_clear_pin(PIN_LCD_RD); /* UNUSED */ |
112 | REG_GPIO_PXDS1C(2) = 0x000C73FC; | 123 | __gpio_as_input(PIN_LCD_RD); /* UNUSED */ |
113 | REG_GPIO_PXDS2C(2) = 0x000C73FC; | ||
114 | 124 | ||
115 | __gpio_clear_pin(PIN_BL_EN); | 125 | __gpio_clear_pin(PIN_BL_EN); |
116 | __gpio_as_output(PIN_BL_EN); | 126 | __gpio_as_output(PIN_BL_EN); |
@@ -125,26 +135,64 @@ void lcd_hw_init(void) | |||
125 | void lcd_write_command(int byte) | 135 | void lcd_write_command(int byte) |
126 | { | 136 | { |
127 | __gpio_clear_pin(PIN_LCD_DC); | 137 | __gpio_clear_pin(PIN_LCD_DC); |
128 | REG_GPIO_PXDATC(2) = 0x000030FC; | 138 | REG_GPIO_PXDATC(2) = LCD_DATA_MASK; |
129 | REG_GPIO_PXDATS(2) = ((byte & 0xC0) << 6) | ((byte & 0x3F) << 2); | 139 | REG_GPIO_PXDATS(2) = FRAMEBUF_TO_LCD_DATA(byte); |
140 | __gpio_clear_pin(PIN_LCD_WR); | ||
141 | BITDELAY(); | ||
142 | __gpio_set_pin(PIN_LCD_WR); | ||
143 | BITDELAY(); | ||
144 | } | ||
145 | |||
146 | static void lcd_write_cmd_triplet(int cmd1, int cmd2, int cmd3) | ||
147 | { | ||
148 | #if 0 | ||
149 | lcd_write_command(cmd1); | ||
150 | lcd_write_command(cmd2); | ||
151 | lcd_write_command(cmd3); | ||
152 | #else | ||
153 | int command = LCD_DATA_MASK; | ||
154 | __gpio_clear_pin(PIN_LCD_DC); | ||
155 | |||
156 | REG_GPIO_PXDATC(2) = command; | ||
157 | command = FRAMEBUF_TO_LCD_DATA(cmd1); | ||
158 | REG_GPIO_PXDATS(2) = command; | ||
130 | __gpio_clear_pin(PIN_LCD_WR); | 159 | __gpio_clear_pin(PIN_LCD_WR); |
131 | bitdelay(); | 160 | BITDELAY(); |
132 | __gpio_set_pin(PIN_LCD_WR); | 161 | __gpio_set_pin(PIN_LCD_WR); |
133 | bitdelay(); | 162 | BITDELAY(); |
163 | |||
164 | REG_GPIO_PXDATC(2) = command; | ||
165 | command = FRAMEBUF_TO_LCD_DATA(cmd2); | ||
166 | REG_GPIO_PXDATS(2) = command; | ||
167 | __gpio_clear_pin(PIN_LCD_WR); | ||
168 | BITDELAY(); | ||
169 | __gpio_set_pin(PIN_LCD_WR); | ||
170 | BITDELAY(); | ||
171 | |||
172 | REG_GPIO_PXDATC(2) = command; | ||
173 | command = FRAMEBUF_TO_LCD_DATA(cmd3); | ||
174 | REG_GPIO_PXDATS(2) = command; | ||
175 | __gpio_clear_pin(PIN_LCD_WR); | ||
176 | BITDELAY(); | ||
177 | __gpio_set_pin(PIN_LCD_WR); | ||
178 | BITDELAY(); | ||
179 | #endif | ||
134 | } | 180 | } |
135 | 181 | ||
136 | void lcd_write_data(const fb_data* p_bytes, int count) | 182 | void lcd_write_data(const fb_data* p_bytes, int count) |
137 | { | 183 | { |
184 | int data = LCD_DATA_MASK; | ||
138 | __gpio_set_pin(PIN_LCD_DC); | 185 | __gpio_set_pin(PIN_LCD_DC); |
139 | while (count--) | 186 | while (count--) |
140 | { | 187 | { |
141 | REG_GPIO_PXDATC(2) = 0x000030FC; | 188 | REG_GPIO_PXDATC(2) = data; |
142 | REG_GPIO_PXDATS(2) = ((*p_bytes & 0xC0) << 6) | ((*p_bytes & 0x3F) << 2); | 189 | data = FRAMEBUF_TO_LCD_DATA(*p_bytes); |
143 | p_bytes++; | 190 | p_bytes++; |
191 | REG_GPIO_PXDATS(2) = data; | ||
144 | __gpio_clear_pin(PIN_LCD_WR); | 192 | __gpio_clear_pin(PIN_LCD_WR); |
145 | bitdelay(); | 193 | BITDELAY(); |
146 | __gpio_set_pin(PIN_LCD_WR); | 194 | __gpio_set_pin(PIN_LCD_WR); |
147 | bitdelay(); | 195 | BITDELAY(); |
148 | } | 196 | } |
149 | } | 197 | } |
150 | 198 | ||
@@ -275,6 +323,7 @@ void lcd_enable(bool enable) | |||
275 | { | 323 | { |
276 | lcd_write_command(LCD_SET_DISPLAY_OFF); | 324 | lcd_write_command(LCD_SET_DISPLAY_OFF); |
277 | lcd_enable_power(enable); | 325 | lcd_enable_power(enable); |
326 | REG_GPIO_PXDATC(2) = LCD_DATA_MASK; | ||
278 | } | 327 | } |
279 | } | 328 | } |
280 | 329 | ||
@@ -296,7 +345,7 @@ void lcd_init_device(void) | |||
296 | 345 | ||
297 | /* Set display clock and oscillator frequency */ | 346 | /* Set display clock and oscillator frequency */ |
298 | lcd_write_command(LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ); | 347 | lcd_write_command(LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ); |
299 | lcd_write_command(0x80); | 348 | lcd_write_command(0x00); /* External clock Bits [0-3] for divider */ |
300 | 349 | ||
301 | /* Set multiplex ratio*/ | 350 | /* Set multiplex ratio*/ |
302 | lcd_write_command(LCD_SET_MULTIPLEX_RATIO); | 351 | lcd_write_command(LCD_SET_MULTIPLEX_RATIO); |
@@ -386,9 +435,12 @@ void lcd_blit_mono(const unsigned char *data, int x, int by, int width, | |||
386 | /* Copy display bitmap to hardware */ | 435 | /* Copy display bitmap to hardware */ |
387 | while (bheight--) | 436 | while (bheight--) |
388 | { | 437 | { |
389 | lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); | 438 | lcd_write_cmd_triplet |
390 | lcd_write_command (column_high); | 439 | ( |
391 | lcd_write_command (column_low); | 440 | (LCD_CNTL_PAGE | (by++ & 0xf)), |
441 | (column_high), | ||
442 | (column_low) | ||
443 | ); | ||
392 | 444 | ||
393 | lcd_write_data(data, width); | 445 | lcd_write_data(data, width); |
394 | data += stride; | 446 | data += stride; |
@@ -405,6 +457,7 @@ void lcd_grey_data(unsigned char *values, unsigned char *phases, int count) | |||
405 | unsigned long *lval = (unsigned long *)values; | 457 | unsigned long *lval = (unsigned long *)values; |
406 | unsigned long *lpha = (unsigned long *)phases; | 458 | unsigned long *lpha = (unsigned long *)phases; |
407 | const unsigned long mask = 0x80808080; | 459 | const unsigned long mask = 0x80808080; |
460 | int data = LCD_DATA_MASK; | ||
408 | 461 | ||
409 | __gpio_set_pin(PIN_LCD_DC); | 462 | __gpio_set_pin(PIN_LCD_DC); |
410 | while(count--) | 463 | while(count--) |
@@ -421,13 +474,13 @@ void lcd_grey_data(unsigned char *values, unsigned char *phases, int count) | |||
421 | lpha[0] = lval[0] + (lpha[0] & ~mask); | 474 | lpha[0] = lval[0] + (lpha[0] & ~mask); |
422 | lpha[1] = lval[1] + (lpha[1] & ~mask); | 475 | lpha[1] = lval[1] + (lpha[1] & ~mask); |
423 | 476 | ||
424 | REG_GPIO_PXDATC(2) = 0x000030FC; | 477 | REG_GPIO_PXDATC(2) = data; |
425 | REG_GPIO_PXDATS(2) = ((ltmp & 0xC0) << 6) | ((ltmp & 0x3F) << 2); | 478 | data = FRAMEBUF_TO_LCD_DATA(ltmp); |
479 | REG_GPIO_PXDATS(2) = data; | ||
426 | __gpio_clear_pin(PIN_LCD_WR); | 480 | __gpio_clear_pin(PIN_LCD_WR); |
427 | bitdelay(); | 481 | BITDELAY(); |
428 | __gpio_set_pin(PIN_LCD_WR); | 482 | __gpio_set_pin(PIN_LCD_WR); |
429 | bitdelay(); | 483 | /*BITDELAY(); //enough instructions above to satisfy data hold time */ |
430 | |||
431 | lpha+=2; | 484 | lpha+=2; |
432 | lval+=2; | 485 | lval+=2; |
433 | } | 486 | } |
@@ -450,9 +503,12 @@ void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | |||
450 | /* Copy display bitmap to hardware */ | 503 | /* Copy display bitmap to hardware */ |
451 | while (bheight--) | 504 | while (bheight--) |
452 | { | 505 | { |
453 | lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); | 506 | lcd_write_cmd_triplet |
454 | lcd_write_command (column_high); | 507 | ( |
455 | lcd_write_command (column_low); | 508 | (LCD_CNTL_PAGE | (by++ & 0xf)), |
509 | (column_high), | ||
510 | (column_low) | ||
511 | ); | ||
456 | 512 | ||
457 | lcd_grey_data(values, phases, width); | 513 | lcd_grey_data(values, phases, width); |
458 | 514 | ||
@@ -479,9 +535,12 @@ void lcd_update(void) | |||
479 | /* Copy display bitmap to hardware */ | 535 | /* Copy display bitmap to hardware */ |
480 | for (y = 0; y < LCD_FBHEIGHT; y++) | 536 | for (y = 0; y < LCD_FBHEIGHT; y++) |
481 | { | 537 | { |
482 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | 538 | lcd_write_cmd_triplet |
483 | lcd_write_command (column_high); | 539 | ( |
484 | lcd_write_command (column_low); | 540 | (LCD_CNTL_PAGE | (y & 0xf)), |
541 | (column_high), | ||
542 | (column_low) | ||
543 | ); | ||
485 | 544 | ||
486 | lcd_write_data (FBADDR(0, y), LCD_WIDTH); | 545 | lcd_write_data (FBADDR(0, y), LCD_WIDTH); |
487 | } | 546 | } |
@@ -530,9 +589,12 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
530 | /* Copy specified rectange bitmap to hardware */ | 589 | /* Copy specified rectange bitmap to hardware */ |
531 | for (; y <= ymax; y++) | 590 | for (; y <= ymax; y++) |
532 | { | 591 | { |
533 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | 592 | lcd_write_cmd_triplet |
534 | lcd_write_command (column_high); | 593 | ( |
535 | lcd_write_command (column_low); | 594 | (LCD_CNTL_PAGE | (y & 0xf)), |
595 | (column_high), | ||
596 | (column_low) | ||
597 | ); | ||
536 | 598 | ||
537 | lcd_write_data (FBADDR(x,y), width); | 599 | lcd_write_data (FBADDR(x,y), width); |
538 | } | 600 | } |