NanoPayload

stage2/jzlcd.c

48:7691d29a3bf1
2015-06-10 Paul Boddie Moved framebuffer workspace initialisation into the specific driver file.
     1 /*     2  * JzRISC LCD controller     3  *     4  * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>     5  * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>     6  *     7  * This program is free software; you can redistribute it and/or     8  * modify it under the terms of the GNU General Public License as     9  * published by the Free Software Foundation; either version 2 of    10  * the License, or (at your option) any later version.    11  *    12  * This program is distributed in the hope that it will be useful,    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the    15  * GNU General Public License for more details.    16  *    17  * You should have received a copy of the GNU General Public License    18  * along with this program; if not, write to the Free Software    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    20  * Boston, MA  02110-1301, USA    21  */    22     23 #include "sdram.h"    24 #include "jzlcd.h"    25 #include "board.h"    26     27 #define ALIGN(x,a)              __ALIGN_MASK((x),(typeof(x))(a)-1)    28 #define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))    29     30 #define align2(n) (n)=((((n)+1)>>1)<<1)    31 #define align4(n) (n)=((((n)+3)>>2)<<2)    32 #define align8(n) (n)=((((n)+7)>>3)<<3)    33     34 extern struct jzfb_info jzfb;    35 extern vidinfo_t panel_info;    36     37 unsigned long lcd_get_size(void)    38 {    39 	int line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;    40         return line_length * panel_info.vl_row;    41 }    42     43 unsigned long lcd_setmem(unsigned long addr)    44 {    45         unsigned long size;    46     47         size = lcd_get_size();    48     49         /* Round up to nearest full page, or MMU section if defined */    50         size = ALIGN(size, PAGE_SIZE);    51         addr = ALIGN(addr - PAGE_SIZE + 1, PAGE_SIZE);    52     53         /* Allocate pages for the frame buffer. */    54         addr -= size;    55     56         return addr;    57 }    58     59 static int  jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid);    60 static void jz_lcd_desc_init(vidinfo_t *vid);    61 static int  jz_lcd_hw_init(vidinfo_t *vid);    62     63 void lcd_ctrl_init (void **lcdbase)    64 {    65 	/* Start from the top of memory and obtain a framebuffer region. */    66 	*lcdbase = (void *) lcd_setmem(get_memory_size());    67     68 	jz_lcd_init_mem(*lcdbase, &panel_info);    69 	jz_lcd_desc_init(&panel_info);    70 	jz_lcd_hw_init(&panel_info);    71 }    72     73 /*    74  * Before enabled lcd controller, lcd registers should be configured correctly.    75  */    76 void lcd_enable (void)    77 {    78 	REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */    79 	REG_LCD_CTRL |= 1<<3;    /* LCDCTRL.ENA*/    80 }    81     82 void lcd_disable (void)    83 {    84 	REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */    85 	/* REG_LCD_CTRL |= (1<<3); */  /* LCDCTRL.DIS, quickly disable */    86 }    87     88 static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid)    89 {    90 	unsigned long palette_mem_size;    91 	struct jz_fb_info *fbi = &vid->jz_fb;    92 	int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;    93     94 	fbi->screen = (unsigned long)lcdbase;    95 	fbi->palette_size = 256;    96 	palette_mem_size = fbi->palette_size * sizeof(u16);    97     98 	/* locate palette and descs at end of page following fb */    99 	fbi->palette = (unsigned long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;   100    101 	return 0;   102 }   103    104 static void jz_lcd_desc_init(vidinfo_t *vid)   105 {   106 	struct jz_fb_info * fbi;   107 	fbi = &vid->jz_fb;   108 	fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);   109 	fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);   110 	fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);   111    112 	#define BYTES_PER_PANEL	 (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)   113    114 	/* populate descriptors */   115 	fbi->dmadesc_fblow->fdadr = virt_to_phys(fbi->dmadesc_fblow);   116 	fbi->dmadesc_fblow->fsadr = virt_to_phys((void *)(fbi->screen + BYTES_PER_PANEL));   117 	fbi->dmadesc_fblow->fidr  = 0;   118 	fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL / 4 ;   119    120 	fbi->fdadr1 = virt_to_phys(fbi->dmadesc_fblow); /* only used in dual-panel mode */   121    122 	fbi->dmadesc_fbhigh->fsadr = virt_to_phys((void *)fbi->screen);   123 	fbi->dmadesc_fbhigh->fidr = 0;   124 	fbi->dmadesc_fbhigh->ldcmd =  BYTES_PER_PANEL / 4; /* length in word */   125    126 	fbi->dmadesc_palette->fsadr = virt_to_phys((void *)fbi->palette);   127 	fbi->dmadesc_palette->fidr  = 0;   128 	fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28);   129    130 	if(NBITS(vid->vl_bpix) < 12)   131 	{   132 		/* assume any mode with <12 bpp is palette driven */   133 		fbi->dmadesc_palette->fdadr = virt_to_phys(fbi->dmadesc_fbhigh);   134 		fbi->dmadesc_fbhigh->fdadr = virt_to_phys(fbi->dmadesc_palette);   135 		/* flips back and forth between pal and fbhigh */   136 		fbi->fdadr0 = virt_to_phys(fbi->dmadesc_palette);   137 	} else {   138 		/* palette shouldn't be loaded in true-color mode */   139 		fbi->dmadesc_fbhigh->fdadr = virt_to_phys((void *)fbi->dmadesc_fbhigh);   140 		fbi->fdadr0 = virt_to_phys(fbi->dmadesc_fbhigh); /* no pal just fbhigh */   141 	}   142    143 	flush_cache_all();   144 }   145    146 static int  jz_lcd_hw_init(vidinfo_t *vid)   147 {   148 	struct jz_fb_info *fbi = &vid->jz_fb;   149 	unsigned int val = 0;   150 	unsigned int pclk;   151 	unsigned int stnH;   152 #ifndef CONFIG_CPU_JZ4730   153 	int pll_div;   154 #endif   155    156 	/* Setting Control register */   157 	switch (jzfb.bpp) {   158 	case 1:   159 		val |= LCD_CTRL_BPP_1;   160 		break;   161 	case 2:   162 		val |= LCD_CTRL_BPP_2;   163 		break;   164 	case 4:   165 		val |= LCD_CTRL_BPP_4;   166 		break;   167 	case 8:   168 		val |= LCD_CTRL_BPP_8;   169 		break;   170 	case 15:   171 		val |= LCD_CTRL_RGB555;   172 	case 16:   173 		val |= LCD_CTRL_BPP_16;   174 		break;   175 #ifndef CONFIG_CPU_JZ4730   176 	case 17 ... 32:   177 		val |= LCD_CTRL_BPP_18_24;	/* target is 4bytes/pixel */   178 		break;   179 #endif   180 	default:   181 		/* printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp); */   182 		val |= LCD_CTRL_BPP_16;   183 		break;   184 	}   185    186 	switch (jzfb.cfg & MODE_MASK) {   187 	case MODE_STN_MONO_DUAL:   188 	case MODE_STN_COLOR_DUAL:   189 	case MODE_STN_MONO_SINGLE:   190 	case MODE_STN_COLOR_SINGLE:   191 		switch (jzfb.bpp) {   192 		case 1:   193 			/* val |= LCD_CTRL_PEDN; */   194 		case 2:   195 			val |= LCD_CTRL_FRC_2;   196 			break;   197 		case 4:   198 			val |= LCD_CTRL_FRC_4;   199 			break;   200 		case 8:   201 		default:   202 			val |= LCD_CTRL_FRC_16;   203 			break;   204 		}   205 		break;   206 	}   207    208 	val |= LCD_CTRL_BST_16;		/* Burst Length is 16WORD=64Byte */   209 	val |= LCD_CTRL_OFUP;		/* OutFIFO underrun protect */   210    211 	switch (jzfb.cfg & MODE_MASK) {   212 	case MODE_STN_MONO_DUAL:   213 	case MODE_STN_COLOR_DUAL:   214 	case MODE_STN_MONO_SINGLE:   215 	case MODE_STN_COLOR_SINGLE:   216 		switch (jzfb.cfg & STN_DAT_PINMASK) {   217 		case STN_DAT_PIN1:   218 			/* Do not adjust the hori-param value. */   219 			break;   220 		case STN_DAT_PIN2:   221 			align2(jzfb.hsw);   222 			align2(jzfb.elw);   223 			align2(jzfb.blw);   224 			break;   225 		case STN_DAT_PIN4:   226 			align4(jzfb.hsw);   227 			align4(jzfb.elw);   228 			align4(jzfb.blw);   229 			break;   230 		case STN_DAT_PIN8:   231 			align8(jzfb.hsw);   232 			align8(jzfb.elw);   233 			align8(jzfb.blw);   234 			break;   235 		}   236 		break;   237 	}   238    239 	REG_LCD_CTRL = val;   240    241 	switch (jzfb.cfg & MODE_MASK) {   242 	case MODE_STN_MONO_DUAL:   243 	case MODE_STN_COLOR_DUAL:   244 	case MODE_STN_MONO_SINGLE:   245 	case MODE_STN_COLOR_SINGLE:   246 		if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) ||   247 		    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))   248 			stnH = jzfb.h >> 1;   249 		else   250 			stnH = jzfb.h;   251    252 		REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;   253 		REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw);   254    255 		/* Screen setting */   256 		REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw);   257 		REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w);   258 		REG_LCD_DAV = (0 << 16) | (stnH);   259    260 		/* AC BIAs signal */   261 		REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw);   262    263 		break;   264    265 	case MODE_TFT_GEN:   266 	case MODE_TFT_SHARP:   267 	case MODE_TFT_CASIO:   268 	case MODE_TFT_SAMSUNG:   269 	case MODE_8BIT_SERIAL_TFT:   270 	case MODE_TFT_18BIT:   271 		REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;   272 		REG_LCD_HSYNC = (0 << 16) | jzfb.hsw;   273 		REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h);   274 		REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w );   275 		REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \   276 			| (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw);   277 		break;   278 	}   279    280 	switch (jzfb.cfg & MODE_MASK) {   281 	case MODE_TFT_SAMSUNG:   282 	{   283 		unsigned int total, tp_s, tp_e, ckv_s, ckv_e;   284 		unsigned int rev_s, rev_e, inv_s, inv_e;   285    286 		pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *   287 			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */   288    289 		total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;   290 		tp_s = jzfb.blw + jzfb.w + 1;   291 		tp_e = tp_s + 1;   292 		/* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */   293 		ckv_s = tp_s - pclk/(1000000000/4100);   294 		ckv_e = tp_s + total;   295 		rev_s = tp_s - 11;	/* -11.5 clk */   296 		rev_e = rev_s + total;   297 		inv_s = tp_s;   298 		inv_e = inv_s + total;   299 		REG_LCD_CLS = (tp_s << 16) | tp_e;   300 		REG_LCD_PS = (ckv_s << 16) | ckv_e;   301 		REG_LCD_SPL = (rev_s << 16) | rev_e;   302 		REG_LCD_REV = (inv_s << 16) | inv_e;   303 		jzfb.cfg |= STFT_REVHI | STFT_SPLHI;   304 		break;   305 	}   306 	case MODE_TFT_SHARP:   307 	{   308 		unsigned int total, cls_s, cls_e, ps_s, ps_e;   309 		unsigned int spl_s, spl_e, rev_s, rev_e;   310 		total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;   311 		spl_s = 1;   312 		spl_e = spl_s + 1;   313 		cls_s = 0;   314 		cls_e = total - 60;	/* > 4us (pclk = 80ns) */   315 		ps_s = cls_s;   316 		ps_e = cls_e;   317 		rev_s = total - 40;	/* > 3us (pclk = 80ns) */   318 		rev_e = rev_s + total;   319 		jzfb.cfg |= STFT_PSHI;    320 		REG_LCD_SPL = (spl_s << 16) | spl_e;   321 		REG_LCD_CLS = (cls_s << 16) | cls_e;   322 		REG_LCD_PS = (ps_s << 16) | ps_e;   323 		REG_LCD_REV = (rev_s << 16) | rev_e;   324 		break;   325 	}   326 	case MODE_TFT_CASIO:   327 		break;   328 	}   329    330 	/* Configure the LCD panel */   331 	REG_LCD_CFG = jzfb.cfg;   332    333 	/* Timing setting */   334 	__cpm_stop_lcd();   335    336 	val = jzfb.fclk; /* frame clk */   337 	if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {   338 		pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *   339 			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */   340 	} else {   341 		/* serial mode: Hsync period = 3*Width_Pixel */   342 		pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *   343 			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */   344 	}   345    346 	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||   347 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))   348 		pclk = (pclk * 3);   349    350 	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||   351 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||   352 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||   353 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))   354 		pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);   355    356 	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||   357 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))   358 		pclk >>= 1;   359    360 #ifdef CONFIG_CPU_JZ4730   361         val = __cpm_get_pllout() / pclk;   362         REG_CPM_CFCR2 = val - 1;   363         val = pclk * 4 ;   364         if ( val > 150000000 ) {   365                 val = 150000000;   366         }   367         val = __cpm_get_pllout() / val;   368         val--;   369         if ( val > 0xF )   370                 val = 0xF;   371         __cpm_set_lcdclk_div(val);   372         REG_CPM_CFCR |= CPM_CFCR_UPE;   373 #else   374 	pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */   375 	pll_div = pll_div ? 1 : 2 ;   376 	val = ( __cpm_get_pllout()/pll_div ) / pclk;   377 	val--;   378 	if ( val > 0x1ff ) {   379 		val = 0x1ff;   380 	}   381 	__cpm_set_pixdiv(val);   382    383 	val = pclk * 3 ;	/* LCDClock > 2.5*Pixclock */   384 	if ( val > 150000000 ) {   385 		val = 150000000;   386 	}   387 	val = ( __cpm_get_pllout()/pll_div ) / val;   388 	val--;   389 	if ( val > 0x1f ) {   390 		val = 0x1f;   391 	}   392 	__cpm_set_ldiv( val );   393 	REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */   394 #endif   395 	__cpm_start_lcd();   396 	udelay(1000);   397    398 	REG_LCD_DA0 = fbi->fdadr0; /* frame descripter*/   399    400 	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||   401 	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))   402 		REG_LCD_DA1 = fbi->fdadr1; /* frame descripter*/   403    404 	return 0;   405 }   406    407 void lcd_setcolreg (unsigned short regno, unsigned short red, unsigned short green, unsigned short blue)   408 {   409 }   410    411 void lcd_initcolregs (void)   412 {   413 }