diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c b/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c new file mode 100644 index 0000000000..c9cce6d653 --- /dev/null +++ b/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c | |||
@@ -0,0 +1,230 @@ | |||
1 | #include "config.h" | ||
2 | #include "cpu.h" | ||
3 | #include "string.h" | ||
4 | #include "lcd.h" | ||
5 | #include "kernel.h" | ||
6 | #include "lcd-target.h" | ||
7 | |||
8 | #define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) | ||
9 | |||
10 | static volatile bool lcd_on = true; | ||
11 | volatile bool lcd_poweroff = false; | ||
12 | /* | ||
13 | ** These are imported from lcd-16bit.c | ||
14 | */ | ||
15 | extern unsigned fg_pattern; | ||
16 | extern unsigned bg_pattern; | ||
17 | |||
18 | #if 0 | ||
19 | bool lcd_enabled() | ||
20 | { | ||
21 | return lcd_on; | ||
22 | } | ||
23 | #endif | ||
24 | |||
25 | void printscreen(unsigned int colour) { | ||
26 | int i; | ||
27 | int base = 0x84100000; | ||
28 | for(i=0;i<(320*240*2);i++) { | ||
29 | writel(colour,base); | ||
30 | base++; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | unsigned int LCDBANK(unsigned int address) | ||
35 | { | ||
36 | return ((address >> 22) & 0xff); | ||
37 | } | ||
38 | |||
39 | unsigned int LCDBASEU(unsigned int address) | ||
40 | { | ||
41 | return (address & ((1 << 22)-1)) >> 1; | ||
42 | } | ||
43 | |||
44 | unsigned int LCDBASEL(unsigned int address) | ||
45 | { | ||
46 | address += 320*240*2; | ||
47 | return (address & ((1 << 22)-1)) >> 1; | ||
48 | } | ||
49 | |||
50 | |||
51 | /* LCD init */ | ||
52 | void lcd_init_device(void) | ||
53 | { | ||
54 | int i; | ||
55 | #ifdef BOOTLOADER | ||
56 | /* When the Rockbox bootloader starts, we are changing framebuffer address, | ||
57 | but we don't want what's shown on the LCD to change until we do an | ||
58 | lcd_update(), so copy the data from the old framebuffer to the new one */ | ||
59 | unsigned short *buf = (unsigned short*)FRAME1; | ||
60 | |||
61 | memcpy(FRAME1, (short *)((LCDSADDR1)<<1), 320*240*2); | ||
62 | |||
63 | /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode | ||
64 | so convert the frambuffer data accordingly */ | ||
65 | for(i=0; i< 320*240; i++){ | ||
66 | *buf = ((*buf>>1) & 0x1F) | (*buf & 0xffc0); | ||
67 | buf++; | ||
68 | } | ||
69 | return; | ||
70 | #endif | ||
71 | } | ||
72 | |||
73 | /* Update a fraction of the display. */ | ||
74 | void lcd_update_rect(int x, int y, int width, int height) | ||
75 | { | ||
76 | (void)x; | ||
77 | (void)width; | ||
78 | (void)y; | ||
79 | (void)height; | ||
80 | |||
81 | if(!lcd_on) | ||
82 | { | ||
83 | sleep(200); | ||
84 | return; | ||
85 | } | ||
86 | memcpy(((char*)FRAME2) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH))); | ||
87 | } | ||
88 | |||
89 | void lcd_enable(bool state) | ||
90 | { | ||
91 | (void)state; | ||
92 | } | ||
93 | |||
94 | bool lcd_enabled(void) | ||
95 | { | ||
96 | return true; | ||
97 | } | ||
98 | |||
99 | /* Update the display. | ||
100 | This must be called after all other LCD functions that change the display. */ | ||
101 | void lcd_update(void) | ||
102 | { | ||
103 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
104 | } | ||
105 | |||
106 | void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | ||
107 | int stride, int x, int y, int width, | ||
108 | int height) | ||
109 | { | ||
110 | fb_data *dst, *dst_end; | ||
111 | unsigned int transcolor; | ||
112 | |||
113 | /* nothing to draw? */ | ||
114 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
115 | || (x + width <= 0) || (y + height <= 0)) | ||
116 | return; | ||
117 | |||
118 | /* clipping */ | ||
119 | if (x < 0) | ||
120 | { | ||
121 | width += x; | ||
122 | src_x -= x; | ||
123 | x = 0; | ||
124 | } | ||
125 | if (y < 0) | ||
126 | { | ||
127 | height += y; | ||
128 | src_y -= y; | ||
129 | y = 0; | ||
130 | } | ||
131 | if (x + width > LCD_WIDTH) | ||
132 | width = LCD_WIDTH - x; | ||
133 | if (y + height > LCD_HEIGHT) | ||
134 | height = LCD_HEIGHT - y; | ||
135 | |||
136 | src += stride * src_y + src_x; /* move starting point */ | ||
137 | dst = &lcd_framebuffer[(y)][(x)]; | ||
138 | dst_end = dst + height * LCD_WIDTH; | ||
139 | width *= 2; | ||
140 | stride *= 2; | ||
141 | transcolor = TRANSPARENT_COLOR; | ||
142 | asm volatile( | ||
143 | "rowstart: \n" | ||
144 | "mov r0, #0 \n" | ||
145 | "nextpixel: \n" | ||
146 | "ldrh r1, [%0, r0] \n" /* Load word src+r0 */ | ||
147 | "cmp r1, %5 \n" /* Compare to transparent color */ | ||
148 | "strneh r1, [%1, r0] \n" /* Store dst+r0 if not transparent */ | ||
149 | "add r0, r0, #2 \n" | ||
150 | "cmp r0, %2 \n" /* r0 == width? */ | ||
151 | "bne nextpixel \n" /* More in this row? */ | ||
152 | "add %0, %0, %4 \n" /* src += stride */ | ||
153 | "add %1, %1, #480 \n" /* dst += LCD_WIDTH (x2) */ | ||
154 | "cmp %1, %3 \n" | ||
155 | "bne rowstart \n" /* if(dst != dst_end), keep going */ | ||
156 | : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" ); | ||
157 | } | ||
158 | |||
159 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
160 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
161 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | ||
162 | unsigned char const * const src[3], | ||
163 | int width, | ||
164 | int stride); | ||
165 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
166 | /* For the Gigabeat - show it rotated */ | ||
167 | /* So the LCD_WIDTH is now the height */ | ||
168 | void lcd_yuv_blit(unsigned char * const src[3], | ||
169 | int src_x, int src_y, int stride, | ||
170 | int x, int y, int width, int height) | ||
171 | { | ||
172 | /* Caches for chroma data so it only need be recaculated every other | ||
173 | line */ | ||
174 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ | ||
175 | unsigned char const * yuv_src[3]; | ||
176 | off_t z; | ||
177 | |||
178 | if (!lcd_on) | ||
179 | return; | ||
180 | |||
181 | /* Sorry, but width and height must be >= 2 or else */ | ||
182 | width &= ~1; | ||
183 | height >>= 1; | ||
184 | |||
185 | fb_data *dst = (fb_data*)FRAME1 + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; | ||
186 | |||
187 | z = stride*src_y; | ||
188 | yuv_src[0] = src[0] + z + src_x; | ||
189 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
190 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
191 | |||
192 | do | ||
193 | { | ||
194 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, | ||
195 | stride); | ||
196 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
197 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
198 | yuv_src[2] += stride >> 1; | ||
199 | dst -= 2; | ||
200 | } | ||
201 | while (--height > 0); | ||
202 | } | ||
203 | |||
204 | void lcd_set_contrast(int val) { | ||
205 | (void) val; | ||
206 | // TODO: | ||
207 | } | ||
208 | |||
209 | void lcd_set_invert_display(bool yesno) { | ||
210 | (void) yesno; | ||
211 | // TODO: | ||
212 | } | ||
213 | |||
214 | void lcd_blit(const fb_data* data, int bx, int y, int bwidth, | ||
215 | int height, int stride) | ||
216 | { | ||
217 | (void) data; | ||
218 | (void) bx; | ||
219 | (void) y; | ||
220 | (void) bwidth; | ||
221 | (void) height; | ||
222 | (void) stride; | ||
223 | //TODO: | ||
224 | } | ||
225 | |||
226 | void lcd_set_flip(bool yesno) { | ||
227 | (void) yesno; | ||
228 | // TODO: | ||
229 | } | ||
230 | |||