NanoPayload

Annotated stage2/jzlcd.c

195:aa19895c149a
2016-05-14 Paul Boddie Removed superfluous void argument type declarations.
paul@33 1
/*
paul@38 2
 * JzRISC LCD controller
paul@33 3
 *
paul@33 4
 * Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
paul@93 5
 * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
paul@33 6
 *
paul@33 7
 * This program is free software; you can redistribute it and/or
paul@33 8
 * modify it under the terms of the GNU General Public License as
paul@33 9
 * published by the Free Software Foundation; either version 2 of
paul@33 10
 * the License, or (at your option) any later version.
paul@33 11
 *
paul@33 12
 * This program is distributed in the hope that it will be useful,
paul@33 13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@33 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
paul@33 15
 * GNU General Public License for more details.
paul@33 16
 *
paul@33 17
 * You should have received a copy of the GNU General Public License
paul@33 18
 * along with this program; if not, write to the Free Software
paul@42 19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@42 20
 * Boston, MA  02110-1301, USA
paul@33 21
 */
paul@33 22
paul@33 23
#include "sdram.h"
paul@33 24
#include "jzlcd.h"
paul@62 25
#include "cpu.h"
paul@33 26
#include "board.h"
paul@33 27
paul@33 28
#define align2(n) (n)=((((n)+1)>>1)<<1)
paul@33 29
#define align4(n) (n)=((((n)+3)>>2)<<2)
paul@33 30
#define align8(n) (n)=((((n)+7)>>3)<<3)
paul@33 31
paul@33 32
extern struct jzfb_info jzfb;
paul@34 33
extern vidinfo_t panel_info;
paul@33 34
paul@100 35
static unsigned short lcd_get_panels()
paul@100 36
{
paul@100 37
	return ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) ||
