diff options
Diffstat (limited to 'firmware/drivers/lcd-ipod.c')
-rw-r--r-- | firmware/drivers/lcd-ipod.c | 99 |
1 files changed, 69 insertions, 30 deletions
diff --git a/firmware/drivers/lcd-ipod.c b/firmware/drivers/lcd-ipod.c index d9b0df5b3c..3f777cf7a9 100644 --- a/firmware/drivers/lcd-ipod.c +++ b/firmware/drivers/lcd-ipod.c | |||
@@ -36,7 +36,6 @@ static inline bool timer_check(int clock_start, int usecs) | |||
36 | return ((int)(USEC_TIMER - clock_start)) >= usecs; | 36 | return ((int)(USEC_TIMER - clock_start)) >= usecs; |
37 | } | 37 | } |
38 | 38 | ||
39 | |||
40 | #if (CONFIG_LCD == LCD_IPOD2BPP) | 39 | #if (CONFIG_LCD == LCD_IPOD2BPP) |
41 | 40 | ||
42 | /*** hardware configuration ***/ | 41 | /*** hardware configuration ***/ |
@@ -63,16 +62,19 @@ static inline bool timer_check(int clock_start, int usecs) | |||
63 | #define R_ROTATION 0x06 | 62 | #define R_ROTATION 0x06 |
64 | #define R_DISPLAY_CONTROL 0x07 | 63 | #define R_DISPLAY_CONTROL 0x07 |
65 | #define R_CURSOR_CONTROL 0x08 | 64 | #define R_CURSOR_CONTROL 0x08 |
66 | #define R_DOUBLE_HEIGHT_POS 0x09 | 65 | #define R_HORIZONTAL_CURSOR_POS 0x0b |
67 | #define R_VERTICAL_SCROLL 0x0a | 66 | #define R_VERTICAL_CURSOR_POS 0x0c |
68 | #define R_VERTICAL_CURSOR_POS 0x0b | 67 | #define R_1ST_SCR_DRV_POS 0x0d |
69 | #define R_HORIZONTAL_CURSOR_POS 0x0c | 68 | #define R_2ND_SCR_DRV_POS 0x0e |
70 | #define R_RAM_WRITE_MASK 0x10 | 69 | #define R_RAM_WRITE_MASK 0x10 |
71 | #define R_RAM_ADDR_SET 0x11 | 70 | #define R_RAM_ADDR_SET 0x11 |
72 | #define R_RAM_DATA 0x12 | 71 | #define R_RAM_DATA 0x12 |
73 | 72 | ||
74 | static unsigned int lcd_contrast = 0x2a; | 73 | /* needed for flip */ |
75 | 74 | static int addr_offset = 0; | |
75 | #if defined(IPOD_MINI) || defined(IPOD_MINI2G) | ||
76 | static int pix_offset = 0; | ||
77 | #endif | ||
76 | 78 | ||
77 | /* wait for LCD with timeout */ | 79 | /* wait for LCD with timeout */ |
78 | static void lcd_wait_write(void) | 80 | static void lcd_wait_write(void) |
@@ -86,7 +88,7 @@ static void lcd_wait_write(void) | |||
86 | 88 | ||
87 | 89 | ||
88 | /* send LCD data */ | 90 | /* send LCD data */ |
89 | static void lcd_send_data(int data) | 91 | static void lcd_send_data(unsigned data) |
90 | { | 92 | { |
91 | lcd_wait_write(); | 93 | lcd_wait_write(); |
92 | #ifdef IPOD_MINI2G | 94 | #ifdef IPOD_MINI2G |
@@ -100,7 +102,7 @@ static void lcd_send_data(int data) | |||
100 | } | 102 | } |
101 | 103 | ||
102 | /* send LCD command */ | 104 | /* send LCD command */ |
103 | static void lcd_prepare_cmd(int cmd) | 105 | static void lcd_prepare_cmd(unsigned cmd) |
104 | { | 106 | { |
105 | lcd_wait_write(); | 107 | lcd_wait_write(); |
106 | #ifdef IPOD_MINI2G | 108 | #ifdef IPOD_MINI2G |
@@ -114,22 +116,17 @@ static void lcd_prepare_cmd(int cmd) | |||
114 | } | 116 | } |
115 | 117 | ||
116 | /* send LCD command and data */ | 118 | /* send LCD command and data */ |
117 | static void lcd_cmd_and_data(int cmd, int data) | 119 | static void lcd_cmd_and_data(unsigned cmd, unsigned data) |
118 | { | 120 | { |
119 | lcd_prepare_cmd(cmd); | 121 | lcd_prepare_cmd(cmd); |
120 | lcd_send_data(data); | 122 | lcd_send_data(data); |
121 | } | 123 | } |
122 | 124 | ||
123 | /* LCD init */ | 125 | /* LCD init */ |
124 | void lcd_init_device(void){ | 126 | void lcd_init_device(void) |
125 | #if defined(IPOD_MINI) || defined(IPOD_MINI2G) | 127 | { |
126 | /* driver output control - 160x112 (ipod mini) */ | 128 | lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0015); |
127 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000d); | 129 | lcd_set_flip(false); |
128 | #else | ||
129 | /* driver output control - 160x128 */ | ||
130 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010f); | ||
131 | #endif | ||
132 | |||
133 | lcd_cmd_and_data(R_ENTRY_MODE, 0x0010); | 130 | lcd_cmd_and_data(R_ENTRY_MODE, 0x0010); |
134 | 131 | ||
135 | #ifdef APPLE_IPOD4G | 132 | #ifdef APPLE_IPOD4G |
@@ -168,22 +165,46 @@ void lcd_set_contrast(int val) | |||
168 | else if (val > 63) val = 63; | 165 | else if (val > 63) val = 63; |
169 | 166 | ||
170 | lcd_cmd_and_data(R_CONTRAST_CONTROL, 0x400 | (val + 64)); | 167 | lcd_cmd_and_data(R_CONTRAST_CONTROL, 0x400 | (val + 64)); |
171 | lcd_contrast = val; | ||
172 | } | 168 | } |
173 | 169 | ||
174 | void lcd_set_invert_display(bool yesno) | 170 | void lcd_set_invert_display(bool yesno) |
175 | { | 171 | { |
176 | if (yesno) | 172 | if (yesno) |
177 | lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0003); | 173 | lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0017); |
178 | else | 174 | else |
179 | lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0001); | 175 | lcd_cmd_and_data(R_DISPLAY_CONTROL, 0x0015); |
180 | } | 176 | } |
181 | 177 | ||
182 | /* turn the display upside down (call lcd_update() afterwards) */ | 178 | /* turn the display upside down (call lcd_update() afterwards) */ |
183 | void lcd_set_flip(bool yesno) | 179 | void lcd_set_flip(bool yesno) |
184 | { | 180 | { |
185 | /* TODO: Implement lcd_set_flip() */ | 181 | #if defined(IPOD_MINI) || defined(IPOD_MINI2G) |
186 | (void)yesno; | 182 | if (yesno) { |
183 | /* 160x112, inverse SEG & COM order */ | ||
184 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x030d); | ||
185 | lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8316); /* 22..131 */ | ||
186 | addr_offset = (22 << 5) | 3; | ||
187 | pix_offset = 6; | ||
188 | } else { | ||
189 | /* 160x112 */ | ||
190 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x000d); | ||
191 | lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x6d00); /* 0..109 */ | ||
192 | addr_offset = 0; | ||
193 | pix_offset = 0; | ||
194 | } | ||
195 | #else | ||
196 | if (yesno) { | ||
197 | /* 160x128, inverse COM order */ | ||
198 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x020f); | ||
199 | lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x8304); /* 0..127 */ | ||
200 | addr_offset = (4 << 5) | 1; | ||
201 | } else { | ||
202 | /* 160x128, inverse SEG order */ | ||
203 | lcd_cmd_and_data(R_DRV_OUTPUT_CONTROL, 0x010f); | ||
204 | lcd_cmd_and_data(R_1ST_SCR_DRV_POS, 0x7f00); /* 4..131 */ | ||
205 | addr_offset = 0; | ||
206 | } | ||
207 | #endif | ||
187 | } | 208 | } |
188 | 209 | ||
189 | void lcd_update_rect(int x, int y, int width, int height) | 210 | void lcd_update_rect(int x, int y, int width, int height) |
@@ -199,6 +220,9 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
199 | if (ymax >= LCD_HEIGHT) | 220 | if (ymax >= LCD_HEIGHT) |
200 | ymax = LCD_HEIGHT - 1; | 221 | ymax = LCD_HEIGHT - 1; |
201 | 222 | ||
223 | #if defined(IPOD_MINI) || defined(IPOD_MINI2G) | ||
224 | x += pix_offset; | ||
225 | #endif | ||
202 | /* writing is done in 16-bit units (8 pixels) */ | 226 | /* writing is done in 16-bit units (8 pixels) */ |
203 | xmax = (x + width - 1) >> 3; | 227 | xmax = (x + width - 1) >> 3; |
204 | x >>= 3; | 228 | x >>= 3; |
@@ -206,17 +230,32 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
206 | 230 | ||
207 | for (; y <= ymax; y++) { | 231 | for (; y <= ymax; y++) { |
208 | unsigned char *data, *data_end; | 232 | unsigned char *data, *data_end; |
209 | int ram_addr = x | (y << 5); | 233 | int ram_addr = (x | (y << 5)) + addr_offset; |
210 | 234 | ||
211 | lcd_cmd_and_data(R_RAM_ADDR_SET, ram_addr); | 235 | lcd_cmd_and_data(R_RAM_ADDR_SET, ram_addr); |
212 | lcd_prepare_cmd(R_RAM_DATA); | 236 | lcd_prepare_cmd(R_RAM_DATA); |
213 | 237 | ||
214 | data = &lcd_framebuffer[y][2*x]; | 238 | data = &lcd_framebuffer[y][2*x]; |
215 | data_end = data + 2 * width; | 239 | data_end = data + 2 * width; |
216 | do { | 240 | #if defined(IPOD_MINI) || defined(IPOD_MINI2G) |
217 | int lowbyte = *data++; | 241 | if (pix_offset == 6) { |
218 | lcd_send_data((*data++ << 8) | lowbyte); | 242 | data -= 2; |
219 | } while (data < data_end); | 243 | data_end -= 1; |
244 | unsigned cur_word = *data++ >> 4; | ||
245 | do { | ||
246 | cur_word |= *data++ << 4; | ||
247 | cur_word |= *data++ << 12; | ||
248 | lcd_send_data(cur_word & 0xffff); | ||
249 | cur_word >>= 16; | ||
250 | } while (data < data_end); | ||
251 | } else | ||
252 | #endif | ||
253 | { | ||
254 | do { | ||
255 | unsigned lowbyte = *data++; | ||
256 | lcd_send_data(lowbyte | (*data++ << 8)); | ||
257 | } while (data < data_end); | ||
258 | } | ||
220 | } | 259 | } |
221 | } | 260 | } |
222 | 261 | ||