⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 viafbdev.c

📁 VIA Framebuffer driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*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 + -