NanoPayload

Annotated stage2/jzlcd.c

102:cfccad7eb8e9
2016-01-25 Paul Boddie Made the palette size correspond to the pixel depth. Reordered and commented various functions. stage2-non-pic
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@98 239
static unsigned int jz_lcd_get_pixel_clock()
paul@98 240
{
paul@98 241
	unsigned int pclk;
paul@98 242
paul@98 243
	/* Derive pixel clock from frame clock. */
paul@98 244
paul@98 245
	if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {
paul@98 246
		pclk = jzfb.fclk * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
paul@98 247
			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw);
paul@98 248
	} else {
paul@98 249
		/* serial mode: Hsync period = 3*Width_Pixel */
paul@98 250
		pclk = jzfb.fclk * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *
paul@98 251
			(jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw);
paul@98 252
	}
paul@98 253
paul@98 254
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
paul@98 255
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
paul@98 256
		pclk = (pclk * 3);
paul@98 257
paul@98 258
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
paul@98 259
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@98 260
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||
paul@98 261
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@98 262
		pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);
paul@98 263
paul@98 264
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@98 265
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@98 266
		pclk >>= 1;
paul@98 267
paul@98 268
	return pclk;
paul@98 269
}
paul@98 270
paul@98 271
static void jz_lcd_set_timing(unsigned int pclk)
paul@98 272
{
paul@98 273
	unsigned int val;
paul@98 274
paul@98 275
#ifdef CONFIG_CPU_JZ4730
paul@98 276
        val = __cpm_get_pllout() / pclk;
paul@98 277
        REG_CPM_CFCR2 = val - 1;
paul@98 278
        val = pclk * 4 ;
paul@98 279
        if ( val > 150000000 ) {
paul@98 280
                val = 150000000;
paul@98 281
        }
paul@98 282
        val = __cpm_get_pllout() / val;
paul@98 283
        val--;
paul@98 284
        if ( val > 0xF )
paul@98 285
                val = 0xF;
paul@98 286
#else
paul@98 287
	int pll_div;
paul@98 288
paul@98 289
	pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */
paul@98 290
	pll_div = pll_div ? 1 : 2 ;
paul@98 291
	val = ( __cpm_get_pllout()/pll_div ) / pclk;
paul@98 292
	val--;
paul@98 293
	if ( val > 0x1ff ) {
paul@98 294
		val = 0x1ff;
paul@98 295
	}
paul@98 296
	__cpm_set_pixdiv(val);
paul@98 297
paul@98 298
	val = pclk * 3 ;	/* LCDClock > 2.5*Pixclock */
paul@98 299
	if ( val > 150000000 ) {
paul@98 300
		val = 150000000;
paul@98 301
	}
paul@98 302
	val = ( __cpm_get_pllout()/pll_div ) / val;
paul@98 303
	val--;
paul@98 304
	if ( val > 0x1f ) {
paul@98 305
		val = 0x1f;
paul@98 306
	}
paul@98 307
#endif
paul@98 308
	__cpm_set_ldiv( val );
paul@98 309
	REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */
paul@98 310
}
paul@98 311
paul@96 312
static int jz_lcd_hw_init(vidinfo_t *vid)
paul@33 313
{
paul@33 314
	struct jz_fb_info *fbi = &vid->jz_fb;
paul@33 315
	unsigned int val = 0;
paul@98 316
	unsigned int pclk = jz_lcd_get_pixel_clock();
paul@33 317
paul@33 318
	/* Setting Control register */
paul@33 319
	switch (jzfb.bpp) {
paul@33 320
	case 1:
paul@33 321
		val |= LCD_CTRL_BPP_1;
paul@33 322
		break;
paul@33 323
	case 2:
paul@33 324
		val |= LCD_CTRL_BPP_2;
paul@33 325
		break;
paul@33 326
	case 4:
paul@33 327
		val |= LCD_CTRL_BPP_4;
paul@33 328
		break;
paul@33 329
	case 8:
paul@33 330
		val |= LCD_CTRL_BPP_8;
paul@33 331
		break;
paul@33 332
	case 15:
paul@33 333
		val |= LCD_CTRL_RGB555;
paul@33 334
	case 16:
paul@33 335
		val |= LCD_CTRL_BPP_16;
paul@33 336
		break;
paul@43 337
#ifndef CONFIG_CPU_JZ4730
paul@33 338
	case 17 ... 32:
paul@33 339
		val |= LCD_CTRL_BPP_18_24;	/* target is 4bytes/pixel */
paul@33 340
		break;
paul@43 341
#endif
paul@33 342
	default:
paul@33 343
		/* printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp); */
paul@33 344
		val |= LCD_CTRL_BPP_16;
paul@33 345
		break;
paul@33 346
	}
paul@33 347
paul@33 348
	switch (jzfb.cfg & MODE_MASK) {
paul@33 349
	case MODE_STN_MONO_DUAL:
paul@33 350
	case MODE_STN_COLOR_DUAL:
paul@96 351
		val |= jz_lcd_stn_init(jzfb.h >> 1);
paul@33 352
		break;
paul@33 353
paul@33 354
	case MODE_STN_MONO_SINGLE:
paul@33 355
	case MODE_STN_COLOR_SINGLE:
paul@96 356
		val |= jz_lcd_stn_init(jzfb.h);
paul@33 357
		break;
paul@33 358
paul@33 359
	case MODE_TFT_GEN:
paul@33 360
	case MODE_TFT_CASIO:
paul@33 361
	case MODE_8BIT_SERIAL_TFT:
paul@33 362
	case MODE_TFT_18BIT:
paul@96 363
		jz_lcd_tft_init();
paul@33 364
		break;
paul@33 365
paul@33 366
	case MODE_TFT_SAMSUNG:
paul@33 367
	{
paul@33 368
		unsigned int total, tp_s, tp_e, ckv_s, ckv_e;
paul@33 369
		unsigned int rev_s, rev_e, inv_s, inv_e;
paul@33 370
paul@96 371
		jz_lcd_tft_init();
paul@96 372
paul@33 373
		total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
paul@33 374
		tp_s = jzfb.blw + jzfb.w + 1;
paul@33 375
		tp_e = tp_s + 1;
paul@33 376
		/* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
paul@33 377
		ckv_s = tp_s - pclk/(1000000000/4100);
paul@33 378
		ckv_e = tp_s + total;
paul@33 379
		rev_s = tp_s - 11;	/* -11.5 clk */
paul@33 380
		rev_e = rev_s + total;
paul@33 381
		inv_s = tp_s;
paul@33 382
		inv_e = inv_s + total;
paul@33 383
		REG_LCD_CLS = (tp_s << 16) | tp_e;
paul@33 384
		REG_LCD_PS = (ckv_s << 16) | ckv_e;
paul@33 385
		REG_LCD_SPL = (rev_s << 16) | rev_e;
paul@33 386
		REG_LCD_REV = (inv_s << 16) | inv_e;
paul@33 387
		jzfb.cfg |= STFT_REVHI | STFT_SPLHI;
paul@33 388
		break;
paul@33 389
	}
paul@96 390
paul@33 391
	case MODE_TFT_SHARP:
paul@33 392
	{
paul@33 393
		unsigned int total, cls_s, cls_e, ps_s, ps_e;
paul@33 394
		unsigned int spl_s, spl_e, rev_s, rev_e;
paul@96 395
paul@96 396
		jz_lcd_tft_init();
paul@96 397
paul@33 398
		total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
paul@33 399
		spl_s = 1;
paul@33 400
		spl_e = spl_s + 1;
paul@33 401
		cls_s = 0;
paul@33 402
		cls_e = total - 60;	/* > 4us (pclk = 80ns) */
paul@33 403
		ps_s = cls_s;
paul@33 404
		ps_e = cls_e;
paul@33 405
		rev_s = total - 40;	/* > 3us (pclk = 80ns) */
paul@33 406
		rev_e = rev_s + total;
paul@33 407
		jzfb.cfg |= STFT_PSHI; 
paul@33 408
		REG_LCD_SPL = (spl_s << 16) | spl_e;
paul@33 409
		REG_LCD_CLS = (cls_s << 16) | cls_e;
paul@33 410
		REG_LCD_PS = (ps_s << 16) | ps_e;
paul@33 411
		REG_LCD_REV = (rev_s << 16) | rev_e;
paul@33 412
		break;
paul@33 413
	}
paul@96 414
paul@96 415
	default:
paul@33 416
		break;
paul@33 417
	}
paul@33 418
paul@33 419
	/* Configure the LCD panel */
paul@96 420
paul@96 421
	val |= LCD_CTRL_BST_16;		/* Burst Length is 16WORD=64Byte */
paul@96 422
	val |= LCD_CTRL_OFUP;		/* OutFIFO underrun protect */
paul@96 423
	REG_LCD_CTRL = val;
paul@33 424
	REG_LCD_CFG = jzfb.cfg;
paul@33 425
paul@98 426
	/* Timing reset. */
paul@33 427
paul@98 428
	__cpm_stop_lcd();
paul@98 429
	jz_lcd_set_timing(pclk);
paul@33 430
	__cpm_start_lcd();
paul@33 431
	udelay(1000);
paul@33 432
paul@96 433
	/* Configure DMA. */
paul@96 434
paul@95 435
	REG_LCD_DA0 = (unsigned long) fbi->fdadr0; /* frame descriptor */
paul@33 436
paul@33 437
	if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
paul@33 438
	    ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
paul@95 439
		REG_LCD_DA1 = (unsigned long) fbi->fdadr1; /* frame descriptor */
paul@33 440
paul@33 441
	return 0;
paul@33 442
}
paul@33 443
paul@102 444
/* Public operations. */
paul@102 445
paul@101 446
void lcd_enable(void)
paul@33 447
{
paul@102 448
	/* Clear the disable bit and set the enable bit. */
paul@102 449
paul@102 450
	REG_LCD_CTRL &= ~(1<<4);	/* LCDCTRL.DIS */
paul@102 451
	REG_LCD_CTRL |= 1<<3;		/* LCDCTRL.ENA*/
paul@101 452
}
paul@101 453
paul@101 454
void lcd_disable(void)
paul@101 455
{
paul@102 456
	REG_LCD_CTRL |= (1<<4);		/* LCDCTRL.DIS, regular disable */
paul@102 457
}
paul@102 458
paul@102 459
void lcd_quick_disable(void)
paul@102 460
{
paul@102 461
	REG_LCD_CTRL &= ~(1<<4);	/* LCDCTRL.ENA, quick disable */
paul@102 462
}
paul@102 463
paul@102 464
static inline u16 rgb8_to_rgb16(u8 rgb)
paul@102 465
{
paul@102 466
	return ((rgb & 0xe0) << 8) | ((rgb & 0x1c) << 6) | ((rgb & 0x03) << 3);
paul@102 467
}
paul@102 468
paul@102 469
static void lcd_init_palette(vidinfo_t *vid)
paul@102 470
{
paul@102 471
	u16 *palette = (u16 *) lcd_get_palette(get_memory_size());
paul@102 472
	u16 *end = (u16 *) ((unsigned long) palette + lcd_get_palette_size(vid));
paul@102 473
	u16 value = 0;
paul@102 474
paul@102 475
	while (palette < end)
paul@102 476
	{
paul@102 477
		*palette = rgb8_to_rgb16(value);
paul@102 478
		value++;
paul@102 479
		palette++;
paul@102 480
	}
paul@33 481
}
paul@33 482
paul@101 483
unsigned long lcd_ctrl_init()
paul@33 484
{
paul@101 485
	struct jz_fb_info *fbi = &panel_info.jz_fb;
paul@101 486
paul@101 487
	/* Start from the top of memory and obtain palette and framebuffer regions. */
paul@101 488
paul@101 489
	fbi->screen = lcd_get_framebuffer(get_memory_size(), 0);
paul@101 490
	fbi->palette = lcd_get_palette(get_memory_size());
paul@101 491
paul@101 492
	if (NBITS(panel_info.vl_bpix) < 12)
paul@102 493
		lcd_init_palette(&panel_info);
paul@101 494
paul@101 495
	jz_lcd_desc_init(&panel_info);
paul@101 496
	jz_lcd_hw_init(&panel_info);
paul@101 497
paul@101 498
	return fbi->screen;
paul@33 499
}