diff options
Diffstat (limited to 'firmware/drivers/lcd-ipod.c')
-rw-r--r-- | firmware/drivers/lcd-ipod.c | 141 |
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 */ |
34 | static int timer_check(int clock_start, int usecs) | 34 | static 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 | ||
61 | static 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 | |||
74 | static 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 */ |
76 | static void lcd_send_data(int data_lo, int data_hi) | 89 | static 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 */ |
104 | static void lcd_cmd_and_data(int cmd, int data_lo, int data_hi) | 117 | static 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 | **/ | ||
115 | void lcd_init_device(void){ | 124 | void 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. */ | ||
157 | void 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 */ |
163 | void lcd_set_contrast(int val) | 165 | void 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 | ||
172 | void lcd_set_invert_display(bool yesno) | 174 | void 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 | ||
185 | void lcd_update_rect(int x, int y, int width, int height) | 189 | void 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. */ |
226 | void lcd_enable (bool on){ | 224 | void 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 |