2 * JzRISC lcd controller
4 * xiangfu liu <xiangfu.z@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 #include <asm/io.h> /* virt_to_phys() */
28 #include <asm/jz4740.h>
29 #include "nanonote_gpm940b0.h"
31 #define align2(n) (n)=((((n)+1)>>1)<<1)
32 #define align4(n) (n)=((((n)+3)>>2)<<2)
33 #define align8(n) (n)=((((n)+7)>>3)<<3)
36 unsigned int cfg
; /* panel mode and pin usage etc. */
39 unsigned int bpp
; /* bit per pixel */
40 unsigned int fclk
; /* frame clk */
41 unsigned int hsw
; /* hsync width, in pclk */
42 unsigned int vsw
; /* vsync width, in line count */
43 unsigned int elw
; /* end of line, in pclk */
44 unsigned int blw
; /* begin of line, in pclk */
45 unsigned int efw
; /* end of frame, in line count */
46 unsigned int bfw
; /* begin of frame, in line count */
49 static struct jzfb_info jzfb
= {
50 MODE_8BIT_SERIAL_TFT
| PCLK_N
| HSYNC_N
| VSYNC_N
,
51 320, 240, 32, 70, 1, 1, 273, 140, 1, 20
54 vidinfo_t panel_info
= {
63 * Frame buffer memory information
65 void *lcd_base
; /* Start of framebuffer memory */
66 void *lcd_console_address
; /* Start of console buffer */
71 void lcd_ctrl_init (void *lcdbase
);
72 void lcd_enable (void);
73 void lcd_disable (void);
75 static int jz_lcd_init_mem(void *lcdbase
, vidinfo_t
*vid
);
76 static void jz_lcd_desc_init(vidinfo_t
*vid
);
77 static int jz_lcd_hw_init( vidinfo_t
*vid
);
78 extern int flush_cache_all(void);
80 void lcd_ctrl_init (void *lcdbase
)
82 __lcd_display_pin_init();
84 jz_lcd_init_mem(lcdbase
, &panel_info
);
85 jz_lcd_desc_init(&panel_info
);
86 jz_lcd_hw_init(&panel_info
);
92 * Before enabled lcd controller, lcd registers should be configured correctly.
95 void lcd_enable (void)
97 REG_LCD_CTRL
&= ~(1<<4); /* LCDCTRL.DIS */
98 REG_LCD_CTRL
|= 1<<3; /* LCDCTRL.ENA*/
101 void lcd_disable (void)
103 REG_LCD_CTRL
|= (1<<4); /* LCDCTRL.DIS, regular disable */
104 /* REG_LCD_CTRL |= (1<<3); */ /* LCDCTRL.DIS, quikly disable */
107 static int jz_lcd_init_mem(void *lcdbase
, vidinfo_t
*vid
)
109 u_long palette_mem_size
;
110 struct jz_fb_info
*fbi
= &vid
->jz_fb
;
111 int fb_size
= vid
->vl_row
* (vid
->vl_col
* NBITS (vid
->vl_bpix
)) / 8;
113 fbi
->screen
= (u_long
)lcdbase
;
114 fbi
->palette_size
= 256;
115 palette_mem_size
= fbi
->palette_size
* sizeof(u16
);
117 debug("jz_lcd.c palette_mem_size = 0x%08lx\n", (u_long
) palette_mem_size
);
118 /* locate palette and descs at end of page following fb */
119 fbi
->palette
= (u_long
)lcdbase
+ fb_size
+ PAGE_SIZE
- palette_mem_size
;
124 static void jz_lcd_desc_init(vidinfo_t
*vid
)
126 struct jz_fb_info
* fbi
;
128 fbi
->dmadesc_fblow
= (struct jz_fb_dma_descriptor
*)((unsigned int)fbi
->palette
- 3*16);
129 fbi
->dmadesc_fbhigh
= (struct jz_fb_dma_descriptor
*)((unsigned int)fbi
->palette
- 2*16);
130 fbi
->dmadesc_palette
= (struct jz_fb_dma_descriptor
*)((unsigned int)fbi
->palette
- 1*16);
132 #define BYTES_PER_PANEL (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)
134 /* populate descriptors */
135 fbi
->dmadesc_fblow
->fdadr
= virt_to_phys(fbi
->dmadesc_fblow
);
136 fbi
->dmadesc_fblow
->fsadr
= virt_to_phys((void *)(fbi
->screen
+ BYTES_PER_PANEL
));
137 fbi
->dmadesc_fblow
->fidr
= 0;
138 fbi
->dmadesc_fblow
->ldcmd
= BYTES_PER_PANEL
/ 4 ;
140 fbi
->fdadr1
= virt_to_phys(fbi
->dmadesc_fblow
); /* only used in dual-panel mode */
142 fbi
->dmadesc_fbhigh
->fsadr
= virt_to_phys((void *)fbi
->screen
);
143 fbi
->dmadesc_fbhigh
->fidr
= 0;
144 fbi
->dmadesc_fbhigh
->ldcmd
= BYTES_PER_PANEL
/ 4; /* length in word */
146 fbi
->dmadesc_palette
->fsadr
= virt_to_phys((void *)fbi
->palette
);
147 fbi
->dmadesc_palette
->fidr
= 0;
148 fbi
->dmadesc_palette
->ldcmd
= (fbi
->palette_size
* 2)/4 | (1<<28);
150 if(NBITS(vid
->vl_bpix
) < 12)
152 /* assume any mode with <12 bpp is palette driven */
153 fbi
->dmadesc_palette
->fdadr
= virt_to_phys(fbi
->dmadesc_fbhigh
);
154 fbi
->dmadesc_fbhigh
->fdadr
= virt_to_phys(fbi
->dmadesc_palette
);
155 /* flips back and forth between pal and fbhigh */
156 fbi
->fdadr0
= virt_to_phys(fbi
->dmadesc_palette
);
158 /* palette shouldn't be loaded in true-color mode */
159 fbi
->dmadesc_fbhigh
->fdadr
= virt_to_phys((void *)fbi
->dmadesc_fbhigh
);
160 fbi
->fdadr0
= virt_to_phys(fbi
->dmadesc_fbhigh
); /* no pal just fbhigh */
166 static int jz_lcd_hw_init(vidinfo_t
*vid
)
168 struct jz_fb_info
*fbi
= &vid
->jz_fb
;
169 unsigned int val
= 0;
174 /* Setting Control register */
177 val
|= LCD_CTRL_BPP_1
;
180 val
|= LCD_CTRL_BPP_2
;
183 val
|= LCD_CTRL_BPP_4
;
186 val
|= LCD_CTRL_BPP_8
;
189 val
|= LCD_CTRL_RGB555
;
191 val
|= LCD_CTRL_BPP_16
;
194 val
|= LCD_CTRL_BPP_18_24
; /* target is 4bytes/pixel */
198 printf("jz_lcd.c The BPP %d is not supported\n", jzfb
.bpp
);
199 val
|= LCD_CTRL_BPP_16
;
203 switch (jzfb
.cfg
& MODE_MASK
) {
204 case MODE_STN_MONO_DUAL
:
205 case MODE_STN_COLOR_DUAL
:
206 case MODE_STN_MONO_SINGLE
:
207 case MODE_STN_COLOR_SINGLE
:
210 /* val |= LCD_CTRL_PEDN; */
212 val
|= LCD_CTRL_FRC_2
;
215 val
|= LCD_CTRL_FRC_4
;
219 val
|= LCD_CTRL_FRC_16
;
225 val
|= LCD_CTRL_BST_16
; /* Burst Length is 16WORD=64Byte */
226 val
|= LCD_CTRL_OFUP
; /* OutFIFO underrun protect */
228 switch (jzfb
.cfg
& MODE_MASK
) {
229 case MODE_STN_MONO_DUAL
:
230 case MODE_STN_COLOR_DUAL
:
231 case MODE_STN_MONO_SINGLE
:
232 case MODE_STN_COLOR_SINGLE
:
233 switch (jzfb
.cfg
& STN_DAT_PINMASK
) {
235 /* Do not adjust the hori-param value. */
258 switch (jzfb
.cfg
& MODE_MASK
) {
259 case MODE_STN_MONO_DUAL
:
260 case MODE_STN_COLOR_DUAL
:
261 case MODE_STN_MONO_SINGLE
:
262 case MODE_STN_COLOR_SINGLE
:
263 if (((jzfb
.cfg
& MODE_MASK
) == MODE_STN_MONO_DUAL
) ||
264 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_DUAL
))
269 REG_LCD_VSYNC
= (0 << 16) | jzfb
.vsw
;
270 REG_LCD_HSYNC
= ((jzfb
.blw
+jzfb
.w
) << 16) | (jzfb
.blw
+jzfb
.w
+jzfb
.hsw
);
273 REG_LCD_VAT
= ((jzfb
.blw
+ jzfb
.w
+ jzfb
.hsw
+ jzfb
.elw
) << 16) | (stnH
+ jzfb
.vsw
+ jzfb
.bfw
+ jzfb
.efw
);
274 REG_LCD_DAH
= (jzfb
.blw
<< 16) | (jzfb
.blw
+ jzfb
.w
);
275 REG_LCD_DAV
= (0 << 16) | (stnH
);
278 REG_LCD_PS
= (0 << 16) | (stnH
+jzfb
.vsw
+jzfb
.efw
+jzfb
.bfw
);
285 case MODE_TFT_SAMSUNG
:
286 case MODE_8BIT_SERIAL_TFT
:
288 REG_LCD_VSYNC
= (0 << 16) | jzfb
.vsw
;
289 REG_LCD_HSYNC
= (0 << 16) | jzfb
.hsw
;
290 REG_LCD_DAV
=((jzfb
.vsw
+jzfb
.bfw
) << 16) | (jzfb
.vsw
+jzfb
.bfw
+jzfb
.h
);
291 REG_LCD_DAH
= ((jzfb
.hsw
+ jzfb
.blw
) << 16) | (jzfb
.hsw
+ jzfb
.blw
+ jzfb
.w
);
292 REG_LCD_VAT
= (((jzfb
.blw
+ jzfb
.w
+ jzfb
.elw
+ jzfb
.hsw
)) << 16) \
293 | (jzfb
.vsw
+ jzfb
.bfw
+ jzfb
.h
+ jzfb
.efw
);
297 switch (jzfb
.cfg
& MODE_MASK
) {
298 case MODE_TFT_SAMSUNG
:
300 unsigned int total
, tp_s
, tp_e
, ckv_s
, ckv_e
;
301 unsigned int rev_s
, rev_e
, inv_s
, inv_e
;
303 pclk
= val
* (jzfb
.w
+ jzfb
.hsw
+ jzfb
.elw
+ jzfb
.blw
) *
304 (jzfb
.h
+ jzfb
.vsw
+ jzfb
.efw
+ jzfb
.bfw
); /* Pixclk */
306 total
= jzfb
.blw
+ jzfb
.w
+ jzfb
.elw
+ jzfb
.hsw
;
307 tp_s
= jzfb
.blw
+ jzfb
.w
+ 1;
309 /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
310 ckv_s
= tp_s
- pclk
/(1000000000/4100);
311 ckv_e
= tp_s
+ total
;
312 rev_s
= tp_s
- 11; /* -11.5 clk */
313 rev_e
= rev_s
+ total
;
315 inv_e
= inv_s
+ total
;
316 REG_LCD_CLS
= (tp_s
<< 16) | tp_e
;
317 REG_LCD_PS
= (ckv_s
<< 16) | ckv_e
;
318 REG_LCD_SPL
= (rev_s
<< 16) | rev_e
;
319 REG_LCD_REV
= (inv_s
<< 16) | inv_e
;
320 jzfb
.cfg
|= STFT_REVHI
| STFT_SPLHI
;
325 unsigned int total
, cls_s
, cls_e
, ps_s
, ps_e
;
326 unsigned int spl_s
, spl_e
, rev_s
, rev_e
;
327 total
= jzfb
.blw
+ jzfb
.w
+ jzfb
.elw
+ jzfb
.hsw
;
331 cls_e
= total
- 60; /* > 4us (pclk = 80ns) */
334 rev_s
= total
- 40; /* > 3us (pclk = 80ns) */
335 rev_e
= rev_s
+ total
;
336 jzfb
.cfg
|= STFT_PSHI
;
337 REG_LCD_SPL
= (spl_s
<< 16) | spl_e
;
338 REG_LCD_CLS
= (cls_s
<< 16) | cls_e
;
339 REG_LCD_PS
= (ps_s
<< 16) | ps_e
;
340 REG_LCD_REV
= (rev_s
<< 16) | rev_e
;
347 /* Configure the LCD panel */
348 REG_LCD_CFG
= jzfb
.cfg
;
353 val
= jzfb
.fclk
; /* frame clk */
354 if ( (jzfb
.cfg
& MODE_MASK
) != MODE_8BIT_SERIAL_TFT
) {
355 pclk
= val
* (jzfb
.w
+ jzfb
.hsw
+ jzfb
.elw
+ jzfb
.blw
) *
356 (jzfb
.h
+ jzfb
.vsw
+ jzfb
.efw
+ jzfb
.bfw
); /* Pixclk */
358 /* serial mode: Hsync period = 3*Width_Pixel */
359 pclk
= val
* (jzfb
.w
*3 + jzfb
.hsw
+ jzfb
.elw
+ jzfb
.blw
) *
360 (jzfb
.h
+ jzfb
.vsw
+ jzfb
.efw
+ jzfb
.bfw
); /* Pixclk */
363 if (((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_SINGLE
) ||
364 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_DUAL
))
367 if (((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_SINGLE
) ||
368 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_DUAL
) ||
369 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_MONO_SINGLE
) ||
370 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_MONO_DUAL
))
371 pclk
= pclk
>> ((jzfb
.cfg
& STN_DAT_PINMASK
) >> 4);
373 if (((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_DUAL
) ||
374 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_MONO_DUAL
))
377 pll_div
= ( REG_CPM_CPCCR
& CPM_CPCCR_PCS
); /* clock source,0:pllout/2 1: pllout */
378 pll_div
= pll_div
? 1 : 2 ;
379 val
= ( __cpm_get_pllout()/pll_div
) / pclk
;
382 printf("CPM_LPCDR too large, set it to 0x1ff\n");
385 __cpm_set_pixdiv(val
);
387 val
= pclk
* 3 ; /* LCDClock > 2.5*Pixclock */
388 if ( val
> 150000000 ) {
389 printf("Warning: LCDClock=%d\n, LCDClock must less or equal to 150MHz.\n", val
);
390 printf("Change LCDClock to 150MHz\n");
393 val
= ( __cpm_get_pllout()/pll_div
) / val
;
396 printf("CPM_CPCCR.LDIV too large, set it to 0x1f\n");
399 __cpm_set_ldiv( val
);
400 REG_CPM_CPCCR
|= CPM_CPCCR_CE
; /* update divide */
405 REG_LCD_DA0
= fbi
->fdadr0
; /* frame descripter*/
407 if (((jzfb
.cfg
& MODE_MASK
) == MODE_STN_COLOR_DUAL
) ||
408 ((jzfb
.cfg
& MODE_MASK
) == MODE_STN_MONO_DUAL
))
409 REG_LCD_DA1
= fbi
->fdadr1
; /* frame descripter*/
414 void lcd_setcolreg (ushort regno
, ushort red
, ushort green
, ushort blue
)
418 void lcd_initcolregs (void)
This page took 0.061191 seconds and 5 git commands to generate.