paul@100 38
		((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1;
paul@100 39
}
paul@100 40
paul@102 41
paul@102 42
paul@102 43
/* Functions returning region sizes. */
paul@102 44
paul@93 45
static unsigned long lcd_get_size(vidinfo_t *vid)
paul@33 46
{
paul@100 47
	/* Lines must be aligned to a word boundary. */
paul@100 48
	unsigned long line_length = ALIGN((vid->vl_col * NBITS(vid->vl_bpix)) / 8, sizeof(u32));
paul@93 49
        return line_length * vid->vl_row;
paul@33 50
}
paul@33 51
paul@100 52
static unsigned long lcd_get_aligned_size(vidinfo_t *vid)
paul@100 53
{
paul@100 54
	/* LCD_CTRL_BST_16 requires 16-word alignment. */
paul@100 55
        return ALIGN(lcd_get_size(vid), 16 * sizeof(u32));
paul@100 56
}
paul@100 57
paul@100 58
static unsigned long lcd_get_min_size(vidinfo_t *vid)
paul@100 59
{
paul@100 60
	/* Lines must be aligned to a word boundary. */
paul@100 61
	unsigned long line_length = ALIGN((vid->vl_col * 32) / 8, sizeof(u32));
paul@100 62
        return line_length * vid->vl_row;
paul@100 63
}
paul@100 64
paul@100 65
static unsigned long lcd_get_aligned_min_size(vidinfo_t *vid)
paul@100 66
{
paul@100 67
	/* LCD_CTRL_BST_16 requires 16-word alignment. */
paul@100 68
        return ALIGN(lcd_get_min_size(vid), 16 * sizeof(u32));
paul@100 69
}
paul@100 70
paul@102 71
static unsigned long lcd_get_palette_size(vidinfo_t *vid)
paul@97 72
{
paul@102 73
	if (NBITS(vid->vl_bpix) < 12)
paul@102 74
		return NCOLORS(vid->vl_bpix) * sizeof(u16);
paul@102 75
	else
paul@102 76
		return 0;
paul@97 77
}
paul@97 78
paul@102 79
static unsigned long lcd_get_aligned_palette_size(vidinfo_t *vid)
paul@100 80
{
paul@100 81
	/* LCD_CTRL_BST_16 requires 16-word alignment. */
paul@102 82
	return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(u32));
paul@100 83
}
paul@100 84
paul@98 85
static unsigned long lcd_get_descriptors_size()
paul@98 86
{
paul@98 87
	return 3 * sizeof(struct jz_fb_dma_descriptor);
paul@98 88
}
paul@98 89
paul@100 90
static unsigned long lcd_get_total_size(vidinfo_t *vid)
paul@97 91
{
paul@100 92
	unsigned long size = lcd_get_aligned_size(vid) * lcd_get_panels();
paul@100 93
	unsigned long min_size = lcd_get_aligned_min_size(vid);
paul@100 94
paul@100 95
        /* Round up to nearest full page, or MMU section if defined. */
paul@102 96
	return ALIGN((size >= min_size ? size : min_size) + lcd_get_aligned_palette_size(vid) + lcd_get_descriptors_size(), PAGE_SIZE);
paul@93 97
}
paul@48 98
paul@102 99
paul@102 100
paul@102 101
/* Functions returning addresses of each data region. */
paul@102 102
paul@97 103
static unsigned long lcd_get_palette(unsigned long addr)
paul@93 104
{
paul@98 105
        /* Allocate memory at the end of the region for the palette. */
paul@102 106
	return addr - lcd_get_aligned_palette_size(&panel_info);
paul@98 107
}
paul@98 108
paul@98 109
static unsigned long lcd_get_descriptors(unsigned long addr)
paul@98 110
{
paul@98 111
        /* Allocate memory before the palette for the descriptor array. */
paul@100 112
	return lcd_get_palette(addr) - lcd_get_descriptors_size();
paul@48 113
}
paul@48 114
paul@100 115
static unsigned long lcd_get_framebuffer(unsigned long addr, unsigned short panel)
paul@97 116
{
paul@97 117
        /* Allocate pages for the frame buffer and palette. */
paul@100 118
        return addr - lcd_get_total_size(&panel_info) + (panel * lcd_get_aligned_size(&panel_info));
paul@97 119
}
paul@97 120
paul@102 121
paul@102 122
paul@102 123
/* Initialisation functions. */
paul@102 124
paul@33 125
static void jz_lcd_desc_init(vidinfo_t *vid)
paul@33 126
{
paul@94 127
	struct jz_fb_dma_descriptor *descriptors;
paul@33 128
	struct jz_fb_info * fbi;
paul@95 129
paul@33 130
	fbi = &vid->jz_fb;
paul@96 131
paul@96 132
	/* Allocate space for descriptors before the palette entries. */
paul@96 133
paul@98 134
	descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(get_memory_size());
paul@94 135
	fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *) &descriptors[0];
paul@94 136
	fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *) &descriptors[1];
paul@94 137
	fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *) &descriptors[2];
paul@33 138
paul@96 139
	/* Populate descriptors. */
paul@96 140
paul@100 141
	if (lcd_get_panels() == 2)
paul@100 142
	{
paul@100 143
		fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow;
paul@100 144
		fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1);
paul@100 145
		fbi->dmadesc_fblow->fidr  = 0;
paul@100 146
		fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ;
paul@33 147
paul@100 148
		fbi->fdadr1 = fbi->dmadesc_fblow; /* only used in dual-panel mode */
paul@100 149
	}
paul@33 150
paul@95 151
	fbi->dmadesc_fbhigh->fsadr = fbi->screen;
paul@33 152
	fbi->dmadesc_fbhigh->fidr = 0;
paul@100 153
	fbi->dmadesc_fbhigh->ldcmd =  lcd_get_size(vid) / 4; /* length in words */
paul@33 154
paul@100 155
	if (NBITS(vid->vl_bpix) < 12)
paul@33 156
	{
paul@101 157
		fbi->dmadesc_palette->fsadr = fbi->palette;
paul@101 158
		fbi->dmadesc_palette->fidr  = 0;
paul@102 159
		fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | (1<<28);
paul@101 160
paul@33 161
		/* assume any mode with <12 bpp is palette driven */
paul@95 162
		fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh;
paul@95 163
		fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_palette;
paul@33 164
		/* flips back and forth between pal and fbhigh */
paul@95 165
		fbi->fdadr0 = fbi->dmadesc_palette;
paul@33 166
	} else {
paul@33 167
		/* palette shouldn't be loaded in true-color mode */
paul@95 168
		fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_fbhigh;
paul@95 169
		fbi->fdadr0 = fbi->dmadesc_fbhigh; /* no pal just fbhigh */
paul@33 170
	}
