1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Richard S. La Charité III
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #include "lcd-remote.h"
27 #include "scroll_engine.h"
31 #define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0
32 #define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1
33 #define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0
34 #define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8
35 #define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae
36 #define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4
37 #define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6
38 #define LCD_REMOTE_CNTL_NOP 0xe3
39 #define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b
40 #define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20
41 #define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2
42 #define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81
43 #define LCD_REMOTE_CNTL_INIT_LINE 0x40
44 #define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0
46 #define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */
47 #define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */
49 #define CS_LO and_l(~0x00000004, &GPIO1_OUT)
50 #define CS_HI or_l(0x00000004, &GPIO1_OUT)
51 #define CLK_LO and_l(~0x10000000, &GPIO_OUT)
52 #define CLK_HI or_l(0x10000000, &GPIO_OUT)
53 #define DATA_LO and_l(~0x00040000, &GPIO1_OUT)
54 #define DATA_HI or_l(0x00040000, &GPIO1_OUT)
55 #define RS_LO and_l(~0x00010000, &GPIO_OUT)
56 #define RS_HI or_l(0x00010000, &GPIO_OUT)
58 static int xoffset
; /* needed for flip */
60 /* timeout counter for deasserting /CS after access, <0 means not counting */
61 int remote_cs_countdown IDATA_ATTR
= 0;
62 #define CS_TIMEOUT (HZ/10)
64 #ifdef HAVE_REMOTE_LCD_TICKING
65 /* If set to true, will prevent "ticking" to headphones. */
66 static bool emireduce
= false;
67 int remote_byte_delay
= 0; /* used in lcd-remote-as-iriver.S */
70 bool remote_initialized
= false;
71 static int _remote_type
= REMOTETYPE_UNPLUGGED
;
73 /* cached settings values */
74 static bool cached_invert
= false;
75 static bool cached_flip
= false;
76 static int cached_contrast
= DEFAULT_REMOTE_CONTRAST_SETTING
;
79 /*** hardware configuration ***/
81 int lcd_remote_default_contrast(void)
83 return DEFAULT_REMOTE_CONTRAST_SETTING
;
86 #ifdef HAVE_REMOTE_LCD_TICKING
87 void lcd_remote_emireduce(bool state
)
94 void lcd_remote_powersave(bool on
)
96 if (remote_initialized
)
98 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF
| (on
? 0 : 1));
99 lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF
| (on
? 1 : 0));
104 void lcd_remote_set_contrast(int val
)
106 cached_contrast
= val
;
107 if (remote_initialized
)
108 lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE
, val
);
111 void lcd_remote_set_invert_display(bool yesno
)
113 cached_invert
= yesno
;
114 if (remote_initialized
)
115 lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF
| (yesno
?1:0));
118 /* turn the display upside down (call lcd_remote_update() afterwards) */
119 void lcd_remote_set_flip(bool yesno
)
125 if (remote_initialized
)
127 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL
);
128 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL
);
133 xoffset
= 132 - LCD_REMOTE_WIDTH
;
134 if (remote_initialized
)
136 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE
);
137 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE
);
142 bool remote_detect(void)
144 return (GPIO_READ
& 0x40000000)?false:true;
147 int remote_type(void)
152 void lcd_remote_on(void)
156 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS
| 0x0);
158 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL
| 0x5);
160 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL
| 0x6);
162 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL
| 0x7);
164 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_REGULATOR
| 0x4); // 0x4 Select regulator @ 5.0 (default);
168 lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE
| 0x0); // init line
169 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS
| 0x0); // page address
170 lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB
172 lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF
| 1);
174 remote_initialized
= true;
176 lcd_remote_set_flip(cached_flip
);
177 lcd_remote_set_contrast(cached_contrast
);
178 lcd_remote_set_invert_display(cached_invert
);
181 void lcd_remote_off(void)
183 remote_initialized
= false;
189 /* Monitor remote hotswap */
190 static void remote_tick(void)
192 static bool last_status
= false;
193 static int countdown
= 0;
194 static int init_delay
= 0;
199 current_status
= remote_detect();
200 /* Only report when the status has changed */
201 if (current_status
!= last_status
)
203 last_status
= current_status
;
204 countdown
= current_status
? 20*HZ
: 1;
208 /* Count down until it gets negative */
214 if (!(countdown
% 8))
216 /* Determine which type of remote it is */
217 level
= disable_irq_save();
218 val
= adc_scan(ADC_REMOTEDETECT
);
221 if (val
< ADCVAL_H100_LCD_REMOTE_HOLD
)
223 if (val
< ADCVAL_H100_LCD_REMOTE
)
224 if (val
< ADCVAL_H300_LCD_REMOTE
)
225 _remote_type
= REMOTETYPE_H300_LCD
; /* hold off */
227 _remote_type
= REMOTETYPE_H100_LCD
; /* hold off */
229 if (val
< ADCVAL_H300_LCD_REMOTE_HOLD
)
230 _remote_type
= REMOTETYPE_H300_LCD
; /* hold on */
232 _remote_type
= REMOTETYPE_H100_LCD
; /* hold on */
234 if (--init_delay
<= 0)
236 queue_broadcast(SYS_REMOTE_PLUGGED
, 0);
242 _remote_type
= REMOTETYPE_H300_NONLCD
; /* hold on or off */
250 _remote_type
= REMOTETYPE_UNPLUGGED
;
252 queue_broadcast(SYS_REMOTE_UNPLUGGED
, 0);
257 /* handle chip select timeout */
258 if (remote_cs_countdown
>= 0)
259 remote_cs_countdown
--;
260 if (remote_cs_countdown
== 0)
265 void lcd_remote_init_device(void)
267 #ifdef IRIVER_H300_SERIES
268 or_l(0x10010000, &GPIO_FUNCTION
); /* GPIO16: RS
271 or_l(0x00040006, &GPIO1_FUNCTION
); /* GPO33: Backlight
274 or_l(0x10010000, &GPIO_ENABLE
);
275 or_l(0x00040006, &GPIO1_ENABLE
);
277 or_l(0x10010800, &GPIO_FUNCTION
); /* GPIO11: Backlight
281 or_l(0x00040004, &GPIO1_FUNCTION
); /* GPIO34: CS
283 or_l(0x10010800, &GPIO_ENABLE
);
284 or_l(0x00040004, &GPIO1_ENABLE
);
287 lcd_remote_clear_display();
291 tick_add_task(remote_tick
);
295 /* Update the display.
296 This must be called after all other LCD functions that change the display. */
297 void lcd_remote_update(void)
301 if (!remote_initialized
)
304 #ifdef HAVE_REMOTE_LCD_TICKING
305 /* Adjust byte delay for emi reduction. */
306 remote_byte_delay
= emireduce
? cpu_frequency
/ 206200 - 85: 0;
309 /* Copy display bitmap to hardware */
310 for (y
= 0; y
< LCD_REMOTE_FBHEIGHT
; y
++)
312 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS
| y
);
313 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL
| ((xoffset
>> 4) & 0xf));
314 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL
| (xoffset
& 0xf));
315 lcd_remote_write_data(FBREMOTEADDR(0, y
), LCD_REMOTE_WIDTH
);
319 /* Update a fraction of the display. */
320 void lcd_remote_update_rect(int x
, int y
, int width
, int height
)
324 if (!remote_initialized
)
327 /* The Y coordinates have to work on even 8 pixel rows */
328 ymax
= (y
+ height
-1) >> 3;
331 if(x
+ width
> LCD_REMOTE_WIDTH
)
332 width
= LCD_REMOTE_WIDTH
- x
;
334 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
335 if(ymax
>= LCD_REMOTE_FBHEIGHT
)
336 ymax
= LCD_REMOTE_FBHEIGHT
-1;
338 #ifdef HAVE_REMOTE_LCD_TICKING
339 /* Adjust byte delay for emi reduction */
340 remote_byte_delay
= emireduce
? cpu_frequency
/ 206200 - 85: 0;
343 /* Copy specified rectange bitmap to hardware */
344 for (; y
<= ymax
; y
++)
346 lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS
| y
);
347 lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL
| (((x
+xoffset
) >> 4) & 0xf));
348 lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL
| ((x
+xoffset
) & 0xf));
349 lcd_remote_write_data(FBREMOTEADDR(x
,y
), width
);