summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2007-02-25 22:09:14 +0000
committerJens Arnold <amiconn@rockbox.org>2007-02-25 22:09:14 +0000
commitd528e54b619007ec30bfbbe9dca6c0886c822b74 (patch)
tree06e5cfff57231381877837fe9fa216b587768b76
parente812ec54407947265da52c8d474b16fb3ee2497d (diff)
downloadrockbox-d528e54b619007ec30bfbbe9dca6c0886c822b74.tar.gz
rockbox-d528e54b619007ec30bfbbe9dca6c0886c822b74.zip
Move target specific parts of the H100 remote LCD driver to target tree.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12485 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/drivers/lcd-remote-1bit-v.c (renamed from firmware/drivers/lcd-h100-remote.c)636
-rw-r--r--firmware/export/lcd-remote.h12
-rw-r--r--firmware/target/coldfire/iriver/lcd-remote-iriver.c610
-rwxr-xr-xfirmware/target/coldfire/iriver/lcd-remote-target.h44
5 files changed, 685 insertions, 621 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 74955a4d91..03d2b16d1d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -85,7 +85,7 @@ drivers/lcd-16bit.c
85 85
86#ifdef HAVE_REMOTE_LCD 86#ifdef HAVE_REMOTE_LCD
87#if LCD_REMOTE_DEPTH == 1 87#if LCD_REMOTE_DEPTH == 1
88drivers/lcd-h100-remote.c 88drivers/lcd-remote-1bit-v.c
89#elif LCD_REMOTE_DEPTH == 2 89#elif LCD_REMOTE_DEPTH == 2
90drivers/lcd-remote-2bit-vi.c 90drivers/lcd-remote-2bit-vi.c
91#endif /* LCD_REMOTE_DEPTH */ 91#endif /* LCD_REMOTE_DEPTH */
@@ -378,6 +378,7 @@ target/coldfire/iriver/h300/power-h300.c
378target/coldfire/ata-as-coldfire.S 378target/coldfire/ata-as-coldfire.S
379target/coldfire/pcf50606-coldfire.c 379target/coldfire/pcf50606-coldfire.c
380target/coldfire/iriver/ata-iriver.c 380target/coldfire/iriver/ata-iriver.c
381target/coldfire/iriver/lcd-remote-iriver.c
381target/coldfire/iriver/system-iriver.c 382target/coldfire/iriver/system-iriver.c
382target/coldfire/iriver/h300/adc-h300.c 383target/coldfire/iriver/h300/adc-h300.c
383target/coldfire/iriver/h300/backlight-h300.c 384target/coldfire/iriver/h300/backlight-h300.c
@@ -397,6 +398,7 @@ target/coldfire/iriver/h100/power-h100.c
397#ifndef SIMULATOR 398#ifndef SIMULATOR
398target/coldfire/ata-as-coldfire.S 399target/coldfire/ata-as-coldfire.S
399target/coldfire/iriver/ata-iriver.c 400target/coldfire/iriver/ata-iriver.c
401target/coldfire/iriver/lcd-remote-iriver.c
400target/coldfire/iriver/system-iriver.c 402target/coldfire/iriver/system-iriver.c
401target/coldfire/iriver/h100/adc-h100.c 403target/coldfire/iriver/h100/adc-h100.c
402target/coldfire/iriver/h100/backlight-h100.c 404target/coldfire/iriver/h100/backlight-h100.c
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-remote-1bit-v.c
index e8d22213b8..c81ccc83c9 100644
--- a/firmware/drivers/lcd-h100-remote.c
+++ b/firmware/drivers/lcd-remote-1bit-v.c
@@ -32,36 +32,7 @@
32#include "rbunicode.h" 32#include "rbunicode.h"
33#include "bidi.h" 33#include "bidi.h"
34 34
35/*** definitions ***/ 35#define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
36
37#define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0
38#define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1
39#define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0
40#define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8
41#define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae
42#define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4
43#define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6
44#define LCD_REMOTE_CNTL_NOP 0xe3
45#define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b
46#define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20
47#define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2
48#define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81
49#define LCD_REMOTE_CNTL_INIT_LINE 0x40
50#define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0
51
52#define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */
53#define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */
54
55#define CS_LO and_l(~0x00000004, &GPIO1_OUT)
56#define CS_HI or_l(0x00000004, &GPIO1_OUT)
57#define CLK_LO and_l(~0x10000000, &GPIO_OUT)
58#define CLK_HI or_l(0x10000000, &GPIO_OUT)
59#define DATA_LO and_l(~0x00040000, &GPIO1_OUT)
60#define DATA_HI or_l(0x00040000, &GPIO1_OUT)
61#define RS_LO and_l(~0x00010000, &GPIO_OUT)
62#define RS_HI or_l(0x00010000, &GPIO_OUT)
63
64#define SCROLLABLE_LINES 13
65 36
66/*** globals ***/ 37/*** globals ***/
67 38
@@ -73,33 +44,6 @@ static int xmargin = 0;
73static int ymargin = 0; 44static int ymargin = 0;
74static int curfont = FONT_SYSFIXED; 45static int curfont = FONT_SYSFIXED;
75 46
76#ifndef SIMULATOR
77static int xoffset; /* needed for flip */
78
79/* timeout counter for deasserting /CS after access, <0 means not counting */
80static int cs_countdown IDATA_ATTR = 0;
81#define CS_TIMEOUT (HZ/10)
82
83#ifdef HAVE_REMOTE_LCD_TICKING
84/* If set to true, will prevent "ticking" to headphones. */
85static bool emireduce = false;
86static int byte_delay = 0;
87#endif
88
89/* remote hotplug */
90static struct event_queue remote_scroll_queue;
91#define REMOTE_INIT_LCD 1
92#define REMOTE_DEINIT_LCD 2
93
94static bool remote_initialized = false;
95static int _remote_type = REMOTETYPE_UNPLUGGED;
96
97/* cached settings values */
98static bool cached_invert = false;
99static bool cached_flip = false;
100static int cached_contrast = DEFAULT_REMOTE_CONTRAST_SETTING;
101#endif
102
103/* scrolling */ 47/* scrolling */
104static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ 48static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
105static void scroll_thread(void); 49static void scroll_thread(void);
@@ -117,562 +61,10 @@ static const char scroll_tick_table[16] = {
117 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 61 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
118}; 62};
119 63
120/*** driver routines ***/ 64/* remote hotplug */
121
122#ifndef SIMULATOR
123
124#ifdef HAVE_REMOTE_LCD_TICKING
125static inline void _byte_delay(int delay)
126{
127 asm (
128 "move.l %[dly], %%d0 \n"
129 "ble.s 2f \n"
130 "1: \n"
131 "subq.l #1, %%d0 \n"
132 "bne.s 1b \n"
133 "2: \n"
134 : /* outputs */
135 : /* inputs */
136 [dly]"d"(delay)
137 : /* clobbers */
138 "d0"
139 );
140}
141#endif /* HAVE_REMOTE_LCD_TICKING */
142
143/* Standard low-level byte writer. Requires CLK low on entry */
144static inline void _write_byte(unsigned data)
145{
146 asm volatile (
147 "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */
148 "and.l %[dbit], %%d0 \n"
149 "beq.s 1f \n" /* and set it as previous-state bit */
150 "bset #8, %[data] \n"
151 "1: \n"
152 "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */
153 "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */
154 "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */
155 "swap %[data] \n" /* Shift data to upper byte */
156 "lsl.l #8, %[data] \n"
157
158 "lsl.l #1,%[data] \n" /* Shift out MSB */
159 "bcc.s 1f \n"
160 "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */
161 "1: \n"
162 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */
163 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */
164
165 "lsl.l #1,%[data] \n" /* ..unrolled.. */
166 "bcc.s 1f \n"
167 "eor.l %[dbit], (%[gpo1]) \n"
168 "1: \n"
169 "eor.l %[cbit], (%[gpo0]) \n"
170 "eor.l %[cbit], (%[gpo0]) \n"
171
172 "lsl.l #1,%[data] \n"
173 "bcc.s 1f \n"
174 "eor.l %[dbit], (%[gpo1]) \n"
175 "1: \n"
176 "eor.l %[cbit], (%[gpo0]) \n"
177 "eor.l %[cbit], (%[gpo0]) \n"
178
179 "lsl.l #1,%[data] \n"
180 "bcc.s 1f \n"
181 "eor.l %[dbit], (%[gpo1]) \n"
182 "1: \n"
183 "eor.l %[cbit], (%[gpo0]) \n"
184 "eor.l %[cbit], (%[gpo0]) \n"
185
186 "lsl.l #1,%[data] \n"
187 "bcc.s 1f \n"
188 "eor.l %[dbit], (%[gpo1]) \n"
189 "1: \n"
190 "eor.l %[cbit], (%[gpo0]) \n"
191 "eor.l %[cbit], (%[gpo0]) \n"
192
193 "lsl.l #1,%[data] \n"
194 "bcc.s 1f \n"
195 "eor.l %[dbit], (%[gpo1]) \n"
196 "1: \n"
197 "eor.l %[cbit], (%[gpo0]) \n"
198 "eor.l %[cbit], (%[gpo0]) \n"
199
200 "lsl.l #1,%[data] \n"
201 "bcc.s 1f \n"
202 "eor.l %[dbit], (%[gpo1]) \n"
203 "1: \n"
204 "eor.l %[cbit], (%[gpo0]) \n"
205 "eor.l %[cbit], (%[gpo0]) \n"
206
207 "lsl.l #1,%[data] \n"
208 "bcc.s 1f \n"
209 "eor.l %[dbit], (%[gpo1]) \n"
210 "1: \n"
211 "eor.l %[cbit], (%[gpo0]) \n"
212 "eor.l %[cbit], (%[gpo0]) \n"
213 : /* outputs */
214 [data]"+d"(data)
215 : /* inputs */
216 [gpo0]"a"(&GPIO_OUT),
217 [cbit]"d"(0x10000000),
218 [gpo1]"a"(&GPIO1_OUT),
219 [dbit]"d"(0x00040000)
220 : /* clobbers */
221 "d0"
222 );
223}
224
225/* Fast low-level byte writer. Don't use with high CPU clock.
226 * Requires CLK low on entry */
227static inline void _write_fast(unsigned data)
228{
229 asm volatile (
230 "move.w %%sr,%%d3 \n" /* Get current interrupt level */
231 "move.w #0x2700,%%sr \n" /* Disable interrupts */
232
233 "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */
234 "move.l %%d0, %%d1 \n"
235 "and.l %[dbit], %%d1 \n" /* Check current state of data line */
236 "beq.s 1f \n" /* and set it as previous-state bit */
237 "bset #8, %[data] \n"
238 "1: \n"
239 "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */
240 "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */
241 "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */
242 "swap %[data] \n" /* Shift data to upper byte */
243 "lsl.l #8, %[data] \n"
244
245 "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */
246 "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */
247 "eor.l %%d1, %%d2 \n"
248
249 "lsl.l #1,%[data] \n" /* Shift out MSB */
250 "bcc.s 1f \n"
251 "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */
252 "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */
253 "1: \n"
254 "move.l %%d2, (%[gpo0]) \n" /* Set CLK */
255 "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */
256
257 "lsl.l #1,%[data] \n" /* ..unrolled.. */
258 "bcc.s 1f \n"
259 "eor.l %[dbit], %%d0 \n"
260 "move.l %%d0, (%[gpo1]) \n"
261 "1: \n"
262 "move.l %%d2, (%[gpo0]) \n"
263 "move.l %%d1, (%[gpo0]) \n"
264
265 "lsl.l #1,%[data] \n"
266 "bcc.s 1f \n"
267 "eor.l %[dbit], %%d0 \n"
268 "move.l %%d0, (%[gpo1]) \n"
269 "1: \n"
270 "move.l %%d2, (%[gpo0]) \n"
271 "move.l %%d1, (%[gpo0]) \n"
272
273 "lsl.l #1,%[data] \n"
274 "bcc.s 1f \n"
275 "eor.l %[dbit], %%d0 \n"
276 "move.l %%d0, (%[gpo1]) \n"
277 "1: \n"
278 "move.l %%d2, (%[gpo0]) \n"
279 "move.l %%d1, (%[gpo0]) \n"
280
281 "lsl.l #1,%[data] \n"
282 "bcc.s 1f \n"
283 "eor.l %[dbit], %%d0 \n"
284 "move.l %%d0, (%[gpo1]) \n"
285 "1: \n"
286 "move.l %%d2, (%[gpo0]) \n"
287 "move.l %%d1, (%[gpo0]) \n"
288
289 "lsl.l #1,%[data] \n"
290 "bcc.s 1f \n"
291 "eor.l %[dbit], %%d0 \n"
292 "move.l %%d0, (%[gpo1]) \n"
293 "1: \n"
294 "move.l %%d2, (%[gpo0]) \n"
295 "move.l %%d1, (%[gpo0]) \n"
296
297 "lsl.l #1,%[data] \n"
298 "bcc.s 1f \n"
299 "eor.l %[dbit], %%d0 \n"
300 "move.l %%d0, (%[gpo1]) \n"
301 "1: \n"
302 "move.l %%d2, (%[gpo0]) \n"
303 "move.l %%d1, (%[gpo0]) \n"
304
305 "lsl.l #1,%[data] \n"
306 "bcc.s 1f \n"
307 "eor.l %[dbit], %%d0 \n"
308 "move.l %%d0, (%[gpo1]) \n"
309 "1: \n"
310 "move.l %%d2, (%[gpo0]) \n"
311 "move.l %%d1, (%[gpo0]) \n"
312
313 "move.w %%d3, %%sr \n" /* Restore interrupt level */
314 : /* outputs */
315 [data]"+d"(data)
316 : /* inputs */
317 [gpo0]"a"(&GPIO_OUT),
318 [cbit]"i"(0x10000000),
319 [gpo1]"a"(&GPIO1_OUT),
320 [dbit]"d"(0x00040000)
321 : /* clobbers */
322 "d0", "d1", "d2", "d3"
323 );
324}
325
326void lcd_remote_write_command(int cmd)
327{
328 cs_countdown = 0;
329 RS_LO;
330 CS_LO;
331
332 _write_byte(cmd);
333#ifdef HAVE_REMOTE_LCD_TICKING
334 _byte_delay(byte_delay - 148);
335#endif
336
337 cs_countdown = CS_TIMEOUT;
338}
339
340void lcd_remote_write_command_ex(int cmd, int data)
341{
342 cs_countdown = 0;
343 RS_LO;
344 CS_LO;
345
346 _write_byte(cmd);
347#ifdef HAVE_REMOTE_LCD_TICKING
348 _byte_delay(byte_delay - 148);
349#endif
350 _write_byte(data);
351#ifdef HAVE_REMOTE_LCD_TICKING
352 _byte_delay(byte_delay - 148);
353#endif
354
355 cs_countdown = CS_TIMEOUT;
356}
357
358void lcd_remote_write_data(const unsigned char* p_bytes, int count) ICODE_ATTR;
359void lcd_remote_write_data(const unsigned char* p_bytes, int count)
360{
361 const unsigned char *p_end = p_bytes + count;
362
363 cs_countdown = 0;
364 RS_HI;
365 CS_LO;
366
367 /* This is safe as long as lcd_remote_write_data() isn't called from within
368 * an ISR. */
369 if (cpu_frequency < 50000000)
370 {
371 while (p_bytes < p_end)
372 {
373 _write_fast(*p_bytes++);
374#ifdef HAVE_REMOTE_LCD_TICKING
375 _byte_delay(byte_delay - 87);
376#endif
377 }
378 }
379 else
380 {
381 while (p_bytes < p_end)
382 {
383 _write_byte(*p_bytes++);
384#ifdef HAVE_REMOTE_LCD_TICKING
385 _byte_delay(byte_delay - 148);
386#endif
387 }
388 }
389
390 cs_countdown = CS_TIMEOUT;
391}
392#endif /* !SIMULATOR */
393
394/*** hardware configuration ***/
395
396int lcd_remote_default_contrast(void)
397{
398 return DEFAULT_REMOTE_CONTRAST_SETTING;
399}
400
401#ifndef SIMULATOR 65#ifndef SIMULATOR
402 66struct event_queue remote_scroll_queue;
403#ifdef HAVE_REMOTE_LCD_TICKING
404void lcd_remote_emireduce(bool state)
405{
406 emireduce = state;
407}
408#endif
409
410void lcd_remote_powersave(bool on)
411{
412 if (remote_initialized)
413 {
414 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1));
415 lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0));
416 }
417}
418
419void lcd_remote_set_contrast(int val)
420{
421 cached_contrast = val;
422 if (remote_initialized)
423 lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val);
424}
425
426void lcd_remote_set_invert_display(bool yesno)
427{
428 cached_invert = yesno;
429 if (remote_initialized)
430 lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | (yesno?1:0));
431}
432
433/* turn the display upside down (call lcd_remote_update() afterwards) */
434void lcd_remote_set_flip(bool yesno)
435{
436 cached_flip = yesno;
437 if (yesno)
438 {
439 xoffset = 0;
440 if (remote_initialized)
441 {
442 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL);
443 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL);
444 }
445 }
446 else
447 {
448 xoffset = 132 - LCD_REMOTE_WIDTH;
449 if (remote_initialized)
450 {
451 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE);
452 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE);
453 }
454 }
455}
456
457/* The actual LCD init */
458static void remote_lcd_init(void)
459{
460 CS_HI;
461 CLK_LO;
462 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0);
463
464 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5);
465 sleep(1);
466 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6);
467 sleep(1);
468 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x7);
469
470 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_REGULATOR | 0x4); // 0x4 Select regulator @ 5.0 (default);
471
472 sleep(1);
473
474 lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line
475 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address
476 lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB
477
478 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1);
479
480 remote_initialized = true;
481
482 lcd_remote_set_flip(cached_flip);
483 lcd_remote_set_contrast(cached_contrast);
484 lcd_remote_set_invert_display(cached_invert);
485}
486
487bool remote_detect(void)
488{
489 return (GPIO_READ & 0x40000000)?false:true;
490}
491
492int remote_type(void)
493{
494 return _remote_type;
495}
496
497/* Monitor remote hotswap */
498static void remote_tick(void)
499{
500 static bool last_status = false;
501 static int countdown = 0;
502 static int init_delay = 0;
503 bool current_status;
504 int val;
505 int level;
506
507 current_status = remote_detect();
508 /* Only report when the status has changed */
509 if (current_status != last_status)
510 {
511 last_status = current_status;
512 countdown = current_status ? 20*HZ : 1;
513 }
514 else
515 {
516 /* Count down until it gets negative */
517 if (countdown >= 0)
518 countdown--;
519
520 if (current_status)
521 {
522 if (!(countdown % 8))
523 {
524 /* Determine which type of remote it is */
525 level = set_irq_level(HIGHEST_IRQ_LEVEL);
526 val = adc_scan(ADC_REMOTEDETECT);
527 set_irq_level(level);
528
529 if (val < ADCVAL_H100_LCD_REMOTE_HOLD)
530 {
531 if (val < ADCVAL_H100_LCD_REMOTE)
532 if (val < ADCVAL_H300_LCD_REMOTE)
533 _remote_type = REMOTETYPE_H300_LCD; /* hold off */
534 else
535 _remote_type = REMOTETYPE_H100_LCD; /* hold off */
536 else
537 if (val < ADCVAL_H300_LCD_REMOTE_HOLD)
538 _remote_type = REMOTETYPE_H300_LCD; /* hold on */
539 else
540 _remote_type = REMOTETYPE_H100_LCD; /* hold on */
541
542 if (--init_delay <= 0)
543 {
544 queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0);
545 init_delay = 6;
546 }
547 }
548 else
549 {
550 _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */
551 }
552 }
553 }
554 else
555 {
556 if (countdown == 0)
557 {
558 _remote_type = REMOTETYPE_UNPLUGGED;
559
560 queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0);
561 }
562 }
563 }
564
565 /* handle chip select timeout */
566 if (cs_countdown >= 0)
567 cs_countdown--;
568 if (cs_countdown == 0)
569 CS_HI;
570}
571#endif /* !SIMULATOR */
572
573/* LCD init */
574#ifdef SIMULATOR
575
576void lcd_remote_init(void)
577{
578 create_thread(scroll_thread, scroll_stack,
579 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
580}
581#else /* !SIMULATOR */
582
583/* Initialise ports and kick off monitor */
584void lcd_remote_init(void)
585{
586#ifdef IRIVER_H300_SERIES
587 or_l(0x10010000, &GPIO_FUNCTION); /* GPIO16: RS
588 GPIO28: CLK */
589
590 or_l(0x00040006, &GPIO1_FUNCTION); /* GPO33: Backlight
591 GPIO34: CS
592 GPIO50: Data */
593 or_l(0x10010000, &GPIO_ENABLE);
594 or_l(0x00040006, &GPIO1_ENABLE);
595#else
596 or_l(0x10010800, &GPIO_FUNCTION); /* GPIO11: Backlight
597 GPIO16: RS
598 GPIO28: CLK */
599
600 or_l(0x00040004, &GPIO1_FUNCTION); /* GPIO34: CS
601 GPIO50: Data */
602 or_l(0x10010800, &GPIO_ENABLE);
603 or_l(0x00040004, &GPIO1_ENABLE);
604#endif 67#endif
605 lcd_remote_clear_display();
606
607 /* private queue */
608 queue_init(&remote_scroll_queue, false);
609 tick_add_task(remote_tick);
610 create_thread(scroll_thread, scroll_stack,
611 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
612}
613
614/*** update functions ***/
615
616/* Update the display.
617 This must be called after all other LCD functions that change the display. */
618void lcd_remote_update(void) ICODE_ATTR;
619void lcd_remote_update(void)
620{
621 int y;
622
623 if (!remote_initialized)
624 return;
625
626#ifdef HAVE_REMOTE_LCD_TICKING
627 /* Adjust byte delay for emi reduction. */
628 byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0;
629#endif
630
631 /* Copy display bitmap to hardware */
632 for (y = 0; y < LCD_REMOTE_FBHEIGHT; y++)
633 {
634 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y);
635 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf));
636 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf));
637 lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH);
638 }
639}
640
641/* Update a fraction of the display. */
642void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR;
643void lcd_remote_update_rect(int x, int y, int width, int height)
644{
645 int ymax;
646
647 if (!remote_initialized)
648 return;
649
650 /* The Y coordinates have to work on even 8 pixel rows */
651 ymax = (y + height-1) >> 3;
652 y >>= 3;
653
654 if(x + width > LCD_REMOTE_WIDTH)
655 width = LCD_REMOTE_WIDTH - x;
656 if (width <= 0)
657 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
658 if(ymax >= LCD_REMOTE_FBHEIGHT)
659 ymax = LCD_REMOTE_FBHEIGHT-1;
660
661#ifdef HAVE_REMOTE_LCD_TICKING
662 /* Adjust byte delay for emi reduction */
663 byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0;
664#endif
665
666 /* Copy specified rectange bitmap to hardware */
667 for (; y <= ymax; y++)
668 {
669 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y);
670 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf));
671 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | ((x+xoffset) & 0xf));
672 lcd_remote_write_data(&lcd_remote_framebuffer[y][x], width);
673 }
674}
675#endif /* !SIMULATOR */
676 68
677/*** parameter handling ***/ 69/*** parameter handling ***/
678 70
@@ -1335,12 +727,12 @@ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string)
1335 727
1336void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style) 728void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style)
1337{ 729{
1338 lcd_remote_puts_scroll_style_offset(x, y, string, style, 0); 730 lcd_remote_puts_scroll_style_offset(x, y, string, style, 0);
1339} 731}
1340 732
1341void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) 733void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset)
1342{ 734{
1343 lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); 735 lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset);
1344} 736}
1345 737
1346void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string, 738void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string,
@@ -1430,14 +822,12 @@ static void scroll_thread(void)
1430 switch (ev.id) 822 switch (ev.id)
1431 { 823 {
1432 case REMOTE_INIT_LCD: 824 case REMOTE_INIT_LCD:
1433 remote_lcd_init(); 825 lcd_remote_on();
1434 lcd_remote_update(); 826 lcd_remote_update();
1435 break; 827 break;
1436 828
1437 case REMOTE_DEINIT_LCD: 829 case REMOTE_DEINIT_LCD:
1438 CLK_LO; 830 lcd_remote_off();
1439 CS_HI;
1440 remote_initialized = false;
1441 break; 831 break;
1442 } 832 }
1443 833
@@ -1503,3 +893,15 @@ static void scroll_thread(void)
1503 } 893 }
1504} 894}
1505 895
896/* LCD init */
897void lcd_remote_init(void)
898{
899#ifndef SIMULATOR
900 /* Call device specific init */
901 lcd_remote_init_device();
902 /* private queue */
903 queue_init(&remote_scroll_queue, false);
904#endif
905 create_thread(scroll_thread, scroll_stack,
906 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE));
907}
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h
index 7ed52bd188..08accf7116 100644
--- a/firmware/export/lcd-remote.h
+++ b/firmware/export/lcd-remote.h
@@ -27,13 +27,20 @@
27 27
28#ifdef HAVE_REMOTE_LCD 28#ifdef HAVE_REMOTE_LCD
29 29
30#if defined(TARGET_TREE) && !defined(SIMULATOR)
31#include "lcd-remote-target.h"
32#endif
33
30#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) 34#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
31#define REMOTETYPE_UNPLUGGED 0 35#define REMOTETYPE_UNPLUGGED 0
32#define REMOTETYPE_H100_LCD 1 36#define REMOTETYPE_H100_LCD 1
33#define REMOTETYPE_H300_LCD 2 37#define REMOTETYPE_H300_LCD 2
34#define REMOTETYPE_H300_NONLCD 3 38#define REMOTETYPE_H300_NONLCD 3
35extern int remote_type(void); 39int remote_type(void);
36extern bool remote_detect(void); 40#endif
41
42#ifndef SIMULATOR
43extern struct event_queue remote_scroll_queue;
37#endif 44#endif
38 45
39#define STYLE_DEFAULT 0 46#define STYLE_DEFAULT 0
@@ -105,7 +112,6 @@ extern fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBW
105extern void lcd_remote_init(void); 112extern void lcd_remote_init(void);
106extern int lcd_remote_default_contrast(void); 113extern int lcd_remote_default_contrast(void);
107extern void lcd_remote_set_contrast(int val); 114extern void lcd_remote_set_contrast(int val);
108extern void lcd_remote_emireduce(bool state);
109 115
110extern void lcd_remote_clear_display(void); 116extern void lcd_remote_clear_display(void);
111extern void lcd_remote_puts(int x, int y, const unsigned char *str); 117extern void lcd_remote_puts(int x, int y, const unsigned char *str);
diff --git a/firmware/target/coldfire/iriver/lcd-remote-iriver.c b/firmware/target/coldfire/iriver/lcd-remote-iriver.c
new file mode 100644
index 0000000000..cdc5acacca
--- /dev/null
+++ b/firmware/target/coldfire/iriver/lcd-remote-iriver.c
@@ -0,0 +1,610 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Richard S. La Charité III
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "system.h"
22#include "kernel.h"
23#include "lcd-remote.h"
24
25/*** definitions ***/
26
27#define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0
28#define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1
29#define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0
30#define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8
31#define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae
32#define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4
33#define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6
34#define LCD_REMOTE_CNTL_NOP 0xe3
35#define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b
36#define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20
37#define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2
38#define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81
39#define LCD_REMOTE_CNTL_INIT_LINE 0x40
40#define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0
41
42#define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */
43#define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */
44
45#define CS_LO and_l(~0x00000004, &GPIO1_OUT)
46#define CS_HI or_l(0x00000004, &GPIO1_OUT)
47#define CLK_LO and_l(~0x10000000, &GPIO_OUT)
48#define CLK_HI or_l(0x10000000, &GPIO_OUT)
49#define DATA_LO and_l(~0x00040000, &GPIO1_OUT)
50#define DATA_HI or_l(0x00040000, &GPIO1_OUT)
51#define RS_LO and_l(~0x00010000, &GPIO_OUT)
52#define RS_HI or_l(0x00010000, &GPIO_OUT)
53
54static int xoffset; /* needed for flip */
55
56/* timeout counter for deasserting /CS after access, <0 means not counting */
57static int cs_countdown IDATA_ATTR = 0;
58#define CS_TIMEOUT (HZ/10)
59
60#ifdef HAVE_REMOTE_LCD_TICKING
61/* If set to true, will prevent "ticking" to headphones. */
62static bool emireduce = false;
63static int byte_delay = 0;
64#endif
65
66bool remote_initialized = false;
67static int _remote_type = REMOTETYPE_UNPLUGGED;
68
69/* cached settings values */
70static bool cached_invert = false;
71static bool cached_flip = false;
72static int cached_contrast = DEFAULT_REMOTE_CONTRAST_SETTING;
73
74static void remote_tick(void);
75
76#ifdef HAVE_REMOTE_LCD_TICKING
77static inline void _byte_delay(int delay)
78{
79 asm (
80 "move.l %[dly], %%d0 \n"
81 "ble.s 2f \n"
82 "1: \n"
83 "subq.l #1, %%d0 \n"
84 "bne.s 1b \n"
85 "2: \n"
86 : /* outputs */
87 : /* inputs */
88 [dly]"d"(delay)
89 : /* clobbers */
90 "d0"
91 );
92}
93#endif /* HAVE_REMOTE_LCD_TICKING */
94
95/* Standard low-level byte writer. Requires CLK low on entry */
96static inline void _write_byte(unsigned data)
97{
98 asm volatile (
99 "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */
100 "and.l %[dbit], %%d0 \n"
101 "beq.s 1f \n" /* and set it as previous-state bit */
102 "bset #8, %[data] \n"
103 "1: \n"
104 "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */
105 "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */
106 "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */
107 "swap %[data] \n" /* Shift data to upper byte */
108 "lsl.l #8, %[data] \n"
109
110 "lsl.l #1,%[data] \n" /* Shift out MSB */
111 "bcc.s 1f \n"
112 "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */
113 "1: \n"
114 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */
115 "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */
116
117 "lsl.l #1,%[data] \n" /* ..unrolled.. */
118 "bcc.s 1f \n"
119 "eor.l %[dbit], (%[gpo1]) \n"
120 "1: \n"
121 "eor.l %[cbit], (%[gpo0]) \n"
122 "eor.l %[cbit], (%[gpo0]) \n"
123
124 "lsl.l #1,%[data] \n"
125 "bcc.s 1f \n"
126 "eor.l %[dbit], (%[gpo1]) \n"
127 "1: \n"
128 "eor.l %[cbit], (%[gpo0]) \n"
129 "eor.l %[cbit], (%[gpo0]) \n"
130
131 "lsl.l #1,%[data] \n"
132 "bcc.s 1f \n"
133 "eor.l %[dbit], (%[gpo1]) \n"
134 "1: \n"
135 "eor.l %[cbit], (%[gpo0]) \n"
136 "eor.l %[cbit], (%[gpo0]) \n"
137
138 "lsl.l #1,%[data] \n"
139 "bcc.s 1f \n"
140 "eor.l %[dbit], (%[gpo1]) \n"
141 "1: \n"
142 "eor.l %[cbit], (%[gpo0]) \n"
143 "eor.l %[cbit], (%[gpo0]) \n"
144
145 "lsl.l #1,%[data] \n"
146 "bcc.s 1f \n"
147 "eor.l %[dbit], (%[gpo1]) \n"
148 "1: \n"
149 "eor.l %[cbit], (%[gpo0]) \n"
150 "eor.l %[cbit], (%[gpo0]) \n"
151
152 "lsl.l #1,%[data] \n"
153 "bcc.s 1f \n"
154 "eor.l %[dbit], (%[gpo1]) \n"
155 "1: \n"
156 "eor.l %[cbit], (%[gpo0]) \n"
157 "eor.l %[cbit], (%[gpo0]) \n"
158
159 "lsl.l #1,%[data] \n"
160 "bcc.s 1f \n"
161 "eor.l %[dbit], (%[gpo1]) \n"
162 "1: \n"
163 "eor.l %[cbit], (%[gpo0]) \n"
164 "eor.l %[cbit], (%[gpo0]) \n"
165 : /* outputs */
166 [data]"+d"(data)
167 : /* inputs */
168 [gpo0]"a"(&GPIO_OUT),
169 [cbit]"d"(0x10000000),
170 [gpo1]"a"(&GPIO1_OUT),
171 [dbit]"d"(0x00040000)
172 : /* clobbers */
173 "d0"
174 );
175}
176
177/* Fast low-level byte writer. Don't use with high CPU clock.
178 * Requires CLK low on entry */
179static inline void _write_fast(unsigned data)
180{
181 asm volatile (
182 "move.w %%sr,%%d3 \n" /* Get current interrupt level */
183 "move.w #0x2700,%%sr \n" /* Disable interrupts */
184
185 "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */
186 "move.l %%d0, %%d1 \n"
187 "and.l %[dbit], %%d1 \n" /* Check current state of data line */
188 "beq.s 1f \n" /* and set it as previous-state bit */
189 "bset #8, %[data] \n"
190 "1: \n"
191 "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */
192 "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */
193 "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */
194 "swap %[data] \n" /* Shift data to upper byte */
195 "lsl.l #8, %[data] \n"
196
197 "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */
198 "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */
199 "eor.l %%d1, %%d2 \n"
200
201 "lsl.l #1,%[data] \n" /* Shift out MSB */
202 "bcc.s 1f \n"
203 "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */
204 "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */
205 "1: \n"
206 "move.l %%d2, (%[gpo0]) \n" /* Set CLK */
207 "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */
208
209 "lsl.l #1,%[data] \n" /* ..unrolled.. */
210 "bcc.s 1f \n"
211 "eor.l %[dbit], %%d0 \n"
212 "move.l %%d0, (%[gpo1]) \n"
213 "1: \n"
214 "move.l %%d2, (%[gpo0]) \n"
215 "move.l %%d1, (%[gpo0]) \n"
216
217 "lsl.l #1,%[data] \n"
218 "bcc.s 1f \n"
219 "eor.l %[dbit], %%d0 \n"
220 "move.l %%d0, (%[gpo1]) \n"
221 "1: \n"
222 "move.l %%d2, (%[gpo0]) \n"
223 "move.l %%d1, (%[gpo0]) \n"
224
225 "lsl.l #1,%[data] \n"
226 "bcc.s 1f \n"
227 "eor.l %[dbit], %%d0 \n"
228 "move.l %%d0, (%[gpo1]) \n"
229 "1: \n"
230 "move.l %%d2, (%[gpo0]) \n"
231 "move.l %%d1, (%[gpo0]) \n"
232
233 "lsl.l #1,%[data] \n"
234 "bcc.s 1f \n"
235 "eor.l %[dbit], %%d0 \n"
236 "move.l %%d0, (%[gpo1]) \n"
237 "1: \n"
238 "move.l %%d2, (%[gpo0]) \n"
239 "move.l %%d1, (%[gpo0]) \n"
240
241 "lsl.l #1,%[data] \n"
242 "bcc.s 1f \n"
243 "eor.l %[dbit], %%d0 \n"
244 "move.l %%d0, (%[gpo1]) \n"
245 "1: \n"
246 "move.l %%d2, (%[gpo0]) \n"
247 "move.l %%d1, (%[gpo0]) \n"
248
249 "lsl.l #1,%[data] \n"
250 "bcc.s 1f \n"
251 "eor.l %[dbit], %%d0 \n"
252 "move.l %%d0, (%[gpo1]) \n"
253 "1: \n"
254 "move.l %%d2, (%[gpo0]) \n"
255 "move.l %%d1, (%[gpo0]) \n"
256
257 "lsl.l #1,%[data] \n"
258 "bcc.s 1f \n"
259 "eor.l %[dbit], %%d0 \n"
260 "move.l %%d0, (%[gpo1]) \n"
261 "1: \n"
262 "move.l %%d2, (%[gpo0]) \n"
263 "move.l %%d1, (%[gpo0]) \n"
264
265 "move.w %%d3, %%sr \n" /* Restore interrupt level */
266 : /* outputs */
267 [data]"+d"(data)
268 : /* inputs */
269 [gpo0]"a"(&GPIO_OUT),
270 [cbit]"i"(0x10000000),
271 [gpo1]"a"(&GPIO1_OUT),
272 [dbit]"d"(0x00040000)
273 : /* clobbers */
274 "d0", "d1", "d2", "d3"
275 );
276}
277
278void lcd_remote_write_command(int cmd)
279{
280 cs_countdown = 0;
281 RS_LO;
282 CS_LO;
283
284 _write_byte(cmd);
285#ifdef HAVE_REMOTE_LCD_TICKING
286 _byte_delay(byte_delay - 148);
287#endif
288
289 cs_countdown = CS_TIMEOUT;
290}
291
292void lcd_remote_write_command_ex(int cmd, int data)
293{
294 cs_countdown = 0;
295 RS_LO;
296 CS_LO;
297
298 _write_byte(cmd);
299#ifdef HAVE_REMOTE_LCD_TICKING
300 _byte_delay(byte_delay - 148);
301#endif
302 _write_byte(data);
303#ifdef HAVE_REMOTE_LCD_TICKING
304 _byte_delay(byte_delay - 148);
305#endif
306
307 cs_countdown = CS_TIMEOUT;
308}
309
310void lcd_remote_write_data(const unsigned char* p_bytes, int count) ICODE_ATTR;
311void lcd_remote_write_data(const unsigned char* p_bytes, int count)
312{
313 const unsigned char *p_end = p_bytes + count;
314
315 cs_countdown = 0;
316 RS_HI;
317 CS_LO;
318
319 /* This is safe as long as lcd_remote_write_data() isn't called from within
320 * an ISR. */
321 if (cpu_frequency < 50000000)
322 {
323 while (p_bytes < p_end)
324 {
325 _write_fast(*p_bytes++);
326#ifdef HAVE_REMOTE_LCD_TICKING
327 _byte_delay(byte_delay - 87);
328#endif
329 }
330 }
331 else
332 {
333 while (p_bytes < p_end)
334 {
335 _write_byte(*p_bytes++);
336#ifdef HAVE_REMOTE_LCD_TICKING
337 _byte_delay(byte_delay - 148);
338#endif
339 }
340 }
341
342 cs_countdown = CS_TIMEOUT;
343}
344
345/*** hardware configuration ***/
346
347int lcd_remote_default_contrast(void)
348{
349 return DEFAULT_REMOTE_CONTRAST_SETTING;
350}
351
352#ifdef HAVE_REMOTE_LCD_TICKING
353void lcd_remote_emireduce(bool state)
354{
355 emireduce = state;
356}
357#endif
358
359void lcd_remote_powersave(bool on)
360{
361 if (remote_initialized)
362 {
363 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1));
364 lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0));
365 }
366}
367
368void lcd_remote_set_contrast(int val)
369{
370 cached_contrast = val;
371 if (remote_initialized)
372 lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val);
373}
374
375void lcd_remote_set_invert_display(bool yesno)
376{
377 cached_invert = yesno;
378 if (remote_initialized)
379 lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | (yesno?1:0));
380}
381
382/* turn the display upside down (call lcd_remote_update() afterwards) */
383void lcd_remote_set_flip(bool yesno)
384{
385 cached_flip = yesno;
386 if (yesno)
387 {
388 xoffset = 0;
389 if (remote_initialized)
390 {
391 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL);
392 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL);
393 }
394 }
395 else
396 {
397 xoffset = 132 - LCD_REMOTE_WIDTH;
398 if (remote_initialized)
399 {
400 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE);
401 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE);
402 }
403 }
404}
405
406bool remote_detect(void)
407{
408 return (GPIO_READ & 0x40000000)?false:true;
409}
410
411int remote_type(void)
412{
413 return _remote_type;
414}
415
416void lcd_remote_init_device(void)
417{
418#ifdef IRIVER_H300_SERIES
419 or_l(0x10010000, &GPIO_FUNCTION); /* GPIO16: RS
420 GPIO28: CLK */
421
422 or_l(0x00040006, &GPIO1_FUNCTION); /* GPO33: Backlight
423 GPIO34: CS
424 GPIO50: Data */
425 or_l(0x10010000, &GPIO_ENABLE);
426 or_l(0x00040006, &GPIO1_ENABLE);
427#else
428 or_l(0x10010800, &GPIO_FUNCTION); /* GPIO11: Backlight
429 GPIO16: RS
430 GPIO28: CLK */
431
432 or_l(0x00040004, &GPIO1_FUNCTION); /* GPIO34: CS
433 GPIO50: Data */
434 or_l(0x10010800, &GPIO_ENABLE);
435 or_l(0x00040004, &GPIO1_ENABLE);
436#endif
437 lcd_remote_clear_display();
438 tick_add_task(remote_tick);
439}
440
441void lcd_remote_on(void)
442{
443 CS_HI;
444 CLK_LO;
445 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0);
446
447 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5);
448 sleep(1);
449 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6);
450 sleep(1);
451 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x7);
452
453 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_REGULATOR | 0x4); // 0x4 Select regulator @ 5.0 (default);
454
455 sleep(1);
456
457 lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line
458 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address
459 lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB
460
461 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1);
462
463 remote_initialized = true;
464
465 lcd_remote_set_flip(cached_flip);
466 lcd_remote_set_contrast(cached_contrast);
467 lcd_remote_set_invert_display(cached_invert);
468}
469
470void lcd_remote_off(void)
471{
472 remote_initialized = false;
473 CLK_LO;
474 CS_HI;
475}
476
477/* Monitor remote hotswap */
478static void remote_tick(void)
479{
480 static bool last_status = false;
481 static int countdown = 0;
482 static int init_delay = 0;
483 bool current_status;
484 int val;
485 int level;
486
487 current_status = remote_detect();
488 /* Only report when the status has changed */
489 if (current_status != last_status)
490 {
491 last_status = current_status;
492 countdown = current_status ? 20*HZ : 1;
493 }
494 else
495 {
496 /* Count down until it gets negative */
497 if (countdown >= 0)
498 countdown--;
499
500 if (current_status)
501 {
502 if (!(countdown % 8))
503 {
504 /* Determine which type of remote it is */
505 level = set_irq_level(HIGHEST_IRQ_LEVEL);
506 val = adc_scan(ADC_REMOTEDETECT);
507 set_irq_level(level);
508
509 if (val < ADCVAL_H100_LCD_REMOTE_HOLD)
510 {
511 if (val < ADCVAL_H100_LCD_REMOTE)
512 if (val < ADCVAL_H300_LCD_REMOTE)
513 _remote_type = REMOTETYPE_H300_LCD; /* hold off */
514 else
515 _remote_type = REMOTETYPE_H100_LCD; /* hold off */
516 else
517 if (val < ADCVAL_H300_LCD_REMOTE_HOLD)
518 _remote_type = REMOTETYPE_H300_LCD; /* hold on */
519 else
520 _remote_type = REMOTETYPE_H100_LCD; /* hold on */
521
522 if (--init_delay <= 0)
523 {
524 queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0);
525 init_delay = 6;
526 }
527 }
528 else
529 {
530 _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */
531 }
532 }
533 }
534 else
535 {
536 if (countdown == 0)
537 {
538 _remote_type = REMOTETYPE_UNPLUGGED;
539
540 queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0);
541 }
542 }
543 }
544
545 /* handle chip select timeout */
546 if (cs_countdown >= 0)
547 cs_countdown--;
548 if (cs_countdown == 0)
549 CS_HI;
550}
551
552/* Update the display.
553 This must be called after all other LCD functions that change the display. */
554void lcd_remote_update(void) ICODE_ATTR;
555void lcd_remote_update(void)
556{
557 int y;
558
559 if (!remote_initialized)
560 return;
561
562#ifdef HAVE_REMOTE_LCD_TICKING
563 /* Adjust byte delay for emi reduction. */
564 byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0;
565#endif
566
567 /* Copy display bitmap to hardware */
568 for (y = 0; y < LCD_REMOTE_FBHEIGHT; y++)
569 {
570 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y);
571 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf));
572 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf));
573 lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH);
574 }
575}
576
577/* Update a fraction of the display. */
578void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR;
579void lcd_remote_update_rect(int x, int y, int width, int height)
580{
581 int ymax;
582
583 if (!remote_initialized)
584 return;
585
586 /* The Y coordinates have to work on even 8 pixel rows */
587 ymax = (y + height-1) >> 3;
588 y >>= 3;
589
590 if(x + width > LCD_REMOTE_WIDTH)
591 width = LCD_REMOTE_WIDTH - x;
592 if (width <= 0)
593 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
594 if(ymax >= LCD_REMOTE_FBHEIGHT)
595 ymax = LCD_REMOTE_FBHEIGHT-1;
596
597#ifdef HAVE_REMOTE_LCD_TICKING
598 /* Adjust byte delay for emi reduction */
599 byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0;
600#endif
601
602 /* Copy specified rectange bitmap to hardware */
603 for (; y <= ymax; y++)
604 {
605 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y);
606 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf));
607 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | ((x+xoffset) & 0xf));
608 lcd_remote_write_data(&lcd_remote_framebuffer[y][x], width);
609 }
610}
diff --git a/firmware/target/coldfire/iriver/lcd-remote-target.h b/firmware/target/coldfire/iriver/lcd-remote-target.h
new file mode 100755
index 0000000000..a95f9adade
--- /dev/null
+++ b/firmware/target/coldfire/iriver/lcd-remote-target.h
@@ -0,0 +1,44 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: lcd-remote-target.h 11967 2007-01-09 23:29:07Z linus $
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef LCD_REMOTE_TARGET_H
20#define LCD_REMOTE_TARGET_H
21
22#define REMOTE_INIT_LCD 1
23#define REMOTE_DEINIT_LCD 2
24
25void lcd_remote_write_command(int cmd);
26void lcd_remote_write_command_ex(int cmd, int data);
27void lcd_remote_write_data(const unsigned char* p_bytes, int count);
28#ifdef HAVE_REMOTE_LCD_TICKING
29void lcd_remote_emireduce(bool state);
30#endif
31void lcd_remote_powersave(bool on);
32void lcd_remote_set_invert_display(bool yesno);
33void lcd_remote_set_flip(bool yesno);
34
35bool remote_detect(void);
36void lcd_remote_init_device(void);
37void lcd_remote_on(void);
38void lcd_remote_off(void);
39void lcd_remote_update(void);
40void lcd_remote_update_rect(int, int, int, int);
41
42extern bool remote_initialized;
43
44#endif