diff options
author | Tomasz Moń <desowin@gmail.com> | 2011-11-16 14:08:01 +0000 |
---|---|---|
committer | Tomasz Moń <desowin@gmail.com> | 2011-11-16 14:08:01 +0000 |
commit | e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4 (patch) | |
tree | 084e1cdf27a339ce58e24cff8fec8c31432b52db /firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | |
parent | 992d4eb775cac48e107e18d72783ebfb39c4234f (diff) | |
download | rockbox-e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4.tar.gz rockbox-e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4.zip |
Sandisk Sansa Connect port (FS #12363)
Included are drivers for buttons, backlight, lcd, audio and storage.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31000 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c')
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c new file mode 100644 index 0000000000..fcfc82e876 --- /dev/null +++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Tomasz Moń | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <sys/types.h> | ||
23 | #include "config.h" | ||
24 | #include "cpu.h" | ||
25 | #include "string.h" | ||
26 | #include "kernel.h" | ||
27 | #include "system.h" | ||
28 | #include "system-target.h" | ||
29 | #include "lcd.h" | ||
30 | #include "lcd-target.h" | ||
31 | #include "avr-sansaconnect.h" | ||
32 | |||
33 | /* Copies a rectangle from one framebuffer to another. Can be used in | ||
34 | single transfer mode with width = num pixels, and height = 1 which | ||
35 | allows a full-width rectangle to be copied more efficiently. */ | ||
36 | extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, | ||
37 | int width, int height); | ||
38 | |||
39 | static bool lcd_on = true; | ||
40 | |||
41 | bool lcd_active(void) | ||
42 | { | ||
43 | return lcd_on; | ||
44 | } | ||
45 | |||
46 | #if defined(HAVE_LCD_SLEEP) | ||
47 | void lcd_sleep(void) | ||
48 | { | ||
49 | if (lcd_on) | ||
50 | { | ||
51 | lcd_on = false; | ||
52 | avr_hid_lcm_sleep(); | ||
53 | sleep(HZ/20); | ||
54 | |||
55 | /* disable video encoder */ | ||
56 | bitclr16(&IO_VID_ENC_VMOD, 0x01); | ||
57 | |||
58 | sleep(HZ/20); | ||
59 | |||
60 | /* disable video encoder clock */ | ||
61 | bitclr16(&IO_CLK_MOD1, CLK_MOD1_VENC); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | void lcd_awake(void) | ||
66 | { | ||
67 | if (!lcd_on) | ||
68 | { | ||
69 | lcd_on = true; | ||
70 | /* enable video encoder clock */ | ||
71 | bitset16(&IO_CLK_MOD1, CLK_MOD1_VENC); | ||
72 | |||
73 | /* enable video encoder */ | ||
74 | bitset16(&IO_VID_ENC_VMOD, 0x01); | ||
75 | |||
76 | avr_hid_lcm_wake(); | ||
77 | |||
78 | send_event(LCD_EVENT_ACTIVATION, NULL); | ||
79 | |||
80 | lcd_update(); | ||
81 | } | ||
82 | } | ||
83 | #endif | ||
84 | |||
85 | void lcd_init_device(void) | ||
86 | { | ||
87 | unsigned int addr; | ||
88 | |||
89 | /* Disable Video Encoder clock */ | ||
90 | bitclr16(&IO_CLK_MOD1, CLK_MOD1_VENC); | ||
91 | |||
92 | /* configure GIO39, GIO34 and GIO33 as outputs */ | ||
93 | IO_GIO_DIR2 &= ~((1 << 7) /* GIO39 */ | (1 << 2) /* GIO34 */ | | ||
94 | (1 << 1) /* GIO33 */); | ||
95 | |||
96 | IO_GIO_FSEL3 = (IO_GIO_FSEL3 & ~(0x300F)) | | ||
97 | (0x1000) /* GIO39 - FIELD_VENC */ | | ||
98 | (0x3) /* GIO33 - CLKOUT1B (bootloader does this) */ | | ||
99 | (0x4); /* GIO34 - PWM1 (brightness control) */ | ||
100 | |||
101 | /* OSD Clock = VENC Clock /2, | ||
102 | CCD clock PCLK, | ||
103 | VENC Clock from PLLA */ | ||
104 | IO_CLK_SEL1 = 0x3; | ||
105 | |||
106 | /* Set VENC Clock Division to 11 | ||
107 | OF bootloader sets division to 8, vmlinux sets it to 11 */ | ||
108 | IO_CLK_DIV3 = (IO_CLK_DIV3 & ~(0x1F00)) | 0xB00; | ||
109 | |||
110 | /* Enable DAC and OSD clocks */ | ||
111 | bitset16(&IO_CLK_MOD1, CLK_MOD1_DAC | CLK_MOD1_OSD); | ||
112 | |||
113 | /* magic values based on OF bootloader initialization */ | ||
114 | IO_VID_ENC_VMOD = 0x2010; | ||
115 | IO_VID_ENC_VDPRO = 0x80; | ||
116 | IO_VID_ENC_HSPLS = 0x4; | ||
117 | IO_VID_ENC_HINT = 0x4B0; | ||
118 | IO_VID_ENC_HSTART = 0x88; | ||
119 | IO_VID_ENC_HVALID = 0x3C0; | ||
120 | IO_VID_ENC_HSDLY = 0; | ||
121 | IO_VID_ENC_VSPLS = 0x2; | ||
122 | IO_VID_ENC_VINT = 0x152; | ||
123 | IO_VID_ENC_VSTART = 0x6; | ||
124 | IO_VID_ENC_VVALID = 0x140; | ||
125 | IO_VID_ENC_VSDLY = 0; | ||
126 | IO_VID_ENC_DCLKCTL = 0x3; | ||
127 | IO_VID_ENC_DCLKPTN0 = 0xC; | ||
128 | IO_VID_ENC_VDCTL = 0x6000; | ||
129 | IO_VID_ENC_SYNCTL = 0x2; | ||
130 | IO_VID_ENC_LCDOUT = 0x101; | ||
131 | IO_VID_ENC_VMOD = 0x2011; | ||
132 | |||
133 | /* Copy Rockbox frame buffer to the second framebuffer */ | ||
134 | lcd_update(); | ||
135 | |||
136 | avr_hid_lcm_power_on(); | ||
137 | |||
138 | /* set framebuffer address - OF sets RAM start address to 0x1000000 */ | ||
139 | addr = ((int)FRAME-CONFIG_SDRAM_START)/32; | ||
140 | |||
141 | IO_OSD_OSDWINADH = addr >> 16; | ||
142 | IO_OSD_OSDWIN0ADL = addr & 0xFFFF; | ||
143 | |||
144 | IO_OSD_BASEPX = 0x44; | ||
145 | IO_OSD_BASEPY = 0x6; | ||
146 | IO_OSD_OSDWIN0XP = 0; | ||
147 | IO_OSD_OSDWIN0YP = 0; | ||
148 | IO_OSD_OSDWIN0XL = LCD_WIDTH*2; /* OF bootloader sets 480 */ | ||
149 | IO_OSD_OSDWIN0YL = LCD_HEIGHT; /* OF bootloader sets 320 */ | ||
150 | IO_OSD_OSDWIN0OFST = 0xF; | ||
151 | IO_OSD_OSDWINMD0 = 0x25FB;/* OF bootloader sets 25C3, | ||
152 | vmlinux changes this to 0x25FB */ | ||
153 | IO_OSD_VIDWINMD = 0; /* disable video windows (OF sets 0x03) */ | ||
154 | |||
155 | IO_OSD_OSDWINMD1 = 0; /* disable OSD window 1 */ | ||
156 | |||
157 | /* Enable DAC, Video Encoder and OSD clocks */ | ||
158 | bitset16(&IO_CLK_MOD1, CLK_MOD1_DAC | CLK_MOD1_VENC | CLK_MOD1_OSD); | ||
159 | |||
160 | /* Enable Video Encoder - RGB666, custom timing */ | ||
161 | IO_VID_ENC_VMOD = 0x2011; | ||
162 | avr_hid_lcm_wake(); | ||
163 | } | ||
164 | |||
165 | /* Update a fraction of the display. */ | ||
166 | void lcd_update_rect(int x, int y, int width, int height) | ||
167 | __attribute__ ((section(".icode"))); | ||
168 | void lcd_update_rect(int x, int y, int width, int height) | ||
169 | { | ||
170 | register fb_data *dst, *src; | ||
171 | |||
172 | if (!lcd_on) | ||
173 | return; | ||
174 | |||
175 | if ((width | height) < 0) | ||
176 | return; /* Nothing left to do */ | ||
177 | |||
178 | if (x + width > LCD_WIDTH) | ||
179 | width = LCD_WIDTH - x; /* Clip right */ | ||
180 | if (x < 0) | ||
181 | width += x, x = 0; /* Clip left */ | ||
182 | |||
183 | if (y + height > LCD_HEIGHT) | ||
184 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
185 | if (y < 0) | ||
186 | height += y, y = 0; /* Clip top */ | ||
187 | |||
188 | dst = FRAME + LCD_WIDTH*y + x; | ||
189 | src = &lcd_framebuffer[y][x]; | ||
190 | |||
191 | /* Copy part of the Rockbox framebuffer to the second framebuffer */ | ||
192 | if (width < LCD_WIDTH) | ||
193 | { | ||
194 | /* Not full width - do line-by-line */ | ||
195 | lcd_copy_buffer_rect(dst, src, width, height); | ||
196 | } | ||
197 | else | ||
198 | { | ||
199 | /* Full width - copy as one line */ | ||
200 | lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /* Update the display. | ||
205 | This must be called after all other LCD functions that change the display. */ | ||
206 | void lcd_update(void) __attribute__ ((section(".icode"))); | ||
207 | void lcd_update(void) | ||
208 | { | ||
209 | if (!lcd_on) | ||
210 | return; | ||
211 | |||
212 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
213 | } | ||
214 | |||
215 | void lcd_set_contrast(int val) { | ||
216 | (void) val; | ||
217 | // TODO: | ||
218 | } | ||
219 | |||
220 | void lcd_set_invert_display(bool yesno) { | ||
221 | (void) yesno; | ||
222 | // TODO: | ||
223 | } | ||
224 | |||
225 | void lcd_set_flip(bool yesno) { | ||
226 | (void) yesno; | ||
227 | // TODO: | ||
228 | } | ||
229 | |||
230 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
231 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
232 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | ||
233 | unsigned char const * const src[3], | ||
234 | int width, int stride); | ||
235 | |||
236 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
237 | void lcd_blit_yuv(unsigned char * const src[3], | ||
238 | int src_x, int src_y, int stride, | ||
239 | int x, int y, int width, int height) | ||
240 | { | ||
241 | /* Caches for chroma data so it only need be recalculated every other | ||
242 | line */ | ||
243 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ | ||
244 | unsigned char const * yuv_src[3]; | ||
245 | off_t z; | ||
246 | |||
247 | if (!lcd_on) | ||
248 | return; | ||
249 | |||
250 | /* Sorry, but width and height must be >= 2 or else */ | ||
251 | width &= ~1; | ||
252 | height >>= 1; | ||
253 | |||
254 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; | ||
255 | |||
256 | z = stride*src_y; | ||
257 | yuv_src[0] = src[0] + z + src_x; | ||
258 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
259 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
260 | |||
261 | do | ||
262 | { | ||
263 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, | ||
264 | stride); | ||
265 | |||
266 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
267 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
268 | yuv_src[2] += stride >> 1; | ||
269 | dst -= 2; | ||
270 | } | ||
271 | while (--height > 0); | ||
272 | } | ||
273 | |||