summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-03-31 07:32:38 +0000
committerJens Arnold <amiconn@rockbox.org>2006-03-31 07:32:38 +0000
commit8c6e737bfb13516277e663d217abad8597fe84f4 (patch)
treecc859afc071fac29cd45a1c61078dc19a012ac9d /firmware
parentbfeb9f7f7de1a08892c5e24ccf8691d7301b2ba0 (diff)
downloadrockbox-8c6e737bfb13516277e663d217abad8597fe84f4.tar.gz
rockbox-8c6e737bfb13516277e663d217abad8597fe84f4.zip
Greyscale iPod LCD driver: Fixed lcd_update_rect() to work properly for partial updates. Working display invert. Use register name macros. Some cleanup & optimisations.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9378 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-ipod.c141
1 files changed, 64 insertions, 77 deletions
diff --git a/firmware/drivers/lcd-ipod.c b/firmware/drivers/lcd-ipod.c
index 8936dad912..d9b0df5b3c 100644
--- a/firmware/drivers/lcd-ipod.c
+++ b/firmware/drivers/lcd-ipod.c
@@ -31,13 +31,9 @@
31 31
32 32
33/* check if number of useconds has past */ 33/* check if number of useconds has past */
34static int timer_check(int clock_start, int usecs) 34static inline bool timer_check(int clock_start, int usecs)
35{ 35{
36 if ( ((int)(USEC_TIMER - clock_start)) >= usecs ) { 36 return ((int)(USEC_TIMER - clock_start)) >= usecs;
37 return 1;
38 } else {
39 return 0;
40 }
41} 37}
42 38
43 39
@@ -53,12 +49,29 @@ static int timer_check(int clock_start, int usecs)
53#define IPOD_LCD_BUSY_MASK 0x00008000 49#define IPOD_LCD_BUSY_MASK 0x00008000
54#endif 50#endif
55 51
56/* LCD command codes for HD66789R */ 52/* LCD command codes for HD66753 */
57 53
58#define LCD_CMD 0x08 54#define LCD_CMD 0x08
59#define LCD_DATA 0x10 55#define LCD_DATA 0x10
60 56
61static unsigned int lcd_contrast = 0x6a; 57#define R_START_OSC 0x00
58#define R_DRV_OUTPUT_CONTROL 0x01
59#define R_DRV_WAVEFORM_CONTROL 0x02
60#define R_POWER_CONTROL 0x03
61#define R_CONTRAST_CONTROL 0x04
62#define R_ENTRY_MODE 0x05
63#define R_ROTATION 0x06
64#define R_DISPLAY_CONTROL 0x07
65#define R_CURSOR_CONTROL 0x08
66#define R_DOUBLE_HEIGHT_POS 0x09
67#define R_VERTICAL_SCROLL 0x0a
68#define R_VERTICAL_CURSOR_POS 0x0b
69#define R_HORIZONTAL_CURSOR_POS 0x0c
70#define R_RAM_WRITE_MASK 0x10
71#define R_RAM_ADDR_SET 0x11
72#define R_RAM_DATA 0x12
73
74static unsigned int lcd_contrast = 0x2a;
62 75
63 76
64/* wait for LCD with timeout */ 77/* wait for LCD with timeout */
@@ -73,16 +86,16 @@ static void lcd_wait_write(void)
73 86
74 87
75/* send LCD data */ 88/* send LCD data */
76static void lcd_send_data(int data_lo, int data_hi) 89static void lcd_send_data(int data)
77{ 90{
78 lcd_wait_write(); 91 lcd_wait_write();
79#ifdef IPOD_MINI2G 92#ifdef IPOD_MINI2G
80 outl((inl(IPOD_LCD_BASE) & ~0x1f00000) | 0x1700000, IPOD_LCD_BASE); 93 outl((inl(IPOD_LCD_BASE) & ~0x1f00000) | 0x1700000, IPOD_LCD_BASE);
81 outl(data_hi | (data_lo << 8) | 0x760000, IPOD_LCD_BASE+8); 94 outl(data | 0x760000, IPOD_LCD_BASE+8);
82#else 95#else
83 outl(data_lo, IPOD_LCD_BASE + LCD_DATA); 96 outl(data >> 8, IPOD_LCD_BASE + LCD_DATA);
84 lcd_wait_write(); 97 lcd_wait_write();
85 outl(data_hi, IPOD_LCD_BASE + LCD_DATA); 98 outl(data & 0xff, IPOD_LCD_BASE + LCD_DATA);
86#endif 99#endif
87} 100}
88 101
@@ -101,27 +114,23 @@ static void lcd_prepare_cmd(int cmd)
101} 114}
102 115
103/* send LCD command and data */ 116/* send LCD command and data */
104static void lcd_cmd_and_data(int cmd, int data_lo, int data_hi) 117static void lcd_cmd_and_data(int cmd, int data)
105{ 118{
106 lcd_prepare_cmd(cmd); 119 lcd_prepare_cmd(cmd);
107 120 lcd_send_data(data);
108 lcd_send_data(data_lo, data_hi);
109} 121}
110 122
111/** 123/* LCD init */
112 *
113 * LCD init
114 **/
115void lcd_init_device(void){ 124void lcd_init_device(void){
116#if defined(IPOD_MINI) || defined(IPOD_MINI2G) 125#if defined(IPOD_MINI) || defined(IPOD_MINI2G)
117 /* driver output control - 160x112 (ipod mini) */ 126 /* driver output control - 160x112 (ipod mini) */
118 lcd_cmd_and_data(0x1, 0x0, 0xd); 127 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000d);
119#else 128#else
120 /* driver output control - 160x128 */ 129 /* driver output control - 160x128 */
121 lcd_cmd_and_data(0x1, 0x1, 0xf); 130 lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010f);
122#endif 131#endif
123 132
124 lcd_cmd_and_data(0x5, 0x0, 0x10); 133 lcd_cmd_and_data(R_ENTRY_MODE, 0x0010);
125 134
126#ifdef APPLE_IPOD4G 135#ifdef APPLE_IPOD4G
127 outl(inl(0x6000d004) | 0x4, 0x6000d004); /* B02 enable */ 136 outl(inl(0x6000d004) | 0x4, 0x6000d004); /* B02 enable */
@@ -152,27 +161,22 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
152 161
153/*** hardware configuration ***/ 162/*** hardware configuration ***/
154 163
155/* Update the display.
156 This must be called after all other LCD functions that change the display. */
157void lcd_update(void)
158{
159 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
160}
161
162/* Rockbox stores the contrast as 0..63 - we add 64 to it */ 164/* Rockbox stores the contrast as 0..63 - we add 64 to it */
163void lcd_set_contrast(int val) 165void lcd_set_contrast(int val)
164{ 166{
165 if (val < 0) val = 0; 167 if (val < 0) val = 0;
166 else if (val > 63) val = 63; 168 else if (val > 63) val = 63;
167 169
168 lcd_cmd_and_data(0x4, 0x4, val + 64); 170 lcd_cmd_and_data(R_CONTRAST_CONTROL, 0x400 | (val + 64));
169 lcd_contrast = val; 171 lcd_contrast = val;
170} 172}
171 173
172void lcd_set_invert_display(bool yesno) 174void lcd_set_invert_display(bool yesno)
173{ 175{
174 /* TODO: Implement lcd_set_invert_display() */ 176 if (yesno)
175 (void)yesno; 177 lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0003);
178 else
179 lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0001);
176} 180}
177 181
178/* turn the display upside down (call lcd_update() afterwards) */ 182/* turn the display upside down (call lcd_update() afterwards) */
@@ -184,59 +188,42 @@ void lcd_set_flip(bool yesno)
184 188
185void lcd_update_rect(int x, int y, int width, int height) 189void lcd_update_rect(int x, int y, int width, int height)
186{ 190{
187 int cursor_pos, xx; 191 int xmax, ymax;
188 int ny;
189 int sx = x, sy = y, mx = width, my = height;
190 192
191 /* only update the ipod if we are writing to the screen */ 193 if (x + width > LCD_WIDTH)
194 width = LCD_WIDTH - x;
195 if (width <= 0)
196 return;
192 197
193 sx >>= 3; 198 ymax = y + height - 1;
194 //mx = (mx+7)>>3; 199 if (ymax >= LCD_HEIGHT)
195 mx >>= 3; 200 ymax = LCD_HEIGHT - 1;
196 201
197 cursor_pos = sx + (sy << 5); 202 /* writing is done in 16-bit units (8 pixels) */
203 xmax = (x + width - 1) >> 3;
204 x >>= 3;
205 width = xmax - x + 1;
198 206
199 for ( ny = sy; ny <= my; ny++ ) { 207 for (; y <= ymax; y++) {
200 unsigned char * img_data; 208 unsigned char *data, *data_end;
201 209 int ram_addr = x | (y << 5);
202 210
203 // move the cursor 211 lcd_cmd_and_data(R_RAM_ADDR_SET, ram_addr);
204 lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff); 212 lcd_prepare_cmd(R_RAM_DATA);
205 213
206 // setup for printing 214 data = &lcd_framebuffer[y][2*x];
207 lcd_prepare_cmd(0x12); 215 data_end = data + 2 * width;
208 216 do {
209 img_data = &lcd_framebuffer[ny][sx<<1]; 217 int lowbyte = *data++;
210 218 lcd_send_data((*data++ << 8) | lowbyte);
211 // 160/8 -> 20 == loops 20 times 219 } while (data < data_end);
212 // make sure we loop at least once
213 for ( xx = sx; xx <= mx; xx++ ) {
214 // display a character
215 lcd_send_data(*(img_data+1), *img_data);
216
217 img_data += 2;
218 }
219
220 // update cursor pos counter
221 cursor_pos += 0x20;
222 } 220 }
223} 221}
224 222
225/** Switch on or off the backlight **/ 223/* Update the display. */
226void lcd_enable (bool on){ 224void lcd_update(void)
227 int lcd_state; 225{
228 226 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
229 lcd_state = inl(IPOD_LCD_BASE);
230 if (on){
231 lcd_state = lcd_state | 0x2;
232 outl(lcd_state, IPOD_LCD_BASE);
233 lcd_cmd_and_data(0x7, 0x0, 0x11);
234 }
235 else {
236 lcd_state = lcd_state & ~0x2;
237 outl(lcd_state, IPOD_LCD_BASE);
238 lcd_cmd_and_data(0x7, 0x0, 0x9);
239 }
240} 227}
241 228
242#else 229#else