paul@33 171
paul@33 172
	flush_cache_all();
paul@33 173
}
paul@33 174
paul@96 175
static unsigned int jz_lcd_stn_init(unsigned int stnH)
paul@96 176
{
paul@96 177
	unsigned int val = 0;
paul@96 178
paul@96 179
	switch (jzfb.bpp) {
paul@96 180
	case 1:
paul@96 181
		/* val |= LCD_CTRL_PEDN; */
paul@96 182
	case 2:
paul@96 183
		val |= LCD_CTRL_FRC_2;
paul@96 184
		break;
paul@96 185
	case 4:
paul@96 186
		val |= LCD_CTRL_FRC_4;
paul@96 187
		break;
paul@96 188
	case 8:
paul@96 189
	default:
paul@96 190
		val |= LCD_CTRL_FRC_16;
paul@96 191
		break;
paul@96 192
	}
paul@96 193
paul@96 194
	switch (jzfb.cfg & STN_DAT_PINMASK) {
paul@96 195
	case STN_DAT_PIN1:
paul@96 196
		/* Do not adjust the hori-param value. */
paul@96 197
		break;
paul@96 198
	case STN_DAT_PIN2:
paul@96 199
		align2(jzfb.hsw);
paul@96 200
		align2(jzfb.elw);
paul@96 201
		align2(jzfb.blw);
paul@96 202
		break;
paul@96 203
	case STN_DAT_PIN4:
paul@96 204
		align4(jzfb.hsw);
paul@96 205
		align4(jzfb.elw);
paul@96 206
		align4(jzfb.blw);
paul@96 207
		break;
paul@96 208
	case STN_DAT_PIN8:
paul@96 209
		align8(jzfb.hsw);
paul@96 210
		align8(jzfb.elw);
paul@96 211
		align8(jzfb.blw);
paul@96 212
		break;
paul@96 213
	}
paul@96 214
paul@96 215
	REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
paul@96 216
	REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw);
paul@96 217
paul@96 218
	/* Screen setting */
paul@96 219
	REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw);
paul@96 220
	REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w);
paul@96 221
	REG_LCD_DAV = (0 << 16) | (stnH);
paul@96 222
paul@96 223
	/* AC BIAs signal */
paul@96 224
	REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw);
paul@96 225
paul@96 226
	return val;
paul@96 227
}
paul@96 228
paul@96 229
static void jz_lcd_tft_init()
paul@96 230
{
paul@96 231
	REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
paul@96 232
	REG_LCD_HSYNC = (0 << 16) | jzfb.hsw;
paul@96 233
	REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h);
paul@96 234
	REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w );
paul@96 235
	REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \
paul@96 236
		| (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw);
