📄 viafbdev.c
字号:
/*
*Copyright (C) 2003 VIA Technologies, Inc. All Rights Reserved.
*This program is free software; you can redistribute it and/or modify it under
*the terms of the GNU *General Public License as published by the Free Software
*Foundation; either version 2 of the License, or (at your option) any later
*version.
*
*This program is distributed in the hope that it will be useful, but WITHOUT ANY
*WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
*A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*You should have received a copy of the GNU General Public License along with
*this program; if not, write to the Free Software Foundation, Inc.,
*59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include "viafbdev.h"
#include "share.h"
#include "chip.h"
#include "debug.h"
#define VERSION "0.8"
extern unsigned int get_memsize(void);
extern int setmode(int vmode_index,int hor_res,int ver_res,int video_bpp);
extern void write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
extern void init_chip_info(void);
extern inline u8 read_reg(int io_port, u8 index);
extern void init_dac(int set_iga);
extern int get_pixclock(int hres, int vres, int vmode_refresh);
extern int get_refresh(int hres, int vres, int pixclock);
extern void update_device_setting(int hres, int vres, int bpp, int vmode_refresh);
static int get_mode_index(int hres, int vres);
struct chip_information chip_info;
struct crt_setting_information crt_setting_info;
struct tv_setting_information tv_setting_info;
struct tmds_setting_information tmds_setting_info;
struct lvds_setting_information lvds_setting_info;
struct viafb_par {
struct fb_var_screeninfo var;
int bpp;
int hres;
int vres;
int linelength;
int vclk; //in MHz
int vtotal;
int vdispend;
int vsyncstart;
int vsyncend;
int vblankstart;
int vblankend;
int htotal;
int hdispend;
int hsyncstart;
int hsyncend;
int hblankstart;
int hblankend;
};
struct viafb_info {
struct fb_info_gen gen;
unsigned int fbmem_virt; //framebuffer virtual memory address
unsigned int fbmem; //framebuffer physical memory address
unsigned int memsize; //size of fbmem
unsigned int io; //io space address
unsigned int io_virt; //iospace virtual memory address
struct viafb_par currentmode;
unsigned char eng_oper; //engine operation...
};
static struct fb_ops viafb_ops;
static struct viafb_info fb_info;
static struct display disp;
static struct { unsigned char red,green,blue,transp; } palette[256];
static struct fb_var_screeninfo default_var;
static char * viafb_name = "Via";
static int defaultaccel=0;
static int pseudo_pal[16];
/* video mode */
static char *mode __initdata = "640x480";
static int bpp __initdata = 32;
static int resMode = VIA_RES_640X480;
static int noaccel __initdata = 1;
int memsize=0;
int CRT_ON=1,DVI_ON=0,TV_ON=0,LCD_ON=0;
/* Display Mode Information */
int refresh __initdata = 60;
int tv_level __initdata = 0;
int tv_system __initdata = NTSC;
int tv_out_signal __initdata = TV_OUTPUT_COMPOSITE_SVIDEO;
int tv_dedotcrawl __initdata = 0;
#ifndef VIA_MMIO
#define VIA_MMIO 0
#endif
#if VIA_MMIO
// #define t_outb(addr, data) *(volatile unsigned char *)(fb_info.io_virt + (addr)) = (data)
// #define t_inb(addr) *(volatile unsigned char *)(fb_info.io_virt + (addr))
#define t_outb(val,reg) writeb(val,fb_info.io_virt + reg)
#define t_inb(reg) readb(fb_info.io_virt + reg)
#else
#define t_outb(val,reg) outb(val,reg)
#define t_inb(reg) inb(reg)
#endif
#define VIASETREG(addr, data) outl(data,addr)
#define VIAGETREG(addr) inl(addr)
/*
* Accel functions called by the upper layers
*/
/*static void WaitIdle(void)
{
}*/
static void via_bmove (struct display *p, int sy, int sx,
int dy, int dx, int height, int width)
{
}
static void via_clear_helper (int c, struct display *p,
int sy, int sx, int height, int width)
{
}
#ifdef FBCON_HAS_CFB8
static void via_8bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = attr_bgcol_ec(p,conp) & 0xFF;
c |= c<<8;
c |= c<<16;
via_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch via_8bpp = {
setup: fbcon_cfb8_setup,
bmove: via_bmove,
clear: via_8bpp_clear,
putc: fbcon_cfb8_putc,
putcs: fbcon_cfb8_putcs,
revc: fbcon_cfb8_revc,
clear_margins: fbcon_cfb8_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
#ifdef FBCON_HAS_CFB16
static void via_16bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
c = c | c<<16;
via_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch via_16bpp = {
setup: fbcon_cfb16_setup,
bmove: via_bmove,
clear: via_16bpp_clear,
putc: fbcon_cfb16_putc,
putcs: fbcon_cfb16_putcs,
revc: fbcon_cfb16_revc,
clear_margins: fbcon_cfb16_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
#ifdef FBCON_HAS_CFB32
static void via_32bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = ((u32*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
via_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch via_32bpp = {
setup: fbcon_cfb32_setup,
bmove: via_bmove,
clear: via_32bpp_clear,
putc: fbcon_cfb32_putc,
putcs: fbcon_cfb32_putcs,
revc: fbcon_cfb32_revc,
clear_margins: fbcon_cfb32_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
/* Fill in fix */
static int via_encode_fix(struct fb_fix_screeninfo *fix,
const void *par,
struct fb_info_gen *info)
{
struct viafb_info * i = (struct viafb_info *)info;
struct viafb_par * p = (struct viafb_par *)par;
DEBUG_MSG(KERN_INFO "via_encode_fix!\n" );
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,viafb_name);
fix->smem_start = i->fbmem;
fix->smem_len = i->memsize;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->visual = p->bpp==8 ? FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
fix->xpanstep = fix->ywrapstep = 0;
fix->ypanstep = 1;
fix->line_length = p->linelength;
fix->mmio_start = 0;
fix->mmio_len = 0;
fix->accel = FB_ACCEL_NONE;
return 0;
}
/* Fill in par from var */
static int via_decode_var(const struct fb_var_screeninfo *var,
void *par,
struct fb_info_gen *info)
{
struct viafb_par * p = (struct viafb_par *)par;
struct viafb_info * i = (struct viafb_info *)info;
int vres,vfront,vback,vsync;
DEBUG_MSG(KERN_INFO "via_decode_var!\n" );
p->var = *var;
p->bpp = var->bits_per_pixel;
if (p->bpp == 24 )
p->bpp = 32;
p->linelength = var->xres_virtual * p->bpp/8;
switch (p->bpp) {
case 8:
p->var.red.offset = 0;
p->var.green.offset = 0;
p->var.blue.offset = 0;
p->var.red.length = 6;
p->var.green.length = 6;
p->var.blue.length = 6;
break;
case 16:
p->var.red.offset = 11;
p->var.green.offset = 5;
p->var.blue.offset = 0;
p->var.red.length = 5;
p->var.green.length = 6;
p->var.blue.length = 5;
break;
case 32:
p->var.red.offset = 16;
p->var.green.offset = 8;
p->var.blue.offset = 0;
p->var.red.length = 8;
p->var.green.length = 8;
p->var.blue.length = 8;
break;
default:
return -EINVAL;
}
/* convert from picoseconds to MHz */
refresh= get_refresh(var->xres, var->yres, var->pixclock);
p->vclk = 1000000/var->pixclock;
if (p->bpp == 32)
p->vclk *=2;
p->hres = var->xres;
vres = p->vres = var->yres;
/* See if requested resolution fits in available memory */
if (p->hres * p->vres * p->bpp/8 > i->memsize) {
return -EINVAL;
}
vfront = var->upper_margin;
vback = var->lower_margin;
vsync = var->vsync_len;
/* Compute horizontal and vertical VGA CRTC timing values */
if (var->vmode & FB_VMODE_INTERLACED) {
vres /= 2;
vfront /=2;
vback /=2;
vsync /=2;
}
if (var->vmode & FB_VMODE_DOUBLE) {
vres *= 2;
vfront *=2;
vback *=2;
vsync *=2;
}
p->htotal = (p->hres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10;
p->hdispend = p->hres/8 - 1;
p->hsyncstart = (p->hres + var->right_margin)/8;
p->hsyncend = var->hsync_len/8;
p->hblankstart = p->hdispend + 1;
p->hblankend = p->htotal + 5;
p->vtotal = vres + vfront + vback + vsync - 2;
p->vdispend = vres - 1;
p->vsyncstart = vres + vback;
p->vsyncend = vsync;
p->vblankstart = vres;
p->vblankend = p->vtotal + 2;
return 0;
}
/* Fill in var from info */
static int via_encode_var(struct fb_var_screeninfo *var,
const void *par,
struct fb_info_gen *info)
{
struct viafb_par * p = (struct viafb_par *)par;
DEBUG_MSG(KERN_INFO "via_encode_var!\n" );
*var = p->var;
var->bits_per_pixel = p->bpp;
return 0;
}
/* Fill in par from hardware */
static void via_get_par(void *par, struct fb_info_gen *info)
{
struct viafb_par * p = (struct viafb_par *)par;
struct viafb_info * i = (struct viafb_info *)info;
DEBUG_MSG(KERN_INFO "via_get_par!\n" );
*p = i->currentmode;
}
/* Pan the display */
static int via_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info)
{
unsigned int offset;
struct viafb_info * i = (struct viafb_info *)info;
DEBUG_MSG(KERN_INFO "via_pan_display!\n" );
offset = (var->xoffset + (var->yoffset * var->xres))
* var->bits_per_pixel/32;
i->currentmode.var.xoffset = var->xoffset;
i->currentmode.var.yoffset = var->yoffset;
return 0;
}
/* Set the hardware from par */
static void via_set_par(const void *par, struct fb_info_gen *info)
{
int vmode_index;
struct viafb_par * p = (struct viafb_par *)par;
struct viafb_info * i = (struct viafb_info *)info;
DEBUG_MSG(KERN_INFO "via_set_par!\n" );
i->currentmode = *p;
update_device_setting(i->currentmode.hres, i->currentmode.vres, i->currentmode.bpp, refresh);
vmode_index=get_mode_index(i->currentmode.hres, i->currentmode.vres);
setmode(vmode_index,i->currentmode.hres,i->currentmode.vres,i->currentmode.bpp);
via_pan_display(&p->var,info);
}
/* Get value of one color register */
static int via_getcolreg(unsigned regno, unsigned *red,
unsigned *green, unsigned *blue,
unsigned *transp, struct fb_info *info)
{
struct viafb_info * i = (struct viafb_info *)info;
int m = i->currentmode.bpp==8?256:16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -