162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Silicon Motion SM7XX frame buffer device
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2006 Silicon Motion Technology Corp.
562306a36Sopenharmony_ci * Authors:  Ge Wang, gewang@siliconmotion.com
662306a36Sopenharmony_ci *	     Boyod boyod.yang@siliconmotion.com.cn
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2009 Lemote, Inc.
962306a36Sopenharmony_ci * Author:   Wu Zhangjin, wuzhangjin@gmail.com
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Copyright (C) 2011 Igalia, S.L.
1262306a36Sopenharmony_ci * Author:   Javier M. Mellid <jmunhoz@igalia.com>
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
1562306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for
1662306a36Sopenharmony_ci * more details.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/aperture.h>
2262306a36Sopenharmony_ci#include <linux/io.h>
2362306a36Sopenharmony_ci#include <linux/fb.h>
2462306a36Sopenharmony_ci#include <linux/pci.h>
2562306a36Sopenharmony_ci#include <linux/init.h>
2662306a36Sopenharmony_ci#include <linux/slab.h>
2762306a36Sopenharmony_ci#include <linux/uaccess.h>
2862306a36Sopenharmony_ci#include <linux/module.h>
2962306a36Sopenharmony_ci#include <linux/console.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <linux/pm.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "sm712.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct smtcfb_screen_info {
3662306a36Sopenharmony_ci	u16 lfb_width;
3762306a36Sopenharmony_ci	u16 lfb_height;
3862306a36Sopenharmony_ci	u16 lfb_depth;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*
4262306a36Sopenharmony_ci * Private structure
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_cistruct smtcfb_info {
4562306a36Sopenharmony_ci	struct pci_dev *pdev;
4662306a36Sopenharmony_ci	struct fb_info *fb;
4762306a36Sopenharmony_ci	u16 chip_id;
4862306a36Sopenharmony_ci	u8  chip_rev_id;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	void __iomem *lfb;	/* linear frame buffer */
5162306a36Sopenharmony_ci	void __iomem *dp_regs;	/* drawing processor control regs */
5262306a36Sopenharmony_ci	void __iomem *vp_regs;	/* video processor control regs */
5362306a36Sopenharmony_ci	void __iomem *cp_regs;	/* capture processor control regs */
5462306a36Sopenharmony_ci	void __iomem *mmio;	/* memory map IO port */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	u_int width;
5762306a36Sopenharmony_ci	u_int height;
5862306a36Sopenharmony_ci	u_int hz;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	u32 colreg[17];
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_civoid __iomem *smtc_regbaseaddress;	/* Memory Map IO starting address */
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic const struct fb_var_screeninfo smtcfb_var = {
6662306a36Sopenharmony_ci	.xres           = 1024,
6762306a36Sopenharmony_ci	.yres           = 600,
6862306a36Sopenharmony_ci	.xres_virtual   = 1024,
6962306a36Sopenharmony_ci	.yres_virtual   = 600,
7062306a36Sopenharmony_ci	.bits_per_pixel = 16,
7162306a36Sopenharmony_ci	.red            = {16, 8, 0},
7262306a36Sopenharmony_ci	.green          = {8, 8, 0},
7362306a36Sopenharmony_ci	.blue           = {0, 8, 0},
7462306a36Sopenharmony_ci	.activate       = FB_ACTIVATE_NOW,
7562306a36Sopenharmony_ci	.height         = -1,
7662306a36Sopenharmony_ci	.width          = -1,
7762306a36Sopenharmony_ci	.vmode          = FB_VMODE_NONINTERLACED,
7862306a36Sopenharmony_ci	.nonstd         = 0,
7962306a36Sopenharmony_ci	.accel_flags    = FB_ACCELF_TEXT,
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic struct fb_fix_screeninfo smtcfb_fix = {
8362306a36Sopenharmony_ci	.id             = "smXXXfb",
8462306a36Sopenharmony_ci	.type           = FB_TYPE_PACKED_PIXELS,
8562306a36Sopenharmony_ci	.visual         = FB_VISUAL_TRUECOLOR,
8662306a36Sopenharmony_ci	.line_length    = 800 * 3,
8762306a36Sopenharmony_ci	.accel          = FB_ACCEL_SMI_LYNX,
8862306a36Sopenharmony_ci	.type_aux       = 0,
8962306a36Sopenharmony_ci	.xpanstep       = 0,
9062306a36Sopenharmony_ci	.ypanstep       = 0,
9162306a36Sopenharmony_ci	.ywrapstep      = 0,
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistruct vesa_mode {
9562306a36Sopenharmony_ci	char index[6];
9662306a36Sopenharmony_ci	u16  lfb_width;
9762306a36Sopenharmony_ci	u16  lfb_height;
9862306a36Sopenharmony_ci	u16  lfb_depth;
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic const struct vesa_mode vesa_mode_table[] = {
10262306a36Sopenharmony_ci	{"0x301", 640,  480,  8},
10362306a36Sopenharmony_ci	{"0x303", 800,  600,  8},
10462306a36Sopenharmony_ci	{"0x305", 1024, 768,  8},
10562306a36Sopenharmony_ci	{"0x307", 1280, 1024, 8},
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	{"0x311", 640,  480,  16},
10862306a36Sopenharmony_ci	{"0x314", 800,  600,  16},
10962306a36Sopenharmony_ci	{"0x317", 1024, 768,  16},
11062306a36Sopenharmony_ci	{"0x31A", 1280, 1024, 16},
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	{"0x312", 640,  480,  24},
11362306a36Sopenharmony_ci	{"0x315", 800,  600,  24},
11462306a36Sopenharmony_ci	{"0x318", 1024, 768,  24},
11562306a36Sopenharmony_ci	{"0x31B", 1280, 1024, 24},
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/**********************************************************************
11962306a36Sopenharmony_ci			 SM712 Mode table.
12062306a36Sopenharmony_ci **********************************************************************/
12162306a36Sopenharmony_cistatic const struct modeinit vgamode[] = {
12262306a36Sopenharmony_ci	{
12362306a36Sopenharmony_ci		/*  mode#0: 640 x 480  16Bpp  60Hz */
12462306a36Sopenharmony_ci		640, 480, 16, 60,
12562306a36Sopenharmony_ci		/*  Init_MISC */
12662306a36Sopenharmony_ci		0xE3,
12762306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
12862306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x00, 0x0E,
12962306a36Sopenharmony_ci		},
13062306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
13162306a36Sopenharmony_ci			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
13262306a36Sopenharmony_ci			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13362306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
13462306a36Sopenharmony_ci		},
13562306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
13662306a36Sopenharmony_ci			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
13762306a36Sopenharmony_ci			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
13862306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
13962306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
14062306a36Sopenharmony_ci			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
14162306a36Sopenharmony_ci			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
14262306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
14362306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
14462306a36Sopenharmony_ci			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
14562306a36Sopenharmony_ci		},
14662306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
14762306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
14862306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
14962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
15062306a36Sopenharmony_ci		},
15162306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
15262306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
15362306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
15462306a36Sopenharmony_ci		},
15562306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
15662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
15762306a36Sopenharmony_ci			0xFF,
15862306a36Sopenharmony_ci		},
15962306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
16062306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
16162306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
16262306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
16362306a36Sopenharmony_ci		},
16462306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
16562306a36Sopenharmony_ci			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
16662306a36Sopenharmony_ci			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16762306a36Sopenharmony_ci			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
16862306a36Sopenharmony_ci			0xFF,
16962306a36Sopenharmony_ci		},
17062306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
17162306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
17262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
17362306a36Sopenharmony_ci			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
17462306a36Sopenharmony_ci			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
17562306a36Sopenharmony_ci		},
17662306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
17762306a36Sopenharmony_ci			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
17862306a36Sopenharmony_ci			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
17962306a36Sopenharmony_ci			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
18062306a36Sopenharmony_ci		},
18162306a36Sopenharmony_ci	},
18262306a36Sopenharmony_ci	{
18362306a36Sopenharmony_ci		/*  mode#1: 640 x 480  24Bpp  60Hz */
18462306a36Sopenharmony_ci		640, 480, 24, 60,
18562306a36Sopenharmony_ci		/*  Init_MISC */
18662306a36Sopenharmony_ci		0xE3,
18762306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
18862306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x00, 0x0E,
18962306a36Sopenharmony_ci		},
19062306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
19162306a36Sopenharmony_ci			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
19262306a36Sopenharmony_ci			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19362306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
19462306a36Sopenharmony_ci		},
19562306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
19662306a36Sopenharmony_ci			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
19762306a36Sopenharmony_ci			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
19862306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
19962306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
20062306a36Sopenharmony_ci			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
20162306a36Sopenharmony_ci			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
20262306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
20362306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
20462306a36Sopenharmony_ci			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
20562306a36Sopenharmony_ci		},
20662306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
20762306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
20862306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
20962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
21062306a36Sopenharmony_ci		},
21162306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
21262306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
21362306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
21462306a36Sopenharmony_ci		},
21562306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
21662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
21762306a36Sopenharmony_ci			0xFF,
21862306a36Sopenharmony_ci		},
21962306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
22062306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
22162306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
22262306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
22362306a36Sopenharmony_ci		},
22462306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
22562306a36Sopenharmony_ci			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
22662306a36Sopenharmony_ci			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22762306a36Sopenharmony_ci			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
22862306a36Sopenharmony_ci			0xFF,
22962306a36Sopenharmony_ci		},
23062306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
23162306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
23262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
23362306a36Sopenharmony_ci			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
23462306a36Sopenharmony_ci			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
23562306a36Sopenharmony_ci		},
23662306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
23762306a36Sopenharmony_ci			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
23862306a36Sopenharmony_ci			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
23962306a36Sopenharmony_ci			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
24062306a36Sopenharmony_ci		},
24162306a36Sopenharmony_ci	},
24262306a36Sopenharmony_ci	{
24362306a36Sopenharmony_ci		/*  mode#0: 640 x 480  32Bpp  60Hz */
24462306a36Sopenharmony_ci		640, 480, 32, 60,
24562306a36Sopenharmony_ci		/*  Init_MISC */
24662306a36Sopenharmony_ci		0xE3,
24762306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
24862306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x00, 0x0E,
24962306a36Sopenharmony_ci		},
25062306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
25162306a36Sopenharmony_ci			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
25262306a36Sopenharmony_ci			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25362306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
25462306a36Sopenharmony_ci		},
25562306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
25662306a36Sopenharmony_ci			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
25762306a36Sopenharmony_ci			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
25862306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
25962306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
26062306a36Sopenharmony_ci			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
26162306a36Sopenharmony_ci			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
26262306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
26362306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
26462306a36Sopenharmony_ci			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
26562306a36Sopenharmony_ci		},
26662306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
26762306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
26862306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
26962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
27062306a36Sopenharmony_ci		},
27162306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
27262306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
27362306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
27462306a36Sopenharmony_ci		},
27562306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
27662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
27762306a36Sopenharmony_ci			0xFF,
27862306a36Sopenharmony_ci		},
27962306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
28062306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
28162306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
28262306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
28362306a36Sopenharmony_ci		},
28462306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
28562306a36Sopenharmony_ci			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
28662306a36Sopenharmony_ci			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28762306a36Sopenharmony_ci			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
28862306a36Sopenharmony_ci			0xFF,
28962306a36Sopenharmony_ci		},
29062306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
29162306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
29262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
29362306a36Sopenharmony_ci			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
29462306a36Sopenharmony_ci			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
29562306a36Sopenharmony_ci		},
29662306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
29762306a36Sopenharmony_ci			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
29862306a36Sopenharmony_ci			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
29962306a36Sopenharmony_ci			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
30062306a36Sopenharmony_ci		},
30162306a36Sopenharmony_ci	},
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	{	/*  mode#2: 800 x 600  16Bpp  60Hz */
30462306a36Sopenharmony_ci		800, 600, 16, 60,
30562306a36Sopenharmony_ci		/*  Init_MISC */
30662306a36Sopenharmony_ci		0x2B,
30762306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
30862306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
30962306a36Sopenharmony_ci		},
31062306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
31162306a36Sopenharmony_ci			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
31262306a36Sopenharmony_ci			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
31362306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
31462306a36Sopenharmony_ci		},
31562306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
31662306a36Sopenharmony_ci			0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
31762306a36Sopenharmony_ci			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
31862306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
31962306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
32062306a36Sopenharmony_ci			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
32162306a36Sopenharmony_ci			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
32262306a36Sopenharmony_ci			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
32362306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
32462306a36Sopenharmony_ci			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
32562306a36Sopenharmony_ci		},
32662306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
32762306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
32862306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
32962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
33062306a36Sopenharmony_ci		},
33162306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
33262306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
33362306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
33462306a36Sopenharmony_ci		},
33562306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
33662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
33762306a36Sopenharmony_ci			0xFF,
33862306a36Sopenharmony_ci		},
33962306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
34062306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
34162306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
34262306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
34362306a36Sopenharmony_ci		},
34462306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
34562306a36Sopenharmony_ci			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
34662306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34762306a36Sopenharmony_ci			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
34862306a36Sopenharmony_ci			0xFF,
34962306a36Sopenharmony_ci		},
35062306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
35162306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
35262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
35362306a36Sopenharmony_ci			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
35462306a36Sopenharmony_ci			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
35562306a36Sopenharmony_ci		},
35662306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
35762306a36Sopenharmony_ci			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
35862306a36Sopenharmony_ci			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
35962306a36Sopenharmony_ci			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
36062306a36Sopenharmony_ci		},
36162306a36Sopenharmony_ci	},
36262306a36Sopenharmony_ci	{	/*  mode#3: 800 x 600  24Bpp  60Hz */
36362306a36Sopenharmony_ci		800, 600, 24, 60,
36462306a36Sopenharmony_ci		0x2B,
36562306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
36662306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
36762306a36Sopenharmony_ci		},
36862306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
36962306a36Sopenharmony_ci			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
37062306a36Sopenharmony_ci			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37162306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
37262306a36Sopenharmony_ci		},
37362306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
37462306a36Sopenharmony_ci			0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
37562306a36Sopenharmony_ci			0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
37662306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
37762306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
37862306a36Sopenharmony_ci			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
37962306a36Sopenharmony_ci			0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
38062306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
38162306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
38262306a36Sopenharmony_ci			0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
38362306a36Sopenharmony_ci		},
38462306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
38562306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
38662306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
38762306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
38862306a36Sopenharmony_ci		},
38962306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
39062306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
39162306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
39262306a36Sopenharmony_ci		},
39362306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
39462306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
39562306a36Sopenharmony_ci			0xFF,
39662306a36Sopenharmony_ci		},
39762306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
39862306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
39962306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
40062306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
40162306a36Sopenharmony_ci		},
40262306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
40362306a36Sopenharmony_ci			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
40462306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40562306a36Sopenharmony_ci			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
40662306a36Sopenharmony_ci			0xFF,
40762306a36Sopenharmony_ci		},
40862306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
40962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
41062306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
41162306a36Sopenharmony_ci			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
41262306a36Sopenharmony_ci			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
41362306a36Sopenharmony_ci		},
41462306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
41562306a36Sopenharmony_ci			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
41662306a36Sopenharmony_ci			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
41762306a36Sopenharmony_ci			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
41862306a36Sopenharmony_ci		},
41962306a36Sopenharmony_ci	},
42062306a36Sopenharmony_ci	{	/*  mode#7: 800 x 600  32Bpp  60Hz */
42162306a36Sopenharmony_ci		800, 600, 32, 60,
42262306a36Sopenharmony_ci		/*  Init_MISC */
42362306a36Sopenharmony_ci		0x2B,
42462306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
42562306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
42662306a36Sopenharmony_ci		},
42762306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
42862306a36Sopenharmony_ci			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
42962306a36Sopenharmony_ci			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
43062306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
43162306a36Sopenharmony_ci		},
43262306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
43362306a36Sopenharmony_ci			0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
43462306a36Sopenharmony_ci			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
43562306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
43662306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
43762306a36Sopenharmony_ci			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
43862306a36Sopenharmony_ci			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
43962306a36Sopenharmony_ci			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
44062306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
44162306a36Sopenharmony_ci			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
44262306a36Sopenharmony_ci		},
44362306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
44462306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
44562306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
44662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
44762306a36Sopenharmony_ci		},
44862306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
44962306a36Sopenharmony_ci			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
45062306a36Sopenharmony_ci			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
45162306a36Sopenharmony_ci		},
45262306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
45362306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
45462306a36Sopenharmony_ci			0xFF,
45562306a36Sopenharmony_ci		},
45662306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
45762306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
45862306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
45962306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
46062306a36Sopenharmony_ci		},
46162306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
46262306a36Sopenharmony_ci			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
46362306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46462306a36Sopenharmony_ci			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
46562306a36Sopenharmony_ci			0xFF,
46662306a36Sopenharmony_ci		},
46762306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
46862306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
46962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
47062306a36Sopenharmony_ci			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
47162306a36Sopenharmony_ci			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
47262306a36Sopenharmony_ci		},
47362306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
47462306a36Sopenharmony_ci			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
47562306a36Sopenharmony_ci			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
47662306a36Sopenharmony_ci			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
47762306a36Sopenharmony_ci		},
47862306a36Sopenharmony_ci	},
47962306a36Sopenharmony_ci	/* We use 1024x768 table to light 1024x600 panel for lemote */
48062306a36Sopenharmony_ci	{	/*  mode#4: 1024 x 600  16Bpp  60Hz  */
48162306a36Sopenharmony_ci		1024, 600, 16, 60,
48262306a36Sopenharmony_ci		/*  Init_MISC */
48362306a36Sopenharmony_ci		0xEB,
48462306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
48562306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x00, 0x0E,
48662306a36Sopenharmony_ci		},
48762306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
48862306a36Sopenharmony_ci			0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
48962306a36Sopenharmony_ci			0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
49062306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x00, 0x01,
49162306a36Sopenharmony_ci		},
49262306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
49362306a36Sopenharmony_ci			0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
49462306a36Sopenharmony_ci			0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
49562306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
49662306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
49762306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
49862306a36Sopenharmony_ci			0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
49962306a36Sopenharmony_ci			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
50062306a36Sopenharmony_ci			0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
50162306a36Sopenharmony_ci			0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
50262306a36Sopenharmony_ci		},
50362306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
50462306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
50562306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
50662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
50762306a36Sopenharmony_ci		},
50862306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
50962306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
51062306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
51162306a36Sopenharmony_ci		},
51262306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
51362306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
51462306a36Sopenharmony_ci			0xFF,
51562306a36Sopenharmony_ci		},
51662306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
51762306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
51862306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
51962306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
52062306a36Sopenharmony_ci		},
52162306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
52262306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
52362306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52462306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
52562306a36Sopenharmony_ci			0xFF,
52662306a36Sopenharmony_ci		},
52762306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
52862306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
52962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
53062306a36Sopenharmony_ci			0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
53162306a36Sopenharmony_ci			0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
53262306a36Sopenharmony_ci		},
53362306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
53462306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
53562306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
53662306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
53762306a36Sopenharmony_ci		},
53862306a36Sopenharmony_ci	},
53962306a36Sopenharmony_ci	{	/*  1024 x 768  16Bpp  60Hz */
54062306a36Sopenharmony_ci		1024, 768, 16, 60,
54162306a36Sopenharmony_ci		/*  Init_MISC */
54262306a36Sopenharmony_ci		0xEB,
54362306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
54462306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
54562306a36Sopenharmony_ci		},
54662306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
54762306a36Sopenharmony_ci			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
54862306a36Sopenharmony_ci			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
54962306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
55062306a36Sopenharmony_ci		},
55162306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
55262306a36Sopenharmony_ci			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
55362306a36Sopenharmony_ci			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
55462306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
55562306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
55662306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
55762306a36Sopenharmony_ci			0x0F, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
55862306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
55962306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
56062306a36Sopenharmony_ci			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
56162306a36Sopenharmony_ci		},
56262306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
56362306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
56462306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
56562306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
56662306a36Sopenharmony_ci		},
56762306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
56862306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
56962306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
57062306a36Sopenharmony_ci		},
57162306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
57262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
57362306a36Sopenharmony_ci			0xFF,
57462306a36Sopenharmony_ci		},
57562306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
57662306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
57762306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
57862306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
57962306a36Sopenharmony_ci		},
58062306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
58162306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
58262306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58362306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
58462306a36Sopenharmony_ci			0xFF,
58562306a36Sopenharmony_ci		},
58662306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
58762306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
58862306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
58962306a36Sopenharmony_ci			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
59062306a36Sopenharmony_ci			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
59162306a36Sopenharmony_ci		},
59262306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
59362306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
59462306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
59562306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
59662306a36Sopenharmony_ci		},
59762306a36Sopenharmony_ci	},
59862306a36Sopenharmony_ci	{	/*  mode#5: 1024 x 768  24Bpp  60Hz */
59962306a36Sopenharmony_ci		1024, 768, 24, 60,
60062306a36Sopenharmony_ci		/*  Init_MISC */
60162306a36Sopenharmony_ci		0xEB,
60262306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
60362306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
60462306a36Sopenharmony_ci		},
60562306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
60662306a36Sopenharmony_ci			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
60762306a36Sopenharmony_ci			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
60862306a36Sopenharmony_ci			0xC4, 0x30, 0x02, 0x01, 0x01,
60962306a36Sopenharmony_ci		},
61062306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
61162306a36Sopenharmony_ci			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
61262306a36Sopenharmony_ci			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
61362306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
61462306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
61562306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
61662306a36Sopenharmony_ci			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
61762306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
61862306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
61962306a36Sopenharmony_ci			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
62062306a36Sopenharmony_ci		},
62162306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
62262306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
62362306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
62462306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
62562306a36Sopenharmony_ci		},
62662306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
62762306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
62862306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
62962306a36Sopenharmony_ci		},
63062306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
63162306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
63262306a36Sopenharmony_ci			0xFF,
63362306a36Sopenharmony_ci		},
63462306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
63562306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
63662306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
63762306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
63862306a36Sopenharmony_ci		},
63962306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
64062306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
64162306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64262306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
64362306a36Sopenharmony_ci			0xFF,
64462306a36Sopenharmony_ci		},
64562306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
64662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
64762306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
64862306a36Sopenharmony_ci			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
64962306a36Sopenharmony_ci			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
65062306a36Sopenharmony_ci		},
65162306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
65262306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
65362306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
65462306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
65562306a36Sopenharmony_ci		},
65662306a36Sopenharmony_ci	},
65762306a36Sopenharmony_ci	{	/*  mode#4: 1024 x 768  32Bpp  60Hz */
65862306a36Sopenharmony_ci		1024, 768, 32, 60,
65962306a36Sopenharmony_ci		/*  Init_MISC */
66062306a36Sopenharmony_ci		0xEB,
66162306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
66262306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
66362306a36Sopenharmony_ci		},
66462306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
66562306a36Sopenharmony_ci			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
66662306a36Sopenharmony_ci			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
66762306a36Sopenharmony_ci			0xC4, 0x32, 0x02, 0x01, 0x01,
66862306a36Sopenharmony_ci		},
66962306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
67062306a36Sopenharmony_ci			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
67162306a36Sopenharmony_ci			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
67262306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
67362306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
67462306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
67562306a36Sopenharmony_ci			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
67662306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
67762306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
67862306a36Sopenharmony_ci			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
67962306a36Sopenharmony_ci		},
68062306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
68162306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
68262306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
68362306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
68462306a36Sopenharmony_ci		},
68562306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
68662306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
68762306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
68862306a36Sopenharmony_ci		},
68962306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
69062306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
69162306a36Sopenharmony_ci			0xFF,
69262306a36Sopenharmony_ci		},
69362306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
69462306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
69562306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
69662306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
69762306a36Sopenharmony_ci		},
69862306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
69962306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
70062306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70162306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
70262306a36Sopenharmony_ci			0xFF,
70362306a36Sopenharmony_ci		},
70462306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
70562306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
70662306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
70762306a36Sopenharmony_ci			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
70862306a36Sopenharmony_ci			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
70962306a36Sopenharmony_ci		},
71062306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
71162306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
71262306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
71362306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
71462306a36Sopenharmony_ci		},
71562306a36Sopenharmony_ci	},
71662306a36Sopenharmony_ci	{	/*  mode#6: 320 x 240  16Bpp  60Hz */
71762306a36Sopenharmony_ci		320, 240, 16, 60,
71862306a36Sopenharmony_ci		/*  Init_MISC */
71962306a36Sopenharmony_ci		0xEB,
72062306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
72162306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
72262306a36Sopenharmony_ci		},
72362306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
72462306a36Sopenharmony_ci			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
72562306a36Sopenharmony_ci			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
72662306a36Sopenharmony_ci			0xC4, 0x32, 0x02, 0x01, 0x01,
72762306a36Sopenharmony_ci		},
72862306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
72962306a36Sopenharmony_ci			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
73062306a36Sopenharmony_ci			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
73162306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
73262306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
73362306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
73462306a36Sopenharmony_ci			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
73562306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
73662306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
73762306a36Sopenharmony_ci			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
73862306a36Sopenharmony_ci		},
73962306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
74062306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
74162306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
74262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
74362306a36Sopenharmony_ci		},
74462306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
74562306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
74662306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
74762306a36Sopenharmony_ci		},
74862306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
74962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
75062306a36Sopenharmony_ci			0xFF,
75162306a36Sopenharmony_ci		},
75262306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
75362306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75462306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
75562306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
75662306a36Sopenharmony_ci		},
75762306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
75862306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
75962306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76062306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
76162306a36Sopenharmony_ci			0xFF,
76262306a36Sopenharmony_ci		},
76362306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
76462306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
76562306a36Sopenharmony_ci			0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
76662306a36Sopenharmony_ci			0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
76762306a36Sopenharmony_ci			0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
76862306a36Sopenharmony_ci		},
76962306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
77062306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
77162306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
77262306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
77362306a36Sopenharmony_ci		},
77462306a36Sopenharmony_ci	},
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	{	/*  mode#8: 320 x 240  32Bpp  60Hz */
77762306a36Sopenharmony_ci		320, 240, 32, 60,
77862306a36Sopenharmony_ci		/*  Init_MISC */
77962306a36Sopenharmony_ci		0xEB,
78062306a36Sopenharmony_ci		{	/*  Init_SR0_SR4 */
78162306a36Sopenharmony_ci			0x03, 0x01, 0x0F, 0x03, 0x0E,
78262306a36Sopenharmony_ci		},
78362306a36Sopenharmony_ci		{	/*  Init_SR10_SR24 */
78462306a36Sopenharmony_ci			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
78562306a36Sopenharmony_ci			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
78662306a36Sopenharmony_ci			0xC4, 0x32, 0x02, 0x01, 0x01,
78762306a36Sopenharmony_ci		},
78862306a36Sopenharmony_ci		{	/*  Init_SR30_SR75 */
78962306a36Sopenharmony_ci			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
79062306a36Sopenharmony_ci			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
79162306a36Sopenharmony_ci			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
79262306a36Sopenharmony_ci			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
79362306a36Sopenharmony_ci			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
79462306a36Sopenharmony_ci			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
79562306a36Sopenharmony_ci			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
79662306a36Sopenharmony_ci			0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
79762306a36Sopenharmony_ci			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
79862306a36Sopenharmony_ci		},
79962306a36Sopenharmony_ci		{	/*  Init_SR80_SR93 */
80062306a36Sopenharmony_ci			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
80162306a36Sopenharmony_ci			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
80262306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00,
80362306a36Sopenharmony_ci		},
80462306a36Sopenharmony_ci		{	/*  Init_SRA0_SRAF */
80562306a36Sopenharmony_ci			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
80662306a36Sopenharmony_ci			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
80762306a36Sopenharmony_ci		},
80862306a36Sopenharmony_ci		{	/*  Init_GR00_GR08 */
80962306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
81062306a36Sopenharmony_ci			0xFF,
81162306a36Sopenharmony_ci		},
81262306a36Sopenharmony_ci		{	/*  Init_AR00_AR14 */
81362306a36Sopenharmony_ci			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
81462306a36Sopenharmony_ci			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
81562306a36Sopenharmony_ci			0x41, 0x00, 0x0F, 0x00, 0x00,
81662306a36Sopenharmony_ci		},
81762306a36Sopenharmony_ci		{	/*  Init_CR00_CR18 */
81862306a36Sopenharmony_ci			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
81962306a36Sopenharmony_ci			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82062306a36Sopenharmony_ci			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
82162306a36Sopenharmony_ci			0xFF,
82262306a36Sopenharmony_ci		},
82362306a36Sopenharmony_ci		{	/*  Init_CR30_CR4D */
82462306a36Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
82562306a36Sopenharmony_ci			0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
82662306a36Sopenharmony_ci			0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
82762306a36Sopenharmony_ci			0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
82862306a36Sopenharmony_ci		},
82962306a36Sopenharmony_ci		{	/*  Init_CR90_CRA7 */
83062306a36Sopenharmony_ci			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
83162306a36Sopenharmony_ci			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
83262306a36Sopenharmony_ci			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
83362306a36Sopenharmony_ci		},
83462306a36Sopenharmony_ci	},
83562306a36Sopenharmony_ci};
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_cistatic struct smtcfb_screen_info smtc_scr_info;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistatic char *mode_option;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci/* process command line options, get vga parameter */
84262306a36Sopenharmony_cistatic void __init sm7xx_vga_setup(char *options)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	int i;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	if (!options || !*options)
84762306a36Sopenharmony_ci		return;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	smtc_scr_info.lfb_width = 0;
85062306a36Sopenharmony_ci	smtc_scr_info.lfb_height = 0;
85162306a36Sopenharmony_ci	smtc_scr_info.lfb_depth = 0;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	pr_debug("%s = %s\n", __func__, options);
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
85662306a36Sopenharmony_ci		if (strstr(options, vesa_mode_table[i].index)) {
85762306a36Sopenharmony_ci			smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
85862306a36Sopenharmony_ci			smtc_scr_info.lfb_height =
85962306a36Sopenharmony_ci						vesa_mode_table[i].lfb_height;
86062306a36Sopenharmony_ci			smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
86162306a36Sopenharmony_ci			return;
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_cistatic void sm712_setpalette(int regno, unsigned int red, unsigned int green,
86762306a36Sopenharmony_ci			     unsigned int blue, struct fb_info *info)
86862306a36Sopenharmony_ci{
86962306a36Sopenharmony_ci	/* set bit 5:4 = 01 (write LCD RAM only) */
87062306a36Sopenharmony_ci	smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	smtc_mmiowb(regno, dac_reg);
87362306a36Sopenharmony_ci	smtc_mmiowb(red >> 10, dac_val);
87462306a36Sopenharmony_ci	smtc_mmiowb(green >> 10, dac_val);
87562306a36Sopenharmony_ci	smtc_mmiowb(blue >> 10, dac_val);
87662306a36Sopenharmony_ci}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci/* chan_to_field
87962306a36Sopenharmony_ci *
88062306a36Sopenharmony_ci * convert a colour value into a field position
88162306a36Sopenharmony_ci *
88262306a36Sopenharmony_ci * from pxafb.c
88362306a36Sopenharmony_ci */
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic inline unsigned int chan_to_field(unsigned int chan,
88662306a36Sopenharmony_ci					 struct fb_bitfield *bf)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	chan &= 0xffff;
88962306a36Sopenharmony_ci	chan >>= 16 - bf->length;
89062306a36Sopenharmony_ci	return chan << bf->offset;
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_cistatic int smtc_blank(int blank_mode, struct fb_info *info)
89462306a36Sopenharmony_ci{
89562306a36Sopenharmony_ci	struct smtcfb_info *sfb = info->par;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	/* clear DPMS setting */
89862306a36Sopenharmony_ci	switch (blank_mode) {
89962306a36Sopenharmony_ci	case FB_BLANK_UNBLANK:
90062306a36Sopenharmony_ci		/* Screen On: HSync: On, VSync : On */
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci		switch (sfb->chip_id) {
90362306a36Sopenharmony_ci		case 0x710:
90462306a36Sopenharmony_ci		case 0x712:
90562306a36Sopenharmony_ci			smtc_seqw(0x6a, 0x16);
90662306a36Sopenharmony_ci			smtc_seqw(0x6b, 0x02);
90762306a36Sopenharmony_ci			break;
90862306a36Sopenharmony_ci		case 0x720:
90962306a36Sopenharmony_ci			smtc_seqw(0x6a, 0x0d);
91062306a36Sopenharmony_ci			smtc_seqw(0x6b, 0x02);
91162306a36Sopenharmony_ci			break;
91262306a36Sopenharmony_ci		}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
91562306a36Sopenharmony_ci		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
91662306a36Sopenharmony_ci		smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
91762306a36Sopenharmony_ci		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
91862306a36Sopenharmony_ci		smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
91962306a36Sopenharmony_ci		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
92062306a36Sopenharmony_ci		break;
92162306a36Sopenharmony_ci	case FB_BLANK_NORMAL:
92262306a36Sopenharmony_ci		/* Screen Off: HSync: On, VSync : On   Soft blank */
92362306a36Sopenharmony_ci		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
92462306a36Sopenharmony_ci		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
92562306a36Sopenharmony_ci		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
92662306a36Sopenharmony_ci		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
92762306a36Sopenharmony_ci		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
92862306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x16);
92962306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
93062306a36Sopenharmony_ci		break;
93162306a36Sopenharmony_ci	case FB_BLANK_VSYNC_SUSPEND:
93262306a36Sopenharmony_ci		/* Screen On: HSync: On, VSync : Off */
93362306a36Sopenharmony_ci		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
93462306a36Sopenharmony_ci		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
93562306a36Sopenharmony_ci		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
93662306a36Sopenharmony_ci		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
93762306a36Sopenharmony_ci		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
93862306a36Sopenharmony_ci		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
93962306a36Sopenharmony_ci		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
94062306a36Sopenharmony_ci		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
94162306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x0c);
94262306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
94362306a36Sopenharmony_ci		break;
94462306a36Sopenharmony_ci	case FB_BLANK_HSYNC_SUSPEND:
94562306a36Sopenharmony_ci		/* Screen On: HSync: Off, VSync : On */
94662306a36Sopenharmony_ci		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
94762306a36Sopenharmony_ci		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
94862306a36Sopenharmony_ci		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
94962306a36Sopenharmony_ci		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
95062306a36Sopenharmony_ci		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
95162306a36Sopenharmony_ci		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
95262306a36Sopenharmony_ci		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
95362306a36Sopenharmony_ci		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
95462306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x0c);
95562306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
95662306a36Sopenharmony_ci		break;
95762306a36Sopenharmony_ci	case FB_BLANK_POWERDOWN:
95862306a36Sopenharmony_ci		/* Screen On: HSync: Off, VSync : Off */
95962306a36Sopenharmony_ci		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
96062306a36Sopenharmony_ci		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
96162306a36Sopenharmony_ci		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
96262306a36Sopenharmony_ci		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
96362306a36Sopenharmony_ci		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
96462306a36Sopenharmony_ci		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
96562306a36Sopenharmony_ci		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
96662306a36Sopenharmony_ci		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
96762306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x0c);
96862306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
96962306a36Sopenharmony_ci		break;
97062306a36Sopenharmony_ci	default:
97162306a36Sopenharmony_ci		return -EINVAL;
97262306a36Sopenharmony_ci	}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	return 0;
97562306a36Sopenharmony_ci}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_cistatic int smtc_setcolreg(unsigned int regno, unsigned int red,
97862306a36Sopenharmony_ci			  unsigned int green, unsigned int blue,
97962306a36Sopenharmony_ci			  unsigned int trans, struct fb_info *info)
98062306a36Sopenharmony_ci{
98162306a36Sopenharmony_ci	struct smtcfb_info *sfb;
98262306a36Sopenharmony_ci	u32 val;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	sfb = info->par;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	if (regno > 255)
98762306a36Sopenharmony_ci		return 1;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	switch (sfb->fb->fix.visual) {
99062306a36Sopenharmony_ci	case FB_VISUAL_DIRECTCOLOR:
99162306a36Sopenharmony_ci	case FB_VISUAL_TRUECOLOR:
99262306a36Sopenharmony_ci		/*
99362306a36Sopenharmony_ci		 * 16/32 bit true-colour, use pseudo-palette for 16 base color
99462306a36Sopenharmony_ci		 */
99562306a36Sopenharmony_ci		if (regno >= 16)
99662306a36Sopenharmony_ci			break;
99762306a36Sopenharmony_ci		if (sfb->fb->var.bits_per_pixel == 16) {
99862306a36Sopenharmony_ci			u32 *pal = sfb->fb->pseudo_palette;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci			val = chan_to_field(red, &sfb->fb->var.red);
100162306a36Sopenharmony_ci			val |= chan_to_field(green, &sfb->fb->var.green);
100262306a36Sopenharmony_ci			val |= chan_to_field(blue, &sfb->fb->var.blue);
100362306a36Sopenharmony_ci			pal[regno] = pal_rgb(red, green, blue, val);
100462306a36Sopenharmony_ci		} else {
100562306a36Sopenharmony_ci			u32 *pal = sfb->fb->pseudo_palette;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci			val = chan_to_field(red, &sfb->fb->var.red);
100862306a36Sopenharmony_ci			val |= chan_to_field(green, &sfb->fb->var.green);
100962306a36Sopenharmony_ci			val |= chan_to_field(blue, &sfb->fb->var.blue);
101062306a36Sopenharmony_ci			pal[regno] = big_swap(val);
101162306a36Sopenharmony_ci		}
101262306a36Sopenharmony_ci		break;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	case FB_VISUAL_PSEUDOCOLOR:
101562306a36Sopenharmony_ci		/* color depth 8 bit */
101662306a36Sopenharmony_ci		sm712_setpalette(regno, red, green, blue, info);
101762306a36Sopenharmony_ci		break;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	default:
102062306a36Sopenharmony_ci		return 1;	/* unknown type */
102162306a36Sopenharmony_ci	}
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	return 0;
102462306a36Sopenharmony_ci}
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_cistatic ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
102762306a36Sopenharmony_ci			   size_t count, loff_t *ppos)
102862306a36Sopenharmony_ci{
102962306a36Sopenharmony_ci	unsigned long p = *ppos;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	u32 *buffer, *dst;
103262306a36Sopenharmony_ci	u32 __iomem *src;
103362306a36Sopenharmony_ci	int c, i, cnt = 0, err = 0;
103462306a36Sopenharmony_ci	unsigned long total_size;
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	if (!info->screen_base)
103762306a36Sopenharmony_ci		return -ENODEV;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	total_size = info->screen_size;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	if (total_size == 0)
104262306a36Sopenharmony_ci		total_size = info->fix.smem_len;
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	if (p >= total_size)
104562306a36Sopenharmony_ci		return 0;
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	if (count >= total_size)
104862306a36Sopenharmony_ci		count = total_size;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	if (count + p > total_size)
105162306a36Sopenharmony_ci		count = total_size - p;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
105462306a36Sopenharmony_ci	if (!buffer)
105562306a36Sopenharmony_ci		return -ENOMEM;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	src = (u32 __iomem *)(info->screen_base + p);
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	if (info->fbops->fb_sync)
106062306a36Sopenharmony_ci		info->fbops->fb_sync(info);
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	while (count) {
106362306a36Sopenharmony_ci		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
106462306a36Sopenharmony_ci		dst = buffer;
106562306a36Sopenharmony_ci		for (i = (c + 3) >> 2; i--;) {
106662306a36Sopenharmony_ci			u32 val;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci			val = fb_readl(src);
106962306a36Sopenharmony_ci			*dst = big_swap(val);
107062306a36Sopenharmony_ci			src++;
107162306a36Sopenharmony_ci			dst++;
107262306a36Sopenharmony_ci		}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		if (copy_to_user(buf, buffer, c)) {
107562306a36Sopenharmony_ci			err = -EFAULT;
107662306a36Sopenharmony_ci			break;
107762306a36Sopenharmony_ci		}
107862306a36Sopenharmony_ci		*ppos += c;
107962306a36Sopenharmony_ci		buf += c;
108062306a36Sopenharmony_ci		cnt += c;
108162306a36Sopenharmony_ci		count -= c;
108262306a36Sopenharmony_ci	}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	kfree(buffer);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	return (err) ? err : cnt;
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_cistatic ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
109062306a36Sopenharmony_ci			    size_t count, loff_t *ppos)
109162306a36Sopenharmony_ci{
109262306a36Sopenharmony_ci	unsigned long p = *ppos;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	u32 *buffer, *src;
109562306a36Sopenharmony_ci	u32 __iomem *dst;
109662306a36Sopenharmony_ci	int c, i, cnt = 0, err = 0;
109762306a36Sopenharmony_ci	unsigned long total_size;
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	if (!info->screen_base)
110062306a36Sopenharmony_ci		return -ENODEV;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	total_size = info->screen_size;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	if (total_size == 0)
110562306a36Sopenharmony_ci		total_size = info->fix.smem_len;
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	if (p > total_size)
110862306a36Sopenharmony_ci		return -EFBIG;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (count > total_size) {
111162306a36Sopenharmony_ci		err = -EFBIG;
111262306a36Sopenharmony_ci		count = total_size;
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	if (count + p > total_size) {
111662306a36Sopenharmony_ci		if (!err)
111762306a36Sopenharmony_ci			err = -ENOSPC;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci		count = total_size - p;
112062306a36Sopenharmony_ci	}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
112362306a36Sopenharmony_ci	if (!buffer)
112462306a36Sopenharmony_ci		return -ENOMEM;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	dst = (u32 __iomem *)(info->screen_base + p);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	if (info->fbops->fb_sync)
112962306a36Sopenharmony_ci		info->fbops->fb_sync(info);
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	while (count) {
113262306a36Sopenharmony_ci		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
113362306a36Sopenharmony_ci		src = buffer;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci		if (copy_from_user(src, buf, c)) {
113662306a36Sopenharmony_ci			err = -EFAULT;
113762306a36Sopenharmony_ci			break;
113862306a36Sopenharmony_ci		}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci		for (i = (c + 3) >> 2; i--;) {
114162306a36Sopenharmony_ci			fb_writel(big_swap(*src), dst);
114262306a36Sopenharmony_ci			dst++;
114362306a36Sopenharmony_ci			src++;
114462306a36Sopenharmony_ci		}
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci		*ppos += c;
114762306a36Sopenharmony_ci		buf += c;
114862306a36Sopenharmony_ci		cnt += c;
114962306a36Sopenharmony_ci		count -= c;
115062306a36Sopenharmony_ci	}
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	kfree(buffer);
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	return (cnt) ? cnt : err;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic void sm7xx_set_timing(struct smtcfb_info *sfb)
115862306a36Sopenharmony_ci{
115962306a36Sopenharmony_ci	int i = 0, j = 0;
116062306a36Sopenharmony_ci	u32 m_nscreenstride;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	dev_dbg(&sfb->pdev->dev,
116362306a36Sopenharmony_ci		"sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
116462306a36Sopenharmony_ci		sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
116762306a36Sopenharmony_ci		if (vgamode[j].mmsizex != sfb->width ||
116862306a36Sopenharmony_ci		    vgamode[j].mmsizey != sfb->height ||
116962306a36Sopenharmony_ci		    vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
117062306a36Sopenharmony_ci		    vgamode[j].hz != sfb->hz)
117162306a36Sopenharmony_ci			continue;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci		dev_dbg(&sfb->pdev->dev,
117462306a36Sopenharmony_ci			"vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
117562306a36Sopenharmony_ci			vgamode[j].mmsizex, vgamode[j].mmsizey,
117662306a36Sopenharmony_ci			vgamode[j].bpp, vgamode[j].hz);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci		dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci		smtc_mmiowb(0x0, 0x3c6);
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci		smtc_seqw(0, 0x1);
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci		smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci		/* init SEQ register SR00 - SR04 */
118762306a36Sopenharmony_ci		for (i = 0; i < SIZE_SR00_SR04; i++)
118862306a36Sopenharmony_ci			smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci		/* init SEQ register SR10 - SR24 */
119162306a36Sopenharmony_ci		for (i = 0; i < SIZE_SR10_SR24; i++)
119262306a36Sopenharmony_ci			smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci		/* init SEQ register SR30 - SR75 */
119562306a36Sopenharmony_ci		for (i = 0; i < SIZE_SR30_SR75; i++)
119662306a36Sopenharmony_ci			if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
119762306a36Sopenharmony_ci			    (i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
119862306a36Sopenharmony_ci			    (i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
119962306a36Sopenharmony_ci			    (i + 0x30) != 0x74 && (i + 0x30) != 0x75)
120062306a36Sopenharmony_ci				smtc_seqw(i + 0x30,
120162306a36Sopenharmony_ci					  vgamode[j].init_sr30_sr75[i]);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci		/* init SEQ register SR80 - SR93 */
120462306a36Sopenharmony_ci		for (i = 0; i < SIZE_SR80_SR93; i++)
120562306a36Sopenharmony_ci			smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci		/* init SEQ register SRA0 - SRAF */
120862306a36Sopenharmony_ci		for (i = 0; i < SIZE_SRA0_SRAF; i++)
120962306a36Sopenharmony_ci			smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci		/* init Graphic register GR00 - GR08 */
121262306a36Sopenharmony_ci		for (i = 0; i < SIZE_GR00_GR08; i++)
121362306a36Sopenharmony_ci			smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci		/* init Attribute register AR00 - AR14 */
121662306a36Sopenharmony_ci		for (i = 0; i < SIZE_AR00_AR14; i++)
121762306a36Sopenharmony_ci			smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci		/* init CRTC register CR00 - CR18 */
122062306a36Sopenharmony_ci		for (i = 0; i < SIZE_CR00_CR18; i++)
122162306a36Sopenharmony_ci			smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci		/* init CRTC register CR30 - CR4D */
122462306a36Sopenharmony_ci		for (i = 0; i < SIZE_CR30_CR4D; i++) {
122562306a36Sopenharmony_ci			if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
122662306a36Sopenharmony_ci				/* side-effect, don't write to CR3B-CR3F */
122762306a36Sopenharmony_ci				continue;
122862306a36Sopenharmony_ci			smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
122962306a36Sopenharmony_ci		}
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci		/* init CRTC register CR90 - CRA7 */
123262306a36Sopenharmony_ci		for (i = 0; i < SIZE_CR90_CRA7; i++)
123362306a36Sopenharmony_ci			smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
123462306a36Sopenharmony_ci	}
123562306a36Sopenharmony_ci	smtc_mmiowb(0x67, 0x3c2);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	/* set VPR registers */
123862306a36Sopenharmony_ci	writel(0x0, sfb->vp_regs + 0x0C);
123962306a36Sopenharmony_ci	writel(0x0, sfb->vp_regs + 0x40);
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	/* set data width */
124262306a36Sopenharmony_ci	m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
124362306a36Sopenharmony_ci	switch (sfb->fb->var.bits_per_pixel) {
124462306a36Sopenharmony_ci	case 8:
124562306a36Sopenharmony_ci		writel(0x0, sfb->vp_regs + 0x0);
124662306a36Sopenharmony_ci		break;
124762306a36Sopenharmony_ci	case 16:
124862306a36Sopenharmony_ci		writel(0x00020000, sfb->vp_regs + 0x0);
124962306a36Sopenharmony_ci		break;
125062306a36Sopenharmony_ci	case 24:
125162306a36Sopenharmony_ci		writel(0x00040000, sfb->vp_regs + 0x0);
125262306a36Sopenharmony_ci		break;
125362306a36Sopenharmony_ci	case 32:
125462306a36Sopenharmony_ci		writel(0x00030000, sfb->vp_regs + 0x0);
125562306a36Sopenharmony_ci		break;
125662306a36Sopenharmony_ci	}
125762306a36Sopenharmony_ci	writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
125862306a36Sopenharmony_ci	       sfb->vp_regs + 0x10);
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic void smtc_set_timing(struct smtcfb_info *sfb)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	switch (sfb->chip_id) {
126462306a36Sopenharmony_ci	case 0x710:
126562306a36Sopenharmony_ci	case 0x712:
126662306a36Sopenharmony_ci	case 0x720:
126762306a36Sopenharmony_ci		sm7xx_set_timing(sfb);
126862306a36Sopenharmony_ci		break;
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci}
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_cistatic void smtcfb_setmode(struct smtcfb_info *sfb)
127362306a36Sopenharmony_ci{
127462306a36Sopenharmony_ci	switch (sfb->fb->var.bits_per_pixel) {
127562306a36Sopenharmony_ci	case 32:
127662306a36Sopenharmony_ci		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
127762306a36Sopenharmony_ci		sfb->fb->fix.line_length  = sfb->fb->var.xres * 4;
127862306a36Sopenharmony_ci		sfb->fb->var.red.length   = 8;
127962306a36Sopenharmony_ci		sfb->fb->var.green.length = 8;
128062306a36Sopenharmony_ci		sfb->fb->var.blue.length  = 8;
128162306a36Sopenharmony_ci		sfb->fb->var.red.offset   = 16;
128262306a36Sopenharmony_ci		sfb->fb->var.green.offset = 8;
128362306a36Sopenharmony_ci		sfb->fb->var.blue.offset  = 0;
128462306a36Sopenharmony_ci		break;
128562306a36Sopenharmony_ci	case 24:
128662306a36Sopenharmony_ci		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
128762306a36Sopenharmony_ci		sfb->fb->fix.line_length  = sfb->fb->var.xres * 3;
128862306a36Sopenharmony_ci		sfb->fb->var.red.length   = 8;
128962306a36Sopenharmony_ci		sfb->fb->var.green.length = 8;
129062306a36Sopenharmony_ci		sfb->fb->var.blue.length  = 8;
129162306a36Sopenharmony_ci		sfb->fb->var.red.offset   = 16;
129262306a36Sopenharmony_ci		sfb->fb->var.green.offset = 8;
129362306a36Sopenharmony_ci		sfb->fb->var.blue.offset  = 0;
129462306a36Sopenharmony_ci		break;
129562306a36Sopenharmony_ci	case 8:
129662306a36Sopenharmony_ci		sfb->fb->fix.visual       = FB_VISUAL_PSEUDOCOLOR;
129762306a36Sopenharmony_ci		sfb->fb->fix.line_length  = sfb->fb->var.xres;
129862306a36Sopenharmony_ci		sfb->fb->var.red.length   = 3;
129962306a36Sopenharmony_ci		sfb->fb->var.green.length = 3;
130062306a36Sopenharmony_ci		sfb->fb->var.blue.length  = 2;
130162306a36Sopenharmony_ci		sfb->fb->var.red.offset   = 5;
130262306a36Sopenharmony_ci		sfb->fb->var.green.offset = 2;
130362306a36Sopenharmony_ci		sfb->fb->var.blue.offset  = 0;
130462306a36Sopenharmony_ci		break;
130562306a36Sopenharmony_ci	case 16:
130662306a36Sopenharmony_ci	default:
130762306a36Sopenharmony_ci		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
130862306a36Sopenharmony_ci		sfb->fb->fix.line_length  = sfb->fb->var.xres * 2;
130962306a36Sopenharmony_ci		sfb->fb->var.red.length   = 5;
131062306a36Sopenharmony_ci		sfb->fb->var.green.length = 6;
131162306a36Sopenharmony_ci		sfb->fb->var.blue.length  = 5;
131262306a36Sopenharmony_ci		sfb->fb->var.red.offset   = 11;
131362306a36Sopenharmony_ci		sfb->fb->var.green.offset = 5;
131462306a36Sopenharmony_ci		sfb->fb->var.blue.offset  = 0;
131562306a36Sopenharmony_ci		break;
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	sfb->width  = sfb->fb->var.xres;
131962306a36Sopenharmony_ci	sfb->height = sfb->fb->var.yres;
132062306a36Sopenharmony_ci	sfb->hz = 60;
132162306a36Sopenharmony_ci	smtc_set_timing(sfb);
132262306a36Sopenharmony_ci}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_cistatic int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
132562306a36Sopenharmony_ci{
132662306a36Sopenharmony_ci	/* sanity checks */
132762306a36Sopenharmony_ci	if (var->xres_virtual < var->xres)
132862306a36Sopenharmony_ci		var->xres_virtual = var->xres;
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	if (var->yres_virtual < var->yres)
133162306a36Sopenharmony_ci		var->yres_virtual = var->yres;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	/* set valid default bpp */
133462306a36Sopenharmony_ci	if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
133562306a36Sopenharmony_ci	    (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
133662306a36Sopenharmony_ci		var->bits_per_pixel = 16;
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	return 0;
133962306a36Sopenharmony_ci}
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_cistatic int smtc_set_par(struct fb_info *info)
134262306a36Sopenharmony_ci{
134362306a36Sopenharmony_ci	smtcfb_setmode(info->par);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	return 0;
134662306a36Sopenharmony_ci}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_cistatic const struct fb_ops smtcfb_ops = {
134962306a36Sopenharmony_ci	.owner        = THIS_MODULE,
135062306a36Sopenharmony_ci	.fb_check_var = smtc_check_var,
135162306a36Sopenharmony_ci	.fb_set_par   = smtc_set_par,
135262306a36Sopenharmony_ci	.fb_setcolreg = smtc_setcolreg,
135362306a36Sopenharmony_ci	.fb_blank     = smtc_blank,
135462306a36Sopenharmony_ci	.fb_fillrect  = cfb_fillrect,
135562306a36Sopenharmony_ci	.fb_imageblit = cfb_imageblit,
135662306a36Sopenharmony_ci	.fb_copyarea  = cfb_copyarea,
135762306a36Sopenharmony_ci	.fb_read      = smtcfb_read,
135862306a36Sopenharmony_ci	.fb_write     = smtcfb_write,
135962306a36Sopenharmony_ci};
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci/*
136262306a36Sopenharmony_ci * Unmap in the memory mapped IO registers
136362306a36Sopenharmony_ci */
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_cistatic void smtc_unmap_mmio(struct smtcfb_info *sfb)
136662306a36Sopenharmony_ci{
136762306a36Sopenharmony_ci	if (sfb && smtc_regbaseaddress)
136862306a36Sopenharmony_ci		smtc_regbaseaddress = NULL;
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci/*
137262306a36Sopenharmony_ci * Map in the screen memory
137362306a36Sopenharmony_ci */
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_cistatic int smtc_map_smem(struct smtcfb_info *sfb,
137662306a36Sopenharmony_ci			 struct pci_dev *pdev, u_long smem_len)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	if (sfb->chip_id == 0x720)
138162306a36Sopenharmony_ci		/* on SM720, the framebuffer starts at the 1 MB offset */
138262306a36Sopenharmony_ci		sfb->fb->fix.smem_start += 0x00200000;
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	/* XXX: is it safe for SM720 on Big-Endian? */
138562306a36Sopenharmony_ci	if (sfb->fb->var.bits_per_pixel == 32)
138662306a36Sopenharmony_ci		sfb->fb->fix.smem_start += big_addr;
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci	sfb->fb->fix.smem_len = smem_len;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	sfb->fb->screen_base = sfb->lfb;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	if (!sfb->fb->screen_base) {
139362306a36Sopenharmony_ci		dev_err(&pdev->dev,
139462306a36Sopenharmony_ci			"%s: unable to map screen memory\n", sfb->fb->fix.id);
139562306a36Sopenharmony_ci		return -ENOMEM;
139662306a36Sopenharmony_ci	}
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	return 0;
139962306a36Sopenharmony_ci}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci/*
140262306a36Sopenharmony_ci * Unmap in the screen memory
140362306a36Sopenharmony_ci *
140462306a36Sopenharmony_ci */
140562306a36Sopenharmony_cistatic void smtc_unmap_smem(struct smtcfb_info *sfb)
140662306a36Sopenharmony_ci{
140762306a36Sopenharmony_ci	if (sfb && sfb->fb->screen_base) {
140862306a36Sopenharmony_ci		if (sfb->chip_id == 0x720)
140962306a36Sopenharmony_ci			sfb->fb->screen_base -= 0x00200000;
141062306a36Sopenharmony_ci		iounmap(sfb->fb->screen_base);
141162306a36Sopenharmony_ci		sfb->fb->screen_base = NULL;
141262306a36Sopenharmony_ci	}
141362306a36Sopenharmony_ci}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci/*
141662306a36Sopenharmony_ci * We need to wake up the device and make sure its in linear memory mode.
141762306a36Sopenharmony_ci */
141862306a36Sopenharmony_cistatic inline void sm7xx_init_hw(void)
141962306a36Sopenharmony_ci{
142062306a36Sopenharmony_ci	outb_p(0x18, 0x3c4);
142162306a36Sopenharmony_ci	outb_p(0x11, 0x3c5);
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_cistatic u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	u8 vram;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	switch (sfb->chip_id) {
142962306a36Sopenharmony_ci	case 0x710:
143062306a36Sopenharmony_ci	case 0x712:
143162306a36Sopenharmony_ci		/*
143262306a36Sopenharmony_ci		 * Assume SM712 graphics chip has 4MB VRAM.
143362306a36Sopenharmony_ci		 *
143462306a36Sopenharmony_ci		 * FIXME: SM712 can have 2MB VRAM, which is used on earlier
143562306a36Sopenharmony_ci		 * laptops, such as IBM Thinkpad 240X. This driver would
143662306a36Sopenharmony_ci		 * probably crash on those machines. If anyone gets one of
143762306a36Sopenharmony_ci		 * those and is willing to help, run "git blame" and send me
143862306a36Sopenharmony_ci		 * an E-mail.
143962306a36Sopenharmony_ci		 */
144062306a36Sopenharmony_ci		return 0x00400000;
144162306a36Sopenharmony_ci	case 0x720:
144262306a36Sopenharmony_ci		outb_p(0x76, 0x3c4);
144362306a36Sopenharmony_ci		vram = inb_p(0x3c5) >> 6;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci		if (vram == 0x00)
144662306a36Sopenharmony_ci			return 0x00800000;  /* 8 MB */
144762306a36Sopenharmony_ci		else if (vram == 0x01)
144862306a36Sopenharmony_ci			return 0x01000000;  /* 16 MB */
144962306a36Sopenharmony_ci		else if (vram == 0x02)
145062306a36Sopenharmony_ci			return 0x00400000;  /* illegal, fallback to 4 MB */
145162306a36Sopenharmony_ci		else if (vram == 0x03)
145262306a36Sopenharmony_ci			return 0x00400000;  /* 4 MB */
145362306a36Sopenharmony_ci	}
145462306a36Sopenharmony_ci	return 0;  /* unknown hardware */
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistatic void sm7xx_resolution_probe(struct smtcfb_info *sfb)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	/* get mode parameter from smtc_scr_info */
146062306a36Sopenharmony_ci	if (smtc_scr_info.lfb_width != 0) {
146162306a36Sopenharmony_ci		sfb->fb->var.xres = smtc_scr_info.lfb_width;
146262306a36Sopenharmony_ci		sfb->fb->var.yres = smtc_scr_info.lfb_height;
146362306a36Sopenharmony_ci		sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
146462306a36Sopenharmony_ci		goto final;
146562306a36Sopenharmony_ci	}
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	/*
146862306a36Sopenharmony_ci	 * No parameter, default resolution is 1024x768-16.
146962306a36Sopenharmony_ci	 *
147062306a36Sopenharmony_ci	 * FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
147162306a36Sopenharmony_ci	 * panel, also see the comments about Thinkpad 240X above.
147262306a36Sopenharmony_ci	 */
147362306a36Sopenharmony_ci	sfb->fb->var.xres = SCREEN_X_RES;
147462306a36Sopenharmony_ci	sfb->fb->var.yres = SCREEN_Y_RES_PC;
147562306a36Sopenharmony_ci	sfb->fb->var.bits_per_pixel = SCREEN_BPP;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci#ifdef CONFIG_MIPS
147862306a36Sopenharmony_ci	/*
147962306a36Sopenharmony_ci	 * Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
148062306a36Sopenharmony_ci	 * target platform of this driver, but nearly all old x86 laptops have
148162306a36Sopenharmony_ci	 * 1024x768. Lighting 768 panels using 600's timings would partially
148262306a36Sopenharmony_ci	 * garble the display, so we don't want that. But it's not possible to
148362306a36Sopenharmony_ci	 * distinguish them reliably.
148462306a36Sopenharmony_ci	 *
148562306a36Sopenharmony_ci	 * So we change the default to 768, but keep 600 as-is on MIPS.
148662306a36Sopenharmony_ci	 */
148762306a36Sopenharmony_ci	sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
148862306a36Sopenharmony_ci#endif
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_cifinal:
149162306a36Sopenharmony_ci	big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
149262306a36Sopenharmony_ci}
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_cistatic int smtcfb_pci_probe(struct pci_dev *pdev,
149562306a36Sopenharmony_ci			    const struct pci_device_id *ent)
149662306a36Sopenharmony_ci{
149762306a36Sopenharmony_ci	struct smtcfb_info *sfb;
149862306a36Sopenharmony_ci	struct fb_info *info;
149962306a36Sopenharmony_ci	u_long smem_size;
150062306a36Sopenharmony_ci	int err;
150162306a36Sopenharmony_ci	unsigned long mmio_base;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	dev_info(&pdev->dev, "Silicon Motion display driver.\n");
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	err = aperture_remove_conflicting_pci_devices(pdev, "smtcfb");
150662306a36Sopenharmony_ci	if (err)
150762306a36Sopenharmony_ci		return err;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	err = pci_enable_device(pdev);	/* enable SMTC chip */
151062306a36Sopenharmony_ci	if (err)
151162306a36Sopenharmony_ci		return err;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	err = pci_request_region(pdev, 0, "sm7xxfb");
151462306a36Sopenharmony_ci	if (err < 0) {
151562306a36Sopenharmony_ci		dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
151662306a36Sopenharmony_ci		goto failed_regions;
151762306a36Sopenharmony_ci	}
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
152262306a36Sopenharmony_ci	if (!info) {
152362306a36Sopenharmony_ci		err = -ENOMEM;
152462306a36Sopenharmony_ci		goto failed_free;
152562306a36Sopenharmony_ci	}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	sfb = info->par;
152862306a36Sopenharmony_ci	sfb->fb = info;
152962306a36Sopenharmony_ci	sfb->chip_id = ent->device;
153062306a36Sopenharmony_ci	sfb->pdev = pdev;
153162306a36Sopenharmony_ci	info->fbops = &smtcfb_ops;
153262306a36Sopenharmony_ci	info->fix = smtcfb_fix;
153362306a36Sopenharmony_ci	info->var = smtcfb_var;
153462306a36Sopenharmony_ci	info->pseudo_palette = sfb->colreg;
153562306a36Sopenharmony_ci	info->par = sfb;
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	pci_set_drvdata(pdev, sfb);
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	sm7xx_init_hw();
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	/* Map address and memory detection */
154262306a36Sopenharmony_ci	mmio_base = pci_resource_start(pdev, 0);
154362306a36Sopenharmony_ci	pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	smem_size = sm7xx_vram_probe(sfb);
154662306a36Sopenharmony_ci	dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
154762306a36Sopenharmony_ci					smem_size / 1048576);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	switch (sfb->chip_id) {
155062306a36Sopenharmony_ci	case 0x710:
155162306a36Sopenharmony_ci	case 0x712:
155262306a36Sopenharmony_ci		sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
155362306a36Sopenharmony_ci		sfb->fb->fix.mmio_len = 0x00400000;
155462306a36Sopenharmony_ci		sfb->lfb = ioremap(mmio_base, mmio_addr);
155562306a36Sopenharmony_ci		if (!sfb->lfb) {
155662306a36Sopenharmony_ci			dev_err(&pdev->dev,
155762306a36Sopenharmony_ci				"%s: unable to map memory mapped IO!\n",
155862306a36Sopenharmony_ci				sfb->fb->fix.id);
155962306a36Sopenharmony_ci			err = -ENOMEM;
156062306a36Sopenharmony_ci			goto failed_fb;
156162306a36Sopenharmony_ci		}
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci		sfb->mmio = (smtc_regbaseaddress =
156462306a36Sopenharmony_ci		    sfb->lfb + 0x00700000);
156562306a36Sopenharmony_ci		sfb->dp_regs = sfb->lfb + 0x00408000;
156662306a36Sopenharmony_ci		sfb->vp_regs = sfb->lfb + 0x0040c000;
156762306a36Sopenharmony_ci		if (sfb->fb->var.bits_per_pixel == 32) {
156862306a36Sopenharmony_ci			sfb->lfb += big_addr;
156962306a36Sopenharmony_ci			dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
157062306a36Sopenharmony_ci		}
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci		/* set MCLK = 14.31818 * (0x16 / 0x2) */
157362306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x16);
157462306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
157562306a36Sopenharmony_ci		smtc_seqw(0x62, 0x3e);
157662306a36Sopenharmony_ci		/* enable PCI burst */
157762306a36Sopenharmony_ci		smtc_seqw(0x17, 0x20);
157862306a36Sopenharmony_ci		/* enable word swap */
157962306a36Sopenharmony_ci		if (sfb->fb->var.bits_per_pixel == 32)
158062306a36Sopenharmony_ci			seqw17();
158162306a36Sopenharmony_ci		break;
158262306a36Sopenharmony_ci	case 0x720:
158362306a36Sopenharmony_ci		sfb->fb->fix.mmio_start = mmio_base;
158462306a36Sopenharmony_ci		sfb->fb->fix.mmio_len = 0x00200000;
158562306a36Sopenharmony_ci		sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
158662306a36Sopenharmony_ci		if (!sfb->dp_regs) {
158762306a36Sopenharmony_ci			dev_err(&pdev->dev,
158862306a36Sopenharmony_ci				"%s: unable to map memory mapped IO!\n",
158962306a36Sopenharmony_ci				sfb->fb->fix.id);
159062306a36Sopenharmony_ci			err = -ENOMEM;
159162306a36Sopenharmony_ci			goto failed_fb;
159262306a36Sopenharmony_ci		}
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci		sfb->lfb = sfb->dp_regs + 0x00200000;
159562306a36Sopenharmony_ci		sfb->mmio = (smtc_regbaseaddress =
159662306a36Sopenharmony_ci		    sfb->dp_regs + 0x000c0000);
159762306a36Sopenharmony_ci		sfb->vp_regs = sfb->dp_regs + 0x800;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci		smtc_seqw(0x62, 0xff);
160062306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x0d);
160162306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
160262306a36Sopenharmony_ci		break;
160362306a36Sopenharmony_ci	default:
160462306a36Sopenharmony_ci		dev_err(&pdev->dev,
160562306a36Sopenharmony_ci			"No valid Silicon Motion display chip was detected!\n");
160662306a36Sopenharmony_ci		err = -ENODEV;
160762306a36Sopenharmony_ci		goto failed_fb;
160862306a36Sopenharmony_ci	}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	/* probe and decide resolution */
161162306a36Sopenharmony_ci	sm7xx_resolution_probe(sfb);
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	/* can support 32 bpp */
161462306a36Sopenharmony_ci	if (sfb->fb->var.bits_per_pixel == 15)
161562306a36Sopenharmony_ci		sfb->fb->var.bits_per_pixel = 16;
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	sfb->fb->var.xres_virtual = sfb->fb->var.xres;
161862306a36Sopenharmony_ci	sfb->fb->var.yres_virtual = sfb->fb->var.yres;
161962306a36Sopenharmony_ci	err = smtc_map_smem(sfb, pdev, smem_size);
162062306a36Sopenharmony_ci	if (err)
162162306a36Sopenharmony_ci		goto failed;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	/*
162462306a36Sopenharmony_ci	 * The screen would be temporarily garbled when sm712fb takes over
162562306a36Sopenharmony_ci	 * vesafb or VGA text mode. Zero the framebuffer.
162662306a36Sopenharmony_ci	 */
162762306a36Sopenharmony_ci	memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	err = register_framebuffer(info);
163062306a36Sopenharmony_ci	if (err < 0)
163162306a36Sopenharmony_ci		goto failed;
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	dev_info(&pdev->dev,
163462306a36Sopenharmony_ci		 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
163562306a36Sopenharmony_ci		 sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
163662306a36Sopenharmony_ci		 sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	return 0;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_cifailed:
164162306a36Sopenharmony_ci	dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	smtc_unmap_smem(sfb);
164462306a36Sopenharmony_ci	smtc_unmap_mmio(sfb);
164562306a36Sopenharmony_cifailed_fb:
164662306a36Sopenharmony_ci	framebuffer_release(info);
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cifailed_free:
164962306a36Sopenharmony_ci	pci_release_region(pdev, 0);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_cifailed_regions:
165262306a36Sopenharmony_ci	pci_disable_device(pdev);
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	return err;
165562306a36Sopenharmony_ci}
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci/*
165862306a36Sopenharmony_ci * 0x710 (LynxEM)
165962306a36Sopenharmony_ci * 0x712 (LynxEM+)
166062306a36Sopenharmony_ci * 0x720 (Lynx3DM, Lynx3DM+)
166162306a36Sopenharmony_ci */
166262306a36Sopenharmony_cistatic const struct pci_device_id smtcfb_pci_table[] = {
166362306a36Sopenharmony_ci	{ PCI_DEVICE(0x126f, 0x710), },
166462306a36Sopenharmony_ci	{ PCI_DEVICE(0x126f, 0x712), },
166562306a36Sopenharmony_ci	{ PCI_DEVICE(0x126f, 0x720), },
166662306a36Sopenharmony_ci	{0,}
166762306a36Sopenharmony_ci};
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_cistatic void smtcfb_pci_remove(struct pci_dev *pdev)
167262306a36Sopenharmony_ci{
167362306a36Sopenharmony_ci	struct smtcfb_info *sfb;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	sfb = pci_get_drvdata(pdev);
167662306a36Sopenharmony_ci	smtc_unmap_smem(sfb);
167762306a36Sopenharmony_ci	smtc_unmap_mmio(sfb);
167862306a36Sopenharmony_ci	unregister_framebuffer(sfb->fb);
167962306a36Sopenharmony_ci	framebuffer_release(sfb->fb);
168062306a36Sopenharmony_ci	pci_release_region(pdev, 0);
168162306a36Sopenharmony_ci	pci_disable_device(pdev);
168262306a36Sopenharmony_ci}
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_cistatic int __maybe_unused smtcfb_pci_suspend(struct device *device)
168562306a36Sopenharmony_ci{
168662306a36Sopenharmony_ci	struct smtcfb_info *sfb = dev_get_drvdata(device);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	/* set the hw in sleep mode use external clock and self memory refresh
169062306a36Sopenharmony_ci	 * so that we can turn off internal PLLs later on
169162306a36Sopenharmony_ci	 */
169262306a36Sopenharmony_ci	smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
169362306a36Sopenharmony_ci	smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci	console_lock();
169662306a36Sopenharmony_ci	fb_set_suspend(sfb->fb, 1);
169762306a36Sopenharmony_ci	console_unlock();
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	/* additionally turn off all function blocks including internal PLLs */
170062306a36Sopenharmony_ci	smtc_seqw(0x21, 0xff);
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	return 0;
170362306a36Sopenharmony_ci}
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_cistatic int __maybe_unused smtcfb_pci_resume(struct device *device)
170662306a36Sopenharmony_ci{
170762306a36Sopenharmony_ci	struct smtcfb_info *sfb = dev_get_drvdata(device);
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	/* reinit hardware */
171162306a36Sopenharmony_ci	sm7xx_init_hw();
171262306a36Sopenharmony_ci	switch (sfb->chip_id) {
171362306a36Sopenharmony_ci	case 0x710:
171462306a36Sopenharmony_ci	case 0x712:
171562306a36Sopenharmony_ci		/* set MCLK = 14.31818 *  (0x16 / 0x2) */
171662306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x16);
171762306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
171862306a36Sopenharmony_ci		smtc_seqw(0x62, 0x3e);
171962306a36Sopenharmony_ci		/* enable PCI burst */
172062306a36Sopenharmony_ci		smtc_seqw(0x17, 0x20);
172162306a36Sopenharmony_ci		if (sfb->fb->var.bits_per_pixel == 32)
172262306a36Sopenharmony_ci			seqw17();
172362306a36Sopenharmony_ci		break;
172462306a36Sopenharmony_ci	case 0x720:
172562306a36Sopenharmony_ci		smtc_seqw(0x62, 0xff);
172662306a36Sopenharmony_ci		smtc_seqw(0x6a, 0x0d);
172762306a36Sopenharmony_ci		smtc_seqw(0x6b, 0x02);
172862306a36Sopenharmony_ci		break;
172962306a36Sopenharmony_ci	}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
173262306a36Sopenharmony_ci	smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	smtcfb_setmode(sfb);
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	console_lock();
173762306a36Sopenharmony_ci	fb_set_suspend(sfb->fb, 0);
173862306a36Sopenharmony_ci	console_unlock();
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	return 0;
174162306a36Sopenharmony_ci}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_cistatic struct pci_driver smtcfb_driver = {
174662306a36Sopenharmony_ci	.name = "smtcfb",
174762306a36Sopenharmony_ci	.id_table = smtcfb_pci_table,
174862306a36Sopenharmony_ci	.probe = smtcfb_pci_probe,
174962306a36Sopenharmony_ci	.remove = smtcfb_pci_remove,
175062306a36Sopenharmony_ci	.driver.pm  = &sm7xx_pm_ops,
175162306a36Sopenharmony_ci};
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_cistatic int __init sm712fb_init(void)
175462306a36Sopenharmony_ci{
175562306a36Sopenharmony_ci	char *option = NULL;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	if (fb_modesetting_disabled("sm712fb"))
175862306a36Sopenharmony_ci		return -ENODEV;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	if (fb_get_options("sm712fb", &option))
176162306a36Sopenharmony_ci		return -ENODEV;
176262306a36Sopenharmony_ci	if (option && *option)
176362306a36Sopenharmony_ci		mode_option = option;
176462306a36Sopenharmony_ci	sm7xx_vga_setup(mode_option);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	return pci_register_driver(&smtcfb_driver);
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_cimodule_init(sm712fb_init);
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_cistatic void __exit sm712fb_exit(void)
177262306a36Sopenharmony_ci{
177362306a36Sopenharmony_ci	pci_unregister_driver(&smtcfb_driver);
177462306a36Sopenharmony_ci}
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_cimodule_exit(sm712fb_exit);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ciMODULE_AUTHOR("Siliconmotion ");
177962306a36Sopenharmony_ciMODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
178062306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1781