cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sm712fb.c (49105B)


      1/*
      2 * Silicon Motion SM7XX frame buffer device
      3 *
      4 * Copyright (C) 2006 Silicon Motion Technology Corp.
      5 * Authors:  Ge Wang, gewang@siliconmotion.com
      6 *	     Boyod boyod.yang@siliconmotion.com.cn
      7 *
      8 * Copyright (C) 2009 Lemote, Inc.
      9 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
     10 *
     11 * Copyright (C) 2011 Igalia, S.L.
     12 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
     13 *
     14 * This file is subject to the terms and conditions of the GNU General Public
     15 * License. See the file COPYING in the main directory of this archive for
     16 * more details.
     17 *
     18 * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
     19 */
     20
     21#include <linux/io.h>
     22#include <linux/fb.h>
     23#include <linux/pci.h>
     24#include <linux/init.h>
     25#include <linux/slab.h>
     26#include <linux/uaccess.h>
     27#include <linux/module.h>
     28#include <linux/console.h>
     29#include <linux/screen_info.h>
     30
     31#include <linux/pm.h>
     32
     33#include "sm712.h"
     34
     35/*
     36 * Private structure
     37 */
     38struct smtcfb_info {
     39	struct pci_dev *pdev;
     40	struct fb_info *fb;
     41	u16 chip_id;
     42	u8  chip_rev_id;
     43
     44	void __iomem *lfb;	/* linear frame buffer */
     45	void __iomem *dp_regs;	/* drawing processor control regs */
     46	void __iomem *vp_regs;	/* video processor control regs */
     47	void __iomem *cp_regs;	/* capture processor control regs */
     48	void __iomem *mmio;	/* memory map IO port */
     49
     50	u_int width;
     51	u_int height;
     52	u_int hz;
     53
     54	u32 colreg[17];
     55};
     56
     57void __iomem *smtc_regbaseaddress;	/* Memory Map IO starting address */
     58
     59static const struct fb_var_screeninfo smtcfb_var = {
     60	.xres           = 1024,
     61	.yres           = 600,
     62	.xres_virtual   = 1024,
     63	.yres_virtual   = 600,
     64	.bits_per_pixel = 16,
     65	.red            = {16, 8, 0},
     66	.green          = {8, 8, 0},
     67	.blue           = {0, 8, 0},
     68	.activate       = FB_ACTIVATE_NOW,
     69	.height         = -1,
     70	.width          = -1,
     71	.vmode          = FB_VMODE_NONINTERLACED,
     72	.nonstd         = 0,
     73	.accel_flags    = FB_ACCELF_TEXT,
     74};
     75
     76static struct fb_fix_screeninfo smtcfb_fix = {
     77	.id             = "smXXXfb",
     78	.type           = FB_TYPE_PACKED_PIXELS,
     79	.visual         = FB_VISUAL_TRUECOLOR,
     80	.line_length    = 800 * 3,
     81	.accel          = FB_ACCEL_SMI_LYNX,
     82	.type_aux       = 0,
     83	.xpanstep       = 0,
     84	.ypanstep       = 0,
     85	.ywrapstep      = 0,
     86};
     87
     88struct vesa_mode {
     89	char index[6];
     90	u16  lfb_width;
     91	u16  lfb_height;
     92	u16  lfb_depth;
     93};
     94
     95static const struct vesa_mode vesa_mode_table[] = {
     96	{"0x301", 640,  480,  8},
     97	{"0x303", 800,  600,  8},
     98	{"0x305", 1024, 768,  8},
     99	{"0x307", 1280, 1024, 8},
    100
    101	{"0x311", 640,  480,  16},
    102	{"0x314", 800,  600,  16},
    103	{"0x317", 1024, 768,  16},
    104	{"0x31A", 1280, 1024, 16},
    105
    106	{"0x312", 640,  480,  24},
    107	{"0x315", 800,  600,  24},
    108	{"0x318", 1024, 768,  24},
    109	{"0x31B", 1280, 1024, 24},
    110};
    111
    112/**********************************************************************
    113			 SM712 Mode table.
    114 **********************************************************************/
    115static const struct modeinit vgamode[] = {
    116	{
    117		/*  mode#0: 640 x 480  16Bpp  60Hz */
    118		640, 480, 16, 60,
    119		/*  Init_MISC */
    120		0xE3,
    121		{	/*  Init_SR0_SR4 */
    122			0x03, 0x01, 0x0F, 0x00, 0x0E,
    123		},
    124		{	/*  Init_SR10_SR24 */
    125			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    126			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    127			0xC4, 0x30, 0x02, 0x01, 0x01,
    128		},
    129		{	/*  Init_SR30_SR75 */
    130			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
    131			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
    132			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    133			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
    134			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
    135			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
    136			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    137			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
    138			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
    139		},
    140		{	/*  Init_SR80_SR93 */
    141			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
    142			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
    143			0x00, 0x00, 0x00, 0x00,
    144		},
    145		{	/*  Init_SRA0_SRAF */
    146			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    147			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
    148		},
    149		{	/*  Init_GR00_GR08 */
    150			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    151			0xFF,
    152		},
    153		{	/*  Init_AR00_AR14 */
    154			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    155			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    156			0x41, 0x00, 0x0F, 0x00, 0x00,
    157		},
    158		{	/*  Init_CR00_CR18 */
    159			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
    160			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    161			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
    162			0xFF,
    163		},
    164		{	/*  Init_CR30_CR4D */
    165			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
    166			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
    167			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
    168			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
    169		},
    170		{	/*  Init_CR90_CRA7 */
    171			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
    172			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
    173			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
    174		},
    175	},
    176	{
    177		/*  mode#1: 640 x 480  24Bpp  60Hz */
    178		640, 480, 24, 60,
    179		/*  Init_MISC */
    180		0xE3,
    181		{	/*  Init_SR0_SR4 */
    182			0x03, 0x01, 0x0F, 0x00, 0x0E,
    183		},
    184		{	/*  Init_SR10_SR24 */
    185			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    186			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    187			0xC4, 0x30, 0x02, 0x01, 0x01,
    188		},
    189		{	/*  Init_SR30_SR75 */
    190			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
    191			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
    192			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    193			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
    194			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
    195			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
    196			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    197			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
    198			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
    199		},
    200		{	/*  Init_SR80_SR93 */
    201			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
    202			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
    203			0x00, 0x00, 0x00, 0x00,
    204		},
    205		{	/*  Init_SRA0_SRAF */
    206			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    207			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
    208		},
    209		{	/*  Init_GR00_GR08 */
    210			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    211			0xFF,
    212		},
    213		{	/*  Init_AR00_AR14 */
    214			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    215			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    216			0x41, 0x00, 0x0F, 0x00, 0x00,
    217		},
    218		{	/*  Init_CR00_CR18 */
    219			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
    220			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    221			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
    222			0xFF,
    223		},
    224		{	/*  Init_CR30_CR4D */
    225			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
    226			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
    227			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
    228			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
    229		},
    230		{	/*  Init_CR90_CRA7 */
    231			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
    232			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
    233			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
    234		},
    235	},
    236	{
    237		/*  mode#0: 640 x 480  32Bpp  60Hz */
    238		640, 480, 32, 60,
    239		/*  Init_MISC */
    240		0xE3,
    241		{	/*  Init_SR0_SR4 */
    242			0x03, 0x01, 0x0F, 0x00, 0x0E,
    243		},
    244		{	/*  Init_SR10_SR24 */
    245			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    246			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    247			0xC4, 0x30, 0x02, 0x01, 0x01,
    248		},
    249		{	/*  Init_SR30_SR75 */
    250			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
    251			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
    252			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    253			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
    254			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
    255			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
    256			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    257			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
    258			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
    259		},
    260		{	/*  Init_SR80_SR93 */
    261			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
    262			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
    263			0x00, 0x00, 0x00, 0x00,
    264		},
    265		{	/*  Init_SRA0_SRAF */
    266			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    267			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
    268		},
    269		{	/*  Init_GR00_GR08 */
    270			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    271			0xFF,
    272		},
    273		{	/*  Init_AR00_AR14 */
    274			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    275			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    276			0x41, 0x00, 0x0F, 0x00, 0x00,
    277		},
    278		{	/*  Init_CR00_CR18 */
    279			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
    280			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    281			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
    282			0xFF,
    283		},
    284		{	/*  Init_CR30_CR4D */
    285			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
    286			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
    287			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
    288			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
    289		},
    290		{	/*  Init_CR90_CRA7 */
    291			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
    292			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
    293			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
    294		},
    295	},
    296
    297	{	/*  mode#2: 800 x 600  16Bpp  60Hz */
    298		800, 600, 16, 60,
    299		/*  Init_MISC */
    300		0x2B,
    301		{	/*  Init_SR0_SR4 */
    302			0x03, 0x01, 0x0F, 0x03, 0x0E,
    303		},
    304		{	/*  Init_SR10_SR24 */
    305			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    306			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    307			0xC4, 0x30, 0x02, 0x01, 0x01,
    308		},
    309		{	/*  Init_SR30_SR75 */
    310			0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
    311			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
    312			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
    313			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
    314			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
    315			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
    316			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    317			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
    318			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
    319		},
    320		{	/*  Init_SR80_SR93 */
    321			0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
    322			0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
    323			0x00, 0x00, 0x00, 0x00,
    324		},
    325		{	/*  Init_SRA0_SRAF */
    326			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    327			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
    328		},
    329		{	/*  Init_GR00_GR08 */
    330			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    331			0xFF,
    332		},
    333		{	/*  Init_AR00_AR14 */
    334			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    335			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    336			0x41, 0x00, 0x0F, 0x00, 0x00,
    337		},
    338		{	/*  Init_CR00_CR18 */
    339			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
    340			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    341			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
    342			0xFF,
    343		},
    344		{	/*  Init_CR30_CR4D */
    345			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
    346			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
    347			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
    348			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
    349		},
    350		{	/*  Init_CR90_CRA7 */
    351			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
    352			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
    353			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
    354		},
    355	},
    356	{	/*  mode#3: 800 x 600  24Bpp  60Hz */
    357		800, 600, 24, 60,
    358		0x2B,
    359		{	/*  Init_SR0_SR4 */
    360			0x03, 0x01, 0x0F, 0x03, 0x0E,
    361		},
    362		{	/*  Init_SR10_SR24 */
    363			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    364			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    365			0xC4, 0x30, 0x02, 0x01, 0x01,
    366		},
    367		{	/*  Init_SR30_SR75 */
    368			0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
    369			0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
    370			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    371			0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
    372			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
    373			0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
    374			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    375			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
    376			0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
    377		},
    378		{	/*  Init_SR80_SR93 */
    379			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
    380			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
    381			0x00, 0x00, 0x00, 0x00,
    382		},
    383		{	/*  Init_SRA0_SRAF */
    384			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    385			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
    386		},
    387		{	/*  Init_GR00_GR08 */
    388			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    389			0xFF,
    390		},
    391		{	/*  Init_AR00_AR14 */
    392			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    393			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    394			0x41, 0x00, 0x0F, 0x00, 0x00,
    395		},
    396		{	/*  Init_CR00_CR18 */
    397			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
    398			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    399			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
    400			0xFF,
    401		},
    402		{	/*  Init_CR30_CR4D */
    403			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
    404			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
    405			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
    406			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
    407		},
    408		{	/*  Init_CR90_CRA7 */
    409			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
    410			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
    411			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
    412		},
    413	},
    414	{	/*  mode#7: 800 x 600  32Bpp  60Hz */
    415		800, 600, 32, 60,
    416		/*  Init_MISC */
    417		0x2B,
    418		{	/*  Init_SR0_SR4 */
    419			0x03, 0x01, 0x0F, 0x03, 0x0E,
    420		},
    421		{	/*  Init_SR10_SR24 */
    422			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
    423			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    424			0xC4, 0x30, 0x02, 0x01, 0x01,
    425		},
    426		{	/*  Init_SR30_SR75 */
    427			0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
    428			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
    429			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
    430			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
    431			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
    432			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
    433			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    434			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
    435			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
    436		},
    437		{	/*  Init_SR80_SR93 */
    438			0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
    439			0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
    440			0x00, 0x00, 0x00, 0x00,
    441		},
    442		{	/*  Init_SRA0_SRAF */
    443			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
    444			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
    445		},
    446		{	/*  Init_GR00_GR08 */
    447			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    448			0xFF,
    449		},
    450		{	/*  Init_AR00_AR14 */
    451			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    452			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    453			0x41, 0x00, 0x0F, 0x00, 0x00,
    454		},
    455		{	/*  Init_CR00_CR18 */
    456			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
    457			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    458			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
    459			0xFF,
    460		},
    461		{	/*  Init_CR30_CR4D */
    462			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
    463			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
    464			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
    465			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
    466		},
    467		{	/*  Init_CR90_CRA7 */
    468			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
    469			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
    470			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
    471		},
    472	},
    473	/* We use 1024x768 table to light 1024x600 panel for lemote */
    474	{	/*  mode#4: 1024 x 600  16Bpp  60Hz  */
    475		1024, 600, 16, 60,
    476		/*  Init_MISC */
    477		0xEB,
    478		{	/*  Init_SR0_SR4 */
    479			0x03, 0x01, 0x0F, 0x00, 0x0E,
    480		},
    481		{	/*  Init_SR10_SR24 */
    482			0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
    483			0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    484			0xC4, 0x30, 0x02, 0x00, 0x01,
    485		},
    486		{	/*  Init_SR30_SR75 */
    487			0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
    488			0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
    489			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    490			0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
    491			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    492			0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
    493			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    494			0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
    495			0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
    496		},
    497		{	/*  Init_SR80_SR93 */
    498			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    499			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    500			0x00, 0x00, 0x00, 0x00,
    501		},
    502		{	/*  Init_SRA0_SRAF */
    503			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    504			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    505		},
    506		{	/*  Init_GR00_GR08 */
    507			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    508			0xFF,
    509		},
    510		{	/*  Init_AR00_AR14 */
    511			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    512			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    513			0x41, 0x00, 0x0F, 0x00, 0x00,
    514		},
    515		{	/*  Init_CR00_CR18 */
    516			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    517			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    518			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    519			0xFF,
    520		},
    521		{	/*  Init_CR30_CR4D */
    522			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    523			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    524			0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
    525			0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
    526		},
    527		{	/*  Init_CR90_CRA7 */
    528			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    529			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    530			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    531		},
    532	},
    533	{	/*  1024 x 768  16Bpp  60Hz */
    534		1024, 768, 16, 60,
    535		/*  Init_MISC */
    536		0xEB,
    537		{	/*  Init_SR0_SR4 */
    538			0x03, 0x01, 0x0F, 0x03, 0x0E,
    539		},
    540		{	/*  Init_SR10_SR24 */
    541			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
    542			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    543			0xC4, 0x30, 0x02, 0x01, 0x01,
    544		},
    545		{	/*  Init_SR30_SR75 */
    546			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
    547			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
    548			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    549			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
    550			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    551			0x0F, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
    552			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    553			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
    554			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
    555		},
    556		{	/*  Init_SR80_SR93 */
    557			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    558			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    559			0x00, 0x00, 0x00, 0x00,
    560		},
    561		{	/*  Init_SRA0_SRAF */
    562			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    563			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    564		},
    565		{	/*  Init_GR00_GR08 */
    566			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    567			0xFF,
    568		},
    569		{	/*  Init_AR00_AR14 */
    570			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    571			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    572			0x41, 0x00, 0x0F, 0x00, 0x00,
    573		},
    574		{	/*  Init_CR00_CR18 */
    575			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    576			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    577			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    578			0xFF,
    579		},
    580		{	/*  Init_CR30_CR4D */
    581			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    582			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    583			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
    584			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
    585		},
    586		{	/*  Init_CR90_CRA7 */
    587			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    588			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    589			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    590		},
    591	},
    592	{	/*  mode#5: 1024 x 768  24Bpp  60Hz */
    593		1024, 768, 24, 60,
    594		/*  Init_MISC */
    595		0xEB,
    596		{	/*  Init_SR0_SR4 */
    597			0x03, 0x01, 0x0F, 0x03, 0x0E,
    598		},
    599		{	/*  Init_SR10_SR24 */
    600			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
    601			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    602			0xC4, 0x30, 0x02, 0x01, 0x01,
    603		},
    604		{	/*  Init_SR30_SR75 */
    605			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
    606			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
    607			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    608			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
    609			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    610			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
    611			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    612			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
    613			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
    614		},
    615		{	/*  Init_SR80_SR93 */
    616			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    617			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    618			0x00, 0x00, 0x00, 0x00,
    619		},
    620		{	/*  Init_SRA0_SRAF */
    621			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    622			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    623		},
    624		{	/*  Init_GR00_GR08 */
    625			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    626			0xFF,
    627		},
    628		{	/*  Init_AR00_AR14 */
    629			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    630			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    631			0x41, 0x00, 0x0F, 0x00, 0x00,
    632		},
    633		{	/*  Init_CR00_CR18 */
    634			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    635			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    636			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    637			0xFF,
    638		},
    639		{	/*  Init_CR30_CR4D */
    640			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    641			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    642			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
    643			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
    644		},
    645		{	/*  Init_CR90_CRA7 */
    646			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    647			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    648			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    649		},
    650	},
    651	{	/*  mode#4: 1024 x 768  32Bpp  60Hz */
    652		1024, 768, 32, 60,
    653		/*  Init_MISC */
    654		0xEB,
    655		{	/*  Init_SR0_SR4 */
    656			0x03, 0x01, 0x0F, 0x03, 0x0E,
    657		},
    658		{	/*  Init_SR10_SR24 */
    659			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
    660			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    661			0xC4, 0x32, 0x02, 0x01, 0x01,
    662		},
    663		{	/*  Init_SR30_SR75 */
    664			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
    665			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
    666			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    667			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
    668			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    669			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
    670			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    671			0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
    672			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
    673		},
    674		{	/*  Init_SR80_SR93 */
    675			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    676			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    677			0x00, 0x00, 0x00, 0x00,
    678		},
    679		{	/*  Init_SRA0_SRAF */
    680			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    681			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    682		},
    683		{	/*  Init_GR00_GR08 */
    684			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    685			0xFF,
    686		},
    687		{	/*  Init_AR00_AR14 */
    688			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    689			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    690			0x41, 0x00, 0x0F, 0x00, 0x00,
    691		},
    692		{	/*  Init_CR00_CR18 */
    693			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    694			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    695			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    696			0xFF,
    697		},
    698		{	/*  Init_CR30_CR4D */
    699			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    700			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    701			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
    702			0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
    703		},
    704		{	/*  Init_CR90_CRA7 */
    705			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    706			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    707			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    708		},
    709	},
    710	{	/*  mode#6: 320 x 240  16Bpp  60Hz */
    711		320, 240, 16, 60,
    712		/*  Init_MISC */
    713		0xEB,
    714		{	/*  Init_SR0_SR4 */
    715			0x03, 0x01, 0x0F, 0x03, 0x0E,
    716		},
    717		{	/*  Init_SR10_SR24 */
    718			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
    719			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    720			0xC4, 0x32, 0x02, 0x01, 0x01,
    721		},
    722		{	/*  Init_SR30_SR75 */
    723			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
    724			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
    725			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    726			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
    727			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    728			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
    729			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    730			0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
    731			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
    732		},
    733		{	/*  Init_SR80_SR93 */
    734			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    735			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    736			0x00, 0x00, 0x00, 0x00,
    737		},
    738		{	/*  Init_SRA0_SRAF */
    739			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    740			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    741		},
    742		{	/*  Init_GR00_GR08 */
    743			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    744			0xFF,
    745		},
    746		{	/*  Init_AR00_AR14 */
    747			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    748			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    749			0x41, 0x00, 0x0F, 0x00, 0x00,
    750		},
    751		{	/*  Init_CR00_CR18 */
    752			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    753			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    754			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    755			0xFF,
    756		},
    757		{	/*  Init_CR30_CR4D */
    758			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    759			0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    760			0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
    761			0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
    762		},
    763		{	/*  Init_CR90_CRA7 */
    764			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    765			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    766			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    767		},
    768	},
    769
    770	{	/*  mode#8: 320 x 240  32Bpp  60Hz */
    771		320, 240, 32, 60,
    772		/*  Init_MISC */
    773		0xEB,
    774		{	/*  Init_SR0_SR4 */
    775			0x03, 0x01, 0x0F, 0x03, 0x0E,
    776		},
    777		{	/*  Init_SR10_SR24 */
    778			0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
    779			0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    780			0xC4, 0x32, 0x02, 0x01, 0x01,
    781		},
    782		{	/*  Init_SR30_SR75 */
    783			0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
    784			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
    785			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
    786			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
    787			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
    788			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
    789			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
    790			0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
    791			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
    792		},
    793		{	/*  Init_SR80_SR93 */
    794			0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
    795			0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
    796			0x00, 0x00, 0x00, 0x00,
    797		},
    798		{	/*  Init_SRA0_SRAF */
    799			0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
    800			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
    801		},
    802		{	/*  Init_GR00_GR08 */
    803			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
    804			0xFF,
    805		},
    806		{	/*  Init_AR00_AR14 */
    807			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    808			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
    809			0x41, 0x00, 0x0F, 0x00, 0x00,
    810		},
    811		{	/*  Init_CR00_CR18 */
    812			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
    813			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    814			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
    815			0xFF,
    816		},
    817		{	/*  Init_CR30_CR4D */
    818			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
    819			0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
    820			0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
    821			0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
    822		},
    823		{	/*  Init_CR90_CRA7 */
    824			0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
    825			0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
    826			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
    827		},
    828	},
    829};
    830
    831static struct screen_info smtc_scr_info;
    832
    833static char *mode_option;
    834
    835/* process command line options, get vga parameter */
    836static void __init sm7xx_vga_setup(char *options)
    837{
    838	int i;
    839
    840	if (!options || !*options)
    841		return;
    842
    843	smtc_scr_info.lfb_width = 0;
    844	smtc_scr_info.lfb_height = 0;
    845	smtc_scr_info.lfb_depth = 0;
    846
    847	pr_debug("%s = %s\n", __func__, options);
    848
    849	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
    850		if (strstr(options, vesa_mode_table[i].index)) {
    851			smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
    852			smtc_scr_info.lfb_height =
    853						vesa_mode_table[i].lfb_height;
    854			smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
    855			return;
    856		}
    857	}
    858}
    859
    860static void sm712_setpalette(int regno, unsigned int red, unsigned int green,
    861			     unsigned int blue, struct fb_info *info)
    862{
    863	/* set bit 5:4 = 01 (write LCD RAM only) */
    864	smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
    865
    866	smtc_mmiowb(regno, dac_reg);
    867	smtc_mmiowb(red >> 10, dac_val);
    868	smtc_mmiowb(green >> 10, dac_val);
    869	smtc_mmiowb(blue >> 10, dac_val);
    870}
    871
    872/* chan_to_field
    873 *
    874 * convert a colour value into a field position
    875 *
    876 * from pxafb.c
    877 */
    878
    879static inline unsigned int chan_to_field(unsigned int chan,
    880					 struct fb_bitfield *bf)
    881{
    882	chan &= 0xffff;
    883	chan >>= 16 - bf->length;
    884	return chan << bf->offset;
    885}
    886
    887static int smtc_blank(int blank_mode, struct fb_info *info)
    888{
    889	struct smtcfb_info *sfb = info->par;
    890
    891	/* clear DPMS setting */
    892	switch (blank_mode) {
    893	case FB_BLANK_UNBLANK:
    894		/* Screen On: HSync: On, VSync : On */
    895
    896		switch (sfb->chip_id) {
    897		case 0x710:
    898		case 0x712:
    899			smtc_seqw(0x6a, 0x16);
    900			smtc_seqw(0x6b, 0x02);
    901			break;
    902		case 0x720:
    903			smtc_seqw(0x6a, 0x0d);
    904			smtc_seqw(0x6b, 0x02);
    905			break;
    906		}
    907
    908		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
    909		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
    910		smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
    911		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
    912		smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
    913		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
    914		break;
    915	case FB_BLANK_NORMAL:
    916		/* Screen Off: HSync: On, VSync : On   Soft blank */
    917		smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
    918		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
    919		smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
    920		smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
    921		smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
    922		smtc_seqw(0x6a, 0x16);
    923		smtc_seqw(0x6b, 0x02);
    924		break;
    925	case FB_BLANK_VSYNC_SUSPEND:
    926		/* Screen On: HSync: On, VSync : Off */
    927		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
    928		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
    929		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
    930		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
    931		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
    932		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
    933		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
    934		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
    935		smtc_seqw(0x6a, 0x0c);
    936		smtc_seqw(0x6b, 0x02);
    937		break;
    938	case FB_BLANK_HSYNC_SUSPEND:
    939		/* Screen On: HSync: Off, VSync : On */
    940		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
    941		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
    942		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
    943		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
    944		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
    945		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
    946		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
    947		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
    948		smtc_seqw(0x6a, 0x0c);
    949		smtc_seqw(0x6b, 0x02);
    950		break;
    951	case FB_BLANK_POWERDOWN:
    952		/* Screen On: HSync: Off, VSync : Off */
    953		smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
    954		smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
    955		smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
    956		smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
    957		smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
    958		smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
    959		smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
    960		smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
    961		smtc_seqw(0x6a, 0x0c);
    962		smtc_seqw(0x6b, 0x02);
    963		break;
    964	default:
    965		return -EINVAL;
    966	}
    967
    968	return 0;
    969}
    970
    971static int smtc_setcolreg(unsigned int regno, unsigned int red,
    972			  unsigned int green, unsigned int blue,
    973			  unsigned int trans, struct fb_info *info)
    974{
    975	struct smtcfb_info *sfb;
    976	u32 val;
    977
    978	sfb = info->par;
    979
    980	if (regno > 255)
    981		return 1;
    982
    983	switch (sfb->fb->fix.visual) {
    984	case FB_VISUAL_DIRECTCOLOR:
    985	case FB_VISUAL_TRUECOLOR:
    986		/*
    987		 * 16/32 bit true-colour, use pseudo-palette for 16 base color
    988		 */
    989		if (regno >= 16)
    990			break;
    991		if (sfb->fb->var.bits_per_pixel == 16) {
    992			u32 *pal = sfb->fb->pseudo_palette;
    993
    994			val = chan_to_field(red, &sfb->fb->var.red);
    995			val |= chan_to_field(green, &sfb->fb->var.green);
    996			val |= chan_to_field(blue, &sfb->fb->var.blue);
    997			pal[regno] = pal_rgb(red, green, blue, val);
    998		} else {
    999			u32 *pal = sfb->fb->pseudo_palette;
   1000
   1001			val = chan_to_field(red, &sfb->fb->var.red);
   1002			val |= chan_to_field(green, &sfb->fb->var.green);
   1003			val |= chan_to_field(blue, &sfb->fb->var.blue);
   1004			pal[regno] = big_swap(val);
   1005		}
   1006		break;
   1007
   1008	case FB_VISUAL_PSEUDOCOLOR:
   1009		/* color depth 8 bit */
   1010		sm712_setpalette(regno, red, green, blue, info);
   1011		break;
   1012
   1013	default:
   1014		return 1;	/* unknown type */
   1015	}
   1016
   1017	return 0;
   1018}
   1019
   1020static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
   1021			   size_t count, loff_t *ppos)
   1022{
   1023	unsigned long p = *ppos;
   1024
   1025	u32 *buffer, *dst;
   1026	u32 __iomem *src;
   1027	int c, i, cnt = 0, err = 0;
   1028	unsigned long total_size;
   1029
   1030	if (!info || !info->screen_base)
   1031		return -ENODEV;
   1032
   1033	if (info->state != FBINFO_STATE_RUNNING)
   1034		return -EPERM;
   1035
   1036	total_size = info->screen_size;
   1037
   1038	if (total_size == 0)
   1039		total_size = info->fix.smem_len;
   1040
   1041	if (p >= total_size)
   1042		return 0;
   1043
   1044	if (count >= total_size)
   1045		count = total_size;
   1046
   1047	if (count + p > total_size)
   1048		count = total_size - p;
   1049
   1050	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
   1051	if (!buffer)
   1052		return -ENOMEM;
   1053
   1054	src = (u32 __iomem *)(info->screen_base + p);
   1055
   1056	if (info->fbops->fb_sync)
   1057		info->fbops->fb_sync(info);
   1058
   1059	while (count) {
   1060		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
   1061		dst = buffer;
   1062		for (i = (c + 3) >> 2; i--;) {
   1063			u32 val;
   1064
   1065			val = fb_readl(src);
   1066			*dst = big_swap(val);
   1067			src++;
   1068			dst++;
   1069		}
   1070
   1071		if (copy_to_user(buf, buffer, c)) {
   1072			err = -EFAULT;
   1073			break;
   1074		}
   1075		*ppos += c;
   1076		buf += c;
   1077		cnt += c;
   1078		count -= c;
   1079	}
   1080
   1081	kfree(buffer);
   1082
   1083	return (err) ? err : cnt;
   1084}
   1085
   1086static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
   1087			    size_t count, loff_t *ppos)
   1088{
   1089	unsigned long p = *ppos;
   1090
   1091	u32 *buffer, *src;
   1092	u32 __iomem *dst;
   1093	int c, i, cnt = 0, err = 0;
   1094	unsigned long total_size;
   1095
   1096	if (!info || !info->screen_base)
   1097		return -ENODEV;
   1098
   1099	if (info->state != FBINFO_STATE_RUNNING)
   1100		return -EPERM;
   1101
   1102	total_size = info->screen_size;
   1103
   1104	if (total_size == 0)
   1105		total_size = info->fix.smem_len;
   1106
   1107	if (p > total_size)
   1108		return -EFBIG;
   1109
   1110	if (count > total_size) {
   1111		err = -EFBIG;
   1112		count = total_size;
   1113	}
   1114
   1115	if (count + p > total_size) {
   1116		if (!err)
   1117			err = -ENOSPC;
   1118
   1119		count = total_size - p;
   1120	}
   1121
   1122	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
   1123	if (!buffer)
   1124		return -ENOMEM;
   1125
   1126	dst = (u32 __iomem *)(info->screen_base + p);
   1127
   1128	if (info->fbops->fb_sync)
   1129		info->fbops->fb_sync(info);
   1130
   1131	while (count) {
   1132		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
   1133		src = buffer;
   1134
   1135		if (copy_from_user(src, buf, c)) {
   1136			err = -EFAULT;
   1137			break;
   1138		}
   1139
   1140		for (i = (c + 3) >> 2; i--;) {
   1141			fb_writel(big_swap(*src), dst);
   1142			dst++;
   1143			src++;
   1144		}
   1145
   1146		*ppos += c;
   1147		buf += c;
   1148		cnt += c;
   1149		count -= c;
   1150	}
   1151
   1152	kfree(buffer);
   1153
   1154	return (cnt) ? cnt : err;
   1155}
   1156
   1157static void sm7xx_set_timing(struct smtcfb_info *sfb)
   1158{
   1159	int i = 0, j = 0;
   1160	u32 m_nscreenstride;
   1161
   1162	dev_dbg(&sfb->pdev->dev,
   1163		"sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
   1164		sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
   1165
   1166	for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
   1167		if (vgamode[j].mmsizex != sfb->width ||
   1168		    vgamode[j].mmsizey != sfb->height ||
   1169		    vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
   1170		    vgamode[j].hz != sfb->hz)
   1171			continue;
   1172
   1173		dev_dbg(&sfb->pdev->dev,
   1174			"vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
   1175			vgamode[j].mmsizex, vgamode[j].mmsizey,
   1176			vgamode[j].bpp, vgamode[j].hz);
   1177
   1178		dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
   1179
   1180		smtc_mmiowb(0x0, 0x3c6);
   1181
   1182		smtc_seqw(0, 0x1);
   1183
   1184		smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
   1185
   1186		/* init SEQ register SR00 - SR04 */
   1187		for (i = 0; i < SIZE_SR00_SR04; i++)
   1188			smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
   1189
   1190		/* init SEQ register SR10 - SR24 */
   1191		for (i = 0; i < SIZE_SR10_SR24; i++)
   1192			smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
   1193
   1194		/* init SEQ register SR30 - SR75 */
   1195		for (i = 0; i < SIZE_SR30_SR75; i++)
   1196			if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
   1197			    (i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
   1198			    (i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
   1199			    (i + 0x30) != 0x74 && (i + 0x30) != 0x75)
   1200				smtc_seqw(i + 0x30,
   1201					  vgamode[j].init_sr30_sr75[i]);
   1202
   1203		/* init SEQ register SR80 - SR93 */
   1204		for (i = 0; i < SIZE_SR80_SR93; i++)
   1205			smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
   1206
   1207		/* init SEQ register SRA0 - SRAF */
   1208		for (i = 0; i < SIZE_SRA0_SRAF; i++)
   1209			smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
   1210
   1211		/* init Graphic register GR00 - GR08 */
   1212		for (i = 0; i < SIZE_GR00_GR08; i++)
   1213			smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
   1214
   1215		/* init Attribute register AR00 - AR14 */
   1216		for (i = 0; i < SIZE_AR00_AR14; i++)
   1217			smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
   1218
   1219		/* init CRTC register CR00 - CR18 */
   1220		for (i = 0; i < SIZE_CR00_CR18; i++)
   1221			smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
   1222
   1223		/* init CRTC register CR30 - CR4D */
   1224		for (i = 0; i < SIZE_CR30_CR4D; i++) {
   1225			if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
   1226				/* side-effect, don't write to CR3B-CR3F */
   1227				continue;
   1228			smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
   1229		}
   1230
   1231		/* init CRTC register CR90 - CRA7 */
   1232		for (i = 0; i < SIZE_CR90_CRA7; i++)
   1233			smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
   1234	}
   1235	smtc_mmiowb(0x67, 0x3c2);
   1236
   1237	/* set VPR registers */
   1238	writel(0x0, sfb->vp_regs + 0x0C);
   1239	writel(0x0, sfb->vp_regs + 0x40);
   1240
   1241	/* set data width */
   1242	m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
   1243	switch (sfb->fb->var.bits_per_pixel) {
   1244	case 8:
   1245		writel(0x0, sfb->vp_regs + 0x0);
   1246		break;
   1247	case 16:
   1248		writel(0x00020000, sfb->vp_regs + 0x0);
   1249		break;
   1250	case 24:
   1251		writel(0x00040000, sfb->vp_regs + 0x0);
   1252		break;
   1253	case 32:
   1254		writel(0x00030000, sfb->vp_regs + 0x0);
   1255		break;
   1256	}
   1257	writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
   1258	       sfb->vp_regs + 0x10);
   1259}
   1260
   1261static void smtc_set_timing(struct smtcfb_info *sfb)
   1262{
   1263	switch (sfb->chip_id) {
   1264	case 0x710:
   1265	case 0x712:
   1266	case 0x720:
   1267		sm7xx_set_timing(sfb);
   1268		break;
   1269	}
   1270}
   1271
   1272static void smtcfb_setmode(struct smtcfb_info *sfb)
   1273{
   1274	switch (sfb->fb->var.bits_per_pixel) {
   1275	case 32:
   1276		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
   1277		sfb->fb->fix.line_length  = sfb->fb->var.xres * 4;
   1278		sfb->fb->var.red.length   = 8;
   1279		sfb->fb->var.green.length = 8;
   1280		sfb->fb->var.blue.length  = 8;
   1281		sfb->fb->var.red.offset   = 16;
   1282		sfb->fb->var.green.offset = 8;
   1283		sfb->fb->var.blue.offset  = 0;
   1284		break;
   1285	case 24:
   1286		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
   1287		sfb->fb->fix.line_length  = sfb->fb->var.xres * 3;
   1288		sfb->fb->var.red.length   = 8;
   1289		sfb->fb->var.green.length = 8;
   1290		sfb->fb->var.blue.length  = 8;
   1291		sfb->fb->var.red.offset   = 16;
   1292		sfb->fb->var.green.offset = 8;
   1293		sfb->fb->var.blue.offset  = 0;
   1294		break;
   1295	case 8:
   1296		sfb->fb->fix.visual       = FB_VISUAL_PSEUDOCOLOR;
   1297		sfb->fb->fix.line_length  = sfb->fb->var.xres;
   1298		sfb->fb->var.red.length   = 3;
   1299		sfb->fb->var.green.length = 3;
   1300		sfb->fb->var.blue.length  = 2;
   1301		sfb->fb->var.red.offset   = 5;
   1302		sfb->fb->var.green.offset = 2;
   1303		sfb->fb->var.blue.offset  = 0;
   1304		break;
   1305	case 16:
   1306	default:
   1307		sfb->fb->fix.visual       = FB_VISUAL_TRUECOLOR;
   1308		sfb->fb->fix.line_length  = sfb->fb->var.xres * 2;
   1309		sfb->fb->var.red.length   = 5;
   1310		sfb->fb->var.green.length = 6;
   1311		sfb->fb->var.blue.length  = 5;
   1312		sfb->fb->var.red.offset   = 11;
   1313		sfb->fb->var.green.offset = 5;
   1314		sfb->fb->var.blue.offset  = 0;
   1315		break;
   1316	}
   1317
   1318	sfb->width  = sfb->fb->var.xres;
   1319	sfb->height = sfb->fb->var.yres;
   1320	sfb->hz = 60;
   1321	smtc_set_timing(sfb);
   1322}
   1323
   1324static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
   1325{
   1326	/* sanity checks */
   1327	if (var->xres_virtual < var->xres)
   1328		var->xres_virtual = var->xres;
   1329
   1330	if (var->yres_virtual < var->yres)
   1331		var->yres_virtual = var->yres;
   1332
   1333	/* set valid default bpp */
   1334	if ((var->bits_per_pixel != 8)  && (var->bits_per_pixel != 16) &&
   1335	    (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
   1336		var->bits_per_pixel = 16;
   1337
   1338	return 0;
   1339}
   1340
   1341static int smtc_set_par(struct fb_info *info)
   1342{
   1343	smtcfb_setmode(info->par);
   1344
   1345	return 0;
   1346}
   1347
   1348static const struct fb_ops smtcfb_ops = {
   1349	.owner        = THIS_MODULE,
   1350	.fb_check_var = smtc_check_var,
   1351	.fb_set_par   = smtc_set_par,
   1352	.fb_setcolreg = smtc_setcolreg,
   1353	.fb_blank     = smtc_blank,
   1354	.fb_fillrect  = cfb_fillrect,
   1355	.fb_imageblit = cfb_imageblit,
   1356	.fb_copyarea  = cfb_copyarea,
   1357	.fb_read      = smtcfb_read,
   1358	.fb_write     = smtcfb_write,
   1359};
   1360
   1361/*
   1362 * Unmap in the memory mapped IO registers
   1363 */
   1364
   1365static void smtc_unmap_mmio(struct smtcfb_info *sfb)
   1366{
   1367	if (sfb && smtc_regbaseaddress)
   1368		smtc_regbaseaddress = NULL;
   1369}
   1370
   1371/*
   1372 * Map in the screen memory
   1373 */
   1374
   1375static int smtc_map_smem(struct smtcfb_info *sfb,
   1376			 struct pci_dev *pdev, u_long smem_len)
   1377{
   1378	sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
   1379
   1380	if (sfb->chip_id == 0x720)
   1381		/* on SM720, the framebuffer starts at the 1 MB offset */
   1382		sfb->fb->fix.smem_start += 0x00200000;
   1383
   1384	/* XXX: is it safe for SM720 on Big-Endian? */
   1385	if (sfb->fb->var.bits_per_pixel == 32)
   1386		sfb->fb->fix.smem_start += big_addr;
   1387
   1388	sfb->fb->fix.smem_len = smem_len;
   1389
   1390	sfb->fb->screen_base = sfb->lfb;
   1391
   1392	if (!sfb->fb->screen_base) {
   1393		dev_err(&pdev->dev,
   1394			"%s: unable to map screen memory\n", sfb->fb->fix.id);
   1395		return -ENOMEM;
   1396	}
   1397
   1398	return 0;
   1399}
   1400
   1401/*
   1402 * Unmap in the screen memory
   1403 *
   1404 */
   1405static void smtc_unmap_smem(struct smtcfb_info *sfb)
   1406{
   1407	if (sfb && sfb->fb->screen_base) {
   1408		if (sfb->chip_id == 0x720)
   1409			sfb->fb->screen_base -= 0x00200000;
   1410		iounmap(sfb->fb->screen_base);
   1411		sfb->fb->screen_base = NULL;
   1412	}
   1413}
   1414
   1415/*
   1416 * We need to wake up the device and make sure its in linear memory mode.
   1417 */
   1418static inline void sm7xx_init_hw(void)
   1419{
   1420	outb_p(0x18, 0x3c4);
   1421	outb_p(0x11, 0x3c5);
   1422}
   1423
   1424static u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
   1425{
   1426	u8 vram;
   1427
   1428	switch (sfb->chip_id) {
   1429	case 0x710:
   1430	case 0x712:
   1431		/*
   1432		 * Assume SM712 graphics chip has 4MB VRAM.
   1433		 *
   1434		 * FIXME: SM712 can have 2MB VRAM, which is used on earlier
   1435		 * laptops, such as IBM Thinkpad 240X. This driver would
   1436		 * probably crash on those machines. If anyone gets one of
   1437		 * those and is willing to help, run "git blame" and send me
   1438		 * an E-mail.
   1439		 */
   1440		return 0x00400000;
   1441	case 0x720:
   1442		outb_p(0x76, 0x3c4);
   1443		vram = inb_p(0x3c5) >> 6;
   1444
   1445		if (vram == 0x00)
   1446			return 0x00800000;  /* 8 MB */
   1447		else if (vram == 0x01)
   1448			return 0x01000000;  /* 16 MB */
   1449		else if (vram == 0x02)
   1450			return 0x00400000;  /* illegal, fallback to 4 MB */
   1451		else if (vram == 0x03)
   1452			return 0x00400000;  /* 4 MB */
   1453	}
   1454	return 0;  /* unknown hardware */
   1455}
   1456
   1457static void sm7xx_resolution_probe(struct smtcfb_info *sfb)
   1458{
   1459	/* get mode parameter from smtc_scr_info */
   1460	if (smtc_scr_info.lfb_width != 0) {
   1461		sfb->fb->var.xres = smtc_scr_info.lfb_width;
   1462		sfb->fb->var.yres = smtc_scr_info.lfb_height;
   1463		sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
   1464		goto final;
   1465	}
   1466
   1467	/*
   1468	 * No parameter, default resolution is 1024x768-16.
   1469	 *
   1470	 * FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
   1471	 * panel, also see the comments about Thinkpad 240X above.
   1472	 */
   1473	sfb->fb->var.xres = SCREEN_X_RES;
   1474	sfb->fb->var.yres = SCREEN_Y_RES_PC;
   1475	sfb->fb->var.bits_per_pixel = SCREEN_BPP;
   1476
   1477#ifdef CONFIG_MIPS
   1478	/*
   1479	 * Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
   1480	 * target platform of this driver, but nearly all old x86 laptops have
   1481	 * 1024x768. Lighting 768 panels using 600's timings would partially
   1482	 * garble the display, so we don't want that. But it's not possible to
   1483	 * distinguish them reliably.
   1484	 *
   1485	 * So we change the default to 768, but keep 600 as-is on MIPS.
   1486	 */
   1487	sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
   1488#endif
   1489
   1490final:
   1491	big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
   1492}
   1493
   1494static int smtcfb_pci_probe(struct pci_dev *pdev,
   1495			    const struct pci_device_id *ent)
   1496{
   1497	struct smtcfb_info *sfb;
   1498	struct fb_info *info;
   1499	u_long smem_size;
   1500	int err;
   1501	unsigned long mmio_base;
   1502
   1503	dev_info(&pdev->dev, "Silicon Motion display driver.\n");
   1504
   1505	err = pci_enable_device(pdev);	/* enable SMTC chip */
   1506	if (err)
   1507		return err;
   1508
   1509	err = pci_request_region(pdev, 0, "sm7xxfb");
   1510	if (err < 0) {
   1511		dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
   1512		goto failed_regions;
   1513	}
   1514
   1515	sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
   1516
   1517	info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
   1518	if (!info) {
   1519		err = -ENOMEM;
   1520		goto failed_free;
   1521	}
   1522
   1523	sfb = info->par;
   1524	sfb->fb = info;
   1525	sfb->chip_id = ent->device;
   1526	sfb->pdev = pdev;
   1527	info->flags = FBINFO_FLAG_DEFAULT;
   1528	info->fbops = &smtcfb_ops;
   1529	info->fix = smtcfb_fix;
   1530	info->var = smtcfb_var;
   1531	info->pseudo_palette = sfb->colreg;
   1532	info->par = sfb;
   1533
   1534	pci_set_drvdata(pdev, sfb);
   1535
   1536	sm7xx_init_hw();
   1537
   1538	/* Map address and memory detection */
   1539	mmio_base = pci_resource_start(pdev, 0);
   1540	pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
   1541
   1542	smem_size = sm7xx_vram_probe(sfb);
   1543	dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
   1544					smem_size / 1048576);
   1545
   1546	switch (sfb->chip_id) {
   1547	case 0x710:
   1548	case 0x712:
   1549		sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
   1550		sfb->fb->fix.mmio_len = 0x00400000;
   1551		sfb->lfb = ioremap(mmio_base, mmio_addr);
   1552		if (!sfb->lfb) {
   1553			dev_err(&pdev->dev,
   1554				"%s: unable to map memory mapped IO!\n",
   1555				sfb->fb->fix.id);
   1556			err = -ENOMEM;
   1557			goto failed_fb;
   1558		}
   1559
   1560		sfb->mmio = (smtc_regbaseaddress =
   1561		    sfb->lfb + 0x00700000);
   1562		sfb->dp_regs = sfb->lfb + 0x00408000;
   1563		sfb->vp_regs = sfb->lfb + 0x0040c000;
   1564		if (sfb->fb->var.bits_per_pixel == 32) {
   1565			sfb->lfb += big_addr;
   1566			dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
   1567		}
   1568
   1569		/* set MCLK = 14.31818 * (0x16 / 0x2) */
   1570		smtc_seqw(0x6a, 0x16);
   1571		smtc_seqw(0x6b, 0x02);
   1572		smtc_seqw(0x62, 0x3e);
   1573		/* enable PCI burst */
   1574		smtc_seqw(0x17, 0x20);
   1575		/* enable word swap */
   1576		if (sfb->fb->var.bits_per_pixel == 32)
   1577			seqw17();
   1578		break;
   1579	case 0x720:
   1580		sfb->fb->fix.mmio_start = mmio_base;
   1581		sfb->fb->fix.mmio_len = 0x00200000;
   1582		sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
   1583		if (!sfb->dp_regs) {
   1584			dev_err(&pdev->dev,
   1585				"%s: unable to map memory mapped IO!\n",
   1586				sfb->fb->fix.id);
   1587			err = -ENOMEM;
   1588			goto failed_fb;
   1589		}
   1590
   1591		sfb->lfb = sfb->dp_regs + 0x00200000;
   1592		sfb->mmio = (smtc_regbaseaddress =
   1593		    sfb->dp_regs + 0x000c0000);
   1594		sfb->vp_regs = sfb->dp_regs + 0x800;
   1595
   1596		smtc_seqw(0x62, 0xff);
   1597		smtc_seqw(0x6a, 0x0d);
   1598		smtc_seqw(0x6b, 0x02);
   1599		break;
   1600	default:
   1601		dev_err(&pdev->dev,
   1602			"No valid Silicon Motion display chip was detected!\n");
   1603		err = -ENODEV;
   1604		goto failed_fb;
   1605	}
   1606
   1607	/* probe and decide resolution */
   1608	sm7xx_resolution_probe(sfb);
   1609
   1610	/* can support 32 bpp */
   1611	if (sfb->fb->var.bits_per_pixel == 15)
   1612		sfb->fb->var.bits_per_pixel = 16;
   1613
   1614	sfb->fb->var.xres_virtual = sfb->fb->var.xres;
   1615	sfb->fb->var.yres_virtual = sfb->fb->var.yres;
   1616	err = smtc_map_smem(sfb, pdev, smem_size);
   1617	if (err)
   1618		goto failed;
   1619
   1620	/*
   1621	 * The screen would be temporarily garbled when sm712fb takes over
   1622	 * vesafb or VGA text mode. Zero the framebuffer.
   1623	 */
   1624	memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
   1625
   1626	err = register_framebuffer(info);
   1627	if (err < 0)
   1628		goto failed;
   1629
   1630	dev_info(&pdev->dev,
   1631		 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
   1632		 sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
   1633		 sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
   1634
   1635	return 0;
   1636
   1637failed:
   1638	dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
   1639
   1640	smtc_unmap_smem(sfb);
   1641	smtc_unmap_mmio(sfb);
   1642failed_fb:
   1643	framebuffer_release(info);
   1644
   1645failed_free:
   1646	pci_release_region(pdev, 0);
   1647
   1648failed_regions:
   1649	pci_disable_device(pdev);
   1650
   1651	return err;
   1652}
   1653
   1654/*
   1655 * 0x710 (LynxEM)
   1656 * 0x712 (LynxEM+)
   1657 * 0x720 (Lynx3DM, Lynx3DM+)
   1658 */
   1659static const struct pci_device_id smtcfb_pci_table[] = {
   1660	{ PCI_DEVICE(0x126f, 0x710), },
   1661	{ PCI_DEVICE(0x126f, 0x712), },
   1662	{ PCI_DEVICE(0x126f, 0x720), },
   1663	{0,}
   1664};
   1665
   1666MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
   1667
   1668static void smtcfb_pci_remove(struct pci_dev *pdev)
   1669{
   1670	struct smtcfb_info *sfb;
   1671
   1672	sfb = pci_get_drvdata(pdev);
   1673	smtc_unmap_smem(sfb);
   1674	smtc_unmap_mmio(sfb);
   1675	unregister_framebuffer(sfb->fb);
   1676	framebuffer_release(sfb->fb);
   1677	pci_release_region(pdev, 0);
   1678	pci_disable_device(pdev);
   1679}
   1680
   1681static int __maybe_unused smtcfb_pci_suspend(struct device *device)
   1682{
   1683	struct smtcfb_info *sfb = dev_get_drvdata(device);
   1684
   1685
   1686	/* set the hw in sleep mode use external clock and self memory refresh
   1687	 * so that we can turn off internal PLLs later on
   1688	 */
   1689	smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
   1690	smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
   1691
   1692	console_lock();
   1693	fb_set_suspend(sfb->fb, 1);
   1694	console_unlock();
   1695
   1696	/* additionally turn off all function blocks including internal PLLs */
   1697	smtc_seqw(0x21, 0xff);
   1698
   1699	return 0;
   1700}
   1701
   1702static int __maybe_unused smtcfb_pci_resume(struct device *device)
   1703{
   1704	struct smtcfb_info *sfb = dev_get_drvdata(device);
   1705
   1706
   1707	/* reinit hardware */
   1708	sm7xx_init_hw();
   1709	switch (sfb->chip_id) {
   1710	case 0x710:
   1711	case 0x712:
   1712		/* set MCLK = 14.31818 *  (0x16 / 0x2) */
   1713		smtc_seqw(0x6a, 0x16);
   1714		smtc_seqw(0x6b, 0x02);
   1715		smtc_seqw(0x62, 0x3e);
   1716		/* enable PCI burst */
   1717		smtc_seqw(0x17, 0x20);
   1718		if (sfb->fb->var.bits_per_pixel == 32)
   1719			seqw17();
   1720		break;
   1721	case 0x720:
   1722		smtc_seqw(0x62, 0xff);
   1723		smtc_seqw(0x6a, 0x0d);
   1724		smtc_seqw(0x6b, 0x02);
   1725		break;
   1726	}
   1727
   1728	smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
   1729	smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
   1730
   1731	smtcfb_setmode(sfb);
   1732
   1733	console_lock();
   1734	fb_set_suspend(sfb->fb, 0);
   1735	console_unlock();
   1736
   1737	return 0;
   1738}
   1739
   1740static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
   1741
   1742static struct pci_driver smtcfb_driver = {
   1743	.name = "smtcfb",
   1744	.id_table = smtcfb_pci_table,
   1745	.probe = smtcfb_pci_probe,
   1746	.remove = smtcfb_pci_remove,
   1747	.driver.pm  = &sm7xx_pm_ops,
   1748};
   1749
   1750static int __init sm712fb_init(void)
   1751{
   1752	char *option = NULL;
   1753
   1754	if (fb_get_options("sm712fb", &option))
   1755		return -ENODEV;
   1756	if (option && *option)
   1757		mode_option = option;
   1758	sm7xx_vga_setup(mode_option);
   1759
   1760	return pci_register_driver(&smtcfb_driver);
   1761}
   1762
   1763module_init(sm712fb_init);
   1764
   1765static void __exit sm712fb_exit(void)
   1766{
   1767	pci_unregister_driver(&smtcfb_driver);
   1768}
   1769
   1770module_exit(sm712fb_exit);
   1771
   1772MODULE_AUTHOR("Siliconmotion ");
   1773MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
   1774MODULE_LICENSE("GPL");