summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c')
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
new file mode 100644
index 0000000000..dec20ad72f
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c
@@ -0,0 +1,405 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2008 by Maurus Cuelenaere
11*
12* All files in this archive are subject to the GNU General Public License.
13* See the file COPYING in the source tree root for full license agreement.
14*
15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16* KIND, either express or implied.
17*
18****************************************************************************/
19#include "config.h"
20
21#include "hwcompat.h"
22#include "kernel.h"
23#include "lcd.h"
24#include "system.h"
25#include "memory.h"
26#include "cpu.h"
27#include "spi.h"
28#include "spi-target.h"
29#include "lcd-target.h"
30
31/* Power and display status */
32static bool display_on = true; /* Is the display turned on? */
33static bool direct_fb_access = false; /* Does the DM320 has direct access to the FB? */
34
35int lcd_default_contrast(void)
36{
37 return 0x1f;
38}
39
40void lcd_set_contrast(int val)
41{
42 /* iirc there is an ltv250qv command to do this */
43 #warning function not implemented
44 (void)val;
45}
46
47void lcd_set_invert_display(bool yesno) {
48 (void) yesno;
49 // TODO:
50}
51
52void lcd_set_flip(bool yesno) {
53 (void) yesno;
54 // TODO:
55}
56
57
58/* LTV250QV panel functions */
59
60static void lcd_write_reg(unsigned char reg, unsigned short val)
61{
62 unsigned char block[3];
63 block[0] = 0x74;
64 block[1] = 0;
65 block[2] = reg | 0xFF;
66 spi_block_transfer(SPI_target_LTV250QV, block, sizeof(block), NULL, 0);
67 block[0] = 0x76;
68 block[1] = (val >> 8) & 0xFF;
69 block[2] = val & 0xFF;
70 spi_block_transfer(SPI_target_LTV250QV, block, sizeof(block), NULL, 0);
71}
72
73static void sleep_ms(unsigned int ms)
74{
75 sleep(ms*HZ/1000);
76}
77
78static void lcd_display_on(void)
79{
80 /* Enable main power */
81 IO_GIO_BITSET2 |= (1 << 3);
82
83 /* power on sequence as per the ZVM firmware */
84 sleep_ms(250);
85 IO_GIO_BITSET1 = (1 << 13);
86 sleep_ms(5);
87 IO_GIO_BITSET2 = (1 << 5);
88 IO_GIO_BITSET2 = (1 << 8);
89 sleep_ms(1);
90
91 //Init SPI here...
92 sleep_ms(32);
93
94 IO_GIO_BITSET2 = (1 << 0);
95 sleep_ms(5);
96 IO_GIO_BITSET2 = (1 << 7);
97 sleep_ms(5);
98 IO_GIO_BITSET2 = (1 << 4);
99 sleep_ms(5);
100 IO_GIO_BITCLR2 = (1 << 8);
101 //TODO: figure out what OF does after this...
102 IO_GIO_BITSET2 = (1 << 8);
103 sleep_ms(1);
104
105 lcd_write_reg(1, 0x1D);
106 lcd_write_reg(2, 0x0);
107 lcd_write_reg(3, 0x0);
108 lcd_write_reg(4, 0x0);
109 lcd_write_reg(5, 0x40A3);
110 lcd_write_reg(6, 0x0);
111 lcd_write_reg(7, 0x0);
112 lcd_write_reg(8, 0x0);
113 lcd_write_reg(9, 0x0);
114 lcd_write_reg(10, 0x0);
115 lcd_write_reg(16, 0x0);
116 lcd_write_reg(17, 0x0);
117 lcd_write_reg(18, 0x0);
118 lcd_write_reg(19, 0x0);
119 lcd_write_reg(20, 0x0);
120 lcd_write_reg(21, 0x0);
121 lcd_write_reg(22, 0x0);
122 lcd_write_reg(23, 0x0);
123 lcd_write_reg(24, 0x0);
124 lcd_write_reg(25, 0x0);
125 sleep_ms(10);
126
127 lcd_write_reg(9, 0x4055);
128 lcd_write_reg(10, 0x0);
129 sleep_ms(40);
130
131 lcd_write_reg(10, 0x2000);
132 sleep_ms(40);
133
134 lcd_write_reg(1, 0x401D);
135 lcd_write_reg(2, 0x204);
136 lcd_write_reg(3, 0x100);
137 lcd_write_reg(4, 0x1000);
138 lcd_write_reg(5, 0x5033);
139 lcd_write_reg(6, 0x5);
140 lcd_write_reg(7, 0x1B);
141 lcd_write_reg(8, 0x800);
142 lcd_write_reg(16, 0x203);
143 lcd_write_reg(17, 0x302);
144 lcd_write_reg(18, 0xC08);
145 lcd_write_reg(19, 0xC08);
146 lcd_write_reg(20, 0x707);
147 lcd_write_reg(21, 0x707);
148 lcd_write_reg(22, 0x104);
149 lcd_write_reg(23, 0x306);
150 lcd_write_reg(24, 0x0);
151 lcd_write_reg(25, 0x0);
152 sleep_ms(60);
153
154 lcd_write_reg(9, 0xA55);
155 lcd_write_reg(10, 0x111A);
156 sleep_ms(10);
157
158 //TODO: other stuff!
159
160 /* tell that we're on now */
161 display_on = true;
162}
163
164static void lcd_display_off(void)
165{
166 display_on = false;
167
168 /* LQV shutdown sequence */
169 lcd_write_reg(9, 0x855);
170 sleep_ms(20);
171
172 lcd_write_reg(9, 0x55);
173 lcd_write_reg(5, 0x4033);
174 lcd_write_reg(10, 0x0);
175 sleep_ms(20);
176
177 lcd_write_reg(9, 0x0);
178 sleep_ms(10);
179 unsigned char temp[1];
180 temp[0] = 0;
181 spi_block_transfer(SPI_target_LTV250QV, temp, sizeof(temp), NULL, 0);
182
183 IO_GIO_BITCLR2 = (1 << 4);
184 sleep_ms(5);
185 IO_GIO_BITCLR2 = (1 << 7);
186 sleep_ms(5);
187 IO_GIO_BITCLR2 = (1 << 0);
188 sleep_ms(2);
189 IO_GIO_BITCLR2 = (1 << 8);
190 IO_GIO_BITCLR2 = (1 << 5);
191
192 /* Disable main power */
193 IO_GIO_BITCLR2 |= (1 << 3);
194}
195
196
197
198void lcd_enable(bool on)
199{
200 if (on == display_on)
201 return;
202
203 if (on)
204 {
205 display_on = true; //TODO: remove me!
206 //lcd_display_on(); /* Turn on display */
207 lcd_update(); /* Resync display */
208 }
209 else
210 {
211 display_on = false; //TODO: remove me!
212 //lcd_display_off(); /* Turn off display */
213 }
214}
215
216bool lcd_enabled(void)
217{
218 return display_on;
219}
220
221void lcd_set_direct_fb(bool yes)
222{
223 unsigned int addr;
224 direct_fb_access = yes;
225 if(yes)
226 addr = ((unsigned int)&lcd_framebuffer-CONFIG_SDRAM_START) / 32;
227 else
228 addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32;
229 IO_OSD_OSDWINADH = addr >> 16;
230 IO_OSD_OSDWIN0ADL = addr & 0xFFFF;
231}
232
233bool lcd_get_direct_fb(void)
234{
235 return direct_fb_access;
236}
237
238void lcd_init_device(void)
239{
240 /* Based on lcd-mr500.c from Catalin Patulea */
241 unsigned int addr;
242
243 /* Clear the Frame */
244 memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT);
245
246 IO_OSD_MODE = 0x00ff;
247 IO_OSD_VIDWINMD = 0x0002;
248 IO_OSD_OSDWINMD0 = 0x2001;
249 IO_OSD_OSDWINMD1 = 0x0002;
250 IO_OSD_ATRMD = 0x0000;
251 IO_OSD_RECTCUR = 0x0000;
252
253 IO_OSD_OSDWIN0OFST = (LCD_WIDTH*16) / 256;
254 addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32;
255 IO_OSD_OSDWINADH = addr >> 16;
256 IO_OSD_OSDWIN0ADL = addr & 0xFFFF;
257
258#ifndef ZEN_VISION
259 IO_OSD_BASEPX=26;
260 IO_OSD_BASEPY=5;
261#else
262 IO_OSD_BASEPX=80;
263 IO_OSD_BASEPY=0;
264#endif
265
266 IO_OSD_OSDWIN0XP = 0;
267 IO_OSD_OSDWIN0YP = 0;
268 IO_OSD_OSDWIN0XL = LCD_WIDTH;
269 IO_OSD_OSDWIN0YL = LCD_HEIGHT;
270#if 0
271 //TODO: set LCD clock!
272 IO_CLK_MOD1 &= ~0x18; // disable OSD clock and VENC clock
273 IO_CLK_02DIV = 3;
274 IO_CLK_OSEL = (IO_CLK_OSEL & ~0xF00) | 0x400; // reset 'General purpose clock output (GIO26, GIO34)' and set to 'PLLIN clock'
275 IO_CLK_SEL1 = (IO_CLK_SEL1 | 7) | 0x1000; // set to 'GP clock output 2 (GIO26, GIO34)' and turn on 'VENC clock'
276 IO_CLK_MOD1 |= 0x18; // enable OSD clock and VENC clock
277
278 /* Set LCD values in OSD */
279 IO_VID_ENC_VMOD = ( ( (IO_VID_ENC_VMOD & 0xFFFF8C00) | 0x14) | 0x2400 ); // disable NTSC/PAL encoder & set mode to RGB666 parallel 18 bit
280 IO_VID_ENC_VDCTL = ( ( (IO_VID_ENC_VDCTL & 0xFFFFCFE8) | 0x20) | 0x4000 );
281 //TODO: finish this...
282#endif
283}
284
285
286/*** Update functions ***/
287
288
289
290/* Update a fraction of the display. */
291void lcd_update_rect(int x, int y, int width, int height)
292{
293 register fb_data *dst, *src;
294
295 if (!display_on || direct_fb_access)
296 return;
297
298 if (x + width > LCD_WIDTH)
299 width = LCD_WIDTH - x; /* Clip right */
300 if (x < 0)
301 width += x, x = 0; /* Clip left */
302 if (width <= 0)
303 return; /* nothing left to do */
304
305 if (y + height > LCD_HEIGHT)
306 height = LCD_HEIGHT - y; /* Clip bottom */
307 if (y < 0)
308 height += y, y = 0; /* Clip top */
309 if (height <= 0)
310 return; /* nothing left to do */
311
312#if CONFIG_ORIENTATION == SCREEN_PORTAIT
313 dst = (fb_data *)FRAME + LCD_WIDTH*y + x;
314 src = &lcd_framebuffer[y][x];
315
316 /* Copy part of the Rockbox framebuffer to the second framebuffer */
317 if (width < LCD_WIDTH)
318 {
319 /* Not full width - do line-by-line */
320 lcd_copy_buffer_rect(dst, src, width, height);
321 }
322 else
323 {
324 /* Full width - copy as one line */
325 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
326 }
327#else
328 src = &lcd_framebuffer[y][x];
329
330 register int xc, yc;
331 register fb_data *start=FRAME + LCD_HEIGHT*(LCD_WIDTH-x-1) + y + 1;
332
333 for(yc=0;yc<height;yc++)
334 {
335 dst=start+yc;
336 for(xc=0; xc<width; xc++)
337 {
338 *dst=*src++;
339 dst-=LCD_HEIGHT;
340 }
341 src+=x;
342 }
343#endif
344}
345
346/* Update the display.
347This must be called after all other LCD functions that change the display. */
348void lcd_update(void)
349{
350 if (!display_on || direct_fb_access)
351 return;
352#if CONFIG_ORIENTATION == SCREEN_PORTAIT
353 lcd_copy_buffer_rect((fb_data *)FRAME, &lcd_framebuffer[0][0],
354 LCD_WIDTH*LCD_HEIGHT, 1);
355#else
356 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
357#endif
358}
359
360/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
361extern void lcd_write_yuv420_lines(fb_data *dst,
362unsigned char chroma_buf[LCD_HEIGHT/2*3],
363unsigned char const * const src[3],
364int width,
365int stride);
366/* Performance function to blit a YUV bitmap directly to the LCD */
367/* For the Gigabeat - show it rotated */
368/* So the LCD_WIDTH is now the height */
369void lcd_blit_yuv(unsigned char * const src[3],
370int src_x, int src_y, int stride,
371int x, int y, int width, int height)
372{
373 /* Caches for chroma data so it only need be recalculated every other
374 line */
375 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
376 unsigned char const * yuv_src[3];
377 off_t z;
378
379 if (!display_on || direct_fb_access)
380 return;
381
382 /* Sorry, but width and height must be >= 2 or else */
383 width &= ~1;
384 height >>= 1;
385
386 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
387
388 z = stride*src_y;
389 yuv_src[0] = src[0] + z + src_x;
390 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
391 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
392
393 do
394 {
395 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
396 stride);
397
398 yuv_src[0] += stride << 1; /* Skip down two luma lines */
399 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
400 yuv_src[2] += stride >> 1;
401 dst -= 2;
402 }
403 while (--height > 0);
404}
405