/*
* Silicon Motion SM7XX frame buffer device
*
* Copyright (C) 2006 Silicon Motion Technology Corp.
* Authors: Ge Wang, gewang@siliconmotion.com
* Boyod boyod.yang@siliconmotion.com.cn
*
* Copyright (C) 2009 Lemote, Inc.
* Author: Wu Zhangjin, wuzhangjin@gmail.com
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
* Version 0.10.26192.21.01
* - Add PowerPC/Big endian support
* - Add 2D support for Lynx
* - Verified on2.6.19.2 Boyod.yang <boyod.yang@siliconmotion.com.cn>
*
* Version 0.09.2621.00.01
* - Only support Linux Kernel's version 2.6.21.
* Boyod.yang <boyod.yang@siliconmotion.com.cn>
*
* Version 0.09
* - Only support Linux Kernel's version 2.6.12.
* Boyod.yang <boyod.yang@siliconmotion.com.cn>
*/
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/console.h>
#include <linux/screen_info.h>
#ifdef CONFIG_PM
#include <linux/pm.h>
#endif
struct screen_info smtc_screen_info;
#include "smtcfb.h"
#ifdef DEBUG
#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
#else
#define smdbg(format, arg...)
#endif
/*
* Private structure
*/
struct smtcfb_info {
/*
* The following is a pointer to be passed into the
* functions below. The modules outside the main
* voyager.c driver have no knowledge as to what
* is within this structure.
*/
struct fb_info fb;
struct display_switch *dispsw;
struct pci_dev *dev;
signed int currcon;
struct {
u8 red, green, blue;
} palette[NR_RGB];
u_int palette_size;
};
struct par_info {
/*
* Hardware
*/
u16 chipID;
unsigned char __iomem *m_pMMIO;
char __iomem *m_pLFB;
char *m_pDPR;
char *m_pVPR;
char *m_pCPR;
u_int width;
u_int height;
u_int hz;
u_long BaseAddressInVRAM;
u8 chipRevID;
};
struct vesa_mode_table {
char mode_index[6];
u16 lfb_width;
u16 lfb_height;
u16 lfb_depth;
};
static struct vesa_mode_table vesa_mode[] = {
{"0x301", 640, 480, 8},
{"0x303", 800, 600, 8},
{"0x305", 1024, 768, 8},
{"0x307", 1280, 1024, 8},
{"0x311", 640, 480, 16},
{"0x314", 800, 600, 16},
{"0x317", 1024, 768, 16},
{"0x31A", 1280, 1024, 16},
{"0x312", 640, 480, 24},
{"0x315", 800, 600, 24},
{"0x318", 1024, 768, 24},
{"0x31B", 1280, 1024, 24},
};
char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */
char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */
static u32 colreg[17];
static struct par_info hw; /* hardware information */
u16 smtc_ChipIDs[] = {
0x710,
0x712,
0x720
};
#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
static void sm712_set_timing(struct smtcfb_info *sfb,
struct par_info *ppar_info)
{
int i = 0, j = 0;
u32 m_nScreenStride;
smdbg("\nppar_info->width = %d ppar_info->height = %d"
"sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n",
ppar_info->width, ppar_info->height,
sfb->fb.var.bits_per_pixel, ppar_info->hz);
for (j = 0; j < numVGAModes; j++) {
if (VGAMode[j].mmSizeX == ppar_info->width &&
VGAMode[j].mmSizeY == ppar_info->height &&
VGAMode[j].bpp == sfb->fb.var.bit