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

📄 sdum.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Clear the cmdstrings */	cmdstrings =	    (u32 *)ioremap_nocache(*cmdptrs,				   BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS);	if (!cmdstrings)		goto out;	for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32);	     i++)		iowrite32(0, cmdstrings + i);	iounmap((u32 *)cmdstrings);out:	iounmap((u32 *)cmdptrs);}static void lcd_init(void){	lcd_reset();	DUM_OUTP_FORMAT1 = 0; /* RGB666 */	udelay(1);	iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base);	udelay(1);	iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base);	udelay(1);}/* Interface exported to framebuffer drivers */int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,			     dma_addr_t *phys_addr, int *fb_length){	int i;	int ret = -1;	for (i = 0; i < ARRAY_SIZE(fb_addr); i++)		if (fb_addr[i].fb_type == fb_type) {			*virt_addr = (void *)(dum_data.lcd_virt_start +					fb_addr[i].addr_offset);			*phys_addr =			    dum_data.lcd_phys_start + fb_addr[i].addr_offset;			*fb_length = fb_addr[i].fb_length;			ret = 0;			break;		}	return ret;}EXPORT_SYMBOL(pnx4008_get_fb_addresses);int pnx4008_alloc_dum_channel(int dev_id){	int i = 0;	while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1))		i++;	if (i == MAX_DUM_CHANNELS)		return -ENORESOURCESLEFT;	else {		dum_data.fb_owning_channel[i] = dev_id;		return i;	}}EXPORT_SYMBOL(pnx4008_alloc_dum_channel);int pnx4008_free_dum_channel(int channr, int dev_id){	if (channr < 0 || channr > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[channr] != dev_id)		return -EFBNOTOWNER;	else {		clear_channel(channr);		dum_data.fb_owning_channel[channr] = -1;	}	return 0;}EXPORT_SYMBOL(pnx4008_free_dum_channel);int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id){	int i = chan_uf.channelnr;	int ret;	if (i < 0 || i > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[i] != dev_id)		return -EFBNOTOWNER;	else if ((ret =		  display_open(chan_uf.channelnr, 0, chan_uf.dirty,			       chan_uf.source, chan_uf.y_offset,			       chan_uf.x_offset, chan_uf.height,			       chan_uf.width)) != 0)		return ret;	else {		dum_data.chan_uf_store[i].dirty = chan_uf.dirty;		dum_data.chan_uf_store[i].source = chan_uf.source;		dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset;		dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset;		dum_data.chan_uf_store[i].width = chan_uf.width;		dum_data.chan_uf_store[i].height = chan_uf.height;	}	return 0;}EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id){	if (channr < 0 || channr > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[channr] != dev_id)		return -EFBNOTOWNER;	else {		if (val == CONF_SYNC_ON) {			DUM_CH_CONF(channr) |= CONF_SYNCENABLE;			DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK |				DUM_CHANNEL_CFG_SYNC_MASK_SET;		} else if (val == CONF_SYNC_OFF)			DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE;		else			return -EINVAL;	}	return 0;}EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id){	if (channr < 0 || channr > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[channr] != dev_id)		return -EFBNOTOWNER;	else {		if (val == CONF_DIRTYDETECTION_ON)			DUM_CH_CONF(channr) |= CONF_DIRTYENABLE;		else if (val == CONF_DIRTYDETECTION_OFF)			DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE;		else			return -EINVAL;	}	return 0;}EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);#if 0 /* Functions not used currently, but likely to be used in future */static int get_channel(struct dumchannel *p_chan){	int i = p_chan->channelnr;	if (i < 0 || i > MAX_DUM_CHANNELS)		return -EINVAL;	else {		p_chan->dum_ch_min = DUM_CH_MIN(i);		p_chan->dum_ch_max = DUM_CH_MAX(i);		p_chan->dum_ch_conf = DUM_CH_CONF(i);		p_chan->dum_ch_stat = DUM_CH_STAT(i);		p_chan->dum_ch_ctrl = 0;	/* WriteOnly control register */	}	return 0;}int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id){	int i = p_chan_uf->channelnr;	if (i < 0 || i > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[i] != dev_id)		return -EFBNOTOWNER;	else {		p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty;		p_chan_uf->source = dum_data.chan_uf_store[i].source;		p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset;		p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset;		p_chan_uf->width = dum_data.chan_uf_store[i].width;		p_chan_uf->height = dum_data.chan_uf_store[i].height;	}	return 0;}EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);int pnx4008_get_dum_channel_config(int channr, int dev_id){	int ret;	struct dumchannel chan;	if (channr < 0 || channr > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[channr] != dev_id)		return -EFBNOTOWNER;	else {		chan.channelnr = channr;		if ((ret = get_channel(&chan)) != 0)			return ret;	}	return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);}EXPORT_SYMBOL(pnx4008_get_dum_channel_config);int pnx4008_force_update_dum_channel(int channr, int dev_id){	if (channr < 0 || channr > MAX_DUM_CHANNELS)		return -EINVAL;	else if (dum_data.fb_owning_channel[channr] != dev_id)		return -EFBNOTOWNER;	else		DUM_CH_CTRL(channr) = CTRL_SETDIRTY;	return 0;}EXPORT_SYMBOL(pnx4008_force_update_dum_channel);#endifint pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma,		      struct device *dev){	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;	if (off < info->fix.smem_len) {		vma->vm_pgoff += 1;		return dma_mmap_writecombine(dev, vma,				(void *)dum_data.lcd_virt_start,				dum_data.lcd_phys_start,				FB_DMA_SIZE);	}	return -EINVAL;}EXPORT_SYMBOL(pnx4008_sdum_mmap);int pnx4008_set_dum_exit_notification(int dev_id){	int i;	for (i = 0; i < MAX_DUM_CHANNELS; i++)		if (dum_data.fb_owning_channel[i] == dev_id)			return -ERESOURCESNOTFREED;	return 0;}EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);/* Platform device driver for DUM */static int sdum_suspend(struct platform_device *pdev, pm_message_t state){	int retval = 0;	struct clk *clk;	clk = clk_get(0, "dum_ck");	if (!IS_ERR(clk)) {		clk_set_rate(clk, 0);		clk_put(clk);	} else		retval = PTR_ERR(clk);	/* disable BAC */	DUM_CTRL = V_BAC_DISABLE_IDLE;	/* LCD standby & turn off display */	lcd_reset();	return retval;}static int sdum_resume(struct platform_device *pdev){	int retval = 0;	struct clk *clk;	clk = clk_get(0, "dum_ck");	if (!IS_ERR(clk)) {		clk_set_rate(clk, 1);		clk_put(clk);	} else		retval = PTR_ERR(clk);	/* wait for BAC disable */	DUM_CTRL = V_BAC_DISABLE_TRIG;	while (DUM_CTRL & BAC_ENABLED)		udelay(10);	/* re-init LCD */	lcd_init();	/* enable BAC and reset MUX */	DUM_CTRL = V_BAC_ENABLE;	udelay(1);	DUM_CTRL = V_MUX_RESET;	return 0;}static int __devinit sdum_probe(struct platform_device *pdev){	int ret = 0, i = 0;	/* map frame buffer */	dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev,						       FB_DMA_SIZE,						       &dum_data.lcd_phys_start,						       GFP_KERNEL);	if (!dum_data.lcd_virt_start) {		ret = -ENOMEM;		goto out_3;	}	/* map slave registers */	dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE;	dum_data.slave_virt_base =	    (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32));	if (dum_data.slave_virt_base == NULL) {		ret = -ENOMEM;		goto out_2;	}	/* initialize DUM and LCD display */	ret = dum_init(pdev);	if (ret)		goto out_1;	dum_chan_init();	lcd_init();	DUM_CTRL = V_BAC_ENABLE;	udelay(1);	DUM_CTRL = V_MUX_RESET;	/* set decode address and sync clock divider */	DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK;	DUM_CLK_DIV = PNX4008_DUM_CLK_DIV;	for (i = 0; i < MAX_DUM_CHANNELS; i++)		dum_data.fb_owning_channel[i] = -1;	/*setup wakeup interrupt */	start_int_set_rising_edge(SE_DISP_SYNC_INT);	start_int_ack(SE_DISP_SYNC_INT);	start_int_umask(SE_DISP_SYNC_INT);	return 0;out_1:	iounmap((void *)dum_data.slave_virt_base);out_2:	dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,			(void *)dum_data.lcd_virt_start,			dum_data.lcd_phys_start);out_3:	return ret;}static int sdum_remove(struct platform_device *pdev){	struct clk *clk;	start_int_mask(SE_DISP_SYNC_INT);	clk = clk_get(0, "dum_ck");	if (!IS_ERR(clk)) {		clk_set_rate(clk, 0);		clk_put(clk);	}	iounmap((void *)dum_data.slave_virt_base);	dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,			(void *)dum_data.lcd_virt_start,			dum_data.lcd_phys_start);	return 0;}static struct platform_driver sdum_driver = {	.driver = {		.name = "pnx4008-sdum",	},	.probe = sdum_probe,	.remove = sdum_remove,	.suspend = sdum_suspend,	.resume = sdum_resume,};int __init sdum_init(void){	return platform_driver_register(&sdum_driver);}static void __exit sdum_exit(void){	platform_driver_unregister(&sdum_driver);};module_init(sdum_init);module_exit(sdum_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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