paul@96 237
}
paul@96 238
paul@106 239
static void jz_lcd_samsung_init(unsigned int pclk)
paul@106 240
{
paul@106 241
	unsigned int total, tp_s, tp_e, ckv_s, ckv_e;
paul@106 242
	unsigned int rev_s, rev_e, inv_s, inv_e;
paul@106 243
paul@106 244
	jz_lcd_tft_init();
paul@106 245
paul@106 246
	total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
paul@106 247
	tp_s = jzfb.blw + jzfb.w + 1;
paul@106 248
	tp_e = tp_s + 1;
paul@106 249
	/* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
paul@106 250
	ckv_s = tp_s - pclk/(1000000000/4100);
paul@106 251
	ckv_e = tp_s + total;
paul@106 252
	rev_s = tp_s - 11;	/* -11.5 clk */
paul@106 253
	rev_e = rev_s + total;
paul@106 254
	inv_s = tp_s;
paul@106 255
	inv_e = inv_s + total;
paul@106 256
	REG_LCD_CLS = (tp_s << 16) | tp_e;
paul@106 257
	REG_LCD_PS = (ckv_s << 16) | ckv_e;
paul@106 258
	REG_LCD_SPL = (rev_s << 16) | rev_e;
paul@106 259
	REG_LCD_REV = (inv_s << 16) | inv_e;
paul@106 260
	jzfb.cfg |= STFT_REVHI | STFT_SPLHI;
paul@106 261
}
paul@106 262
paul@106 263
static void jz_lcd_sharp_init()
paul@106 264
{
paul@106 265
	unsigned int total, cls_s, cls_e, ps_s, ps_e;
paul@106 266
	unsigned int spl_s, spl_e, rev_s, rev_e;
paul@106 267
paul@106 268
	jz_lcd_tft_init();
paul@106 269
paul@106 270
	total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
paul@106 271
	spl_s = 1;
paul@106 272
	spl_e = spl_s + 1;
paul@106 273
	cls_s = 0;
paul@106 274
	cls_e = total - 60;	/* > 4us (pclk = 80ns) */
paul@106 275
	ps_s = cls_s;
paul@106 276
	ps_e = cls_e;
paul@106 277
	rev_s = total - 40;	/* > 3us (pclk = 80ns) */
paul@106 278
	rev_e = rev_s + total;
paul@106 279
	jzfb.cfg |= STFT_PSHI; 
paul@106 280
	REG_LCD_SPL = (spl_s << 16) | spl_e;
paul@106 281
	REG_LCD_CLS = (cls_s << 16) | cls_e;
paul@106 282
	REG_LCD_PS = (ps_s << 16) | ps_e;
paul@106 283
	REG_LCD_REV = (rev_s << 16) | rev_e;
paul@106 284
}
paul@106 285
paul@98 286
static unsigned int jz_lcd_get_pixel_clock()
paul@98 287
{
paul@98 288
	unsigned int pclk;
paul@98 289
paul@98 290
	/* Derive pixel clock from frame clock. */
paul@98 291
paul@98 292
	if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {
paul@98 293
		pclk = jzfb.fclk * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
paul@98 294
			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw);
paul@98 295
	} else {
paul@98 296
		/* serial mode: Hsync period = 3*Width_Pixel */
paul@98 297
		pclk = jzfb.fclk * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *
paul@98 298
			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw);
paul@98 299
	}
paul@98 300
paul@98 301
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
paul@98 302
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
paul@98 303
		pclk = (pclk * 3);
paul@98 304
paul@98 305
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
paul@98 306
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@98 307
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||
paul@98 308
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@98 309
		pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);
paul@98 310
paul@98 311
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@98 312
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@98 313
		pclk >>= 1;
paul@98 314
paul@98 315
	return pclk;
