diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c index f21670192c..fc0fdaae10 100644 --- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | |||
@@ -44,7 +44,7 @@ static bool display_on = false; /* is the display turned on? */ | |||
44 | static bool display_flipped = false; | 44 | static bool display_flipped = false; |
45 | static int xoffset = 20; /* needed for flip */ | 45 | static int xoffset = 20; /* needed for flip */ |
46 | /* we need to write a red pixel for correct button reads | 46 | /* we need to write a red pixel for correct button reads |
47 | * (see lcd_button_support()), but that must not happen while the lcd is updating | 47 | * (see lcd_button_support()),but that must not happen while the lcd is updating |
48 | * so block lcd_button_support the during updates */ | 48 | * so block lcd_button_support the during updates */ |
49 | static bool lcd_busy = false; | 49 | static bool lcd_busy = false; |
50 | 50 | ||
@@ -54,29 +54,35 @@ static void as3525_dbop_init(void) | |||
54 | 54 | ||
55 | DBOP_TIMPOL_01 = 0xe167e167; | 55 | DBOP_TIMPOL_01 = 0xe167e167; |
56 | DBOP_TIMPOL_23 = 0xe167006e; | 56 | DBOP_TIMPOL_23 = 0xe167006e; |
57 | DBOP_CTRL = 0x41008; | 57 | |
58 | /* short count: 16 | output data width: 16 | readstrobe line */ | ||
59 | DBOP_CTRL = (1<<18|1<<12|1<<3); | ||
58 | 60 | ||
59 | GPIOB_AFSEL = 0xfc; | 61 | GPIOB_AFSEL = 0xfc; |
60 | GPIOC_AFSEL = 0xff; | 62 | GPIOC_AFSEL = 0xff; |
61 | 63 | ||
62 | DBOP_TIMPOL_23 = 0x6000e; | 64 | DBOP_TIMPOL_23 = 0x6000e; |
63 | DBOP_CTRL = 0x51008; | 65 | /* short count: 16|enable write|output data width: 16|read strobe line */ |
66 | DBOP_CTRL = (1<<18|1<<16|1<<12|1<<3); | ||
64 | DBOP_TIMPOL_01 = 0x6e167; | 67 | DBOP_TIMPOL_01 = 0x6e167; |
65 | DBOP_TIMPOL_23 = 0xa167e06f; | 68 | DBOP_TIMPOL_23 = 0xa167e06f; |
66 | 69 | ||
67 | /* TODO: The OF calls some other functions here, but maybe not important */ | 70 | /* TODO: The OF calls some other functions here, but maybe not important */ |
68 | } | 71 | } |
69 | 72 | ||
73 | #define lcd_write_single_data16(value) do {\ | ||
74 | DBOP_CTRL &= ~(1<<14|1<<13); \ | ||
75 | DBOP_DOUT16 = (fb_data)(value); \ | ||
76 | } while(0) | ||
77 | |||
78 | |||
70 | static void lcd_write_cmd(int cmd) | 79 | static void lcd_write_cmd(int cmd) |
71 | { | 80 | { |
72 | int x; | 81 | int x; |
73 | 82 | ||
74 | /* Write register */ | 83 | /* Write register */ |
75 | DBOP_CTRL &= ~(1<<14); | ||
76 | |||
77 | DBOP_TIMPOL_23 = 0xa167006e; | 84 | DBOP_TIMPOL_23 = 0xa167006e; |
78 | 85 | lcd_write_single_data16(cmd); | |
79 | DBOP_DOUT = cmd; | ||
80 | 86 | ||
81 | /* Wait for fifo to empty */ | 87 | /* Wait for fifo to empty */ |
82 | while ((DBOP_STAT & (1<<10)) == 0); | 88 | while ((DBOP_STAT & (1<<10)) == 0); |
@@ -93,13 +99,33 @@ static void lcd_write_cmd(int cmd) | |||
93 | 99 | ||
94 | void lcd_write_data(const fb_data* p_bytes, int count) | 100 | void lcd_write_data(const fb_data* p_bytes, int count) |
95 | { | 101 | { |
96 | while (count--) | 102 | const long *data; |
103 | if ((int)p_bytes & 0x3) | ||
104 | { /* need to do a single 16bit write beforehand if the address is | ||
105 | * not word aligned*/ | ||
106 | lcd_write_single_data16(*p_bytes); | ||
107 | count--;p_bytes++; | ||
108 | } | ||
109 | /* from here, 32bit transfers are save */ | ||
110 | /* set it to transfer 4*(outputwidth) units at a time, | ||
111 | * if bit 12 is set it only does 2 halfwords though */ | ||
112 | DBOP_CTRL |= (1<<13|1<<14); | ||
113 | data = (long*)p_bytes; | ||
114 | while (count > 1) | ||
97 | { | 115 | { |
98 | DBOP_DOUT = *p_bytes++; | 116 | DBOP_DOUT32 = *data++; |
117 | count -= 2; | ||
99 | 118 | ||
100 | /* Wait for fifo to empty */ | 119 | /* Wait for fifo to empty */ |
120 | /* TODO: We should normally fill the fifo until it's full | ||
121 | * instead of waiting after each word, | ||
122 | * but that causes blue lines on the display */ | ||
101 | while ((DBOP_STAT & (1<<10)) == 0); | 123 | while ((DBOP_STAT & (1<<10)) == 0); |
102 | } | 124 | } |
125 | /* due to the 32bit alignment requirement, we possibly need to do a | ||
126 | * 16bit transfer at the end also */ | ||
127 | if (count > 0) | ||
128 | lcd_write_single_data16(*(fb_data*)data); | ||
103 | } | 129 | } |
104 | 130 | ||
105 | static void lcd_write_reg(int reg, int value) | 131 | static void lcd_write_reg(int reg, int value) |
@@ -107,7 +133,7 @@ static void lcd_write_reg(int reg, int value) | |||
107 | unsigned short data = value; | 133 | unsigned short data = value; |
108 | 134 | ||
109 | lcd_write_cmd(reg); | 135 | lcd_write_cmd(reg); |
110 | lcd_write_data(&data, 1); | 136 | lcd_write_single_data16(data); |
111 | } | 137 | } |
112 | 138 | ||
113 | /* turn the display upside down (call lcd_update() afterwards) */ | 139 | /* turn the display upside down (call lcd_update() afterwards) */ |
@@ -239,8 +265,8 @@ extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | |||
239 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | 265 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], |
240 | int width, | 266 | int width, |
241 | int stride, | 267 | int stride, |
242 | int x_screen, /* To align dither pattern */ | 268 | int x_screen, /* To align dither */ |
243 | int y_screen); | 269 | int y_screen); /* pattern */ |
244 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 270 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
245 | void lcd_blit_yuv(unsigned char * const src[3], | 271 | void lcd_blit_yuv(unsigned char * const src[3], |
246 | int src_x, int src_y, int stride, | 272 | int src_x, int src_y, int stride, |
@@ -319,7 +345,6 @@ void lcd_update(void) | |||
319 | { | 345 | { |
320 | if (!display_on) | 346 | if (!display_on) |
321 | return; | 347 | return; |
322 | |||
323 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); | 348 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); |
324 | 349 | ||
325 | lcd_busy = true; | 350 | lcd_busy = true; |
@@ -338,11 +363,12 @@ void lcd_update(void) | |||
338 | void lcd_update_rect(int x, int y, int width, int height) | 363 | void lcd_update_rect(int x, int y, int width, int height) |
339 | { | 364 | { |
340 | int xmax, ymax; | 365 | int xmax, ymax; |
341 | const unsigned short *ptr; | 366 | const fb_data *ptr; |
342 | 367 | ||
343 | if (!display_on) | 368 | if (!display_on) |
344 | return; | 369 | return; |
345 | 370 | ||
371 | |||
346 | xmax = x + width; | 372 | xmax = x + width; |
347 | if (xmax >= LCD_WIDTH) | 373 | if (xmax >= LCD_WIDTH) |
348 | xmax = LCD_WIDTH - 1; /* Clip right */ | 374 | xmax = LCD_WIDTH - 1; /* Clip right */ |
@@ -370,7 +396,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
370 | /* Start write to GRAM */ | 396 | /* Start write to GRAM */ |
371 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 397 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
372 | 398 | ||
373 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; | 399 | ptr = &lcd_framebuffer[y][x]; |
374 | 400 | ||
375 | do | 401 | do |
376 | { | 402 | { |
@@ -394,7 +420,7 @@ bool lcd_button_support(void) | |||
394 | lcd_window_y(-1, 0); | 420 | lcd_window_y(-1, 0); |
395 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 421 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
396 | 422 | ||
397 | lcd_write_data(&data, 1); | 423 | lcd_write_single_data16(data); |
398 | 424 | ||
399 | return true; | 425 | return true; |
400 | } | 426 | } |