summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-05-05 23:23:50 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2014-05-11 19:56:43 +0200
commit85390865b572664d5bc4e289445b1875f58fcc4f (patch)
tree90af65cea89c41ff3a1b46bd2aab3a093886bee6
parent46cd8ea824bcb2dbc79b76964fd429262f50ddc9 (diff)
downloadrockbox-85390865b572664d5bc4e289445b1875f58fcc4f.tar.gz
rockbox-85390865b572664d5bc4e289445b1875f58fcc4f.zip
sansaview: fix lcd code
The lcd driver now works but is awfully slow. The trick is to put it in system mode instead of RGB and setup 16bpp. The GRAM data can then be sent directly with the SPI but since it's bit-banged and the CPU running at slow speed, full screen refresh takes over a second, even with a slightly optmised version. The OF uses a DMA mechanism with a proper LCD controller but the setup is much more complicated and doesn't work at the moment. Change-Id: I6c95d91de31bff97d0a5848b8e2078c21deb5895
-rw-r--r--firmware/export/pp6100.h2
-rw-r--r--firmware/target/arm/sandisk/sansa-view/lcd-view.c309
2 files changed, 105 insertions, 206 deletions
diff --git a/firmware/export/pp6100.h b/firmware/export/pp6100.h
index cbfb7c5028..68d8af83f7 100644
--- a/firmware/export/pp6100.h
+++ b/firmware/export/pp6100.h
@@ -104,4 +104,6 @@
104#define GPIOS 18 104#define GPIOS 18
105#define GPIOT 19 105#define GPIOT 19
106 106
107#define DEV_INIT3 (*(volatile unsigned long *)(0x70000014))
108
107#endif 109#endif
diff --git a/firmware/target/arm/sandisk/sansa-view/lcd-view.c b/firmware/target/arm/sandisk/sansa-view/lcd-view.c
index 9f02d1e2bf..6b24aadc8c 100644
--- a/firmware/target/arm/sandisk/sansa-view/lcd-view.c
+++ b/firmware/target/arm/sandisk/sansa-view/lcd-view.c
@@ -27,12 +27,7 @@
27#include "backlight-target.h" 27#include "backlight-target.h"
28#include "lcd.h" 28#include "lcd.h"
29 29
30#include "bitmaps/rockboxlogo.h" 30static bool display_on SHAREDBSS_ATTR = true;
31
32/* Power and display status */
33static bool power_on = false; /* Is the power turned on? */
34static bool display_on SHAREDBSS_ATTR = false; /* Is the display turned on? */
35static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
36static int lcd_type; 31static int lcd_type;
37 32
38#define LCD_DATA_OUT_GPIO GPIOH_OUTPUT_VAL 33#define LCD_DATA_OUT_GPIO GPIOH_OUTPUT_VAL
@@ -44,147 +39,109 @@ static int lcd_type;
44#define LCD_CS_GPIO GPIOH_OUTPUT_VAL 39#define LCD_CS_GPIO GPIOH_OUTPUT_VAL
45#define LCD_CS_PIN 7 40#define LCD_CS_PIN 7
46 41
47#ifdef BOOTLOADER
48static void lcd_init_gpio(void)
49{
50 /* BOOT: 0x5CC8
51 OF: 0x88284 */
52 42
53 outl(inl(0x70000010) | 0xFC000000, 0x70000010);
54 outl(inl(0x70000014) | 0xC300000, 0x70000014);
55 43
56 GPIOE_ENABLE = 0; 44static void lcd_init_gpio(void)
57 GPIOM_ENABLE &= ~0x3; 45{
58 GPIOF_ENABLE = 0; 46 DEV_INIT1 |= 0xfc000000;
59 GPIOJ_ENABLE &= ~0x1a; 47 DEV_INIT3 |= 0xc300000;
60 GPIOB_ENABLE &= ~0x8; 48
49 GPIOE_ENABLE = 0;
50 GPIOM_ENABLE &= ~0x3;
51 GPIOF_ENABLE = 0;
52 GPIOJ_ENABLE &= ~0x1a;
53 // reset low
54 GPIOB_ENABLE &= ~0x8;
55 // SPI chip select
61 GPIOH_OUTPUT_VAL |= 0x80; 56 GPIOH_OUTPUT_VAL |= 0x80;
62 GPIOH_OUTPUT_EN |= 0x80; 57 GPIOH_OUTPUT_EN |= 0x80;
63 GPIOH_ENABLE |= 0x80; 58 GPIOH_ENABLE |= 0x80;
59 // SPI clock
64 GPIOH_OUTPUT_VAL |= 0x40; 60 GPIOH_OUTPUT_VAL |= 0x40;
65 GPIOH_OUTPUT_EN |= 0x40; 61 GPIOH_OUTPUT_EN |= 0x40;
66 GPIOH_ENABLE |= 0x40; 62 GPIOH_ENABLE |= 0x40;
63 // unk
67 GPIOH_OUTPUT_VAL |= 0x20; 64 GPIOH_OUTPUT_VAL |= 0x20;
68 GPIOH_OUTPUT_EN |= 0x20; 65 GPIOH_OUTPUT_EN |= 0x20;
69 GPIOH_ENABLE |= 0x20; 66 GPIOH_ENABLE |= 0x20;
67 // SPI data
70 GPIOH_OUTPUT_VAL |= 0x10; 68 GPIOH_OUTPUT_VAL |= 0x10;
71 GPIOH_OUTPUT_EN |= 0x10; 69 GPIOH_OUTPUT_EN |= 0x10;
72 GPIOH_ENABLE |= 0x10; 70 GPIOH_ENABLE |= 0x10;
73 GPIOD_OUTPUT_VAL |= 0x1; /* backlight on */ 71 // LCD reset
74 GPIOD_ENABLE |= 0x1;
75 GPIOB_OUTPUT_VAL |= 0x4; 72 GPIOB_OUTPUT_VAL |= 0x4;
76 GPIOB_ENABLE |= 0x4; 73 GPIOB_ENABLE |= 0x4;
77 GPIOB_OUTPUT_EN |= 0x4; 74 GPIOB_OUTPUT_EN |= 0x4;
78 DEV_INIT2 = 0x40000000; 75 DEV_INIT2 = 0x40000000;
79 GPIOG_ENABLE |= 0x8; 76 // LCD type
80 GPIOG_OUTPUT_EN &= ~0x8; 77 GPIOG_ENABLE |= 0x8;
81 78 GPIOG_OUTPUT_EN &= ~0x8;
82 if (GPIOG_INPUT_VAL & 0x8) 79
83 lcd_type = 1; 80 if(GPIOG_INPUT_VAL & 0x8)
84 else
85 lcd_type = 0; 81 lcd_type = 0;
82 else
83 lcd_type = 1;
86} 84}
87#endif
88 85
89static void lcd_send_msg(unsigned char count, unsigned int data) 86static void lcd_send_msg(unsigned char count, unsigned int data)
90{ 87{
91 /* BOOT: 0x645C 88 GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
92 OF: 0x88E90 */ 89 GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
93 int i;
94
95 LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN);
96 LCD_CS_GPIO &= ~(1 << LCD_CS_PIN);
97 90
98 for (i = count - 1; i >= 0; i--) 91 for(int i = count - 1; i >= 0; i--)
99 { 92 {
100 if (data & (1 << i)) 93 if(data & (1 << i))
101 { 94 GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
102 LCD_DATA_OUT_GPIO &= ~(1 << LCD_DATA_OUT_PIN); 95 else
103 } else { 96 GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
104 LCD_DATA_OUT_GPIO |= (1 << LCD_DATA_OUT_PIN); 97 GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
105 }
106 LCD_CLOCK_GPIO &= ~(1 << LCD_CLOCK_PIN);
107 udelay(1); 98 udelay(1);
108 LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN); 99 GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
109 udelay(2); 100 udelay(2);
110 } 101 }
111 102
112 LCD_CS_GPIO |= (1 << LCD_CS_PIN); 103 GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
113 LCD_CLOCK_GPIO |= (1 << LCD_CLOCK_PIN);
114 udelay(1);
115}
116
117/*
118static void lcd_write_reg(unsigned int reg, unsigned int data)
119{
120// OF: 0x6278 - referenced from 0x62840
121
122// So far this function is always called with shift = 0x0 ?
123// If so can remove and simplify
124
125 unsigned int cmd;
126 unsigned int shift = 0;
127
128 cmd = shift << 0x2;
129 cmd |= 0x70;
130 cmd = cmd << 0x10;
131 cmd |= reg;
132 lcd_send_msg(0x18, cmd);
133
134 cmd = shift << 0x2;
135 cmd |= 0x72;
136 cmd = cmd << 0x10;
137 cmd |= data;
138 lcd_send_msg(0x18, cmd);
139
140// lcd_send_msg(0x70, reg);
141// lcd_send_msg(0x72, data);
142} 104}
143*/
144 105
145static void lcd_write_cmd(unsigned int cmd) 106static void lcd_send_cmd(unsigned int cmd)
146{ 107{
147 lcd_send_msg(0x18, (0x700000 | cmd)); 108 lcd_send_msg(24, (0x700000 | cmd));
148} 109}
149 110
150static void lcd_write_info(unsigned int data) 111static void lcd_send_data(unsigned int data)
151{ 112{
152 lcd_send_msg(0x18, (0x720000 | data)); 113 lcd_send_msg(24, (0x720000 | data));
153} 114}
154 115
155static void lcd_write_reg(unsigned int cmd, unsigned int data) 116static void lcd_write_reg(unsigned int cmd, unsigned int data)
156{ 117{
157 lcd_write_cmd(cmd); 118 lcd_send_cmd(cmd);
158 lcd_write_info(data); 119 lcd_send_data(data);
159} 120}
160 121
161void lcd_reset(void) 122void lcd_reset(void)
162{ 123{
163 /* BOOT: 0x623C 124 GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
164 OF: 0x88BDC */
165
166 GPIOB_OUTPUT_VAL |= 0x4;
167 udelay(1000); 125 udelay(1000);
168 GPIOB_OUTPUT_VAL &= ~0x4; 126 GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
169 udelay(10000); 127 udelay(10000);
170 GPIOB_OUTPUT_VAL |= 0x4; 128 GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4);
171 udelay(50000); 129 udelay(50000);
172} 130}
173 131
174/* Run the powerup sequence for the driver IC */ 132/* Run the powerup sequence for the driver IC */
175static void lcd_power_on(void) 133static void lcd_power_on(void)
176{ 134{
135 lcd_init_gpio();
177 lcd_reset(); 136 lcd_reset();
178 /* OF: 0x5DC0 * 137
179 * r2: cmd *
180 * r3: data */
181 lcd_write_reg(0xE5, 0x8000); 138 lcd_write_reg(0xE5, 0x8000);
182 lcd_write_reg(0x0, 0x1); 139 lcd_write_reg(0x0, 0x1);
183 lcd_write_reg(0x1, 0x100); 140 lcd_write_reg(0x1, 0x100);
184 lcd_write_reg(0x2, 0x700); 141 lcd_write_reg(0x2, 0x700);
185 lcd_write_reg(0x3, 0x1230); 142 lcd_write_reg(0x3, 0x5230);
186 lcd_write_reg(0x4, 0x0); 143 lcd_write_reg(0x4, 0x0);
187 lcd_write_reg(0x8, 0x408); 144 lcd_write_reg(0x8, 0x408); /* back porch = 8, front porch = 4 */
188 lcd_write_reg(0x9, 0x0); 145 lcd_write_reg(0x9, 0x0);
189 lcd_write_reg(0xa, 0x0); 146 lcd_write_reg(0xa, 0x0);
190 lcd_write_reg(0xd, 0x0); 147 lcd_write_reg(0xd, 0x0);
@@ -200,8 +157,6 @@ static void lcd_power_on(void)
200 lcd_write_reg(0x12, 0x13c); 157 lcd_write_reg(0x12, 0x13c);
201 sleep(HZ/20); 158 sleep(HZ/20);
202 159
203 /* BOOT: BNE 0x5fb2 */
204
205 if (lcd_type == 0) 160 if (lcd_type == 0)
206 { 161 {
207 lcd_write_reg(0x13, 0x1700); 162 lcd_write_reg(0x13, 0x1700);
@@ -234,19 +189,17 @@ static void lcd_power_on(void)
234 lcd_write_reg(0x36, 0x504); 189 lcd_write_reg(0x36, 0x504);
235 lcd_write_reg(0x37, 0x707); 190 lcd_write_reg(0x37, 0x707);
236 lcd_write_reg(0x38, 0x306); 191 lcd_write_reg(0x38, 0x306);
237 lcd_write_reg(0x39, 0x9); 192 lcd_write_reg(0x39, 0x7);
238 } 193 }
239 194
240 /* BOOT: 0x6066 */
241 lcd_write_reg(0x3c, 0x700); 195 lcd_write_reg(0x3c, 0x700);
242 lcd_write_reg(0x3d, 0x700); 196 lcd_write_reg(0x3d, 0x700);
243 197
244 lcd_write_reg(0x50, 0x0); 198 lcd_write_reg(0x50, 0x0);
245 lcd_write_reg(0x51, 0xef); /* 239 - LCD_WIDTH */ 199 lcd_write_reg(0x51, 0xef);
246 lcd_write_reg(0x52, 0x0); 200 lcd_write_reg(0x52, 0x0);
247 lcd_write_reg(0x53, 0x13f); /* 319 - LCD_HEIGHT */ 201 lcd_write_reg(0x53, 0x13f);
248 202
249 /* BOOT: b 0x6114 */
250 lcd_write_reg(0x60, 0x2700); 203 lcd_write_reg(0x60, 0x2700);
251 lcd_write_reg(0x61, 0x1); 204 lcd_write_reg(0x61, 0x1);
252 lcd_write_reg(0x6a, 0x0); 205 lcd_write_reg(0x6a, 0x0);
@@ -258,7 +211,6 @@ static void lcd_power_on(void)
258 lcd_write_reg(0x84, 0x0); 211 lcd_write_reg(0x84, 0x0);
259 lcd_write_reg(0x85, 0x0); 212 lcd_write_reg(0x85, 0x0);
260 213
261 /* BOOT: 0x61A8 */
262 lcd_write_reg(0x90, 0x10); 214 lcd_write_reg(0x90, 0x10);
263 lcd_write_reg(0x92, 0x0); 215 lcd_write_reg(0x92, 0x0);
264 lcd_write_reg(0x93, 0x3); 216 lcd_write_reg(0x93, 0x3);
@@ -266,28 +218,14 @@ static void lcd_power_on(void)
266 lcd_write_reg(0x97, 0x0); 218 lcd_write_reg(0x97, 0x0);
267 lcd_write_reg(0x98, 0x0); 219 lcd_write_reg(0x98, 0x0);
268 220
269 lcd_write_reg(0xc, 0x110); 221 lcd_write_reg(0xc, 0x000); // SYSTEM mode
270 lcd_write_reg(0x7, 0x173); 222 lcd_write_reg(0x7, 0x173);
271 sleep(HZ/10); 223 sleep(HZ/10);
272
273 power_on = true;
274} 224}
275 225
276/* unknown 01 and 02 - sleep or enable on and off funcs? */
277void unknown01(void)
278{ 226{
279 /* BOOT: 0x62C4
280 OF: 0x88CA0 */
281 227
282 lcd_write_reg(0x10, 0x17B0); 228 lcd_power_on();
283 udelay(100);
284 lcd_write_reg(0x7, 0x173);
285}
286
287void unknown02(void)
288{
289 /* BOOT: 0x6308
290 OF: 0x88D0C */
291 229
292 lcd_write_reg(0x7, 0x160); 230 lcd_write_reg(0x7, 0x160);
293 lcd_write_reg(0x10, 0x17B1); 231 lcd_write_reg(0x10, 0x17B1);
@@ -295,9 +233,6 @@ void unknown02(void)
295 233
296void unknown03(bool r0) 234void unknown03(bool r0)
297{ 235{
298 /* BOOT: 0x6410
299 OF: 0x88E30 */
300
301 if (r0) 236 if (r0)
302 GPIOJ_ENABLE &= ~0x2; 237 GPIOJ_ENABLE &= ~0x2;
303 else 238 else
@@ -308,76 +243,71 @@ void unknown03(bool r0)
308 } 243 }
309} 244}
310 245
311/* Run the display on sequence for the driver IC */ 246void lcd_init_device(void)
312static void lcd_display_on(void)
313{ 247{
314 display_on = true; 248 lcd_power_on();
315} 249}
316 250
317 251#if defined(HAVE_LCD_ENABLE)
318#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
319bool lcd_active(void) 252bool lcd_active(void)
320{ 253{
321 return display_on; 254 return display_on;
322} 255}
323 256
324/* Turn off visible display operations */ 257void lcd_enable(bool on)
325static void lcd_display_off(void)
326{ 258{
327 display_on = false; 259 display_on = on;
260 if(on)
261 {
262 lcd_write_reg(0x10, 0x17B0);
263 udelay(100);
264 lcd_write_reg(0x7, 0x173);
265 }
266 else
267 {
268 lcd_write_reg(0x7, 0x160);
269 lcd_write_reg(0x10, 0x17B1);
270 }
328} 271}
329#endif 272#endif
330 273
331void lcd_init_device(void) 274static inline void lcd_send_frame_byte(unsigned char data)
332{ 275{
333 276 for(int bit = 0; bit < 8; bit++)
334#ifdef BOOTLOADER /* Bother at all to do this again? */ 277 {
335/* Init GPIO ports */ 278 if(data & 0x80)
336 lcd_init_gpio(); 279 GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
337 lcd_power_on(); 280 else
338 lcd_display_on(); 281 GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN);
339#else 282 data <<= 1;
340 283 GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
341 power_on = true; 284 GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
342 display_on = true; 285 }
343
344 lcd_set_invert_display(false);
345 lcd_set_flip(false);
346#endif
347} 286}
348 287
349#if defined(HAVE_LCD_ENABLE) 288static void lcd_send_frame(const fb_data *addr, int count)
350void lcd_enable(bool on)
351{ 289{
352 (void)on; 290 GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN);
353} 291 GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
354#endif
355 292
356#if defined(HAVE_LCD_SLEEP) 293 lcd_send_frame_byte(0x72);
357void lcd_sleep(void) 294 while(count-- > 0)
358{ 295 {
296 lcd_send_frame_byte(*addr >> 8);
297 lcd_send_frame_byte(*addr++ & 0xff);
298 }
359 299
300 GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN);
360} 301}
361#endif
362 302
363void lcd_update(void) 303void lcd_update(void)
364{ 304{
365 const fb_data *addr; 305 if(!display_on)
366 306 return;
367 addr = FBADDR(LCD_WIDTH,LCD_HEIGHT);
368
369 lcd_write_reg(0x20, 0x0); 307 lcd_write_reg(0x20, 0x0);
370 lcd_write_reg(0x21, 0x0); 308 lcd_write_reg(0x21, 0x0);
371 309 lcd_send_cmd(0x22);
372 int i,j; 310 lcd_send_frame(FBADDR(0, 0), LCD_WIDTH * LCD_HEIGHT);
373 for(i=0; i < LCD_HEIGHT; i++)
374 {
375 for(j=0; j < LCD_WIDTH; j++)
376 {
377 lcd_write_reg(0x22, *addr);
378 addr++;
379 }
380 }
381} 311}
382 312
383/* Update a fraction of the display. */ 313/* Update a fraction of the display. */
@@ -408,36 +338,3 @@ void lcd_set_flip(bool yesno)
408{ 338{
409 (void)yesno; 339 (void)yesno;
410} 340}
411
412/* Blitting functions */
413
414void lcd_yuv_set_options(unsigned options)
415{
416 lcd_yuv_options = options;
417}
418
419/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
420extern void lcd_write_yuv420_lines(fb_data *dst,
421 unsigned char const * const src[3],
422 int width,
423 int stride);
424extern void lcd_write_yuv420_lines_odither(fb_data *dst,
425 unsigned char const * const src[3],
426 int width,
427 int stride,
428 int x_screen, /* To align dither pattern */
429 int y_screen);
430
431void lcd_blit_yuv(unsigned char * const src[3],
432 int src_x, int src_y, int stride,
433 int x, int y, int width, int height)
434{
435 (void)src;
436 (void)src_x;
437 (void)src_y;
438 (void)stride;
439 (void)x;
440 (void)y;
441 (void)width;
442 (void)height;
443}