paul@98 316
}
paul@98 317
paul@98 318
static void jz_lcd_set_timing(unsigned int pclk)
paul@98 319
{
paul@98 320
	unsigned int val;
paul@98 321
paul@98 322
#ifdef CONFIG_CPU_JZ4730
paul@98 323
        val = __cpm_get_pllout() / pclk;
paul@98 324
        REG_CPM_CFCR2 = val - 1;
paul@98 325
        val = pclk * 4 ;
paul@98 326
        if ( val > 150000000 ) {
paul@98 327
                val = 150000000;
paul@98 328
        }
paul@98 329
        val = __cpm_get_pllout() / val;
paul@98 330
        val--;
paul@98 331
        if ( val > 0xF )
paul@98 332
                val = 0xF;
paul@98 333
#else
paul@98 334
	int pll_div;
paul@98 335
paul@98 336
	pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */
paul@98 337
	pll_div = pll_div ? 1 : 2 ;
paul@98 338
	val = ( __cpm_get_pllout()/pll_div ) / pclk;
paul@98 339
	val--;
paul@98 340
	if ( val > 0x1ff ) {
paul@98 341
		val = 0x1ff;
paul@98 342
	}
paul@98 343
	__cpm_set_pixdiv(val);
paul@98 344
paul@98 345
	val = pclk * 3 ;	/* LCDClock > 2.5*Pixclock */
paul@98 346
	if ( val > 150000000 ) {
paul@98 347
		val = 150000000;
paul@98 348
	}
paul@98 349
	val = ( __cpm_get_pllout()/pll_div ) / val;
paul@98 350
	val--;
paul@98 351
	if ( val > 0x1f ) {
paul@98 352
		val = 0x1f;
paul@98 353
	}
paul@98 354
#endif
paul@98 355
	__cpm_set_ldiv( val );
paul@98 356
	REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */
paul@98 357
}
paul@98 358
paul@96 359
static int jz_lcd_hw_init(vidinfo_t *vid)
paul@33 360
{
paul@33 361
	struct jz_fb_info *fbi = &vid->jz_fb;
paul@33 362
	unsigned int val = 0;
paul@98 363
	unsigned int pclk = jz_lcd_get_pixel_clock();
paul@33 364
paul@33 365
	/* Setting Control register */
paul@33 366
	switch (jzfb.bpp) {
paul@33 367
	case 1:
paul@33 368
		val |= LCD_CTRL_BPP_1;
paul@33 369
		break;
paul@33 370
	case 2:
paul@33 371
		val |= LCD_CTRL_BPP_2;
paul@33 372
		break;
paul@33 373
	case 4:
paul@33 374
		val |= LCD_CTRL_BPP_4;
paul@33 375
		break;
paul@33 376
	case 8:
paul@33 377
		val |= LCD_CTRL_BPP_8;
paul@33 378
		break;
paul@33 379
	case 15:
paul@33 380
		val |= LCD_CTRL_RGB555;
paul@33 381
	case 16:
paul@33 382
		val |= LCD_CTRL_BPP_16;
paul@33 383
		break;
paul@43 384
#ifndef CONFIG_CPU_JZ4730
paul@33 385
	case 17 ... 32:
paul@33 386
		val |= LCD_CTRL_BPP_18_24;	/* target is 4bytes/pixel */
paul@33 387
		break;
paul@43 388
#endif
paul@33 389
	default:
paul@33 390
		/* printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp); */
paul@33 391
		val |= LCD_CTRL_BPP_16;
paul@33 392
		break;
paul@33 393
	}
paul@33 394
paul@33 395
	switch (jzfb.cfg & MODE_MASK) {
paul@33 396
	case MODE_STN_MONO_DUAL:
paul@33 397
	case MODE_STN_COLOR_DUAL:
paul@96 398
		val |= jz_lcd_stn_init(jzfb.h >> 1);
paul@33 399
		break;
paul@33 400
paul@33 401
	case MODE_STN_MONO_SINGLE:
paul@33 402
	case MODE_STN_COLOR_SINGLE:
paul@96 403
		val |= jz_lcd_stn_init(jzfb.h);
paul@33 404
		break;
paul@33 405
paul@33 406
	case MODE_TFT_GEN:
paul@33 407
	case MODE_TFT_CASIO:
paul@33 408
	case MODE_8BIT_SERIAL_TFT:
paul@33 409
	case MODE_TFT_18BIT:
paul@96 410
		jz_lcd_tft_init();
paul@33 411
		break;
paul@33 412
paul@33 413
	case MODE_TFT_SAMSUNG:
paul@33 414
	{
paul@106 415
		jz_lcd_samsung_init(pclk);
paul@33 416
		break;
paul@33 417
	}
paul@96 418
paul@33 419
	case MODE_TFT_SHARP:
paul@33 420
	{
paul@106 421
		jz_lcd_sharp_init();
paul@33 422
		break;
paul@33 423
	}
paul@96 424
paul@96 425
	default:
paul@33 426
		break;
paul@33 427
	}
paul@33 428
paul@33 429
	/* Configure the LCD panel */
paul@96 430
paul@96 431
	val |= LCD_CTRL_BST_16;		/* Burst Length is 16WORD=64Byte */
paul@96 432
	val |= LCD_CTRL_OFUP;		/* OutFIFO underrun protect */
paul@96 433
	REG_LCD_CTRL = val;
paul@33 434
	REG_LCD_CFG = jzfb.cfg;
paul@33 435
paul@98 436
	/* Timing reset. */
paul@33 437
paul@98 438
	__cpm_stop_lcd();
paul@98 439
	jz_lcd_set_timing(pclk);
paul@33 440
	__cpm_start_lcd();
paul@33 441
	udelay(1000);
paul@33 442
paul@96 443
	/* Configure DMA. */
paul@96 444
paul@95 445
	REG_LCD_DA0 = (unsigned long) fbi->fdadr0; /* frame descriptor */
paul@33 446
paul@33 447
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@33 448
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@95 449
		REG_LCD_DA1 = (unsigned long) fbi->fdadr1; /* frame descriptor */
paul@33 450
paul@33 451
	return 0;
paul@33 452
}
paul@33 453
paul@106 454
static inline u8 LCD_CODE(u8 bpp)
paul@106 455
{       
paul@106 456
        u8 code = 0;
paul@106 457
        while (bpp && !(bpp & 1))
paul@106 458
        {       
paul@106 459
                bpp >>= 1;
paul@106 460
                code += 1;
paul@106 461
        }
paul@106 462
        return code;
paul@106 463
}
paul@106 464
paul@102 465
/* Public operations. */
paul@102 466
paul@106 467
void lcd_set_bpp(u8 bpp)
paul@106 468
{
paul@106 469
	jzfb.bpp = bpp;
paul@106 470
	panel_info.vl_bpix = LCD_CODE(bpp);
paul@106 471
}
paul@106 472
paul@195 473
void lcd_enable()
paul@33 474
{
paul@102 475
	/* Clear the disable bit and set the enable bit. */
paul@102 476
paul@102 477
	REG_LCD_CTRL &= ~(1<<4);	/* LCDCTRL.DIS */
paul@102 478
	REG_LCD_CTRL |= 1<<3;		/* LCDCTRL.ENA*/
paul@101 479
}
paul@101 480
paul@195 481
void lcd_disable()
paul@101 482
{
paul@102 483
	REG_LCD_CTRL |= (1<<4);		/* LCDCTRL.DIS, regular disable */
paul@102 484
}
paul@102 485
paul@195 486
void lcd_quick_disable()
paul@102 487
{
paul@102 488
	REG_LCD_CTRL &= ~(1<<4);	/* LCDCTRL.ENA, quick disable */
paul@102 489
}
paul@102 490
paul@102 491
static inline u16 rgb8_to_rgb16(u8 rgb)
paul@102 492
{
paul@103 493
	return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10);
