1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2011 by Tomasz Moń
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 ****************************************************************************/
22 #include <sys/types.h>
28 #include "system-target.h"
30 #include "lcd-target.h"
31 #include "avr-sansaconnect.h"
33 extern bool lcd_on
; /* lcd-memframe.c */
35 #if defined(HAVE_LCD_SLEEP)
45 /* disable video encoder */
46 bitclr16(&IO_VID_ENC_VMOD
, 0x01);
50 /* disable video encoder clock */
51 bitclr16(&IO_CLK_MOD1
, CLK_MOD1_VENC
);
61 /* enable video encoder clock */
62 bitset16(&IO_CLK_MOD1
, CLK_MOD1_VENC
);
64 /* enable video encoder */
65 bitset16(&IO_VID_ENC_VMOD
, 0x01);
69 send_event(LCD_EVENT_ACTIVATION
, NULL
);
76 void lcd_init_device(void)
80 /* Disable Video Encoder clock */
81 bitclr16(&IO_CLK_MOD1
, CLK_MOD1_VENC
);
83 /* configure GIO39, GIO34 as outputs */
84 IO_GIO_DIR2
&= ~((1 << 7) /* GIO39 */ | (1 << 2) /* GIO34 */);
86 IO_GIO_FSEL3
= (IO_GIO_FSEL3
& ~(0x300F)) |
87 (0x1000) /* GIO39 - FIELD_VENC */ |
88 (0x4); /* GIO34 - PWM1 (brightness control) */
90 /* OSD Clock = VENC Clock /2,
92 VENC Clock from PLLA */
95 /* Set VENC Clock Division to 11
96 OF bootloader sets division to 8, vmlinux sets it to 11 */
97 IO_CLK_DIV3
= (IO_CLK_DIV3
& ~(0x1F00)) | 0xB00;
99 /* Enable OSD clock */
100 bitset16(&IO_CLK_MOD1
, CLK_MOD1_OSD
);
102 /* magic values based on OF bootloader initialization */
103 /* Set DAC to powerdown mode (bit 2 to 1 in VMOD) */
104 IO_VID_ENC_VMOD
= 0x2014; /* OF sets 0x2010 */
105 IO_VID_ENC_VDPRO
= 0x80;
106 IO_VID_ENC_HSPLS
= 0x4;
107 IO_VID_ENC_HINT
= 0x4B0;
108 IO_VID_ENC_HSTART
= 0x88;
109 IO_VID_ENC_HVALID
= 0x3C0;
110 IO_VID_ENC_HSDLY
= 0;
111 IO_VID_ENC_VSPLS
= 0x2;
112 IO_VID_ENC_VINT
= 0x152;
113 IO_VID_ENC_VSTART
= 0x6;
114 IO_VID_ENC_VVALID
= 0x140;
115 IO_VID_ENC_VSDLY
= 0;
116 IO_VID_ENC_DCLKCTL
= 0x3;
117 IO_VID_ENC_DCLKPTN0
= 0xC;
118 IO_VID_ENC_VDCTL
= 0x6000;
119 IO_VID_ENC_SYNCTL
= 0x2;
120 IO_VID_ENC_LCDOUT
= 0x101;
121 IO_VID_ENC_VMOD
= 0x2015; /* OF sets 0x2011 */
123 /* Copy Rockbox frame buffer to the second framebuffer */
127 avr_hid_lcm_power_on();
129 /* set framebuffer address - OF sets RAM start address to 0x1000000 */
130 addr
= ((int)FRAME
-CONFIG_SDRAM_START
)/32;
132 IO_OSD_OSDWINADH
= addr
>> 16;
133 IO_OSD_OSDWIN0ADL
= addr
& 0xFFFF;
135 IO_OSD_BASEPX
= 0x44;
137 IO_OSD_OSDWIN0XP
= 0;
138 IO_OSD_OSDWIN0YP
= 0;
139 IO_OSD_OSDWIN0XL
= LCD_WIDTH
*2; /* OF bootloader sets 480 */
140 IO_OSD_OSDWIN0YL
= LCD_HEIGHT
; /* OF bootloader sets 320 */
141 IO_OSD_OSDWIN0OFST
= 0xF;
142 IO_OSD_OSDWINMD0
= 0x25FB;/* OF bootloader sets 25C3,
143 vmlinux changes this to 0x25FB */
144 IO_OSD_VIDWINMD
= 0; /* disable video windows (OF sets 0x03) */
146 IO_OSD_OSDWINMD1
= 0; /* disable OSD window 1 */
148 /* Enable Video Encoder and OSD clocks */
149 bitset16(&IO_CLK_MOD1
, CLK_MOD1_VENC
| CLK_MOD1_OSD
);
151 /* Enable Video Encoder - RGB666, custom timing */
152 IO_VID_ENC_VMOD
= 0x2015;
158 static void dma_lcd_copy_buffer_rect(int x
, int y
, int width
, int height
)
162 /* Image buffer A is 4KW, every pixel is one Word */
163 /* lines is maximum number of lines we can transfer in single run */
164 int lines
= 4096/width
;
168 /* Set source and destination addresses */
169 dst
= (char*)(FRAME
+ LCD_WIDTH
*y
+ x
);
170 src
= (char*)(FBADDR(x
,y
));
172 /* Flush cache to memory */
175 /* Addresses are relative to start of SDRAM */
176 src
-= CONFIG_SDRAM_START
;
177 dst
-= CONFIG_SDRAM_START
;
179 /* Enable Image Buffer clock */
180 bitset16(&IO_CLK_MOD1
, CLK_MOD1_IMGBUF
);
182 /* Use Image Buffer A for DMA */
183 COP_BUF_MUX0
= (COP_BUF_MUX0
& 0xFFF0) | 0x0003;
185 /* Setup buffer offsets and transfer width/height */
186 COP_BUF_LOFST
= width
;
187 COP_DMA_XNUM
= width
;
188 COP_DMA_YNUM
= lines
;
190 /* DMA: No byte SWAP, no transformation, data bus shift down 0 bit */
191 COP_IMG_MODE
&= 0xC0;
193 /* Set the start address of buffer */
194 COP_BUF_ADDR
= 0x0000;
196 /* Setup SDRAM stride */
197 COP_SDEM_LOFST
= LCD_WIDTH
;
203 addr
>>= 1; /* Addresses are in 16-bit words */
205 /* Setup the registers to initiate the read from SDRAM */
206 COP_SDEM_ADDRH
= addr
>> 16;
207 COP_SDEM_ADDRL
= addr
& 0xFFFF;
209 /* Set direction and start */
210 COP_DMA_CTRL
= 0x0001;
211 COP_DMA_CTRL
|= 0x0002;
213 /* Wait for read to finish */
214 while (COP_DMA_CTRL
& 0x02) {};
219 COP_SDEM_ADDRH
= addr
>> 16;
220 COP_SDEM_ADDRL
= addr
& 0xFFFF;
222 /* Set direction and start transfer */
223 COP_DMA_CTRL
= 0x0000;
224 COP_DMA_CTRL
|= 0x0002;
226 /* Wait for the transfer to complete */
227 while (COP_DMA_CTRL
& 0x02) {};
229 /* Decrease height, update pointers */
230 src
+= (LCD_WIDTH
<< 1)*lines
;
231 dst
+= (LCD_WIDTH
<< 1)*lines
;
237 COP_DMA_YNUM
= height
;
239 } while (height
> 0);
241 /* Disable Image Buffer clock */
242 bitclr16(&IO_CLK_MOD1
, CLK_MOD1_IMGBUF
);
245 /* Update a fraction of the display. */
246 void lcd_update_rect(int x
, int y
, int width
, int height
)
247 __attribute__ ((section(".icode")));
248 void lcd_update_rect(int x
, int y
, int width
, int height
)
253 if ((width
| height
) < 0)
254 return; /* Nothing left to do */
256 if (x
+ width
> LCD_WIDTH
)
257 width
= LCD_WIDTH
- x
; /* Clip right */
259 width
+= x
, x
= 0; /* Clip left */
261 if (y
+ height
> LCD_HEIGHT
)
262 height
= LCD_HEIGHT
- y
; /* Clip bottom */
264 height
+= y
, y
= 0; /* Clip top */
266 dma_lcd_copy_buffer_rect(x
, y
, width
, height
);
269 /* Update the display.
270 This must be called after all other LCD functions that change the display. */
271 void lcd_update(void) __attribute__ ((section(".icode")));
272 void lcd_update(void)
277 lcd_update_rect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
281 void lcd_set_contrast(int val
) {
286 void lcd_set_invert_display(bool yesno
) {
291 void lcd_set_flip(bool yesno
) {