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

📄 ps3fb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device * *	Copyright (C) 2006 Sony Computer Entertainment Inc. *	Copyright 2006, 2007 Sony Corporation * *  This file is based on : * *  linux/drivers/video/vfb.c -- Virtual frame buffer device * *	Copyright (C) 2002 James Simmons * *	Copyright (C) 1997 Geert Uytterhoeven * *  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/interrupt.h>#include <linux/console.h>#include <linux/ioctl.h>#include <linux/kthread.h>#include <linux/freezer.h>#include <linux/uaccess.h>#include <linux/fb.h>#include <linux/init.h>#include <asm/abs_addr.h>#include <asm/lv1call.h>#include <asm/ps3av.h>#include <asm/ps3fb.h>#include <asm/ps3.h>#define DEVICE_NAME		"ps3fb"#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC	0x101#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP	0x102#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP	0x600#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT		0x601#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC	0x602#define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION	(1ULL << 32)#define L1GPU_DISPLAY_SYNC_HSYNC		1#define L1GPU_DISPLAY_SYNC_VSYNC		2#define GPU_CMD_BUF_SIZE			(2 * 1024 * 1024)#define GPU_FB_START				(64 * 1024)#define GPU_IOIF				(0x0d000000UL)#define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)#define GPU_MAX_LINE_LENGTH			(65536 - 64)#define PS3FB_FULL_MODE_BIT			0x80#define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */#define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */#define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */#define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */#define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */#define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */#define GPU_DRIVER_INFO_VERSION			0x211/* gpu internals */struct display_head {	u64 be_time_stamp;	u32 status;	u32 offset;	u32 res1;	u32 res2;	u32 field;	u32 reserved1;	u64 res3;	u32 raster;	u64 vblank_count;	u32 field_vsync;	u32 reserved2;};struct gpu_irq {	u32 irq_outlet;	u32 status;	u32 mask;	u32 video_cause;	u32 graph_cause;	u32 user_cause;	u32 res1;	u64 res2;	u32 reserved[4];};struct gpu_driver_info {	u32 version_driver;	u32 version_gpu;	u32 memory_size;	u32 hardware_channel;	u32 nvcore_frequency;	u32 memory_frequency;	u32 reserved[1063];	struct display_head display_head[8];	struct gpu_irq irq;};struct ps3fb_priv {	unsigned int irq_no;	u64 context_handle, memory_handle;	void *xdr_ea;	size_t xdr_size;	struct gpu_driver_info *dinfo;	u64 vblank_count;	/* frame count */	wait_queue_head_t wait_vsync;	atomic_t ext_flip;	/* on/off flip with vsync */	atomic_t f_count;	/* fb_open count */	int is_blanked;	int is_kicked;	struct task_struct *task;};static struct ps3fb_priv ps3fb;struct ps3fb_par {	u32 pseudo_palette[16];	int mode_id, new_mode_id;	int res_index;	unsigned int num_frames;	/* num of frame buffers */	unsigned int width;	unsigned int height;	unsigned long full_offset;	/* start of fullscreen DDR fb */	unsigned long fb_offset;	/* start of actual DDR fb */	unsigned long pan_offset;};struct ps3fb_res_table {	u32 xres;	u32 yres;	u32 xoff;	u32 yoff;	u32 type;};#define PS3FB_RES_FULL 1static const struct ps3fb_res_table ps3fb_res[] = {	/* res_x,y   margin_x,y  full */	{  720,  480,  72,  48 , 0},	{  720,  576,  72,  58 , 0},	{ 1280,  720,  78,  38 , 0},	{ 1920, 1080, 116,  58 , 0},	/* full mode */	{  720,  480,   0,   0 , PS3FB_RES_FULL},	{  720,  576,   0,   0 , PS3FB_RES_FULL},	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},	/* vesa: normally full mode */	{ 1280,  768,   0,   0 , 0},	{ 1280, 1024,   0,   0 , 0},	{ 1920, 1200,   0,   0 , 0},	{    0,    0,   0,   0 , 0} };/* default resolution */#define GPU_RES_INDEX	0		/* 720 x 480 */static const struct fb_videomode ps3fb_modedb[] = {    /* 60 Hz broadcast modes (modes "1" to "5") */    {        /* 480i */        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    },    {        /* 480p */        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    {        /* 720p */        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    {        /* 1080i */        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    },    {        /* 1080p */        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    /* 50 Hz broadcast modes (modes "6" to "10") */    {        /* 576i */        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    },    {        /* 576p */        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    {        /* 720p */        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    {        /* 1080 */        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    },    {        /* 1080p */        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    /* VESA modes (modes "11" to "13") */    {	/* WXGA */	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,	0, FB_VMODE_NONINTERLACED,	FB_MODE_IS_VESA    }, {	/* SXGA */	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,	FB_MODE_IS_VESA    }, {	/* WUXGA */	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,	FB_MODE_IS_VESA    },    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */    {	/* 480if */	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    }, {	/* 480pf */	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    }, {	/* 720pf */	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    }, {	/* 1080if */	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    }, {	/* 1080pf */	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    },    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */    {	/* 576if */	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    }, {	/* 576pf */	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    }, {	/* 720pf */	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    }, {	/* 1080if */	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED    }, {	/* 1080pf */	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED    }};#define HEAD_A#define HEAD_B#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */#define BPP		4			/* number of bytes per pixel *//* Start of the virtual frame buffer (relative to fullscreen ) */#define VP_OFF(i)	((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP)static int ps3fb_mode;module_param(ps3fb_mode, int, 0);static char *mode_option __devinitdata;static int ps3fb_get_res_table(u32 xres, u32 yres, int mode){	int full_mode;	unsigned int i;	u32 x, y, f;	full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;	for (i = 0;; i++) {		x = ps3fb_res[i].xres;		y = ps3fb_res[i].yres;		f = ps3fb_res[i].type;		if (!x) {			pr_debug("ERROR: ps3fb_get_res_table()\n");			return -1;		}		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL)			continue;		if (x == xres && (yres == 0 || y == yres))			break;		x = x - 2 * ps3fb_res[i].xoff;		y = y - 2 * ps3fb_res[i].yoff;		if (x == xres && (yres == 0 || y == yres))			break;	}	return i;}static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,				    u32 *ddr_line_length, u32 *xdr_line_length){	unsigned int i, mode;	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)		if (var->xres == ps3fb_modedb[i].xres &&		    var->yres == ps3fb_modedb[i].yres &&		    var->pixclock == ps3fb_modedb[i].pixclock &&		    var->hsync_len == ps3fb_modedb[i].hsync_len &&		    var->vsync_len == ps3fb_modedb[i].vsync_len &&		    var->left_margin == ps3fb_modedb[i].left_margin &&		    var->right_margin == ps3fb_modedb[i].right_margin &&		    var->upper_margin == ps3fb_modedb[i].upper_margin &&		    var->lower_margin == ps3fb_modedb[i].lower_margin &&		    var->sync == ps3fb_modedb[i].sync &&		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode)			goto found;	pr_debug("ps3fb_find_mode: mode not found\n");	return 0;found:	/* Cropped broadcast modes use the full line length */	*ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP;	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {		*xdr_line_length = GPU_ALIGN_UP(max(var->xres,						    var->xres_virtual) * BPP);		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)			*xdr_line_length = GPU_MAX_LINE_LENGTH;	} else		*xdr_line_length = *ddr_line_length;	/* Full broadcast modes have the full mode bit set */	mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;	pr_debug("ps3fb_find_mode: mode %u\n", mode);	return mode;}static const struct fb_videomode *ps3fb_default_mode(int id){	u32 mode = id & PS3AV_MODE_MASK;	u32 flags;	if (mode < 1 || mode > 13)		return NULL;	flags = id & ~PS3AV_MODE_MASK;	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {		/* Full broadcast mode */		return &ps3fb_modedb[mode + 12];	}	return &ps3fb_modedb[mode - 1];}static void ps3fb_sync_image(struct device *dev, u64 frame_offset,			     u64 dst_offset, u64 src_offset, u32 width,			     u32 height, u32 dst_line_length,			     u32 src_line_length){	int status;	u64 line_length;	line_length = dst_line_length;	if (src_line_length != dst_line_length)		line_length |= (u64)src_line_length << 32;	src_offset += GPU_FB_START;	status = lv1_gpu_context_attribute(ps3fb.context_handle,					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,					   dst_offset, GPU_IOIF + src_offset,					   L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |					   (width << 16) | height,					   line_length);	if (status)		dev_err(dev,			"%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",			__func__, status);#ifdef HEAD_A	status = lv1_gpu_context_attribute(ps3fb.context_handle,					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,					   0, frame_offset, 0, 0);	if (status)		dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",			__func__, status);#endif#ifdef HEAD_B	status = lv1_gpu_context_attribute(ps3fb.context_handle,					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,					   1, frame_offset, 0, 0);	if (status)		dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",			__func__, status);#endif}static int ps3fb_sync(struct fb_info *info, u32 frame){	struct ps3fb_par *par = info->par;	int i, error = 0;	u32 ddr_line_length, xdr_line_length;	u64 ddr_base, xdr_base;

⌨️ 快捷键说明

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