paul@103 494
}
paul@103 495
paul@103 496
static inline u16 rgb4_to_rgb16(u8 rgb)
paul@103 497
{
paul@103 498
	return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f);
paul@102 499
}
paul@102 500
paul@102 501
static void lcd_init_palette(vidinfo_t *vid)
paul@102 502
{
paul@102 503
	u16 *palette = (u16 *) lcd_get_palette(get_memory_size());
paul@103 504
	u16 *end = (u16 *) palette + NCOLORS(vid->vl_bpix);
paul@103 505
	u8 value = 0;
paul@102 506
paul@102 507
	while (palette < end)
paul@102 508
	{
paul@103 509
		switch (vid->vl_bpix)
paul@103 510
		{
paul@103 511
			case LCD_COLOR4:
paul@103 512
			*palette = rgb4_to_rgb16(value);
paul@103 513
			break;
paul@103 514
paul@103 515
			case LCD_COLOR8:
paul@103 516
			default:
paul@103 517
			*palette = rgb8_to_rgb16(value);
paul@103 518
			break;
paul@103 519
		}
paul@103 520
paul@102 521
		value++;
paul@102 522
		palette++;
paul@102 523
	}
paul@33 524
}
paul@33 525
paul@101 526
unsigned long lcd_ctrl_init()
paul@33 527
{
paul@101 528
	struct jz_fb_info *fbi = &panel_info.jz_fb;
paul@101 529
paul@101 530
	/* Start from the top of memory and obtain palette and framebuffer regions. */
paul@101 531
paul@101 532
	fbi->screen = lcd_get_framebuffer(get_memory_size(), 0);
paul@101 533
	fbi->palette = lcd_get_palette(get_memory_size());
paul@101 534
paul@101 535
	if (NBITS(panel_info.vl_bpix) < 12)
paul@102 536
		lcd_init_palette(&panel_info);
paul@101 537
paul@101 538
	jz_lcd_desc_init(&panel_info);
paul@101 539
	jz_lcd_hw_init(&panel_info);
paul@101 540
paul@101 541
	return fbi->screen;
paul@33 542
}