Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / firmware / target / arm / philips / hdd1630 / lcd-hdd1630.c
blob93abd300ec825f2774238cba17b0b41fa7417a4e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Mark Arigo
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "inttypes.h"
23 #include "config.h"
24 #include "cpu.h"
25 #include "lcd.h"
26 #include "kernel.h"
27 #include "system.h"
29 /* The LCD registers appear to match controllers from Leadis Technology,
30 either the LDS176 (132x132 4k) or the LDS186 (128x160 65k).
31 These defines are from the LDS176 (I couldn't find the LDS186 datasheet. */
32 #define NOP 0x00
33 #define SWRESET 0x01
34 #define BSTROFF 0x02
35 #define BSTRON 0x03
36 #define RDDID 0x04
37 #define RDDST 0x09
38 #define SLPIN 0x10
39 #define SLPOUT 0x11
40 #define PTLON 0x12
41 #define NORON 0x13
42 #define INVOFF 0x20
43 #define INVON 0x21
44 #define APOFF 0x22
45 #define APON 0x23
46 #define WRCNTR 0x25
47 #define DISPOFF 0x28
48 #define DISPON 0x29
49 #define CASET 0x2a
50 #define RASET 0x2b
51 #define RAMWR 0x2c
52 #define RAMRD 0x2e
53 #define RGBSET 0x2d
54 #define PTLAR 0x30
55 #define SCRLAR 0x33
56 #define TEOFF 0x34
57 #define TEON 0x35
58 #define MADCTR 0x36
59 #define VSCSAD 0x37
60 #define IDMOFF 0x38
61 #define IDMON 0x39
62 #define COLMOD 0x3a
63 #define RDID1 0xda
64 #define RDID2 0xdb
65 #define RDID3 0xdc
66 #define CLKINT 0xb0
67 #define CLKEXT 0xb1
68 #define FRMSEL 0xb4
69 #define FRM8SEL 0xb5
70 #define TMPRNG 0xb6
71 #define TMPHIS 0xb7
72 #define TMPREAD 0xb8
73 #define DISCTR 0xba
74 #define EPVOL 0xbb
75 #define EPWRIN 0xd1
76 #define EPWROUT 0xd0
77 #define RDEV 0xd4
78 #define RDRR 0xd5
80 /* Display status */
81 static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
82 static unsigned mad_ctrl = 0;
84 /* wait for LCD */
85 static inline void lcd_wait_write(void)
87 int i = 0;
88 while (LCD2_PORT & LCD2_BUSY_MASK)
90 if (i < 2000)
91 i++;
92 else
93 LCD2_PORT &= ~LCD2_BUSY_MASK;
97 /* send LCD data */
98 static void lcd_send_data(unsigned data)
100 lcd_wait_write();
101 LCD2_PORT = LCD2_DATA_MASK | (data & 0xff);
104 /* send LCD command */
105 static void lcd_send_cmd(unsigned cmd)
107 lcd_wait_write();
108 LCD2_PORT = LCD2_CMD_MASK | (cmd & 0xff);
109 lcd_wait_write();
112 static inline void lcd_send_pixel(unsigned pixel)
114 lcd_send_data(pixel >> 8);
115 lcd_send_data(pixel);
118 void lcd_init_device(void)
120 #if 0
121 /* this sequence from the OF bootloader */
123 DEV_EN2 |= 0x2000;
124 outl(inl(0x70000014) & ~0xf000000, 0x70000014);
125 outl(inl(0x70000014) | 0xa000000, 0x70000014);
126 DEV_INIT1 &= 0xc000;
127 DEV_INIT1 |= 0x8000;
128 MLCD_SCLK_DIV &= ~0x800;
129 CLCD_CLOCK_SRC |= 0xc0000000;
130 DEV_INIT2 &= ~0x400;
131 outl(inl(0x7000002c) | ((1<<4)<<24), 0x7000002c);
132 DEV_INIT2 &= ~((1<<4)<<24);
133 udelay(10000);
135 DEV_INIT2 |= ((1<<4)<<24);
136 outl(0x220, 0x70008a00);
137 outl(0x1f00, 0x70008a04);
138 LCD2_BLOCK_CTRL = 0x10008080;
139 LCD2_BLOCK_CONFIG = 0xF00000;
141 /* lcd power */
142 GPIOJ_ENABLE |= 0x4;
143 GPIOJ_OUTPUT_VAL |= 0x4;
144 GPIOJ_OUTPUT_EN |= 0x4;
146 lcd_send_cmd(SWRESET);
147 udelay(10000);
149 lcd_send_cmd(WRCNTR);
150 lcd_send_data(0x3f);
152 lcd_send_cmd(SLPOUT);
153 udelay(120000);
155 lcd_send_cmd(INVOFF);
156 lcd_send_cmd(IDMOFF);
157 lcd_send_cmd(NORON);
159 lcd_send_cmd(FRMSEL);
160 lcd_send_data(0x2);
161 lcd_send_data(0x6);
162 lcd_send_data(0x8);
163 lcd_send_data(0xd);
165 lcd_send_cmd(FRM8SEL);
166 lcd_send_data(0x2);
167 lcd_send_data(0x6);
168 lcd_send_data(0x8);
169 lcd_send_data(0xd);
171 lcd_send_cmd(TMPRNG);
172 lcd_send_data(0x19);
173 lcd_send_data(0x23);
174 lcd_send_data(0x2d);
176 lcd_send_cmd(TMPHIS);
177 lcd_send_data(0x5);
179 lcd_send_cmd(DISCTR);
180 lcd_send_data(0x7);
181 lcd_send_data(0x18);
183 lcd_send_cmd(MADCTR);
184 lcd_send_data(0);
185 mad_ctrl = 0;
187 lcd_send_cmd(COLMOD);
188 lcd_send_data(0x5);
190 lcd_send_cmd(RGBSET);
191 lcd_send_data(0x1);
192 lcd_send_data(0x2);
193 lcd_send_data(0x3);
194 lcd_send_data(0x4);
195 lcd_send_data(0x5);
196 lcd_send_data(0x6);
197 lcd_send_data(0x7);
198 lcd_send_data(0x8);
199 lcd_send_data(0x9);
200 lcd_send_data(0xa);
201 lcd_send_data(0xb);
202 lcd_send_data(0xc);
203 lcd_send_data(0xd);
204 lcd_send_data(0xe);
205 lcd_send_data(0xf);
206 lcd_send_data(0x10);
207 lcd_send_data(0x11);
208 lcd_send_data(0x12);
209 lcd_send_data(0x13);
210 lcd_send_data(0x14);
211 lcd_send_data(0x15);
212 lcd_send_data(0x16);
213 lcd_send_data(0x17);
214 lcd_send_data(0x18);
215 lcd_send_data(0x19);
216 lcd_send_data(0x1a);
217 lcd_send_data(0x1b);
218 lcd_send_data(0x1c);
219 lcd_send_data(0x1d);
220 lcd_send_data(0x1e);
221 lcd_send_data(0x1f);
222 lcd_send_data(0x20);
223 lcd_send_data(0x21);
224 lcd_send_data(0x22);
225 lcd_send_data(0x23);
226 lcd_send_data(0x24);
227 lcd_send_data(0x25);
228 lcd_send_data(0x26);
229 lcd_send_data(0x27);
230 lcd_send_data(0x28);
231 lcd_send_data(0x29);
232 lcd_send_data(0x2a);
233 lcd_send_data(0x2b);
234 lcd_send_data(0x2c);
235 lcd_send_data(0x2d);
236 lcd_send_data(0x2e);
237 lcd_send_data(0x2f);
238 lcd_send_data(0x30);
240 lcd_send_cmd(DISPON);
241 #endif
244 /*** hardware configuration ***/
245 int lcd_default_contrast(void)
247 return DEFAULT_CONTRAST_SETTING;
250 void lcd_set_contrast(int val)
252 lcd_send_cmd(WRCNTR);
253 lcd_send_data(val);
256 void lcd_set_invert_display(bool yesno)
258 if (yesno)
259 lcd_send_cmd(INVON);
260 else
261 lcd_send_cmd(INVOFF);
264 /* turn the display upside down (call lcd_update() afterwards) */
265 void lcd_set_flip(bool yesno)
267 if (yesno)
268 mad_ctrl |= ((1<<7) | (1<<6)); /* flip */
269 else
270 mad_ctrl &= ~((1<<7) | (1<<6)); /* normal */
272 lcd_send_cmd(MADCTR);
273 lcd_send_data(mad_ctrl);
276 void lcd_yuv_set_options(unsigned options)
278 lcd_yuv_options = options;
281 /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
282 extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
283 int width, int stride);
285 extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
286 int width, int stride,
287 int x_screen, int y_screen);
289 /* Performance function to blit a YUV bitmap directly to the LCD */
290 void lcd_blit_yuv(unsigned char * const src[3],
291 int src_x, int src_y, int stride,
292 int x, int y, int width, int height)
294 unsigned char const * yuv_src[3];
295 off_t z;
297 /* Sorry, but width and height must be >= 2 or else */
298 width &= ~1;
299 height >>= 1;
301 z = stride*src_y;
302 yuv_src[0] = src[0] + z + src_x;
303 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
304 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
306 /* Set vertical address mode */
307 lcd_send_cmd(MADCTR);
308 lcd_send_data(mad_ctrl | (1<<5));
310 lcd_send_cmd(RASET);
311 lcd_send_data(x);
312 lcd_send_data(x + width - 1);
314 if (lcd_yuv_options & LCD_YUV_DITHER)
318 lcd_send_cmd(CASET);
319 lcd_send_data(y);
320 lcd_send_data(y + 1);
322 lcd_send_cmd(RAMWR);
324 lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y);
325 yuv_src[0] += stride << 1; /* Skip down two luma lines */
326 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
327 yuv_src[2] += stride >> 1;
328 y += 2;
330 while (--height > 0);
332 else
336 lcd_send_cmd(CASET);
337 lcd_send_data(y);
338 lcd_send_data(y + 1);
340 lcd_send_cmd(RAMWR);
342 lcd_write_yuv420_lines(yuv_src, width, stride);
343 yuv_src[0] += stride << 1; /* Skip down two luma lines */
344 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
345 yuv_src[2] += stride >> 1;
346 y += 2;
348 while (--height > 0);
351 /* Restore the address mode */
352 lcd_send_cmd(MADCTR);
353 lcd_send_data(mad_ctrl);
356 /* Update the display.
357 This must be called after all other LCD functions that change the display. */
358 void lcd_update(void)
360 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
363 /* Update a fraction of the display. */
364 void lcd_update_rect(int x, int y, int width, int height)
366 const fb_data *addr;
368 if (x + width >= LCD_WIDTH)
369 width = LCD_WIDTH - x;
370 if (y + height >= LCD_HEIGHT)
371 height = LCD_HEIGHT - y;
373 if ((width <= 0) || (height <= 0))
374 return; /* Nothing left to do. */
376 addr = &lcd_framebuffer[y][x];
378 lcd_send_cmd(CASET);
379 lcd_send_data(x);
380 lcd_send_data(x + width - 1);
382 lcd_send_cmd(RASET);
383 lcd_send_data(y);
384 lcd_send_data(y + height - 1);
386 lcd_send_cmd(RAMWR);
387 do {
388 int w = width;
389 do {
390 lcd_send_pixel(*addr++);
391 } while (--w > 0);
392 addr += LCD_WIDTH - width;
393 } while (--height > 0);