summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c')
-rw-r--r--firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c b/firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c
new file mode 100644
index 0000000000..79e14aba70
--- /dev/null
+++ b/firmware/target/arm/tcc77x/c100/lcd-S6B33B2.c
@@ -0,0 +1,349 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: lcd-S6B33B2.c 16981 2008-06-09 04:34:57Z jethead71 $
9 *
10 * Copyright (C) 2007 by Mark Arigo
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#include "cpu.h"
21#include "lcd.h"
22#include "kernel.h"
23#include "system.h"
24
25/* Display status */
26static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
27
28/* LCD command set for Samsung S6B33B2 */
29
30#define R_NOP 0x00
31#define R_OSCILLATION_MODE 0x02
32#define R_DRIVER_OUTPUT_MODE 0x10
33#define R_DCDC_SET 0x20
34#define R_BIAS_SET 0x22
35#define R_DCDC_CLOCK_DIV 0x24
36#define R_DCDC_AMP_ONOFF 0x26
37#define R_TEMP_COMPENSATION 0x28
38#define R_CONTRAST_CONTROL1 0x2a
39#define R_CONTRAST_CONTROL2 0x2b
40#define R_STANDBY_OFF 0x2c
41#define R_STANDBY_ON 0x2d
42#define R_DDRAM_BURST_OFF 0x2e
43#define R_DDRAM_BURST_ON 0x2f
44#define R_ADDRESSING_MODE 0x30
45#define R_ROW_VECTOR_MODE 0x32
46#define R_N_LINE_INVERSION 0x34
47#define R_FRAME_FREQ_CONTROL 0x36
48#define R_RED_PALETTE 0x38
49#define R_GREEN_PALETTE 0x3a
50#define R_BLUE_PALETTE 0x3c
51#define R_ENTRY_MODE 0x40
52#define R_X_ADDR_AREA 0x42
53#define R_Y_ADDR_AREA 0x43
54#define R_RAM_SKIP_AREA 0x45
55#define R_DISPLAY_OFF 0x50
56#define R_DISPLAY_ON 0x51
57#define R_SPEC_DISPLAY_PATTERN 0x53
58#define R_PARTIAL_DISPLAY_MODE 0x55
59#define R_PARTIAL_START_LINE 0x56
60#define R_PARTIAL_END_LINE 0x57
61#define R_AREA_SCROLL_MODE 0x59
62#define R_SCROLL_START_LINE 0x5a
63#define R_DATA_FORMAT_SELECT 0x60
64
65/* TCC77x specific defines */
66#define LCD_BASE 0x50000000
67#define LCD_CMD *(volatile unsigned char*)(LCD_BASE)
68#define LCD_DATA *(volatile unsigned char*)(LCD_BASE+1)
69
70static void lcd_send_command(unsigned cmd)
71{
72 LCD_CMD = cmd;
73
74 asm volatile (
75 "nop \n\t"
76 "nop \n\t"
77 "nop \n\t"
78 );
79}
80
81static void lcd_send_data(unsigned data)
82{
83 LCD_DATA = (data & 0xff00) >> 8;
84 LCD_DATA = (data & 0x00ff);
85}
86
87/* End of TCC77x specific defines */
88
89/* LCD init */
90void lcd_init_device(void)
91{
92 uint32_t bus_width;
93
94 /* Telechips init the same as the original firmware */
95 bus_width = ((MCFG >> 11) & 0x3) ^ 3;
96
97 CSCFG1 = (bus_width << 28) |
98 (3 << 26) | /* MTYPE = 3 */
99 ((LCD_BASE >> 28) << 22) | /* CSBASE = 0x5 */
100 (1 << 20) | /* Unknown */
101 (2 << 11) | /* Setup time = 2 cycles */
102 (2 << 3) | /* Pulse width = 2+1 cycles */
103 (2 << 0); /* Hold time = 2 cycle */
104
105 GPIOE &= ~0x8;
106 sleep(HZ/100); /* 10ms */
107
108 GPIOE |= 0x08;
109 sleep(HZ/100); /* 10ms */
110
111 lcd_send_command(R_STANDBY_OFF);
112 sleep(HZ/20); /* 50ms */
113
114 lcd_send_command(R_OSCILLATION_MODE);
115 lcd_send_command(0x01);
116 sleep(HZ/100); /* 10ms */
117
118 lcd_send_command(R_DCDC_AMP_ONOFF);
119 lcd_send_command(0x01);
120 sleep(HZ/100); /* 10ms */
121
122 lcd_send_command(R_DCDC_AMP_ONOFF);
123 lcd_send_command(0x09);
124 sleep(HZ/100); /* 10ms */
125
126 lcd_send_command(R_DCDC_AMP_ONOFF);
127 lcd_send_command(0x0b);
128 sleep(HZ/100); /* 10ms */
129
130 lcd_send_command(R_DCDC_AMP_ONOFF);
131 lcd_send_command(0x0f);
132 sleep(HZ/100); /* 10ms */
133
134 lcd_send_command(R_DCDC_SET);
135 lcd_send_command(0x01);
136 sleep(HZ/100); /* 10ms */
137 sleep(HZ/10); /* 100ms */
138
139 lcd_send_command(R_TEMP_COMPENSATION);
140 lcd_send_command(0x01);
141 sleep(HZ/100); /* 10ms */
142
143 lcd_send_command(R_DRIVER_OUTPUT_MODE);
144 lcd_send_command(0x03);
145
146 lcd_send_command(R_ENTRY_MODE);
147 lcd_send_command(0x81);
148
149 lcd_send_command(R_N_LINE_INVERSION);
150 lcd_send_command(0x04);
151 lcd_send_command(0xfa);
152 lcd_send_command(0x5f);
153
154 lcd_set_contrast(0x28);
155
156 lcd_send_command(R_SPEC_DISPLAY_PATTERN);
157 lcd_send_command(0x0);
158 sleep(HZ/100); /* 10ms */
159
160 lcd_send_command(R_ADDRESSING_MODE);
161 lcd_send_command(0x0);
162 sleep(HZ/100); /* 10ms */
163
164 lcd_send_command(R_PARTIAL_DISPLAY_MODE);
165 lcd_send_command(0x0);
166 sleep(HZ/100); /* 10ms */
167
168 lcd_send_command(R_X_ADDR_AREA);
169 lcd_send_command(0);
170 lcd_send_command(0x80);
171
172 lcd_send_command(R_Y_ADDR_AREA);
173 lcd_send_command(0x0);
174 lcd_send_command(0x80);
175
176 lcd_send_command(R_DISPLAY_ON);
177
178 lcd_send_command(R_SPEC_DISPLAY_PATTERN);
179 lcd_send_command(0x0);
180
181 /* Rockbox init */
182 lcd_clear_display();
183 lcd_update();
184}
185
186/*** hardware configuration ***/
187int lcd_default_contrast(void)
188{
189 return 0x28;
190}
191
192void lcd_set_contrast(int val)
193{
194 //val &= 0xFF;
195 lcd_send_command(R_CONTRAST_CONTROL1);
196 lcd_send_command(val);
197}
198
199void lcd_set_invert_display(bool yesno)
200{
201 /* TODO: Implement lcd_set_invert_display() */
202 (void)yesno;
203}
204
205/* turn the display upside down (call lcd_update() afterwards) */
206void lcd_set_flip(bool yesno)
207{
208 lcd_send_command(R_DRIVER_OUTPUT_MODE);
209 lcd_send_command(yesno ? 0x02 : 0x07);
210}
211
212/*** update functions ***/
213
214/*** update functions ***/
215
216void lcd_yuv_set_options(unsigned options)
217{
218 lcd_yuv_options = options;
219}
220
221/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
222extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
223 int width,
224 int stride);
225extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
226 int width,
227 int stride,
228 int x_screen, /* To align dither pattern */
229 int y_screen);
230/* Performance function to blit a YUV bitmap directly to the LCD */
231void lcd_blit_yuv(unsigned char * const src[3],
232 int src_x, int src_y, int stride,
233 int x, int y, int width, int height)
234{
235 unsigned char const * yuv_src[3];
236 off_t z;
237
238 /* Sorry, but width and height must be >= 2 or else */
239 width &= ~1;
240 height >>= 1;
241
242 y += 0x1a;
243
244 z = stride*src_y;
245 yuv_src[0] = src[0] + z + src_x;
246 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
247 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
248
249 lcd_send_command(R_ENTRY_MODE);
250 lcd_send_command(0x80);
251
252 lcd_send_command(R_X_ADDR_AREA);
253 lcd_send_command(x);
254 lcd_send_command(x + width - 1);
255
256 if (lcd_yuv_options & LCD_YUV_DITHER)
257 {
258 do
259 {
260 lcd_send_command(R_Y_ADDR_AREA);
261 lcd_send_command(y);
262 lcd_send_command(y + 1);
263
264 /* NOP needed because on some c200s, the previous lcd_send_command
265 is interpreted as a separate command instead of part of
266 R_Y_ADDR_AREA. */
267 lcd_send_command(R_NOP);
268
269 lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y);
270 yuv_src[0] += stride << 1; /* Skip down two luma lines */
271 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
272 yuv_src[2] += stride >> 1;
273 y += 2;
274 }
275 while (--height > 0);
276 }
277 else
278 {
279 do
280 {
281 lcd_send_command(R_Y_ADDR_AREA);
282 lcd_send_command(y);
283 lcd_send_command(y + 1);
284
285 lcd_send_command(R_NOP);
286
287 lcd_write_yuv420_lines(yuv_src, width, stride);
288 yuv_src[0] += stride << 1; /* Skip down two luma lines */
289 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
290 yuv_src[2] += stride >> 1;
291 y += 2;
292 }
293 while (--height > 0);
294 }
295}
296
297
298/* Update the display.
299 This must be called after all other LCD functions that change the display. */
300void lcd_update(void)
301{
302 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
303}
304
305/* Update a fraction of the display. */
306void lcd_update_rect(int x, int y, int width, int height)
307{
308 const fb_data *addr;
309
310 if (x + width >= LCD_WIDTH)
311 width = LCD_WIDTH - x;
312 if (y + height >= LCD_HEIGHT)
313 height = LCD_HEIGHT - y;
314
315 if ((width <= 0) || (height <= 0))
316 return; /* Nothing left to do. */
317
318 addr = &lcd_framebuffer[y][x];
319
320 if (width <= 1) {
321 lcd_send_command(R_ENTRY_MODE); /* The X end address must be larger */
322 lcd_send_command(0x80); /* that the X start address, so we */
323 lcd_send_command(R_X_ADDR_AREA); /* switch to vertical mode for */
324 lcd_send_command(x); /* single column updates and set */
325 lcd_send_command(x + 1); /* the window width to 2 */
326 } else {
327 lcd_send_command(R_ENTRY_MODE);
328 lcd_send_command(0x82);
329 lcd_send_command(R_X_ADDR_AREA);
330 lcd_send_command(x);
331 lcd_send_command(x + width - 1);
332 }
333
334 lcd_send_command(R_Y_ADDR_AREA);
335 lcd_send_command(y);
336 lcd_send_command(y + height - 1);
337
338 /* NOP needed because on some c200s, the previous lcd_send_command is
339 interpreted as a separate command instead of part of R_Y_ADDR_AREA. */
340 lcd_send_command(R_NOP);
341
342 do {
343 int w = width;
344 do {
345 lcd_send_data(*addr++);
346 } while (--w > 0);
347 addr += LCD_WIDTH - width;
348 } while (--height > 0);
349}