📄 voyager.c
字号:
*
* So here's what we should do in our fbdev blank routine:
*
* VESA_NO_BLANKING (mode 0) Video on, front/back light on
* VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off
* VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off
* VESA_POWERDOWN (mode 3) Video off, front/back light off
*
* This will match the matrox implementation.
*/
/*
* smifb_blank():
* Blank the display by setting all palette values to zero. Note, the
* 12 and 16 bpp modes don't really use the palette, so this will not
* blank the display in all modes.
*/
static void smifb_blank(int blank, struct fb_info *info)
{
// struct smifb_info *sfb = (struct smifb_info *)info;
}
static int smifb_updatevar(int con, struct fb_info *info)
{
return 0;
}
#endif //CONFIG_FB_SM501_KERNEL_2_4_X
static struct fb_var_screeninfo smifb_var = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.bits_per_pixel = 16,
.red = { 11, 5, 0 },
.green = { 5, 6, 0 },
.blue = { 0, 5, 0 },
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo smifb_fix = {
.id = "vgxFB",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.line_length = 640*2,
.accel = FB_ACCEL_NONE,
};
#ifdef CONFIG_FB_SM501_KERNEL_2_6_X
static u32 colreg[17];
static int smi_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned trans, struct fb_info *info)
{
struct smifb_info *sfb = (struct smifb_info *)info;
u32 *pal;
switch (sfb->fb.var.bits_per_pixel)
{
case 8:
if (regno >= 256)
return 1;
if (hw.chipID==0x501)
sm501_setpalette(regno,red,green,blue);
break;
case 32:
pal = sfb->fb.pseudo_palette; // System has 16 default color
if (regno >= 16)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
pal[regno] =
(red << sfb->fb.var.red.offset) |
(green << sfb->fb.var.green.offset) |
(blue << sfb->fb.var.blue.offset);
break;
case 16:
default:
pal = sfb->fb.pseudo_palette; // System has 16 default color
if (regno >= 16)
return 1;
pal[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
break;
}
return 0;
}
void smifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
if (!area->width || !area->height)
return;
deCopy(0, 0, info->var.bits_per_pixel,
area->dx, area->dy, area->width, area->height,
0, 0, area->sx, area->sy, 0, 0xC);
}
void smifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
if (!rect->width || !rect->height)
return;
deFillRect(0, 0, rect->dx, rect->dy, rect->width, rect->height, rect->color);
}
void smifb_imageblit(struct fb_info *info, const struct fb_image *image)
{
if (SMI_de_busy)
deWaitForNotBusy();
cfb_imageblit(info, image);
}
static struct fb_ops smifb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = smi_setcolreg,
.fb_fillrect = smifb_fillrect,
.fb_copyarea = smifb_copyarea,
.fb_imageblit = smifb_imageblit,
.fb_cursor = soft_cursor,
};
#endif //CONFIG_FB_SM501_KERNEL_2_6_X
/*
* Alloc struct smifb_info and assign the default value
*/
static struct smifb_info * __devinit
smi_alloc_fb_info(struct pci_dev *dev, char *name)
{
struct smifb_info *sfb;
#if CONFIG_FB_SM501_KERNEL_2_4_X
sfb = kmalloc(sizeof(struct smifb_info) + sizeof(struct display) +
sizeof(u32) * 16, GFP_KERNEL);
if (!sfb)
return NULL;
memset(sfb, 0, sizeof(struct smifb_info) + sizeof(struct display));
#endif //CONFIG_FB_SM501_KERNEL_2_4_X
#if CONFIG_FB_SM501_KERNEL_2_6_X
sfb = kmalloc(sizeof(struct smifb_info), GFP_KERNEL);
if (!sfb)
return NULL;
memset(sfb, 0, sizeof(struct smifb_info));
#endif //CONFIG_FB_SM501_KERNEL_2_6_X
sfb->currcon = -1;
sfb->dev = dev;
/*** Init sfb->fb with default value ***/
sfb->fb.flags = FBINFO_FLAG_DEFAULT;
sfb->fb.fbops = &smifb_ops;
sfb->fb.var = smifb_var;
sfb->fb.fix = smifb_fix;
strcpy(sfb->fb.fix.id, name);
sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
sfb->fb.fix.type_aux = 0;
sfb->fb.fix.xpanstep = 0;
sfb->fb.fix.ypanstep = 0;
sfb->fb.fix.ywrapstep = 0;
sfb->fb.fix.accel = FB_ACCEL_NONE;
sfb->fb.var.nonstd = 0;
sfb->fb.var.activate = FB_ACTIVATE_NOW;
sfb->fb.var.height = -1;
sfb->fb.var.width = -1;
sfb->fb.var.accel_flags = FB_ACCELF_TEXT; /* text mode acceleration */
sfb->fb.var.vmode = FB_VMODE_NONINTERLACED;
#ifdef CONFIG_FB_SM501_KERNEL_2_4_X
strcpy(sfb->fb.modename, sfb->fb.fix.id);
strcpy(sfb->fb.fontname, "VGA8x8");
sfb->fb.changevar = NULL;
sfb->fb.switch_con = smifb_switch;
sfb->fb.updatevar = smifb_updatevar;
sfb->fb.blank = smifb_blank;
sfb->fb.node = -1;
sfb->fb.disp = (struct display *)(sfb + 1);
sfb->fb.pseudo_palette = (void *)(sfb->fb.disp + 1);
#endif //CONFIG_FB_SM501_KERNEL_2_4_X
#ifdef CONFIG_FB_SM501_KERNEL_2_6_X
sfb->fb.pseudo_palette = colreg;
#endif //CONFIG_FB_SM501_KERNEL_2_6_X
return sfb;
}
/*
* Unmap in the memory mapped IO registers
*
*/
static void __devinit
smi_unmap_mmio(struct smifb_info *sfb)
{
if (sfb && SMI_VRAMBaseAddress)
{
iounmap(SMI_VRAMBaseAddress);
SMI_RegBaseAddress = NULL;
}
}
/*
* Map in the screen memory
*
*/
static int __devinit
smi_map_smem(struct smifb_info *sfb, struct pci_dev *dev, u_long smem_len)
{
#if isPCI
sfb->fb.fix.smem_start = pci_resource_start(dev, 0);
#else
sfb->fb.fix.smem_start =FB_PHYSICAL_ADDR;
#endif
sfb->fb.fix.smem_len = smem_len;
sfb->fb.screen_base = SMI_VRAMBaseAddress;
if (!sfb->fb.screen_base)
{
printk("%s: unable to map screen memory\n",sfb->fb.fix.id);
return -ENOMEM;
}
return 0;
}
/*
* Unmap in the screen memory
*
*/
static void __devinit
smi_unmap_smem(struct smifb_info *sfb)
{
if (sfb && sfb->fb.screen_base)
{
iounmap(sfb->fb.screen_base);
sfb->fb.screen_base = NULL;
}
}
/*
* We need to wake up the LynxEM+, and make sure its in linear memory mode.
*/
static inline void __devinit
smi_init_hw(void)
{
outb(0x18, 0x3c4);
outb(0x11, 0x3c5);
}
static void __devinit
smi_free_fb_info(struct smifb_info *sfb)
{
if (sfb) {
fb_alloc_cmap(&sfb->fb.cmap, 0, 0);
kfree(sfb);
}
}
u16 SMI_ChipIDs[numChipIDs] = {0x501};
int __init sm501fb_init(void)
{
struct smifb_info *sfb;
u_long smem_size= 0x00800000; //default 8MB
char name[16];
int err;
char *m_pLAW;
unsigned long pFramebufferPhysical;
unsigned long pRegPhysical;
struct pci_dev *pdev = NULL;
int i = 0;
#if isPCI
do {
pdev = pci_find_device(0x126f,SMI_ChipIDs[i], pdev);
if (pdev == NULL)
i++;
else {
hw.chipID = SMI_ChipIDs[i];
break;
}
} while (i< numChipIDs);
sprintf(name, "voyager");
err = pci_enable_device(pdev); // enable voyager chip
if (err) {
return err;
}
#else
hw.chipID = CHIP_ID;
#endif
err = -ENOMEM;
sfb = smi_alloc_fb_info(pdev, name);
if (!sfb) {
goto failed;
}
// Map address and memory detection
#if isPCI
pFramebufferPhysical = pci_resource_start(pdev,0);
pRegPhysical = pci_resource_start(pdev,1);
#else
pFramebufferPhysical = FB_PHYSICAL_ADDR;
pRegPhysical = REG_PHYSICAL_ADDR;
#endif
switch (hw.chipID)
{
case 0x501:
sfb->fb.fix.mmio_start = pRegPhysical;
sfb->fb.fix.mmio_len = 0x00200000;
smem_size = 0x00800000; //8MB
if (!request_mem_region(pFramebufferPhysical, smem_size, "voyager")) {
printk("request_region pFramebufferPhysical failed!\n");
return -1;
};
if (!request_mem_region(pRegPhysical, sfb->fb.fix.mmio_len, "voyager")) {
printk("request_region pRegPhysical failed!\n");
return -1;
};
#if isACCELENT
{
volatile unsigned char *pCPLDS;
MSC1 &= 0xffff0000;
MSC1 |= 0x00009204; // 0x00009234
MDREFR |= 0x01010000; // Set free running clock and SDCLK[1] to 100MHz
LCCR0 |= LCCR0_DIS; // BIT:10 DISABLE lcd CONTROLLER
GAFR2_L = (GAFR2_L & ~0x30000000) | 0x20000000;
GAFR0_U = (GAFR0_U & ~0x30) | 0x10;
GAFR1_U = (GAFR1_U & ~0xf) | 0xa;
pCPLDS = ioremap_nocache(0x17C00000, 0x1000);
*(volatile unsigned long*) (pCPLDS+0x38) = (*(volatile unsigned long*)(pCPLDS+0x38)) & ~0x10;
iounmap(pCPLDS);
}
#endif //isACCELENT
hw.m_pLFB = SMI_VRAMBaseAddress=m_pLAW = ioremap_nocache(pFramebufferPhysical, smem_size);
hw.m_pMMIO = SMI_RegBaseAddress = ioremap_nocache(pRegPhysical, sfb->fb.fix.mmio_len);
break;
default:
printk("No valid Silicon Motion video chip was detected!\n");
smi_free_fb_info(sfb);
return err;
}
#if isPC
sfb->fb.var.xres = screen_info.lfb_width;
sfb->fb.var.yres = screen_info.lfb_height;
sfb->fb.var.bits_per_pixel = screen_info.lfb_depth;
#else
sfb->fb.var.xres = SCREEN_X_RES; // default resolution 640x480 16bit mode
sfb->fb.var.yres = SCREEN_Y_RES;
sfb->fb.var.bits_per_pixel = SCREEN_BPP;
#endif
if (15 == sfb->fb.var.bits_per_pixel)
sfb->fb.var.bits_per_pixel = 16;
if (24 == sfb->fb.var.bits_per_pixel)
sfb->fb.var.bits_per_pixel = 32; //SM501 does not support 24bpp. It supports 32bpp true color.
sfb->fb.var.xres_virtual = sfb->fb.var.xres;
sfb->fb.var.yres_virtual = sfb->fb.var.yres;
err = smi_map_smem(sfb, pdev, smem_size);
if (err) {
goto failed;
}
#ifdef CONFIG_FB_SM501_KERNEL_2_4_X
smifb_set_var(&sfb->fb.var, -1, &sfb->fb);
#endif //CONFIG_FB_SM501_KERNEL_2_4_X
#ifdef CONFIG_FB_SM501_KERNEL_2_6_X
switch (sfb->fb.var.bits_per_pixel) {
case 8:
sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
sfb->fb.fix.line_length= sfb->fb.var.xres ;
sfb->fb.var.red.offset = 5;
sfb->fb.var.red.length = 3;
sfb->fb.var.green.offset= 2;
sfb->fb.var.green.length= 3;
sfb->fb.var.blue.offset = 0;
sfb->fb.var.blue.length = 2;
break;
case 32:
sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
sfb->fb.fix.line_length= sfb->fb.var.xres * 4;
sfb->fb.var.red.offset = 16;
sfb->fb.var.red.length = 8;
sfb->fb.var.green.offset= 8;
sfb->fb.var.green.length= 8;
sfb->fb.var.blue.offset = 0;
sfb->fb.var.blue.length = 8;
break;
case 16:
default:
sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
sfb->fb.fix.line_length= sfb->fb.var.xres * 2;
sfb->fb.var.red.offset = 11;
sfb->fb.var.red.length = 5;
sfb->fb.var.green.offset= 5;
sfb->fb.var.green.length= 6;
sfb->fb.var.blue.offset = 0;
sfb->fb.var.blue.length = 5;
break;
}
hw.width = sfb->fb.var.xres;
hw.height = sfb->fb.var.yres;
hw.hz = 60;
smi_set_timing(sfb, &hw);
deInit(sfb->fb.var.xres, sfb->fb.var.yres, sfb->fb.var.bits_per_pixel); /* Init SMI drawing engine */
#endif //CONFIG_FB_SM501_KERNEL_2_6_X
err = register_framebuffer(&sfb->fb);
if (err < 0) {
goto failed;
}
MOD_INC_USE_COUNT;
//printk("FBbase=%08X, CURRENT_POWER_GATE=%08X, CURRENT_POWER_CLOCK=%08X\n", (unsigned int)sfb->fb.screen_base, regRead32(CURRENT_POWER_GATE), regRead32(CURRENT_POWER_CLOCK));
printk("Silicon Motion, Inc. SM501 mode %dx%d-%d Init Complete.\n",sfb->fb.var.xres, sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);
return 0;
failed:
smi_unmap_smem(sfb);
smi_unmap_mmio(sfb);
smi_free_fb_info(sfb);
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -