2015-01-19 15:11:00 +07:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Igalia, S.L.
|
|
|
|
* Author: Javier M. Mellid <jmunhoz@igalia.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.
|
|
|
|
*
|
|
|
|
* Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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/module.h>
|
|
|
|
#include <linux/console.h>
|
|
|
|
#include <linux/screen_info.h>
|
|
|
|
|
|
|
|
#include <linux/pm.h>
|
|
|
|
|
2015-08-07 20:01:13 +07:00
|
|
|
#include "sm712.h"
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
/*
|
2017-08-01 22:20:38 +07:00
|
|
|
* Private structure
|
|
|
|
*/
|
2015-01-19 15:11:00 +07:00
|
|
|
struct smtcfb_info {
|
|
|
|
struct pci_dev *pdev;
|
2015-04-23 20:38:16 +07:00
|
|
|
struct fb_info *fb;
|
2015-01-19 15:11:00 +07:00
|
|
|
u16 chip_id;
|
|
|
|
u8 chip_rev_id;
|
|
|
|
|
|
|
|
void __iomem *lfb; /* linear frame buffer */
|
|
|
|
void __iomem *dp_regs; /* drawing processor control regs */
|
|
|
|
void __iomem *vp_regs; /* video processor control regs */
|
|
|
|
void __iomem *cp_regs; /* capture processor control regs */
|
|
|
|
void __iomem *mmio; /* memory map IO port */
|
|
|
|
|
|
|
|
u_int width;
|
|
|
|
u_int height;
|
|
|
|
u_int hz;
|
|
|
|
|
|
|
|
u32 colreg[17];
|
|
|
|
};
|
|
|
|
|
2015-02-03 21:53:33 +07:00
|
|
|
void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2016-09-11 22:17:20 +07:00
|
|
|
static const struct fb_var_screeninfo smtcfb_var = {
|
2015-01-19 15:11:00 +07:00
|
|
|
.xres = 1024,
|
|
|
|
.yres = 600,
|
|
|
|
.xres_virtual = 1024,
|
|
|
|
.yres_virtual = 600,
|
|
|
|
.bits_per_pixel = 16,
|
|
|
|
.red = {16, 8, 0},
|
|
|
|
.green = {8, 8, 0},
|
|
|
|
.blue = {0, 8, 0},
|
|
|
|
.activate = FB_ACTIVATE_NOW,
|
|
|
|
.height = -1,
|
|
|
|
.width = -1,
|
|
|
|
.vmode = FB_VMODE_NONINTERLACED,
|
|
|
|
.nonstd = 0,
|
|
|
|
.accel_flags = FB_ACCELF_TEXT,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct fb_fix_screeninfo smtcfb_fix = {
|
|
|
|
.id = "smXXXfb",
|
|
|
|
.type = FB_TYPE_PACKED_PIXELS,
|
|
|
|
.visual = FB_VISUAL_TRUECOLOR,
|
|
|
|
.line_length = 800 * 3,
|
|
|
|
.accel = FB_ACCEL_SMI_LYNX,
|
|
|
|
.type_aux = 0,
|
|
|
|
.xpanstep = 0,
|
|
|
|
.ypanstep = 0,
|
|
|
|
.ywrapstep = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct vesa_mode {
|
|
|
|
char index[6];
|
|
|
|
u16 lfb_width;
|
|
|
|
u16 lfb_height;
|
|
|
|
u16 lfb_depth;
|
|
|
|
};
|
|
|
|
|
2015-06-17 18:24:40 +07:00
|
|
|
static const struct vesa_mode vesa_mode_table[] = {
|
2015-01-19 15:11:00 +07:00
|
|
|
{"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},
|
|
|
|
};
|
|
|
|
|
2015-06-17 18:24:46 +07:00
|
|
|
/**********************************************************************
|
|
|
|
SM712 Mode table.
|
|
|
|
**********************************************************************/
|
2015-06-17 18:24:48 +07:00
|
|
|
static const struct modeinit vgamode[] = {
|
2015-06-17 18:24:46 +07:00
|
|
|
{
|
2015-06-17 18:24:47 +07:00
|
|
|
/* mode#0: 640 x 480 16Bpp 60Hz */
|
|
|
|
640, 480, 16, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xE3,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x00, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
|
|
|
|
0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
|
|
|
|
0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
|
|
|
|
0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
|
|
|
|
0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
|
|
|
|
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
|
|
|
|
0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
|
|
|
|
0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
|
|
|
|
0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
{
|
2015-06-17 18:24:47 +07:00
|
|
|
/* mode#1: 640 x 480 24Bpp 60Hz */
|
|
|
|
640, 480, 24, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xE3,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x00, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
|
|
|
|
0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
|
|
|
|
0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
|
|
|
|
0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
|
|
|
|
0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
|
|
|
|
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
|
|
|
|
0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
|
|
|
|
0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
|
|
|
|
0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
{
|
2015-06-17 18:24:47 +07:00
|
|
|
/* mode#0: 640 x 480 32Bpp 60Hz */
|
|
|
|
640, 480, 32, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xE3,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x00, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
|
|
|
|
0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
|
|
|
|
0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
|
|
|
|
0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
|
|
|
|
0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
|
|
|
|
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
|
|
|
|
0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
|
|
|
|
0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
|
|
|
|
0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
|
2015-06-17 18:24:47 +07:00
|
|
|
{ /* mode#2: 800 x 600 16Bpp 60Hz */
|
|
|
|
800, 600, 16, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0x2B,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
|
|
|
|
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
|
|
|
|
0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
|
|
|
|
0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
|
|
|
|
0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
|
|
|
|
0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
|
|
|
|
0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
|
|
|
|
0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
|
|
|
|
0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* mode#3: 800 x 600 24Bpp 60Hz */
|
|
|
|
800, 600, 24, 60,
|
|
|
|
0x2B,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
|
|
|
|
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
|
|
|
|
0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
|
|
|
|
0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
|
|
|
|
0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
|
|
|
|
0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
|
|
|
|
0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
|
|
|
|
0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* mode#7: 800 x 600 32Bpp 60Hz */
|
|
|
|
800, 600, 32, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0x2B,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
|
|
|
|
0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
|
|
|
|
0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
|
|
|
|
0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
|
|
|
|
0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
|
|
|
|
0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
|
|
|
|
0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
|
|
|
|
0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
|
|
|
|
0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
/* We use 1024x768 table to light 1024x600 panel for lemote */
|
2015-06-17 18:24:47 +07:00
|
|
|
{ /* mode#4: 1024 x 600 16Bpp 60Hz */
|
|
|
|
1024, 600, 16, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x00, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20,
|
|
|
|
0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x00, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22,
|
|
|
|
0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22,
|
|
|
|
0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02,
|
|
|
|
0x04, 0x45, 0x3F, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00,
|
|
|
|
0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
2019-04-01 22:46:59 +07:00
|
|
|
{ /* 1024 x 768 16Bpp 60Hz */
|
|
|
|
1024, 768, 16, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
|
|
|
|
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x0F, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
|
|
|
|
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
|
|
|
|
0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:47 +07:00
|
|
|
{ /* mode#5: 1024 x 768 24Bpp 60Hz */
|
|
|
|
1024, 768, 24, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x30, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
|
|
|
|
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
|
|
|
|
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
|
|
|
|
0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* mode#4: 1024 x 768 32Bpp 60Hz */
|
|
|
|
1024, 768, 32, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x32, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
|
|
|
|
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
|
|
|
|
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
|
|
|
|
0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ /* mode#6: 320 x 240 16Bpp 60Hz */
|
|
|
|
320, 240, 16, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x32, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
|
|
|
|
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
|
|
|
|
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
|
|
|
|
0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
|
2015-06-17 18:24:47 +07:00
|
|
|
{ /* mode#8: 320 x 240 32Bpp 60Hz */
|
|
|
|
320, 240, 32, 60,
|
|
|
|
/* Init_MISC */
|
|
|
|
0xEB,
|
|
|
|
{ /* Init_SR0_SR4 */
|
|
|
|
0x03, 0x01, 0x0F, 0x03, 0x0E,
|
|
|
|
},
|
|
|
|
{ /* Init_SR10_SR24 */
|
|
|
|
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
|
|
|
|
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0xC4, 0x32, 0x02, 0x01, 0x01,
|
|
|
|
},
|
|
|
|
{ /* Init_SR30_SR75 */
|
|
|
|
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
|
|
|
|
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
|
|
|
|
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
|
|
|
|
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
|
|
|
|
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
|
|
|
|
0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
|
|
|
|
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
|
|
|
|
0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43,
|
|
|
|
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
|
|
|
|
},
|
|
|
|
{ /* Init_SR80_SR93 */
|
|
|
|
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
|
|
|
|
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
|
|
|
|
0x00, 0x00, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_SRA0_SRAF */
|
|
|
|
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
|
|
|
|
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
|
|
|
|
},
|
|
|
|
{ /* Init_GR00_GR08 */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_AR00_AR14 */
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
|
|
0x41, 0x00, 0x0F, 0x00, 0x00,
|
|
|
|
},
|
|
|
|
{ /* Init_CR00_CR18 */
|
|
|
|
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
|
|
|
|
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
|
|
|
|
0xFF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR30_CR4D */
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
|
|
|
|
0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
|
|
|
|
0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00,
|
|
|
|
0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF,
|
|
|
|
},
|
|
|
|
{ /* Init_CR90_CRA7 */
|
|
|
|
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
|
|
|
|
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
|
|
|
|
},
|
|
|
|
},
|
2015-06-17 18:24:46 +07:00
|
|
|
};
|
|
|
|
|
2015-02-03 15:44:28 +07:00
|
|
|
static struct screen_info smtc_scr_info;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-03-09 00:40:09 +07:00
|
|
|
static char *mode_option;
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
/* process command line options, get vga parameter */
|
2015-03-09 00:40:11 +07:00
|
|
|
static void __init sm7xx_vga_setup(char *options)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!options || !*options)
|
2015-03-09 00:40:11 +07:00
|
|
|
return;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
smtc_scr_info.lfb_width = 0;
|
|
|
|
smtc_scr_info.lfb_height = 0;
|
|
|
|
smtc_scr_info.lfb_depth = 0;
|
|
|
|
|
2017-08-01 22:20:38 +07:00
|
|
|
pr_debug("%s = %s\n", __func__, options);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
|
|
|
|
if (strstr(options, vesa_mode_table[i].index)) {
|
|
|
|
smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width;
|
|
|
|
smtc_scr_info.lfb_height =
|
|
|
|
vesa_mode_table[i].lfb_height;
|
|
|
|
smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth;
|
2015-03-09 00:40:11 +07:00
|
|
|
return;
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-01 22:20:38 +07:00
|
|
|
static void sm712_setpalette(int regno, unsigned int red, unsigned int green,
|
|
|
|
unsigned int blue, struct fb_info *info)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
/* set bit 5:4 = 01 (write LCD RAM only) */
|
|
|
|
smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10);
|
|
|
|
|
|
|
|
smtc_mmiowb(regno, dac_reg);
|
|
|
|
smtc_mmiowb(red >> 10, dac_val);
|
|
|
|
smtc_mmiowb(green >> 10, dac_val);
|
|
|
|
smtc_mmiowb(blue >> 10, dac_val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* chan_to_field
|
|
|
|
*
|
|
|
|
* convert a colour value into a field position
|
|
|
|
*
|
|
|
|
* from pxafb.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline unsigned int chan_to_field(unsigned int chan,
|
|
|
|
struct fb_bitfield *bf)
|
|
|
|
{
|
|
|
|
chan &= 0xffff;
|
|
|
|
chan >>= 16 - bf->length;
|
|
|
|
return chan << bf->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int smtc_blank(int blank_mode, struct fb_info *info)
|
|
|
|
{
|
2019-04-01 22:46:59 +07:00
|
|
|
struct smtcfb_info *sfb = info->par;
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
/* clear DPMS setting */
|
|
|
|
switch (blank_mode) {
|
|
|
|
case FB_BLANK_UNBLANK:
|
|
|
|
/* Screen On: HSync: On, VSync : On */
|
2019-04-01 22:46:59 +07:00
|
|
|
|
|
|
|
switch (sfb->chip_id) {
|
|
|
|
case 0x710:
|
|
|
|
case 0x712:
|
|
|
|
smtc_seqw(0x6a, 0x16);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
2019-04-02 22:14:10 +07:00
|
|
|
break;
|
2019-04-01 22:46:59 +07:00
|
|
|
case 0x720:
|
|
|
|
smtc_seqw(0x6a, 0x0d);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
|
|
|
smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
|
|
|
|
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
|
|
|
smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_NORMAL:
|
|
|
|
/* Screen Off: HSync: On, VSync : On Soft blank */
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
|
|
|
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
|
|
|
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x6a, 0x16);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
break;
|
|
|
|
case FB_BLANK_VSYNC_SUSPEND:
|
|
|
|
/* Screen On: HSync: On, VSync : Off */
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
|
|
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
|
|
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
|
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
|
|
|
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x6a, 0x0c);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_HSYNC_SUSPEND:
|
|
|
|
/* Screen On: HSync: Off, VSync : On */
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
|
|
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
|
|
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
|
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
|
|
|
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x6a, 0x0c);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case FB_BLANK_POWERDOWN:
|
|
|
|
/* Screen On: HSync: Off, VSync : Off */
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
|
|
|
|
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
|
|
|
|
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
|
|
|
|
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
|
2015-01-19 15:11:00 +07:00
|
|
|
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
|
|
|
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
|
2019-04-01 22:46:59 +07:00
|
|
|
smtc_seqw(0x6a, 0x0c);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-01 22:20:38 +07:00
|
|
|
static int smtc_setcolreg(unsigned int regno, unsigned int red,
|
|
|
|
unsigned int green, unsigned int blue,
|
|
|
|
unsigned int trans, struct fb_info *info)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
struct smtcfb_info *sfb;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
sfb = info->par;
|
|
|
|
|
|
|
|
if (regno > 255)
|
|
|
|
return 1;
|
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
switch (sfb->fb->fix.visual) {
|
2015-01-19 15:11:00 +07:00
|
|
|
case FB_VISUAL_DIRECTCOLOR:
|
|
|
|
case FB_VISUAL_TRUECOLOR:
|
|
|
|
/*
|
|
|
|
* 16/32 bit true-colour, use pseudo-palette for 16 base color
|
|
|
|
*/
|
2015-06-17 18:24:45 +07:00
|
|
|
if (regno >= 16)
|
|
|
|
break;
|
|
|
|
if (sfb->fb->var.bits_per_pixel == 16) {
|
|
|
|
u32 *pal = sfb->fb->pseudo_palette;
|
|
|
|
|
|
|
|
val = chan_to_field(red, &sfb->fb->var.red);
|
|
|
|
val |= chan_to_field(green, &sfb->fb->var.green);
|
|
|
|
val |= chan_to_field(blue, &sfb->fb->var.blue);
|
2015-07-15 15:29:45 +07:00
|
|
|
pal[regno] = pal_rgb(red, green, blue, val);
|
2015-06-17 18:24:45 +07:00
|
|
|
} else {
|
|
|
|
u32 *pal = sfb->fb->pseudo_palette;
|
2015-01-19 15:11:03 +07:00
|
|
|
|
2015-06-17 18:24:45 +07:00
|
|
|
val = chan_to_field(red, &sfb->fb->var.red);
|
|
|
|
val |= chan_to_field(green, &sfb->fb->var.green);
|
|
|
|
val |= chan_to_field(blue, &sfb->fb->var.blue);
|
2015-07-15 15:29:45 +07:00
|
|
|
pal[regno] = big_swap(val);
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FB_VISUAL_PSEUDOCOLOR:
|
|
|
|
/* color depth 8 bit */
|
|
|
|
sm712_setpalette(regno, red, green, blue, info);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 1; /* unknown type */
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-06-17 18:24:44 +07:00
|
|
|
static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
|
|
|
|
size_t count, loff_t *ppos)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
unsigned long p = *ppos;
|
|
|
|
|
|
|
|
u32 *buffer, *dst;
|
|
|
|
u32 __iomem *src;
|
|
|
|
int c, i, cnt = 0, err = 0;
|
|
|
|
unsigned long total_size;
|
|
|
|
|
|
|
|
if (!info || !info->screen_base)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
if (info->state != FBINFO_STATE_RUNNING)
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
total_size = info->screen_size;
|
|
|
|
|
|
|
|
if (total_size == 0)
|
|
|
|
total_size = info->fix.smem_len;
|
|
|
|
|
|
|
|
if (p >= total_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (count >= total_size)
|
|
|
|
count = total_size;
|
|
|
|
|
|
|
|
if (count + p > total_size)
|
|
|
|
count = total_size - p;
|
|
|
|
|
|
|
|
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-06-17 18:24:43 +07:00
|
|
|
src = (u32 __iomem *)(info->screen_base + p);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
if (info->fbops->fb_sync)
|
|
|
|
info->fbops->fb_sync(info);
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
|
|
|
|
dst = buffer;
|
|
|
|
for (i = c >> 2; i--;) {
|
|
|
|
*dst = fb_readl(src++);
|
2015-07-15 15:29:45 +07:00
|
|
|
*dst = big_swap(*dst);
|
2015-01-19 15:11:00 +07:00
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
if (c & 3) {
|
2015-01-19 15:11:04 +07:00
|
|
|
u8 *dst8 = (u8 *)dst;
|
|
|
|
u8 __iomem *src8 = (u8 __iomem *)src;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
for (i = c & 3; i--;) {
|
|
|
|
if (i & 1) {
|
|
|
|
*dst8++ = fb_readb(++src8);
|
|
|
|
} else {
|
|
|
|
*dst8++ = fb_readb(--src8);
|
|
|
|
src8 += 2;
|
|
|
|
}
|
|
|
|
}
|
2015-01-19 15:11:04 +07:00
|
|
|
src = (u32 __iomem *)src8;
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_to_user(buf, buffer, c)) {
|
|
|
|
err = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*ppos += c;
|
|
|
|
buf += c;
|
|
|
|
cnt += c;
|
|
|
|
count -= c;
|
|
|
|
}
|
|
|
|
|
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
return (err) ? err : cnt;
|
|
|
|
}
|
|
|
|
|
2015-06-17 18:24:44 +07:00
|
|
|
static ssize_t smtcfb_write(struct fb_info *info, const char __user *buf,
|
|
|
|
size_t count, loff_t *ppos)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
unsigned long p = *ppos;
|
|
|
|
|
|
|
|
u32 *buffer, *src;
|
|
|
|
u32 __iomem *dst;
|
|
|
|
int c, i, cnt = 0, err = 0;
|
|
|
|
unsigned long total_size;
|
|
|
|
|
|
|
|
if (!info || !info->screen_base)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
if (info->state != FBINFO_STATE_RUNNING)
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
total_size = info->screen_size;
|
|
|
|
|
|
|
|
if (total_size == 0)
|
|
|
|
total_size = info->fix.smem_len;
|
|
|
|
|
|
|
|
if (p > total_size)
|
|
|
|
return -EFBIG;
|
|
|
|
|
|
|
|
if (count > total_size) {
|
|
|
|
err = -EFBIG;
|
|
|
|
count = total_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count + p > total_size) {
|
|
|
|
if (!err)
|
|
|
|
err = -ENOSPC;
|
|
|
|
|
|
|
|
count = total_size - p;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
|
|
|
|
if (!buffer)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-06-17 18:24:43 +07:00
|
|
|
dst = (u32 __iomem *)(info->screen_base + p);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
if (info->fbops->fb_sync)
|
|
|
|
info->fbops->fb_sync(info);
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
|
|
|
|
src = buffer;
|
|
|
|
|
|
|
|
if (copy_from_user(src, buf, c)) {
|
|
|
|
err = -EFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = c >> 2; i--;) {
|
2015-07-15 15:29:45 +07:00
|
|
|
fb_writel(big_swap(*src), dst++);
|
2015-01-19 15:11:00 +07:00
|
|
|
src++;
|
|
|
|
}
|
|
|
|
if (c & 3) {
|
2015-01-19 15:11:04 +07:00
|
|
|
u8 *src8 = (u8 *)src;
|
|
|
|
u8 __iomem *dst8 = (u8 __iomem *)dst;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
for (i = c & 3; i--;) {
|
|
|
|
if (i & 1) {
|
|
|
|
fb_writeb(*src8++, ++dst8);
|
|
|
|
} else {
|
|
|
|
fb_writeb(*src8++, --dst8);
|
|
|
|
dst8 += 2;
|
|
|
|
}
|
|
|
|
}
|
2015-01-19 15:11:04 +07:00
|
|
|
dst = (u32 __iomem *)dst8;
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
*ppos += c;
|
|
|
|
buf += c;
|
|
|
|
cnt += c;
|
|
|
|
count -= c;
|
|
|
|
}
|
|
|
|
|
|
|
|
kfree(buffer);
|
|
|
|
|
|
|
|
return (cnt) ? cnt : err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sm7xx_set_timing(struct smtcfb_info *sfb)
|
|
|
|
{
|
|
|
|
int i = 0, j = 0;
|
2015-02-03 21:53:34 +07:00
|
|
|
u32 m_nscreenstride;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
dev_dbg(&sfb->pdev->dev,
|
2015-04-23 20:38:16 +07:00
|
|
|
"sfb->width=%d sfb->height=%d sfb->fb->var.bits_per_pixel=%d sfb->hz=%d\n",
|
|
|
|
sfb->width, sfb->height, sfb->fb->var.bits_per_pixel, sfb->hz);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-06-17 18:24:41 +07:00
|
|
|
for (j = 0; j < ARRAY_SIZE(vgamode); j++) {
|
2015-06-17 18:24:45 +07:00
|
|
|
if (vgamode[j].mmsizex != sfb->width ||
|
|
|
|
vgamode[j].mmsizey != sfb->height ||
|
|
|
|
vgamode[j].bpp != sfb->fb->var.bits_per_pixel ||
|
|
|
|
vgamode[j].hz != sfb->hz)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dev_dbg(&sfb->pdev->dev,
|
|
|
|
"vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n",
|
|
|
|
vgamode[j].mmsizex, vgamode[j].mmsizey,
|
|
|
|
vgamode[j].bpp, vgamode[j].hz);
|
|
|
|
|
|
|
|
dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j);
|
|
|
|
|
|
|
|
smtc_mmiowb(0x0, 0x3c6);
|
|
|
|
|
|
|
|
smtc_seqw(0, 0x1);
|
|
|
|
|
|
|
|
smtc_mmiowb(vgamode[j].init_misc, 0x3c2);
|
|
|
|
|
|
|
|
/* init SEQ register SR00 - SR04 */
|
|
|
|
for (i = 0; i < SIZE_SR00_SR04; i++)
|
|
|
|
smtc_seqw(i, vgamode[j].init_sr00_sr04[i]);
|
|
|
|
|
|
|
|
/* init SEQ register SR10 - SR24 */
|
|
|
|
for (i = 0; i < SIZE_SR10_SR24; i++)
|
|
|
|
smtc_seqw(i + 0x10, vgamode[j].init_sr10_sr24[i]);
|
|
|
|
|
|
|
|
/* init SEQ register SR30 - SR75 */
|
|
|
|
for (i = 0; i < SIZE_SR30_SR75; i++)
|
2019-04-01 22:46:58 +07:00
|
|
|
if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
|
2019-04-01 22:46:58 +07:00
|
|
|
(i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
|
|
|
|
(i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
|
|
|
|
(i + 0x30) != 0x74 && (i + 0x30) != 0x75)
|
2015-06-17 18:24:45 +07:00
|
|
|
smtc_seqw(i + 0x30,
|
|
|
|
vgamode[j].init_sr30_sr75[i]);
|
|
|
|
|
|
|
|
/* init SEQ register SR80 - SR93 */
|
|
|
|
for (i = 0; i < SIZE_SR80_SR93; i++)
|
|
|
|
smtc_seqw(i + 0x80, vgamode[j].init_sr80_sr93[i]);
|
|
|
|
|
|
|
|
/* init SEQ register SRA0 - SRAF */
|
|
|
|
for (i = 0; i < SIZE_SRA0_SRAF; i++)
|
|
|
|
smtc_seqw(i + 0xa0, vgamode[j].init_sra0_sraf[i]);
|
|
|
|
|
|
|
|
/* init Graphic register GR00 - GR08 */
|
|
|
|
for (i = 0; i < SIZE_GR00_GR08; i++)
|
|
|
|
smtc_grphw(i, vgamode[j].init_gr00_gr08[i]);
|
|
|
|
|
|
|
|
/* init Attribute register AR00 - AR14 */
|
|
|
|
for (i = 0; i < SIZE_AR00_AR14; i++)
|
|
|
|
smtc_attrw(i, vgamode[j].init_ar00_ar14[i]);
|
|
|
|
|
|
|
|
/* init CRTC register CR00 - CR18 */
|
|
|
|
for (i = 0; i < SIZE_CR00_CR18; i++)
|
|
|
|
smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
|
|
|
|
|
|
|
|
/* init CRTC register CR30 - CR4D */
|
2019-04-01 22:46:58 +07:00
|
|
|
for (i = 0; i < SIZE_CR30_CR4D; i++) {
|
|
|
|
if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
|
|
|
|
/* side-effect, don't write to CR3B-CR3F */
|
|
|
|
continue;
|
2015-06-17 18:24:45 +07:00
|
|
|
smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
|
2019-04-01 22:46:58 +07:00
|
|
|
}
|
2015-06-17 18:24:45 +07:00
|
|
|
|
|
|
|
/* init CRTC register CR90 - CRA7 */
|
|
|
|
for (i = 0; i < SIZE_CR90_CRA7; i++)
|
|
|
|
smtc_crtcw(i + 0x90, vgamode[j].init_cr90_cra7[i]);
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
smtc_mmiowb(0x67, 0x3c2);
|
|
|
|
|
|
|
|
/* set VPR registers */
|
|
|
|
writel(0x0, sfb->vp_regs + 0x0C);
|
|
|
|
writel(0x0, sfb->vp_regs + 0x40);
|
|
|
|
|
|
|
|
/* set data width */
|
2015-06-17 18:24:44 +07:00
|
|
|
m_nscreenstride = (sfb->width * sfb->fb->var.bits_per_pixel) / 64;
|
2015-04-23 20:38:16 +07:00
|
|
|
switch (sfb->fb->var.bits_per_pixel) {
|
2015-01-19 15:11:00 +07:00
|
|
|
case 8:
|
|
|
|
writel(0x0, sfb->vp_regs + 0x0);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
writel(0x00020000, sfb->vp_regs + 0x0);
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
writel(0x00040000, sfb->vp_regs + 0x0);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
writel(0x00030000, sfb->vp_regs + 0x0);
|
|
|
|
break;
|
|
|
|
}
|
2015-06-17 18:24:43 +07:00
|
|
|
writel((u32)(((m_nscreenstride + 2) << 16) | m_nscreenstride),
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->vp_regs + 0x10);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smtc_set_timing(struct smtcfb_info *sfb)
|
|
|
|
{
|
|
|
|
switch (sfb->chip_id) {
|
|
|
|
case 0x710:
|
|
|
|
case 0x712:
|
|
|
|
case 0x720:
|
|
|
|
sm7xx_set_timing(sfb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smtcfb_setmode(struct smtcfb_info *sfb)
|
|
|
|
{
|
2015-04-23 20:38:16 +07:00
|
|
|
switch (sfb->fb->var.bits_per_pixel) {
|
2015-01-19 15:11:00 +07:00
|
|
|
case 32:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
|
|
|
|
sfb->fb->fix.line_length = sfb->fb->var.xres * 4;
|
|
|
|
sfb->fb->var.red.length = 8;
|
|
|
|
sfb->fb->var.green.length = 8;
|
|
|
|
sfb->fb->var.blue.length = 8;
|
|
|
|
sfb->fb->var.red.offset = 16;
|
|
|
|
sfb->fb->var.green.offset = 8;
|
|
|
|
sfb->fb->var.blue.offset = 0;
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case 24:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
|
|
|
|
sfb->fb->fix.line_length = sfb->fb->var.xres * 3;
|
|
|
|
sfb->fb->var.red.length = 8;
|
|
|
|
sfb->fb->var.green.length = 8;
|
|
|
|
sfb->fb->var.blue.length = 8;
|
|
|
|
sfb->fb->var.red.offset = 16;
|
|
|
|
sfb->fb->var.green.offset = 8;
|
|
|
|
sfb->fb->var.blue.offset = 0;
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case 8:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
|
|
|
|
sfb->fb->fix.line_length = sfb->fb->var.xres;
|
|
|
|
sfb->fb->var.red.length = 3;
|
|
|
|
sfb->fb->var.green.length = 3;
|
|
|
|
sfb->fb->var.blue.length = 2;
|
|
|
|
sfb->fb->var.red.offset = 5;
|
|
|
|
sfb->fb->var.green.offset = 2;
|
|
|
|
sfb->fb->var.blue.offset = 0;
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
default:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.visual = FB_VISUAL_TRUECOLOR;
|
|
|
|
sfb->fb->fix.line_length = sfb->fb->var.xres * 2;
|
|
|
|
sfb->fb->var.red.length = 5;
|
|
|
|
sfb->fb->var.green.length = 6;
|
|
|
|
sfb->fb->var.blue.length = 5;
|
|
|
|
sfb->fb->var.red.offset = 11;
|
|
|
|
sfb->fb->var.green.offset = 5;
|
|
|
|
sfb->fb->var.blue.offset = 0;
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->width = sfb->fb->var.xres;
|
|
|
|
sfb->height = sfb->fb->var.yres;
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->hz = 60;
|
|
|
|
smtc_set_timing(sfb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
|
|
|
{
|
|
|
|
/* sanity checks */
|
|
|
|
if (var->xres_virtual < var->xres)
|
|
|
|
var->xres_virtual = var->xres;
|
|
|
|
|
|
|
|
if (var->yres_virtual < var->yres)
|
|
|
|
var->yres_virtual = var->yres;
|
|
|
|
|
|
|
|
/* set valid default bpp */
|
|
|
|
if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) &&
|
|
|
|
(var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
|
|
|
|
var->bits_per_pixel = 16;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int smtc_set_par(struct fb_info *info)
|
|
|
|
{
|
|
|
|
smtcfb_setmode(info->par);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct fb_ops smtcfb_ops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.fb_check_var = smtc_check_var,
|
|
|
|
.fb_set_par = smtc_set_par,
|
|
|
|
.fb_setcolreg = smtc_setcolreg,
|
|
|
|
.fb_blank = smtc_blank,
|
|
|
|
.fb_fillrect = cfb_fillrect,
|
|
|
|
.fb_imageblit = cfb_imageblit,
|
|
|
|
.fb_copyarea = cfb_copyarea,
|
|
|
|
.fb_read = smtcfb_read,
|
|
|
|
.fb_write = smtcfb_write,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unmap in the memory mapped IO registers
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void smtc_unmap_mmio(struct smtcfb_info *sfb)
|
|
|
|
{
|
2015-02-03 21:53:33 +07:00
|
|
|
if (sfb && smtc_regbaseaddress)
|
|
|
|
smtc_regbaseaddress = NULL;
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map in the screen memory
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int smtc_map_smem(struct smtcfb_info *sfb,
|
2015-01-19 15:11:06 +07:00
|
|
|
struct pci_dev *pdev, u_long smem_len)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
will crash the machine instantly, because the VRAM/framebuffer is not
mapped correctly.
On SM712, the framebuffer starts at the beginning of address space, but
SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
sm712fb fails to take this into account, as a result, writing to the
framebuffer will destroy all the registers and kill the system immediately.
Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
Fix this problem by removing the hardcoded VRAM size, adding a function to
query the amount of VRAM from register MCR76 on SM720, and adding proper
framebuffer offset.
Please note that the memory map may have additional problems on Big-Endian
system, which is not available for testing by myself. But I highly suspect
that the original code is also broken on Big-Endian machines for SM720, so
at least we are not making the problem worse. More, the driver also assumed
SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
crash on them. I've never seen one of those machines and cannot fix it, but
I have documented these problems in the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
if (sfb->chip_id == 0x720)
|
|
|
|
/* on SM720, the framebuffer starts at the 1 MB offset */
|
|
|
|
sfb->fb->fix.smem_start += 0x00200000;
|
|
|
|
|
|
|
|
/* XXX: is it safe for SM720 on Big-Endian? */
|
2015-04-23 20:38:16 +07:00
|
|
|
if (sfb->fb->var.bits_per_pixel == 32)
|
2015-07-15 15:29:45 +07:00
|
|
|
sfb->fb->fix.smem_start += big_addr;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.smem_len = smem_len;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->screen_base = sfb->lfb;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
if (!sfb->fb->screen_base) {
|
2015-01-19 15:11:00 +07:00
|
|
|
dev_err(&pdev->dev,
|
2015-04-23 20:38:16 +07:00
|
|
|
"%s: unable to map screen memory\n", sfb->fb->fix.id);
|
2015-01-19 15:11:00 +07:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unmap in the screen memory
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void smtc_unmap_smem(struct smtcfb_info *sfb)
|
|
|
|
{
|
2015-04-23 20:38:16 +07:00
|
|
|
if (sfb && sfb->fb->screen_base) {
|
|
|
|
iounmap(sfb->fb->screen_base);
|
|
|
|
sfb->fb->screen_base = NULL;
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to wake up the device and make sure its in linear memory mode.
|
|
|
|
*/
|
|
|
|
static inline void sm7xx_init_hw(void)
|
|
|
|
{
|
|
|
|
outb_p(0x18, 0x3c4);
|
|
|
|
outb_p(0x11, 0x3c5);
|
|
|
|
}
|
|
|
|
|
fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
will crash the machine instantly, because the VRAM/framebuffer is not
mapped correctly.
On SM712, the framebuffer starts at the beginning of address space, but
SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
sm712fb fails to take this into account, as a result, writing to the
framebuffer will destroy all the registers and kill the system immediately.
Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
Fix this problem by removing the hardcoded VRAM size, adding a function to
query the amount of VRAM from register MCR76 on SM720, and adding proper
framebuffer offset.
Please note that the memory map may have additional problems on Big-Endian
system, which is not available for testing by myself. But I highly suspect
that the original code is also broken on Big-Endian machines for SM720, so
at least we are not making the problem worse. More, the driver also assumed
SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
crash on them. I've never seen one of those machines and cannot fix it, but
I have documented these problems in the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
static u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
|
|
|
|
{
|
|
|
|
u8 vram;
|
|
|
|
|
|
|
|
switch (sfb->chip_id) {
|
|
|
|
case 0x710:
|
|
|
|
case 0x712:
|
|
|
|
/*
|
|
|
|
* Assume SM712 graphics chip has 4MB VRAM.
|
|
|
|
*
|
|
|
|
* FIXME: SM712 can have 2MB VRAM, which is used on earlier
|
|
|
|
* laptops, such as IBM Thinkpad 240X. This driver would
|
|
|
|
* probably crash on those machines. If anyone gets one of
|
|
|
|
* those and is willing to help, run "git blame" and send me
|
|
|
|
* an E-mail.
|
|
|
|
*/
|
|
|
|
return 0x00400000;
|
|
|
|
case 0x720:
|
|
|
|
outb_p(0x76, 0x3c4);
|
|
|
|
vram = inb_p(0x3c5) >> 6;
|
|
|
|
|
|
|
|
if (vram == 0x00)
|
|
|
|
return 0x00800000; /* 8 MB */
|
|
|
|
else if (vram == 0x01)
|
|
|
|
return 0x01000000; /* 16 MB */
|
|
|
|
else if (vram == 0x02)
|
|
|
|
return 0x00400000; /* illegal, fallback to 4 MB */
|
|
|
|
else if (vram == 0x03)
|
|
|
|
return 0x00400000; /* 4 MB */
|
|
|
|
}
|
|
|
|
return 0; /* unknown hardware */
|
|
|
|
}
|
|
|
|
|
fbdev: sm712fb: use 1024x768 by default on non-MIPS, fix garbled display
Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
target platform of this driver, but nearly all old x86 laptops have
1024x768. Lighting 768 panels using 600's timings would partially
garble the display. Since it's not possible to distinguish them reliably,
we change the default to 768, but keep 600 as-is on MIPS.
Further, earlier laptops, such as IBM Thinkpad 240X, has a 800x600 LCD
panel, this driver would probably garbled those display. As we don't
have one for testing, the original behavior of the driver is kept as-is,
but the problem has been documented is the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
static void sm7xx_resolution_probe(struct smtcfb_info *sfb)
|
|
|
|
{
|
|
|
|
/* get mode parameter from smtc_scr_info */
|
|
|
|
if (smtc_scr_info.lfb_width != 0) {
|
|
|
|
sfb->fb->var.xres = smtc_scr_info.lfb_width;
|
|
|
|
sfb->fb->var.yres = smtc_scr_info.lfb_height;
|
|
|
|
sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
|
|
|
|
goto final;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No parameter, default resolution is 1024x768-16.
|
|
|
|
*
|
|
|
|
* FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
|
|
|
|
* panel, also see the comments about Thinkpad 240X above.
|
|
|
|
*/
|
|
|
|
sfb->fb->var.xres = SCREEN_X_RES;
|
|
|
|
sfb->fb->var.yres = SCREEN_Y_RES_PC;
|
|
|
|
sfb->fb->var.bits_per_pixel = SCREEN_BPP;
|
|
|
|
|
|
|
|
#ifdef CONFIG_MIPS
|
|
|
|
/*
|
|
|
|
* Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
|
|
|
|
* target platform of this driver, but nearly all old x86 laptops have
|
|
|
|
* 1024x768. Lighting 768 panels using 600's timings would partially
|
|
|
|
* garble the display, so we don't want that. But it's not possible to
|
|
|
|
* distinguish them reliably.
|
|
|
|
*
|
|
|
|
* So we change the default to 768, but keep 600 as-is on MIPS.
|
|
|
|
*/
|
|
|
|
sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
final:
|
|
|
|
big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
|
|
|
|
}
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
static int smtcfb_pci_probe(struct pci_dev *pdev,
|
2015-01-19 15:11:06 +07:00
|
|
|
const struct pci_device_id *ent)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
struct smtcfb_info *sfb;
|
2015-04-23 20:38:16 +07:00
|
|
|
struct fb_info *info;
|
fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
will crash the machine instantly, because the VRAM/framebuffer is not
mapped correctly.
On SM712, the framebuffer starts at the beginning of address space, but
SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
sm712fb fails to take this into account, as a result, writing to the
framebuffer will destroy all the registers and kill the system immediately.
Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
Fix this problem by removing the hardcoded VRAM size, adding a function to
query the amount of VRAM from register MCR76 on SM720, and adding proper
framebuffer offset.
Please note that the memory map may have additional problems on Big-Endian
system, which is not available for testing by myself. But I highly suspect
that the original code is also broken on Big-Endian machines for SM720, so
at least we are not making the problem worse. More, the driver also assumed
SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
crash on them. I've never seen one of those machines and cannot fix it, but
I have documented these problems in the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
u_long smem_size;
|
2015-01-19 15:11:00 +07:00
|
|
|
int err;
|
|
|
|
unsigned long mmio_base;
|
|
|
|
|
2015-06-17 18:24:42 +07:00
|
|
|
dev_info(&pdev->dev, "Silicon Motion display driver.\n");
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
err = pci_enable_device(pdev); /* enable SMTC chip */
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2015-03-28 16:03:40 +07:00
|
|
|
err = pci_request_region(pdev, 0, "sm7xxfb");
|
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&pdev->dev, "cannot reserve framebuffer region\n");
|
|
|
|
goto failed_regions;
|
|
|
|
}
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
sprintf(smtcfb_fix.id, "sm%Xfb", ent->device);
|
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
info = framebuffer_alloc(sizeof(*sfb), &pdev->dev);
|
|
|
|
if (!info) {
|
|
|
|
dev_err(&pdev->dev, "framebuffer_alloc failed\n");
|
2015-01-19 15:11:00 +07:00
|
|
|
err = -ENOMEM;
|
|
|
|
goto failed_free;
|
|
|
|
}
|
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb = info->par;
|
|
|
|
sfb->fb = info;
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->chip_id = ent->device;
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->pdev = pdev;
|
|
|
|
info->flags = FBINFO_FLAG_DEFAULT;
|
|
|
|
info->fbops = &smtcfb_ops;
|
|
|
|
info->fix = smtcfb_fix;
|
|
|
|
info->var = smtcfb_var;
|
|
|
|
info->pseudo_palette = sfb->colreg;
|
|
|
|
info->par = sfb;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
pci_set_drvdata(pdev, sfb);
|
|
|
|
|
|
|
|
sm7xx_init_hw();
|
|
|
|
|
|
|
|
/* Map address and memory detection */
|
|
|
|
mmio_base = pci_resource_start(pdev, 0);
|
|
|
|
pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
|
|
|
|
|
fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
will crash the machine instantly, because the VRAM/framebuffer is not
mapped correctly.
On SM712, the framebuffer starts at the beginning of address space, but
SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
sm712fb fails to take this into account, as a result, writing to the
framebuffer will destroy all the registers and kill the system immediately.
Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
Fix this problem by removing the hardcoded VRAM size, adding a function to
query the amount of VRAM from register MCR76 on SM720, and adding proper
framebuffer offset.
Please note that the memory map may have additional problems on Big-Endian
system, which is not available for testing by myself. But I highly suspect
that the original code is also broken on Big-Endian machines for SM720, so
at least we are not making the problem worse. More, the driver also assumed
SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
crash on them. I've never seen one of those machines and cannot fix it, but
I have documented these problems in the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
smem_size = sm7xx_vram_probe(sfb);
|
|
|
|
dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
|
|
|
|
smem_size / 1048576);
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
switch (sfb->chip_id) {
|
|
|
|
case 0x710:
|
|
|
|
case 0x712:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
|
|
|
|
sfb->fb->fix.mmio_len = 0x00400000;
|
2015-07-15 15:29:45 +07:00
|
|
|
sfb->lfb = ioremap(mmio_base, mmio_addr);
|
2015-07-07 15:14:34 +07:00
|
|
|
if (!sfb->lfb) {
|
|
|
|
dev_err(&pdev->dev,
|
|
|
|
"%s: unable to map memory mapped IO!\n",
|
|
|
|
sfb->fb->fix.id);
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto failed_fb;
|
|
|
|
}
|
|
|
|
|
2015-02-03 21:53:33 +07:00
|
|
|
sfb->mmio = (smtc_regbaseaddress =
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->lfb + 0x00700000);
|
|
|
|
sfb->dp_regs = sfb->lfb + 0x00408000;
|
|
|
|
sfb->vp_regs = sfb->lfb + 0x0040c000;
|
2015-04-23 20:38:16 +07:00
|
|
|
if (sfb->fb->var.bits_per_pixel == 32) {
|
2015-07-15 15:29:45 +07:00
|
|
|
sfb->lfb += big_addr;
|
2015-06-17 18:24:42 +07:00
|
|
|
dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set MCLK = 14.31818 * (0x16 / 0x2) */
|
|
|
|
smtc_seqw(0x6a, 0x16);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
smtc_seqw(0x62, 0x3e);
|
|
|
|
/* enable PCI burst */
|
|
|
|
smtc_seqw(0x17, 0x20);
|
|
|
|
/* enable word swap */
|
2015-04-23 20:38:16 +07:00
|
|
|
if (sfb->fb->var.bits_per_pixel == 32)
|
2015-07-15 15:29:45 +07:00
|
|
|
seqw17();
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case 0x720:
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->fix.mmio_start = mmio_base;
|
|
|
|
sfb->fb->fix.mmio_len = 0x00200000;
|
fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
On a Thinkpad s30 (Pentium III / i440MX, Lynx3DM), running fbtest or X
will crash the machine instantly, because the VRAM/framebuffer is not
mapped correctly.
On SM712, the framebuffer starts at the beginning of address space, but
SM720's framebuffer starts at the 1 MiB offset from the beginning. However,
sm712fb fails to take this into account, as a result, writing to the
framebuffer will destroy all the registers and kill the system immediately.
Another problem is the driver assumes 8 MiB of VRAM for SM720, but some
SM720 system, such as this IBM Thinkpad, only has 4 MiB of VRAM.
Fix this problem by removing the hardcoded VRAM size, adding a function to
query the amount of VRAM from register MCR76 on SM720, and adding proper
framebuffer offset.
Please note that the memory map may have additional problems on Big-Endian
system, which is not available for testing by myself. But I highly suspect
that the original code is also broken on Big-Endian machines for SM720, so
at least we are not making the problem worse. More, the driver also assumed
SM710/SM712 has 4 MiB of VRAM, but it has a 2 MiB version as well, and used
in earlier laptops, such as IBM Thinkpad 240X, the driver would probably
crash on them. I've never seen one of those machines and cannot fix it, but
I have documented these problems in the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->lfb = sfb->dp_regs + 0x00200000;
|
2015-02-03 21:53:33 +07:00
|
|
|
sfb->mmio = (smtc_regbaseaddress =
|
2015-01-19 15:11:00 +07:00
|
|
|
sfb->dp_regs + 0x000c0000);
|
|
|
|
sfb->vp_regs = sfb->dp_regs + 0x800;
|
|
|
|
|
|
|
|
smtc_seqw(0x62, 0xff);
|
|
|
|
smtc_seqw(0x6a, 0x0d);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
dev_err(&pdev->dev,
|
2015-06-17 18:24:42 +07:00
|
|
|
"No valid Silicon Motion display chip was detected!\n");
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
goto failed_fb;
|
|
|
|
}
|
|
|
|
|
fbdev: sm712fb: use 1024x768 by default on non-MIPS, fix garbled display
Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
target platform of this driver, but nearly all old x86 laptops have
1024x768. Lighting 768 panels using 600's timings would partially
garble the display. Since it's not possible to distinguish them reliably,
we change the default to 768, but keep 600 as-is on MIPS.
Further, earlier laptops, such as IBM Thinkpad 240X, has a 800x600 LCD
panel, this driver would probably garbled those display. As we don't
have one for testing, the original behavior of the driver is kept as-is,
but the problem has been documented is the comments.
Signed-off-by: Yifeng Li <tomli@tomli.me>
Tested-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Teddy Wang <teddy.wang@siliconmotion.com>
Cc: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
2019-04-01 22:46:59 +07:00
|
|
|
/* probe and decide resolution */
|
|
|
|
sm7xx_resolution_probe(sfb);
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
/* can support 32 bpp */
|
2017-08-01 22:20:38 +07:00
|
|
|
if (sfb->fb->var.bits_per_pixel == 15)
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->var.bits_per_pixel = 16;
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->fb->var.xres_virtual = sfb->fb->var.xres;
|
|
|
|
sfb->fb->var.yres_virtual = sfb->fb->var.yres;
|
2015-01-19 15:11:00 +07:00
|
|
|
err = smtc_map_smem(sfb, pdev, smem_size);
|
|
|
|
if (err)
|
|
|
|
goto failed;
|
|
|
|
|
2019-04-01 22:46:59 +07:00
|
|
|
/*
|
|
|
|
* The screen would be temporarily garbled when sm712fb takes over
|
|
|
|
* vesafb or VGA text mode. Zero the framebuffer.
|
|
|
|
*/
|
|
|
|
memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
2015-04-23 20:38:16 +07:00
|
|
|
err = register_framebuffer(info);
|
2015-01-19 15:11:00 +07:00
|
|
|
if (err < 0)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
dev_info(&pdev->dev,
|
2015-06-17 18:24:42 +07:00
|
|
|
"Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.\n",
|
2015-04-23 20:38:16 +07:00
|
|
|
sfb->chip_id, sfb->chip_rev_id, sfb->fb->var.xres,
|
|
|
|
sfb->fb->var.yres, sfb->fb->var.bits_per_pixel);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
failed:
|
2015-06-17 18:24:42 +07:00
|
|
|
dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.\n");
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
smtc_unmap_smem(sfb);
|
|
|
|
smtc_unmap_mmio(sfb);
|
|
|
|
failed_fb:
|
2015-04-23 20:38:16 +07:00
|
|
|
framebuffer_release(info);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
failed_free:
|
2015-03-28 16:03:40 +07:00
|
|
|
pci_release_region(pdev, 0);
|
|
|
|
|
|
|
|
failed_regions:
|
2015-01-19 15:11:00 +07:00
|
|
|
pci_disable_device(pdev);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 0x710 (LynxEM)
|
|
|
|
* 0x712 (LynxEM+)
|
|
|
|
* 0x720 (Lynx3DM, Lynx3DM+)
|
|
|
|
*/
|
|
|
|
static const struct pci_device_id smtcfb_pci_table[] = {
|
|
|
|
{ PCI_DEVICE(0x126f, 0x710), },
|
|
|
|
{ PCI_DEVICE(0x126f, 0x712), },
|
|
|
|
{ PCI_DEVICE(0x126f, 0x720), },
|
|
|
|
{0,}
|
|
|
|
};
|
|
|
|
|
2015-03-24 17:52:24 +07:00
|
|
|
MODULE_DEVICE_TABLE(pci, smtcfb_pci_table);
|
|
|
|
|
2015-01-19 15:11:00 +07:00
|
|
|
static void smtcfb_pci_remove(struct pci_dev *pdev)
|
|
|
|
{
|
|
|
|
struct smtcfb_info *sfb;
|
|
|
|
|
|
|
|
sfb = pci_get_drvdata(pdev);
|
|
|
|
smtc_unmap_smem(sfb);
|
|
|
|
smtc_unmap_mmio(sfb);
|
2015-04-23 20:38:16 +07:00
|
|
|
unregister_framebuffer(sfb->fb);
|
|
|
|
framebuffer_release(sfb->fb);
|
2015-03-28 16:03:40 +07:00
|
|
|
pci_release_region(pdev, 0);
|
2015-03-28 16:03:41 +07:00
|
|
|
pci_disable_device(pdev);
|
2015-01-19 15:11:00 +07:00
|
|
|
}
|
|
|
|
|
2015-11-21 04:48:36 +07:00
|
|
|
static int __maybe_unused smtcfb_pci_suspend(struct device *device)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
struct pci_dev *pdev = to_pci_dev(device);
|
|
|
|
struct smtcfb_info *sfb;
|
|
|
|
|
|
|
|
sfb = pci_get_drvdata(pdev);
|
|
|
|
|
|
|
|
/* set the hw in sleep mode use external clock and self memory refresh
|
|
|
|
* so that we can turn off internal PLLs later on
|
|
|
|
*/
|
|
|
|
smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0));
|
|
|
|
smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7));
|
|
|
|
|
|
|
|
console_lock();
|
2015-04-23 20:38:16 +07:00
|
|
|
fb_set_suspend(sfb->fb, 1);
|
2015-01-19 15:11:00 +07:00
|
|
|
console_unlock();
|
|
|
|
|
|
|
|
/* additionally turn off all function blocks including internal PLLs */
|
|
|
|
smtc_seqw(0x21, 0xff);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-11-21 04:48:36 +07:00
|
|
|
static int __maybe_unused smtcfb_pci_resume(struct device *device)
|
2015-01-19 15:11:00 +07:00
|
|
|
{
|
|
|
|
struct pci_dev *pdev = to_pci_dev(device);
|
|
|
|
struct smtcfb_info *sfb;
|
|
|
|
|
|
|
|
sfb = pci_get_drvdata(pdev);
|
|
|
|
|
|
|
|
/* reinit hardware */
|
|
|
|
sm7xx_init_hw();
|
|
|
|
switch (sfb->chip_id) {
|
|
|
|
case 0x710:
|
|
|
|
case 0x712:
|
|
|
|
/* set MCLK = 14.31818 * (0x16 / 0x2) */
|
|
|
|
smtc_seqw(0x6a, 0x16);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
smtc_seqw(0x62, 0x3e);
|
|
|
|
/* enable PCI burst */
|
|
|
|
smtc_seqw(0x17, 0x20);
|
2015-04-23 20:38:16 +07:00
|
|
|
if (sfb->fb->var.bits_per_pixel == 32)
|
2015-07-15 15:29:45 +07:00
|
|
|
seqw17();
|
2015-01-19 15:11:00 +07:00
|
|
|
break;
|
|
|
|
case 0x720:
|
|
|
|
smtc_seqw(0x62, 0xff);
|
|
|
|
smtc_seqw(0x6a, 0x0d);
|
|
|
|
smtc_seqw(0x6b, 0x02);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0));
|
|
|
|
smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb));
|
|
|
|
|
|
|
|
smtcfb_setmode(sfb);
|
|
|
|
|
|
|
|
console_lock();
|
2015-04-23 20:38:16 +07:00
|
|
|
fb_set_suspend(sfb->fb, 0);
|
2015-01-19 15:11:00 +07:00
|
|
|
console_unlock();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume);
|
|
|
|
|
|
|
|
static struct pci_driver smtcfb_driver = {
|
|
|
|
.name = "smtcfb",
|
|
|
|
.id_table = smtcfb_pci_table,
|
|
|
|
.probe = smtcfb_pci_probe,
|
|
|
|
.remove = smtcfb_pci_remove,
|
2015-11-21 04:48:36 +07:00
|
|
|
.driver.pm = &sm7xx_pm_ops,
|
2015-01-19 15:11:00 +07:00
|
|
|
};
|
|
|
|
|
2015-03-09 00:40:09 +07:00
|
|
|
static int __init sm712fb_init(void)
|
|
|
|
{
|
|
|
|
char *option = NULL;
|
|
|
|
|
|
|
|
if (fb_get_options("sm712fb", &option))
|
|
|
|
return -ENODEV;
|
|
|
|
if (option && *option)
|
|
|
|
mode_option = option;
|
|
|
|
sm7xx_vga_setup(mode_option);
|
|
|
|
|
|
|
|
return pci_register_driver(&smtcfb_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(sm712fb_init);
|
|
|
|
|
|
|
|
static void __exit sm712fb_exit(void)
|
|
|
|
{
|
|
|
|
pci_unregister_driver(&smtcfb_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_exit(sm712fb_exit);
|
2015-01-19 15:11:00 +07:00
|
|
|
|
|
|
|
MODULE_AUTHOR("Siliconmotion ");
|
|
|
|
MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards");
|
|
|
|
MODULE_LICENSE("GPL");
|