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

📄 offb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device * *	Copyright (C) 1997 Geert Uytterhoeven * *  This driver is partly based on the PowerMac console driver: * *	Copyright (C) 1996 Paul Mackerras * *  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. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/prom.h>#ifdef CONFIG_PPC64#include <asm/pci-bridge.h>#endif#ifdef CONFIG_PPC32#include <asm/bootx.h>#endif#include "macmodes.h"/* Supported palette hacks */enum {	cmap_unknown,	cmap_m64,		/* ATI Mach64 */	cmap_r128,		/* ATI Rage128 */	cmap_M3A,		/* ATI Rage Mobility M3 Head A */	cmap_M3B,		/* ATI Rage Mobility M3 Head B */	cmap_radeon,		/* ATI Radeon */	cmap_gxt2000,		/* IBM GXT2000 */	cmap_avivo,		/* ATI R5xx */};struct offb_par {	volatile void __iomem *cmap_adr;	volatile void __iomem *cmap_data;	int cmap_type;	int blanked;};struct offb_par default_par;#ifdef CONFIG_PPC32extern boot_infos_t *boot_infos;#endif/* Definitions used by the Avivo palette hack */#define AVIVO_DC_LUT_RW_SELECT                  0x6480#define AVIVO_DC_LUT_RW_MODE                    0x6484#define AVIVO_DC_LUT_RW_INDEX                   0x6488#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c#define AVIVO_DC_LUT_PWL_DATA                   0x6490#define AVIVO_DC_LUT_30_COLOR                   0x6494#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c#define AVIVO_DC_LUT_AUTOFILL                   0x64a0#define AVIVO_DC_LUTA_CONTROL                   0x64c0#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8#define AVIVO_DC_LUTB_CONTROL                   0x6cc0#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE         0x6cc4#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN        0x6cc8#define AVIVO_DC_LUTB_BLACK_OFFSET_RED          0x6ccc#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE         0x6cd0#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4#define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8    /*     *  Set a single color register. The values supplied are already     *  rounded down to the hardware's capabilities (according to the     *  entries in the var structure). Return != 0 for invalid regno.     */static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			  u_int transp, struct fb_info *info){	struct offb_par *par = (struct offb_par *) info->par;	int i, depth;	u32 *pal = info->pseudo_palette;	depth = info->var.bits_per_pixel;	if (depth == 16)		depth = (info->var.green.length == 5) ? 15 : 16;	if (regno > 255 ||	    (depth == 16 && regno > 63) ||	    (depth == 15 && regno > 31))		return 1;	if (regno < 16) {		switch (depth) {		case 15:			pal[regno] = (regno << 10) | (regno << 5) | regno;			break;		case 16:			pal[regno] = (regno << 11) | (regno << 5) | regno;			break;		case 24:			pal[regno] = (regno << 16) | (regno << 8) | regno;			break;		case 32:			i = (regno << 8) | regno;			pal[regno] = (i << 16) | i;			break;		}	}	red >>= 8;	green >>= 8;	blue >>= 8;	if (!par->cmap_adr)		return 0;	switch (par->cmap_type) {	case cmap_m64:		writeb(regno, par->cmap_adr);		writeb(red, par->cmap_data);		writeb(green, par->cmap_data);		writeb(blue, par->cmap_data);		break;	case cmap_M3A:		/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */		out_le32(par->cmap_adr + 0x58,			 in_le32(par->cmap_adr + 0x58) & ~0x20);	case cmap_r128:		/* Set palette index & data */		out_8(par->cmap_adr + 0xb0, regno);		out_le32(par->cmap_adr + 0xb4,			 (red << 16 | green << 8 | blue));		break;	case cmap_M3B:		/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */		out_le32(par->cmap_adr + 0x58,			 in_le32(par->cmap_adr + 0x58) | 0x20);		/* Set palette index & data */		out_8(par->cmap_adr + 0xb0, regno);		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));		break;	case cmap_radeon:		/* Set palette index & data (could be smarter) */		out_8(par->cmap_adr + 0xb0, regno);		out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue));		break;	case cmap_gxt2000:		out_le32(((unsigned __iomem *) par->cmap_adr) + regno,			 (red << 16 | green << 8 | blue));		break;	case cmap_avivo:		/* Write to both LUTs for now */		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);		break;	}	return 0;}    /*     *  Blank the display.     */static int offb_blank(int blank, struct fb_info *info){	struct offb_par *par = (struct offb_par *) info->par;	int i, j;	if (!par->cmap_adr)		return 0;	if (!par->blanked)		if (!blank)			return 0;	par->blanked = blank;	if (blank)		for (i = 0; i < 256; i++) {			switch (par->cmap_type) {			case cmap_m64:				writeb(i, par->cmap_adr);				for (j = 0; j < 3; j++)					writeb(0, par->cmap_data);				break;			case cmap_M3A:				/* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */				out_le32(par->cmap_adr + 0x58,					 in_le32(par->cmap_adr + 0x58) & ~0x20);			case cmap_r128:				/* Set palette index & data */				out_8(par->cmap_adr + 0xb0, i);				out_le32(par->cmap_adr + 0xb4, 0);				break;			case cmap_M3B:				/* Set PALETTE_ACCESS_CNTL in DAC_CNTL */				out_le32(par->cmap_adr + 0x58,					 in_le32(par->cmap_adr + 0x58) | 0x20);				/* Set palette index & data */				out_8(par->cmap_adr + 0xb0, i);				out_le32(par->cmap_adr + 0xb4, 0);				break;			case cmap_radeon:				out_8(par->cmap_adr + 0xb0, i);				out_le32(par->cmap_adr + 0xb4, 0);				break;			case cmap_gxt2000:				out_le32(((unsigned __iomem *) par->cmap_adr) + i,					 0);				break;			case cmap_avivo:				writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);				writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);				break;			}	} else		fb_set_cmap(&info->cmap, info);	return 0;}static int offb_set_par(struct fb_info *info){	struct offb_par *par = (struct offb_par *) info->par;	/* On avivo, initialize palette control */	if (par->cmap_type == cmap_avivo) {		writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);		writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);	}	return 0;}static struct fb_ops offb_ops = {	.owner		= THIS_MODULE,	.fb_setcolreg	= offb_setcolreg,	.fb_set_par	= offb_set_par,	.fb_blank	= offb_blank,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,};static void __iomem *offb_map_reg(struct device_node *np, int index,				  unsigned long offset, unsigned long size){	const u32 *addrp;	u64 asize, taddr;	unsigned int flags;	addrp = of_get_pci_address(np, index, &asize, &flags);	if (addrp == NULL)		addrp = of_get_address(np, index, &asize, &flags);	if (addrp == NULL)		return NULL;	if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)		return NULL;	if ((offset + size) > asize)		return NULL;	taddr = of_translate_address(np, addrp);	if (taddr == OF_BAD_ADDR)		return NULL;	return ioremap(taddr + offset, size);}static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,				    const char *name, unsigned long address){	struct offb_par *par = (struct offb_par *) info->par;	if (dp && !strncmp(name, "ATY,Rage128", 11)) {		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);		if (par->cmap_adr)			par->cmap_type = cmap_r128;	} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)			  || !strncmp(name, "ATY,RageM3p12A", 14))) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -