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

📄 ps3fb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			ps3fb_sync(info, 0);	/* single buffer */			release_console_sem();		}		schedule();	}	return 0;}static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr){	struct device *dev = ptr;	u64 v1;	int status;	struct display_head *head = &ps3fb.dinfo->display_head[1];	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);	if (status) {		dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__,			status);		return IRQ_NONE;	}	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {		/* VSYNC */		ps3fb.vblank_count = head->vblank_count;		if (ps3fb.task && !ps3fb.is_blanked &&		    !atomic_read(&ps3fb.ext_flip)) {			ps3fb.is_kicked = 1;			wake_up_process(ps3fb.task);		}		wake_up_interruptible(&ps3fb.wait_vsync);	}	return IRQ_HANDLED;}static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,				struct device *dev){	int error;	dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver);	dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet);	dev_dbg(dev,		"version_gpu: %x memory_size: %x ch: %x core_freq: %d "		"mem_freq:%d\n",		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {		dev_err(dev, "%s: version_driver err:%x\n", __func__,			dinfo->version_driver);		return -EINVAL;	}	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,				   &ps3fb.irq_no);	if (error) {		dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error);		return error;	}	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,			    DEVICE_NAME, dev);	if (error) {		dev_err(dev, "%s: request_irq failed %d\n", __func__, error);		ps3_irq_plug_destroy(ps3fb.irq_no);		return error;	}	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |			  (1 << GPU_INTR_STATUS_FLIP_1);	return 0;}static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev){	int status;	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,				       xdr_lpar, ps3fb_videomemory.size, 0);	if (status) {		dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n",			__func__, status);		return -ENXIO;	}	dev_dbg(dev,		"video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,		virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);	status = lv1_gpu_context_attribute(ps3fb.context_handle,					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,					   xdr_lpar, GPU_CMD_BUF_SIZE,					   GPU_IOIF, 0);	if (status) {		dev_err(dev,			"%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",			__func__, status);		return -ENXIO;	}	return 0;}static struct fb_ops ps3fb_ops = {	.fb_open	= ps3fb_open,	.fb_release	= ps3fb_release,	.fb_read        = fb_sys_read,	.fb_write       = fb_sys_write,	.fb_check_var	= ps3fb_check_var,	.fb_set_par	= ps3fb_set_par,	.fb_setcolreg	= ps3fb_setcolreg,	.fb_pan_display	= ps3fb_pan_display,	.fb_fillrect	= sys_fillrect,	.fb_copyarea	= sys_copyarea,	.fb_imageblit	= sys_imageblit,	.fb_mmap	= ps3fb_mmap,	.fb_blank	= ps3fb_blank,	.fb_ioctl	= ps3fb_ioctl,	.fb_compat_ioctl = ps3fb_ioctl};static struct fb_fix_screeninfo ps3fb_fix __initdata = {	.id =		DEVICE_NAME,	.type =		FB_TYPE_PACKED_PIXELS,	.visual =	FB_VISUAL_TRUECOLOR,	.accel =	FB_ACCEL_NONE,};static int ps3fb_set_sync(struct device *dev){	int status;#ifdef HEAD_A	status = lv1_gpu_context_attribute(0x0,					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);	if (status) {		dev_err(dev,			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "			"%d\n",			__func__, status);		return -1;	}#endif#ifdef HEAD_B	status = lv1_gpu_context_attribute(0x0,					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);	if (status) {		dev_err(dev,			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "			"%d\n",			__func__, status);		return -1;	}#endif	return 0;}static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev){	struct fb_info *info;	struct ps3fb_par *par;	int retval = -ENOMEM;	u32 xres, yres;	u64 ddr_lpar = 0;	u64 lpar_dma_control = 0;	u64 lpar_driver_info = 0;	u64 lpar_reports = 0;	u64 lpar_reports_size = 0;	u64 xdr_lpar;	int status, res_index;	struct task_struct *task;	unsigned long max_ps3fb_size;	if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) {		dev_err(&dev->core, "%s: Not enough video memory\n", __func__);		return -ENOMEM;	}	status = ps3_open_hv_device(dev);	if (status) {		dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",			__func__);		goto err;	}	if (!ps3fb_mode)		ps3fb_mode = ps3av_get_mode();	dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode);	if (ps3fb_mode > 0 &&	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {		res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);		dev_dbg(&dev->core, "res_index:%d\n", res_index);	} else		res_index = GPU_RES_INDEX;	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */	init_waitqueue_head(&ps3fb.wait_vsync);	ps3fb_set_sync(&dev->core);	max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;	if (ps3fb_videomemory.size > max_ps3fb_size) {		dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n",			 max_ps3fb_size);		ps3fb_videomemory.size = max_ps3fb_size;	}	/* get gpu context handle */	status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,					 &ps3fb.memory_handle, &ddr_lpar);	if (status) {		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",			__func__, status);		goto err;	}	dev_dbg(&dev->core, "ddr:lpar:0x%lx\n", ddr_lpar);	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,					  &ps3fb.context_handle,					  &lpar_dma_control, &lpar_driver_info,					  &lpar_reports, &lpar_reports_size);	if (status) {		dev_err(&dev->core,			"%s: lv1_gpu_context_attribute failed: %d\n", __func__,			status);		goto err_gpu_memory_free;	}	/* vsync interrupt */	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);	if (!ps3fb.dinfo) {		dev_err(&dev->core, "%s: ioremap failed\n", __func__);		goto err_gpu_context_free;	}	retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core);	if (retval)		goto err_iounmap_dinfo;	/* XDR frame buffer */	ps3fb.xdr_ea = ps3fb_videomemory.address;	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));	/* Clear memory to prevent kernel info leakage into userspace */	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);	/*	 * The GPU command buffer is at the start of video memory	 * As we don't use the full command buffer, we can put the actual	 * frame buffer at offset GPU_FB_START and save some precious XDR	 * memory	 */	ps3fb.xdr_ea += GPU_FB_START;	ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START;	retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);	if (retval)		goto err_free_irq;	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);	if (!info)		goto err_free_irq;	par = info->par;	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */	par->new_mode_id = ps3fb_mode;	par->res_index = res_index;	par->num_frames = 1;	info->screen_base = (char __iomem *)ps3fb.xdr_ea;	info->fbops = &ps3fb_ops;	info->fix = ps3fb_fix;	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);	info->fix.smem_len = ps3fb.xdr_size;	info->pseudo_palette = par->pseudo_palette;	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;	retval = fb_alloc_cmap(&info->cmap, 256, 0);	if (retval < 0)		goto err_framebuffer_release;	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,			  ARRAY_SIZE(ps3fb_modedb),			  ps3fb_default_mode(par->new_mode_id), 32)) {		retval = -EINVAL;		goto err_fb_dealloc;	}	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),				 &info->modelist);	retval = register_framebuffer(info);	if (retval < 0)		goto err_fb_dealloc;	dev->core.driver_data = info;	dev_info(info->device, "%s %s, using %lu KiB of video memory\n",		 dev_driver_string(info->dev), info->dev->bus_id,		 ps3fb.xdr_size >> 10);	task = kthread_run(ps3fbd, info, DEVICE_NAME);	if (IS_ERR(task)) {		retval = PTR_ERR(task);		goto err_unregister_framebuffer;	}	ps3fb.task = task;	ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);	return 0;err_unregister_framebuffer:	unregister_framebuffer(info);err_fb_dealloc:	fb_dealloc_cmap(&info->cmap);err_framebuffer_release:	framebuffer_release(info);err_free_irq:	free_irq(ps3fb.irq_no, &dev->core);	ps3_irq_plug_destroy(ps3fb.irq_no);err_iounmap_dinfo:	iounmap((u8 __iomem *)ps3fb.dinfo);err_gpu_context_free:	lv1_gpu_context_free(ps3fb.context_handle);err_gpu_memory_free:	lv1_gpu_memory_free(ps3fb.memory_handle);err:	return retval;}static int ps3fb_shutdown(struct ps3_system_bus_device *dev){	int status;	struct fb_info *info = dev->core.driver_data;	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);	ps3fb_flip_ctl(0, &ps3fb);	/* flip off */	ps3fb.dinfo->irq.mask = 0;	ps3av_register_flip_ctl(NULL, NULL);	if (ps3fb.task) {		struct task_struct *task = ps3fb.task;		ps3fb.task = NULL;		kthread_stop(task);	}	if (ps3fb.irq_no) {		free_irq(ps3fb.irq_no, &dev->core);		ps3_irq_plug_destroy(ps3fb.irq_no);	}	if (info) {		unregister_framebuffer(info);		fb_dealloc_cmap(&info->cmap);		framebuffer_release(info);		info = dev->core.driver_data = NULL;	}	iounmap((u8 __iomem *)ps3fb.dinfo);	status = lv1_gpu_context_free(ps3fb.context_handle);	if (status)		dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n",			status);	status = lv1_gpu_memory_free(ps3fb.memory_handle);	if (status)		dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n",			status);	ps3_close_hv_device(dev);	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);	return 0;}static struct ps3_system_bus_driver ps3fb_driver = {	.match_id	= PS3_MATCH_ID_GRAPHICS,	.core.name	= DEVICE_NAME,	.core.owner	= THIS_MODULE,	.probe		= ps3fb_probe,	.remove		= ps3fb_shutdown,	.shutdown	= ps3fb_shutdown,};static int __init ps3fb_setup(void){	char *options;#ifdef MODULE	return 0;#endif	if (fb_get_options(DEVICE_NAME, &options))		return -ENXIO;	if (!options || !*options)		return 0;	while (1) {		char *this_opt = strsep(&options, ",");		if (!this_opt)			break;		if (!*this_opt)			continue;		if (!strncmp(this_opt, "mode:", 5))			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);		else			mode_option = this_opt;	}	return 0;}static int __init ps3fb_init(void){	if (!ps3fb_videomemory.address ||  ps3fb_setup())		return -ENXIO;	return ps3_system_bus_driver_register(&ps3fb_driver);}static void __exit ps3fb_exit(void){	pr_debug(" -> %s:%d\n", __func__, __LINE__);	ps3_system_bus_driver_unregister(&ps3fb_driver);	pr_debug(" <- %s:%d\n", __func__, __LINE__);}module_init(ps3fb_init);module_exit(ps3fb_exit);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");MODULE_AUTHOR("Sony Computer Entertainment Inc.");MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);

⌨️ 快捷键说明

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