diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/as3525/lcd-clip.h | 10 | ||||
-rw-r--r-- | firmware/target/arm/as3525/lcd-ssd1303.c | 211 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clip/lcd-clip.c | 28 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c | 32 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-clipv2/lcd-clipv2.c | 29 |
5 files changed, 228 insertions, 82 deletions
diff --git a/firmware/target/arm/as3525/lcd-clip.h b/firmware/target/arm/as3525/lcd-clip.h index eb76401bc0..3bde92430c 100644 --- a/firmware/target/arm/as3525/lcd-clip.h +++ b/firmware/target/arm/as3525/lcd-clip.h | |||
@@ -18,12 +18,22 @@ | |||
18 | * KIND, either express or implied. | 18 | * KIND, either express or implied. |
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #ifndef __LCDCLIP_H__ | ||
22 | #define __LCDCLIP_H__ | ||
21 | 23 | ||
22 | #include "config.h" | 24 | #include "config.h" |
23 | 25 | ||
26 | #if !defined(BOOTLOADER) && defined(SANSA_CLIPPLUS) /* only tested for clipplus */ | ||
27 | /* Ensure empty FIFO for lcd commands is at least 3 deep */ | ||
28 | #define LCD_USE_FIFO_FOR_COMMANDS | ||
29 | #endif | ||
30 | |||
31 | void lcd_write_cmd_triplet(int cmd1, int cmd2, int cmd3); | ||
32 | |||
24 | /* return variant number: 0 = clipv1, clipv2, old clip+, 1 = newer clip+ */ | 33 | /* return variant number: 0 = clipv1, clipv2, old clip+, 1 = newer clip+ */ |
25 | int lcd_hw_init(void) INIT_ATTR; | 34 | int lcd_hw_init(void) INIT_ATTR; |
26 | 35 | ||
27 | /* target-specific power enable */ | 36 | /* target-specific power enable */ |
28 | void lcd_enable_power(bool onoff); | 37 | void lcd_enable_power(bool onoff); |
29 | 38 | ||
39 | #endif /*__LCDCLIP_H__*/ | ||
diff --git a/firmware/target/arm/as3525/lcd-ssd1303.c b/firmware/target/arm/as3525/lcd-ssd1303.c index a00398a998..2aa0b844c5 100644 --- a/firmware/target/arm/as3525/lcd-ssd1303.c +++ b/firmware/target/arm/as3525/lcd-ssd1303.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * Copyright (C) 2002 by Alan Korr | 10 | * Copyright (C) 2002 by Alan Korr |
11 | * Copyright (C) 2008 François Dinel | 11 | * Copyright (C) 2008 François Dinel |
12 | * Copyright (C) 2008-2009 Rafaël Carré | 12 | * Copyright (C) 2008-2009 Rafaël Carré |
13 | * Copyright (C) 2017 William Wilgus | ||
13 | * | 14 | * |
14 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License | 16 | * modify it under the terms of the GNU General Public License |
@@ -118,10 +119,10 @@ void lcd_set_flip(bool yesno) | |||
118 | #ifdef HAVE_LCD_ENABLE | 119 | #ifdef HAVE_LCD_ENABLE |
119 | void lcd_enable(bool enable) | 120 | void lcd_enable(bool enable) |
120 | { | 121 | { |
121 | if(display_on == enable) | 122 | if (display_on == enable) |
122 | return; | 123 | return; |
123 | 124 | ||
124 | if( (display_on = enable) ) /* simple '=' is not a typo ! */ | 125 | if ( (display_on = enable) ) /* simple '=' is not a typo ! */ |
125 | { | 126 | { |
126 | lcd_enable_power(enable); | 127 | lcd_enable_power(enable); |
127 | lcd_write_command(LCD_SET_DISPLAY_ON); | 128 | lcd_write_command(LCD_SET_DISPLAY_ON); |
@@ -149,50 +150,65 @@ void lcd_init_device(void) | |||
149 | variant = lcd_hw_init(); | 150 | variant = lcd_hw_init(); |
150 | offset = (variant == 0) ? 2 : 0; | 151 | offset = (variant == 0) ? 2 : 0; |
151 | 152 | ||
152 | /* Set display clock (divide ratio = 1) and oscillator frequency (1) */ | 153 | /* power on display to accept commands */ |
153 | lcd_write_command(LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ); | 154 | lcd_enable_power(true); |
154 | lcd_write_command(0x10); | 155 | |
155 | 156 | lcd_write_cmd_triplet | |
156 | /* Set VCOM deselect level to 0.76V */ | 157 | ( |
157 | lcd_write_command(LCD_SET_VCOM_DESELECT_LEVEL); | 158 | /* Set display clock */ |
158 | lcd_write_command(0x34); | 159 | (LCD_SET_DISPLAY_CLOCK_AND_OSC_FREQ), |
159 | 160 | /* Set display clock (divide ratio = 1) and oscillator frequency (1) */ | |
160 | /* Set pre-charge period (p1period is 2 dclk and p2period is 5 dclk) */ | 161 | (0x10), |
161 | lcd_write_command(LCD_SET_PRECHARGE_PERIOD); | 162 | /* Set VCOM deselect level */ |
162 | lcd_write_command(0x25); | 163 | (LCD_SET_VCOM_DESELECT_LEVEL) |
164 | ); | ||
165 | |||
166 | lcd_write_cmd_triplet | ||
167 | ( | ||
168 | /* Set VCOM deselect level to 0.76V */ | ||
169 | (0x34), | ||
170 | /* Set pre-charge period */ | ||
171 | (LCD_SET_PRECHARGE_PERIOD), | ||
172 | /* Set pre-charge period (p1period is 2 dclk and p2period is 5 dclk) */ | ||
173 | (0x25) | ||
174 | ); | ||
163 | 175 | ||
164 | /* Set contrast register to 12% */ | 176 | /* Set contrast register to 12% */ |
165 | lcd_set_contrast(lcd_default_contrast()); | 177 | lcd_set_contrast(lcd_default_contrast()); |
166 | 178 | ||
167 | /* Configure DC-DC */ | 179 | lcd_write_cmd_triplet |
168 | lcd_write_command(LCD_SET_DC_DC); | 180 | ( |
169 | lcd_write_command((variant == 0) ? 0x8A : 0x10); | 181 | /* Configure DC-DC */ |
170 | 182 | (LCD_SET_DC_DC), | |
171 | /* Set starting line as 0 */ | 183 | /* Configure DC-DC */ |
172 | lcd_write_command(LCD_SET_DISPLAY_START_LINE /*|(0 & 0x3f)*/); | 184 | ((variant == 0) ? 0x8A : 0x10), |
173 | 185 | /* Set starting line as 0 */ | |
174 | /* Column 131 is remapped to SEG0 */ | 186 | (LCD_SET_DISPLAY_START_LINE /*|(0 & 0x3f)*/) |
175 | lcd_write_command(LCD_SET_SEGMENT_REMAP_INV); | 187 | ); |
176 | 188 | ||
177 | /* Invert COM scan direction (N-1 to 0) */ | 189 | lcd_write_cmd_triplet |
178 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION_INV); | 190 | ( |
179 | 191 | /* Column 131 is remapped to SEG0 */ | |
180 | /* Set normal display mode (not every pixel ON) */ | 192 | (LCD_SET_SEGMENT_REMAP_INV), |
181 | lcd_write_command(LCD_SET_ENTIRE_DISPLAY_OFF); | 193 | /* Invert COM scan direction (N-1 to 0) */ |
182 | 194 | (LCD_SET_COM_OUTPUT_SCAN_DIRECTION_INV), | |
183 | /* Set normal display mode (not inverted) */ | 195 | /* Set normal display mode (not every pixel ON) */ |
184 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); | 196 | (LCD_SET_ENTIRE_DISPLAY_OFF) |
185 | 197 | ); | |
186 | /* Clear whole framebuffer, including "overscan" | 198 | |
187 | * We don't need to handle that out of screen columns in lcd_clear_display() | 199 | lcd_write_cmd_triplet |
188 | * since we will never write into it anymore | 200 | ( |
189 | */ | 201 | /* Set normal display mode (not inverted) */ |
190 | lcd_write_command (LCD_SET_HIGHER_COLUMN_ADDRESS /*| 0*/); | 202 | (LCD_SET_NORMAL_DISPLAY), |
191 | lcd_write_command (LCD_SET_LOWER_COLUMN_ADDRESS /*| 0*/); | 203 | /* set upper 4 bits of 8-bit column address */ |
204 | (LCD_SET_HIGHER_COLUMN_ADDRESS /*| 0*/), | ||
205 | /* set lower 4 bits of 8-bit column address */ | ||
206 | (LCD_SET_LOWER_COLUMN_ADDRESS /*| 0*/) | ||
207 | ); | ||
192 | 208 | ||
193 | fb_data p_bytes[LCD_WIDTH + 2 * offset]; | 209 | fb_data p_bytes[LCD_WIDTH + 2 * offset]; |
194 | memset(p_bytes, 0, sizeof(p_bytes)); /* fills with 0 : pixel off */ | 210 | memset(p_bytes, 0, sizeof(p_bytes)); /* fills with 0 : pixel off */ |
195 | for(i = 0; i < 8; i++) | 211 | for (i = 0; i < 8; i++) |
196 | { | 212 | { |
197 | lcd_write_command (LCD_SET_PAGE_ADDRESS | (i /*& 0xf*/)); | 213 | lcd_write_command (LCD_SET_PAGE_ADDRESS | (i /*& 0xf*/)); |
198 | lcd_write_data(p_bytes, LCD_WIDTH + 2 * offset); | 214 | lcd_write_data(p_bytes, LCD_WIDTH + 2 * offset); |
@@ -205,27 +221,48 @@ void lcd_init_device(void) | |||
205 | 221 | ||
206 | /*** Update functions ***/ | 222 | /*** Update functions ***/ |
207 | 223 | ||
224 | /* returns LCD_CNTL_HIGHCOL or'd with higher 4 bits of | ||
225 | the 8-bit column address for the display data RAM. | ||
226 | */ | ||
227 | static inline int get_column_high_byte(const int x) | ||
228 | { | ||
229 | return (LCD_CNTL_HIGHCOL | (((x+offset) >> 4) & 0xf)); | ||
230 | } | ||
231 | |||
232 | /* returns LCD_CNTL_LOWCOL or'd with lower 4 bits of | ||
233 | the 8-bit column address for the display data RAM. | ||
234 | */ | ||
235 | static inline int get_column_low_byte(const int x) | ||
236 | { | ||
237 | return (LCD_CNTL_LOWCOL | ((x+offset) & 0xf)); | ||
238 | } | ||
239 | |||
208 | /* Performance function that works with an external buffer | 240 | /* Performance function that works with an external buffer |
209 | note that by and bheight are in 8-pixel units! */ | 241 | note that by and bheight are in 8-pixel units! */ |
210 | void lcd_blit_mono(const unsigned char *data, int x, int by, int width, | 242 | void lcd_blit_mono(const unsigned char *data, int x, int by, int width, |
211 | int bheight, int stride) | 243 | int bheight, int stride) |
212 | { | 244 | { |
213 | if(!display_on) | 245 | if (!display_on) |
214 | return; | 246 | return; |
215 | 247 | ||
248 | const int column_high = get_column_high_byte(x); | ||
249 | const int column_low = get_column_low_byte(x); | ||
250 | |||
216 | /* Copy display bitmap to hardware */ | 251 | /* Copy display bitmap to hardware */ |
217 | while (bheight--) | 252 | while (bheight--) |
218 | { | 253 | { |
219 | lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); | 254 | lcd_write_cmd_triplet |
220 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x+offset)>>4) & 0xf)); | 255 | ( |
221 | lcd_write_command (LCD_CNTL_LOWCOL | ((x+offset) & 0xf)); | 256 | (LCD_CNTL_PAGE | (by++ & 0xf)), |
257 | (column_high), | ||
258 | (column_low) | ||
259 | ); | ||
222 | 260 | ||
223 | lcd_write_data(data, width); | 261 | lcd_write_data(data, width); |
224 | data += stride; | 262 | data += stride; |
225 | } | 263 | } |
226 | } | 264 | } |
227 | 265 | ||
228 | |||
229 | #ifndef BOOTLOADER | 266 | #ifndef BOOTLOADER |
230 | /* Helper function for lcd_grey_phase_blit(). */ | 267 | /* Helper function for lcd_grey_phase_blit(). */ |
231 | void lcd_grey_data(unsigned char *values, unsigned char *phases, int count); | 268 | void lcd_grey_data(unsigned char *values, unsigned char *phases, int count); |
@@ -235,16 +272,22 @@ void lcd_grey_data(unsigned char *values, unsigned char *phases, int count); | |||
235 | void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | 272 | void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, |
236 | int x, int by, int width, int bheight, int stride) | 273 | int x, int by, int width, int bheight, int stride) |
237 | { | 274 | { |
238 | if(!display_on) | 275 | if (!display_on) |
239 | return; | 276 | return; |
240 | 277 | ||
278 | const int column_high = get_column_high_byte(x); | ||
279 | const int column_low = get_column_low_byte(x); | ||
280 | |||
241 | stride <<= 3; /* 8 pixels per block */ | 281 | stride <<= 3; /* 8 pixels per block */ |
242 | /* Copy display bitmap to hardware */ | 282 | /* Copy display bitmap to hardware */ |
243 | while (bheight--) | 283 | while (bheight--) |
244 | { | 284 | { |
245 | lcd_write_command (LCD_CNTL_PAGE | (by++ & 0xf)); | 285 | lcd_write_cmd_triplet |
246 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x+offset)>>4) & 0xf)); | 286 | ( |
247 | lcd_write_command (LCD_CNTL_LOWCOL | ((x+offset) & 0xf)); | 287 | (LCD_CNTL_PAGE | (by++ & 0xf)), |
288 | (column_high), | ||
289 | (column_low) | ||
290 | ); | ||
248 | 291 | ||
249 | lcd_grey_data(values, phases, width); | 292 | lcd_grey_data(values, phases, width); |
250 | 293 | ||
@@ -255,26 +298,41 @@ void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | |||
255 | 298 | ||
256 | #endif | 299 | #endif |
257 | 300 | ||
301 | /* Shared internal function for lcd_update and lcd_update_rect | ||
302 | WARNING does NOT check bounds | ||
303 | */ | ||
304 | static void internal_update_rect(int, int, int, int) ICODE_ATTR; | ||
305 | static void internal_update_rect(int x, int y, int width, int height) | ||
306 | { | ||
307 | if (!display_on) | ||
308 | return; | ||
309 | |||
310 | const int column_high = get_column_high_byte(x); | ||
311 | const int column_low = get_column_low_byte(x); | ||
312 | |||
313 | /* Copy specified rectange bitmap to hardware */ | ||
314 | for (; y <= height; y++) | ||
315 | { | ||
316 | lcd_write_cmd_triplet | ||
317 | ( | ||
318 | (LCD_CNTL_PAGE | (y & 0xf)), | ||
319 | (column_high), | ||
320 | (column_low) | ||
321 | ); | ||
322 | |||
323 | lcd_write_data (FBADDR(x,y), width); | ||
324 | } | ||
325 | lcd_write_command (LCD_NOP); /* return to command mode */ | ||
326 | |||
327 | } | ||
258 | 328 | ||
259 | /* Update the display. | 329 | /* Update the display. |
260 | This must be called after all other LCD functions that change the display. */ | 330 | This must be called after all other LCD functions that change the display. */ |
261 | void lcd_update(void) ICODE_ATTR; | 331 | void lcd_update(void) ICODE_ATTR; |
262 | void lcd_update(void) | 332 | void lcd_update(void) |
263 | { | 333 | { |
264 | int y; | ||
265 | |||
266 | if(!display_on) | ||
267 | return; | ||
268 | |||
269 | /* Copy display bitmap to hardware */ | 334 | /* Copy display bitmap to hardware */ |
270 | for (y = 0; y < LCD_FBHEIGHT; y++) | 335 | internal_update_rect(0, 0, LCD_WIDTH, LCD_FBHEIGHT - 1); |
271 | { | ||
272 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | ||
273 | lcd_write_command (LCD_CNTL_HIGHCOL | ((offset >> 4) & 0xf)); | ||
274 | lcd_write_command (LCD_CNTL_LOWCOL | (offset & 0xf)); | ||
275 | |||
276 | lcd_write_data (FBADDR(0, y), LCD_WIDTH); | ||
277 | } | ||
278 | } | 336 | } |
279 | 337 | ||
280 | /* Update a fraction of the display. */ | 338 | /* Update a fraction of the display. */ |
@@ -282,45 +340,34 @@ void lcd_update_rect(int, int, int, int) ICODE_ATTR; | |||
282 | void lcd_update_rect(int x, int y, int width, int height) | 340 | void lcd_update_rect(int x, int y, int width, int height) |
283 | { | 341 | { |
284 | int ymax; | 342 | int ymax; |
285 | 343 | if (!display_on) | |
286 | if(!display_on) | ||
287 | return; | 344 | return; |
288 | 345 | ||
289 | /* The Y coordinates have to work on even 8 pixel rows */ | 346 | /* make sure the rectangle is bounded in the screen */ |
290 | if (x < 0) | 347 | if (width > LCD_WIDTH - x)/* Clip right */ |
348 | width = LCD_WIDTH - x; | ||
349 | if (x < 0)/* Clip left */ | ||
291 | { | 350 | { |
292 | width += x; | 351 | width += x; |
293 | x = 0; | 352 | x = 0; |
294 | } | 353 | } |
295 | |||
296 | if (x + width > LCD_WIDTH) | ||
297 | width = LCD_WIDTH - x; | ||
298 | |||
299 | if (width <= 0) | 354 | if (width <= 0) |
300 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | 355 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
301 | 356 | ||
302 | if (y < 0) | 357 | if (height > LCD_HEIGHT - y) /* Clip bottom */ |
358 | height = LCD_HEIGHT - y; | ||
359 | if (y < 0) /* Clip top */ | ||
303 | { | 360 | { |
304 | height += y; | 361 | height += y; |
305 | y = 0; | 362 | y = 0; |
306 | } | 363 | } |
307 | |||
308 | if (y + height > LCD_HEIGHT) | ||
309 | height = LCD_HEIGHT - y; | ||
310 | |||
311 | if (height <= 0) | 364 | if (height <= 0) |
312 | return; /* nothing left to do */ | 365 | return; /* nothing left to do */ |
313 | 366 | ||
367 | /* The Y coordinates have to work on even 8 pixel rows */ | ||
314 | ymax = (y + height-1) >> 3; | 368 | ymax = (y + height-1) >> 3; |
315 | y >>= 3; | 369 | y >>= 3; |
316 | 370 | ||
317 | /* Copy specified rectange bitmap to hardware */ | 371 | /* Copy specified rectange bitmap to hardware */ |
318 | for (; y <= ymax; y++) | 372 | internal_update_rect(x, y, width, ymax); |
319 | { | ||
320 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | ||
321 | lcd_write_command (LCD_CNTL_HIGHCOL | (((x+offset) >> 4) & 0xf)); | ||
322 | lcd_write_command (LCD_CNTL_LOWCOL | ((x+offset) & 0xf)); | ||
323 | |||
324 | lcd_write_data (FBADDR(x,y), width); | ||
325 | } | ||
326 | } | 373 | } |
diff --git a/firmware/target/arm/as3525/sansa-clip/lcd-clip.c b/firmware/target/arm/as3525/sansa-clip/lcd-clip.c index 21d8902739..8331b9e895 100644 --- a/firmware/target/arm/as3525/sansa-clip/lcd-clip.c +++ b/firmware/target/arm/as3525/sansa-clip/lcd-clip.c | |||
@@ -69,6 +69,34 @@ void lcd_write_command(int byte) | |||
69 | ; | 69 | ; |
70 | } | 70 | } |
71 | 71 | ||
72 | void lcd_write_cmd_triplet(int cmd1, int cmd2, int cmd3) | ||
73 | { | ||
74 | #ifndef LCD_USE_FIFO_FOR_COMMANDS | ||
75 | lcd_write_command(cmd1); | ||
76 | lcd_write_command(cmd2); | ||
77 | lcd_write_command(cmd3); | ||
78 | #else | ||
79 | /* combine writes to data register */ | ||
80 | |||
81 | while ((DBOP_STAT & (1<<10)) == 0) /* While push fifo is not empty */ | ||
82 | ; | ||
83 | /* FIFO is empty at this point */ | ||
84 | |||
85 | /* unset D/C# (data or command) */ | ||
86 | GPIOA_PIN(5) = 0; | ||
87 | |||
88 | /* Write command */ | ||
89 | /* !!makes assumption FIFO is at least (3) levels deep! */ | ||
90 | /* Only bits 15:12 and 3:0 of DBOP_DOUT are meaningful */ | ||
91 | DBOP_DOUT = (cmd1 << 8) | cmd1; | ||
92 | DBOP_DOUT = (cmd2 << 8) | cmd2; | ||
93 | DBOP_DOUT = (cmd3 << 8) | cmd3; | ||
94 | /* While push fifo is not empty */ | ||
95 | while ((DBOP_STAT & (1<<10)) == 0) | ||
96 | ; | ||
97 | #endif | ||
98 | } | ||
99 | |||
72 | void lcd_write_data(const fb_data* p_bytes, int count) | 100 | void lcd_write_data(const fb_data* p_bytes, int count) |
73 | { | 101 | { |
74 | volatile int i = 0; | 102 | volatile int i = 0; |
diff --git a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c index c0b128a486..a50a9e5c80 100644 --- a/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c +++ b/firmware/target/arm/as3525/sansa-clipplus/lcd-clip-plus.c | |||
@@ -64,6 +64,31 @@ void lcd_write_command(int byte) | |||
64 | ; | 64 | ; |
65 | } | 65 | } |
66 | 66 | ||
67 | void lcd_write_cmd_triplet(int cmd1, int cmd2, int cmd3) | ||
68 | { | ||
69 | #ifndef LCD_USE_FIFO_FOR_COMMANDS | ||
70 | lcd_write_command(cmd1); | ||
71 | lcd_write_command(cmd2); | ||
72 | lcd_write_command(cmd3); | ||
73 | #else | ||
74 | /* combine writes to data register */ | ||
75 | while(SSP_SR & (1<<4)) /* BSY flag */ | ||
76 | ; | ||
77 | /* FIFO is empty at this point */ | ||
78 | |||
79 | /* LCD command mode */ | ||
80 | GPIOB_PIN(2) = 0; | ||
81 | |||
82 | /* !!makes assumption FIFO is at least (3) levels deep!! */ | ||
83 | SSP_DATA = cmd1; | ||
84 | SSP_DATA = cmd2; | ||
85 | SSP_DATA = cmd3; | ||
86 | |||
87 | while(SSP_SR & (1<<4)) /* BSY flag */ | ||
88 | ; | ||
89 | #endif | ||
90 | } | ||
91 | |||
67 | void lcd_write_data(const fb_data* p_bytes, int count) | 92 | void lcd_write_data(const fb_data* p_bytes, int count) |
68 | { | 93 | { |
69 | /* LCD data mode */ | 94 | /* LCD data mode */ |
@@ -80,6 +105,13 @@ void lcd_write_data(const fb_data* p_bytes, int count) | |||
80 | 105 | ||
81 | void lcd_enable_power(bool onoff) | 106 | void lcd_enable_power(bool onoff) |
82 | { | 107 | { |
108 | #ifndef BOOTLOADER | ||
109 | if (onoff) | ||
110 | bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | ||
111 | else | ||
112 | bitclr32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE); | ||
113 | #else | ||
83 | (void) onoff; | 114 | (void) onoff; |
115 | #endif | ||
84 | } | 116 | } |
85 | 117 | ||
diff --git a/firmware/target/arm/as3525/sansa-clipv2/lcd-clipv2.c b/firmware/target/arm/as3525/sansa-clipv2/lcd-clipv2.c index d7266f72a0..0b3317255a 100644 --- a/firmware/target/arm/as3525/sansa-clipv2/lcd-clipv2.c +++ b/firmware/target/arm/as3525/sansa-clipv2/lcd-clipv2.c | |||
@@ -63,6 +63,35 @@ void lcd_write_command(int byte) | |||
63 | DBOP_TIMPOL_23 = 0xE037E037; | 63 | DBOP_TIMPOL_23 = 0xE037E037; |
64 | } | 64 | } |
65 | 65 | ||
66 | void lcd_write_cmd_triplet(int cmd1, int cmd2, int cmd3) | ||
67 | { | ||
68 | #ifndef LCD_USE_FIFO_FOR_COMMANDS | ||
69 | lcd_write_command(cmd1); | ||
70 | lcd_write_command(cmd2); | ||
71 | lcd_write_command(cmd3); | ||
72 | #else | ||
73 | /* combine writes to data register */ | ||
74 | |||
75 | while ((DBOP_STAT & (1<<10)) == 0) /* While push fifo is not empty */ | ||
76 | ; | ||
77 | /* FIFO is empty at this point */ | ||
78 | /* unset D/C# (data or command) */ | ||
79 | GPIOB_PIN(2) = 0; | ||
80 | DBOP_TIMPOL_23 = 0xE0370036; | ||
81 | |||
82 | /* Write command */ | ||
83 | /* !!makes assumption FIFO is at least (3) levels deep! */ | ||
84 | DBOP_DOUT8 = cmd1; | ||
85 | DBOP_DOUT8 = cmd2; | ||
86 | DBOP_DOUT8 = cmd3; | ||
87 | /* While push fifo is not empty */ | ||
88 | while ((DBOP_STAT & (1<<10)) == 0) | ||
89 | ; | ||
90 | |||
91 | DBOP_TIMPOL_23 = 0xE037E037; | ||
92 | #endif | ||
93 | } | ||
94 | |||
66 | void lcd_write_data(const fb_data* p_bytes, int count) | 95 | void lcd_write_data(const fb_data* p_bytes, int count) |
67 | { | 96 | { |
68 | volatile int i = 0; | 97 | volatile int i = 0; |