lcd drivers: Convert lcd_[remote_]framebuffer to a pointer
[maemo-rb.git] / firmware / target / coldfire / iriver / lcd-remote-iriver.c
blob03c0e40dbe4eebffc226e3c6b7052762b24da04c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "config.h"
23 #include "system.h"
24 #include "file.h"
25 #include "lcd-remote.h"
26 #include "adc.h"
27 #include "scroll_engine.h"
29 /*** definitions ***/
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 */
68 #endif
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)
89 emireduce = state;
91 #endif
93 #if 0 // FIXME
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));
102 #endif
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)
121 cached_flip = yesno;
122 if (yesno)
124 xoffset = 0;
125 if (remote_initialized)
127 lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL);
128 lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL);
131 else
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)
149 return _remote_type;
152 void lcd_remote_on(void)
154 CS_HI;
155 CLK_LO;
156 lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0);
158 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5);
159 sleep(1);
160 lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6);
161 sleep(1);
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);
166 sleep(1);
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;
184 CLK_LO;
185 CS_HI;
188 #ifndef BOOTLOADER
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;
195 bool current_status;
196 int val;
197 int level;
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;
206 else
208 /* Count down until it gets negative */
209 if (countdown >= 0)
210 countdown--;
212 if (current_status)
214 if (!(countdown % 8))
216 /* Determine which type of remote it is */
217 level = disable_irq_save();
218 val = adc_scan(ADC_REMOTEDETECT);
219 restore_irq(level);
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 */
226 else
227 _remote_type = REMOTETYPE_H100_LCD; /* hold off */
228 else
229 if (val < ADCVAL_H300_LCD_REMOTE_HOLD)
230 _remote_type = REMOTETYPE_H300_LCD; /* hold on */
231 else
232 _remote_type = REMOTETYPE_H100_LCD; /* hold on */
234 if (--init_delay <= 0)
236 queue_broadcast(SYS_REMOTE_PLUGGED, 0);
237 init_delay = 6;
240 else
242 _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */
246 else
248 if (countdown == 0)
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)
261 CS_HI;
263 #endif
265 void lcd_remote_init_device(void)
267 #ifdef IRIVER_H300_SERIES
268 or_l(0x10010000, &GPIO_FUNCTION); /* GPIO16: RS
269 GPIO28: CLK */
271 or_l(0x00040006, &GPIO1_FUNCTION); /* GPO33: Backlight
272 GPIO34: CS
273 GPIO50: Data */
274 or_l(0x10010000, &GPIO_ENABLE);
275 or_l(0x00040006, &GPIO1_ENABLE);
276 #else
277 or_l(0x10010800, &GPIO_FUNCTION); /* GPIO11: Backlight
278 GPIO16: RS
279 GPIO28: CLK */
281 or_l(0x00040004, &GPIO1_FUNCTION); /* GPIO34: CS
282 GPIO50: Data */
283 or_l(0x10010800, &GPIO_ENABLE);
284 or_l(0x00040004, &GPIO1_ENABLE);
285 #endif
287 lcd_remote_clear_display();
288 if (remote_detect())
289 lcd_remote_on();
290 #ifndef BOOTLOADER
291 tick_add_task(remote_tick);
292 #endif
295 /* Update the display.
296 This must be called after all other LCD functions that change the display. */
297 void lcd_remote_update(void)
299 int y;
301 if (!remote_initialized)
302 return;
304 #ifdef HAVE_REMOTE_LCD_TICKING
305 /* Adjust byte delay for emi reduction. */
306 remote_byte_delay = emireduce ? cpu_frequency / 206200 - 85: 0;
307 #endif
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)
322 int ymax;
324 if (!remote_initialized)
325 return;
327 /* The Y coordinates have to work on even 8 pixel rows */
328 ymax = (y + height-1) >> 3;
329 y >>= 3;
331 if(x + width > LCD_REMOTE_WIDTH)
332 width = LCD_REMOTE_WIDTH - x;
333 if (width <= 0)
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;
341 #endif
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);