1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2011 Marcin Bukat
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 ****************************************************************************/
27 #include "spfd5420a.h"
29 static inline void delay_nop(int cycles
)
31 asm volatile ("1: subs %[n], %[n], #1 \n\t"
37 static unsigned int lcd_data_transform(unsigned int data
)
39 /* 18 bit interface */
41 r
= (data
& 0x0000fc00)<<8;
42 /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
43 g
= ((data
& 0x00000300) << 6) | ((data
& 0x000000e0) << 5);
44 b
= (data
& 0x00000001f) << 3;
49 /* converts RGB565 pixel into internal lcd bus format */
50 static unsigned int lcd_pixel_transform(unsigned short rgb565
)
54 g
= (rgb565
>> 5) & 0x3f;
55 r
= (rgb565
>> 11) & 0x1f;
57 return r
<<19 | g
<<10 | b
<<3;
60 static void lcd_cmd(unsigned int cmd
)
62 LCD_COMMAND
= lcd_data_transform(cmd
);
65 static void lcd_data(unsigned int data
)
67 LCD_DATA
= lcd_data_transform(data
);
70 static void lcd_write_reg(unsigned int reg
, unsigned int val
)
76 static void lcdctrl_bypass(unsigned int on_off
)
78 while (!(LCDC_STA
& LCDC_MCU_IDLE
));
81 MCU_CTRL
|= MCU_CTRL_BYPASS
;
83 MCU_CTRL
&= ~MCU_CTRL_BYPASS
;
86 /* This part is unclear. I am unable to use buffered/FIFO based writes
87 * to lcd. Depending on settings of IF I get various patterns on display
88 * but not what I want to display apparently.
90 static void lcdctrl_init(void)
93 * stop at current frame complete
97 LCDC_CTRL
= ALPHA(7) | LCDC_STOP
| LCDC_MCU
| RGB24B
;
98 MCU_CTRL
= ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS
;
100 HOR_ACT
= 400 + 3; /* define horizonatal active region */
101 VERT_ACT
= 240; /* define vertical active region */
102 VERT_PERIOD
= 0xfff; /* CSn/WEn/RDn signal timings */
104 LINE0_YADDR
= LINE_ALPHA_EN
| 0x7fe;
105 LINE1_YADDR
= LINE_ALPHA_EN
| ((1 * 400) - 2);
106 LINE2_YADDR
= LINE_ALPHA_EN
| ((2 * 400) - 2);
107 LINE3_YADDR
= LINE_ALPHA_EN
| ((3 * 400) - 2);
109 LINE0_UVADDR
= 0x7fe + 1;
110 LINE1_UVADDR
= ((1 * 400) - 2 + 1);
111 LINE2_UVADDR
= ((2 * 400) - 2 + 1);
112 LINE3_UVADDR
= ((3 * 400) - 2 + 1);
116 LINE1_YADDR
= (1 * 400);
117 LINE2_YADDR
= (2 * 400);
118 LINE3_YADDR
= (3 * 400);
121 LINE1_UVADDR
= (1 * 400) + 1;
122 LINE2_UVADDR
= (2 * 400) + 1;
123 LINE3_UVADDR
= (3 * 400) + 1;
127 DELTA_X
= 0x200; /* no scaling */
128 DELTA_Y
= 0x200; /* no scaling */
130 LCDC_INTR_MASK
= INTR_MASK_LINE
; /* INTR_MASK_EVENLINE; */
133 /* configure pins to drive lcd in 18bit mode */
134 static void iomux_lcd(void)
138 muxa
= SCU_IOMUXA_CON
& ~(IOMUX_LCD_VSYNC
|IOMUX_LCD_DEN
|0xff);
139 muxa
|= IOMUX_LCD_D18
|IOMUX_LCD_D20
|IOMUX_LCD_D22
|IOMUX_LCD_D17
|IOMUX_LCD_D16
;
141 SCU_IOMUXA_CON
= muxa
;
142 SCU_IOMUXB_CON
|= IOMUX_LCD_D815
;
146 static void lcd_sleep(unsigned int sleep
)
150 /* enter sleep mode */
151 lcd_write_reg(DISPLAY_CTRL1
, 0x0170);
153 lcd_write_reg(DISPLAY_CTRL1
, 0x0000);
155 lcd_write_reg(PWR_CTRL1
, 0x14B4);
159 /* return to normal operation */
160 lcd_write_reg(PWR_CTRL1
, 0x14B0);
162 lcd_write_reg(DISPLAY_CTRL1
, 0x0173);
168 void lcd_init_device()
172 iomux_lcd(); /* setup pins for 18bit lcd interface */
173 lcdctrl_init(); /* basic lcdc module configuration */
175 lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
177 lcd_write_reg(RESET
, 0x0001);
179 lcd_write_reg(RESET
, 0x0000);
181 lcd_write_reg(IF_ENDIAN
, 0x0000); /* order of receiving data */
182 lcd_write_reg(DRIVER_OUT_CTRL
, 0x0000);
183 lcd_write_reg(ENTRY_MODE
, 0x1038);
184 lcd_write_reg(WAVEFORM_CTRL
, 0x0100);
185 lcd_write_reg(SHAPENING_CTRL
, 0x0000);
186 lcd_write_reg(DISPLAY_CTRL2
, 0x0808);
187 lcd_write_reg(LOW_PWR_CTRL1
, 0x0001);
188 lcd_write_reg(LOW_PWR_CTRL2
, 0x0010);
189 lcd_write_reg(EXT_DISP_CTRL1
, 0x0000);
190 lcd_write_reg(EXT_DISP_CTRL2
, 0x0000);
191 lcd_write_reg(BASE_IMG_SIZE
, 0x3100);
192 lcd_write_reg(BASE_IMG_CTRL
, 0x0001);
193 lcd_write_reg(VSCROLL_CTRL
, 0x0000);
194 lcd_write_reg(PART1_POS
, 0x0000);
195 lcd_write_reg(PART1_START
, 0x0000);
196 lcd_write_reg(PART1_END
, 0x018F);
197 lcd_write_reg(PART2_POS
, 0x0000);
198 lcd_write_reg(PART2_START
, 0x0000);
199 lcd_write_reg(PART2_END
, 0x0000);
201 lcd_write_reg(PANEL_IF_CTRL1
, 0x0011);
203 lcd_write_reg(PANEL_IF_CTRL2
, 0x0202);
204 lcd_write_reg(PANEL_IF_CTRL3
, 0x0300);
206 lcd_write_reg(PANEL_IF_CTRL4
, 0x021E);
207 lcd_write_reg(PANEL_IF_CTRL5
, 0x0202);
208 lcd_write_reg(PANEL_IF_CTRL6
, 0x0100);
209 lcd_write_reg(FRAME_MKR_CTRL
, 0x0000);
210 lcd_write_reg(MDDI_CTRL
, 0x0000);
212 lcd_write_reg(GAMMA_CTRL1
, 0x0101);
213 lcd_write_reg(GAMMA_CTRL2
, 0x0000);
214 lcd_write_reg(GAMMA_CTRL3
, 0x0016);
215 lcd_write_reg(GAMMA_CTRL4
, 0x2913);
216 lcd_write_reg(GAMMA_CTRL5
, 0x260B);
217 lcd_write_reg(GAMMA_CTRL6
, 0x0101);
218 lcd_write_reg(GAMMA_CTRL7
, 0x1204);
219 lcd_write_reg(GAMMA_CTRL8
, 0x0415);
220 lcd_write_reg(GAMMA_CTRL9
, 0x0205);
221 lcd_write_reg(GAMMA_CTRL10
, 0x0303);
222 lcd_write_reg(GAMMA_CTRL11
, 0x0E05);
223 lcd_write_reg(GAMMA_CTRL12
, 0x0D01);
224 lcd_write_reg(GAMMA_CTRL13
, 0x010D);
225 lcd_write_reg(GAMMA_CTRL14
, 0x050E);
226 lcd_write_reg(GAMMA_CTRL15
, 0x0303);
227 lcd_write_reg(GAMMA_CTRL16
, 0x0502);
230 lcd_write_reg(DISPLAY_CTRL1
, 0x0001);
231 lcd_write_reg(PWR_CTRL6
, 0x0001);
232 lcd_write_reg(PWR_CTRL7
, 0x0060);
234 lcd_write_reg(PWR_CTRL1
, 0x16B0);
236 lcd_write_reg(PWR_CTRL2
, 0x0147);
238 lcd_write_reg(PWR_CTRL3
, 0x0117);
240 lcd_write_reg(PWR_CTRL4
, 0x2F00);
242 lcd_write_reg(VCOM_HV2
, 0x0000); /* src 0x0090 */
244 lcd_write_reg(VCOM_HV1
, 0x0008); /* src 0x000A */
245 lcd_write_reg(PWR_CTRL3
, 0x01BE);
248 /* addresses setup */
249 lcd_write_reg(WINDOW_H_START
, 0x0000);
250 lcd_write_reg(WINDOW_H_END
, 0x00EF); /* 239 */
251 lcd_write_reg(WINDOW_V_START
, 0x0000);
252 lcd_write_reg(WINDOW_V_END
, 0x018F); /* 399 */
253 lcd_write_reg(GRAM_H_ADDR
, 0x0000);
254 lcd_write_reg(GRAM_V_ADDR
, 0x0000);
257 lcd_write_reg(DISPLAY_CTRL1
, 0x0021);
259 lcd_write_reg(DISPLAY_CTRL1
, 0x0061);
261 lcd_write_reg(DISPLAY_CTRL1
, 0x0173);
268 for (x
=0; x
<400; x
++)
275 /* This is ugly hack. We drive lcd in bypass mode
276 * where all writes goes directly to lcd controller.
277 * This is suboptimal at best. IF module povides
278 * FIFO, internal sram buffer, hardware scaller,
279 * DMA signals, hardware alpha blending and more.
280 * BUT the fact is that I have no idea how to use
281 * this modes. Datasheet floating around is very
282 * unclean in this regard and OF uses ackward
283 * lcd update routines which are hard to understand.
284 * Moreover OF sets some bits in IF module registers
285 * which are referred as reseved in datasheet.
291 for (y
=0; y
<240; y
++)
292 for (x
=0; x
<400; x
++)
293 LCD_DATA
= lcd_pixel_transform(lcd_framebuffer
[y
][x
]);
296 /* not implemented yet */
297 void lcd_update_rect(int x
, int y
, int width
, int height
)