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

📄 bfin_ad7179fb_main.c

📁 ad7179的驱动程序
💻 C
字号:
/* * linux/drivers/video/bfin_ad7179.c -- Analog Devices Blackfin + AD7179 video out chip *  * Based on linux/drivers/video/bfin_ad7171_main.c * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> * Copyright 2004 Ashutosh Kumar Singh (ashutosh.singh@rrap-software.com) * Copyright 2006 Sergio Trofino (sergio.trofino@rayvision.com.br) * 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/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/blackfin.h>#include <asm/irq.h>#include <asm/dma.h>#include <linux/dma-mapping.h>#include "bfin_ad7179fb.h"#define BFIN_FB_PHYS_LEN (RGB_WIDTH*RGB_HEIGHT*sizeof(struct rgb_t))#define BFIN_FB_YCRCB_LEN (YCBCR_WIDTH*YCBCR_HEIGHT)struct dma_descriptor {	unsigned int * next_desc;	unsigned int * start_addr;} descriptor;unsigned char * ycrcb_buffer1 = 0x02000000, * ycrcb_buffer2 = 0x03000000;struct timer_list bfin_framebuffer_timer;static int bfin_ad7179_fb_open(struct fb_info *info, int user);static int bfin_ad7179_fb_release(struct fb_info *info, int user);static int bfin_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);static void bfin_config_ppi(void);static void bfin_config_dma(void *ycrcb_buffer1);static void bfin_disable_dma(void);static void bfin_enable_ppi(void);static void bfin_disable_ppi(void);static void bfin_framebuffer_init(void *ycrcb_buffer1, void *ycrcb_buffer2);static void bfin_framebuffer_update(unsigned char *ycrcb_buffer1, unsigned char *ycrcb_buffer2);static void bfin_framebuffer_timer_setup(void);static void bfin_framebuffer_timerfn(unsigned long data);//extern unsigned long l1_data_A_sram_alloc(unsigned long size);//extern int l1_data_A_sram_free(unsigned long addr);#include <linux/video_encoder.h>#include <linux/videodev.h>static char adv7179_name[] = "adv7179";static char *norms[] = { "PAL", "NTSC" };/* * card parameters */static struct fb_info bfin_ad7179_fb;static struct bfin_ad7179_fb_par {	/* structure holding blackfin / ad7179 paramters when           screen is blanked */	struct {		unsigned char	Mode;		/* ntsc/pal/? */	} vga_state;	atomic_t ref_count;} bfin_par;/* --------------------------------------------------------------------- */static struct fb_var_screeninfo bfin_ad7179_fb_defined = {	.xres		= RGB_WIDTH,	.yres		= RGB_HEIGHT,	.xres_virtual	= RGB_WIDTH,	.yres_virtual	= RGB_HEIGHT,	.bits_per_pixel	= 16,		.activate	= FB_ACTIVATE_TEST,	.height		= -1,	.width		= -1,	.left_margin	= 0,	.right_margin	= 0,	.upper_margin	= 0,	.lower_margin	= 0,	.vmode		= FB_VMODE_INTERLACED,};static struct fb_fix_screeninfo bfin_ad7179_fb_fix __initdata = {	.id		= "BFIN 7179",	.smem_len	= BFIN_FB_PHYS_LEN,	.type		= FB_TYPE_PACKED_PIXELS,	.visual		= FB_VISUAL_TRUECOLOR,	.xpanstep	= 0,	.ypanstep	= 0,	.line_length	= RGB_WIDTH*2,	.accel		= FB_ACCEL_NONE};static struct fb_ops bfin_ad7179_fb_ops = {	.owner		= THIS_MODULE,	.fb_open        = bfin_ad7179_fb_open,	.fb_release     = bfin_ad7179_fb_release,	.fb_mmap	= bfin_fb_mmap,};static void bfin_framebuffer_timer_setup(void){	init_timer(&bfin_framebuffer_timer) ;        bfin_framebuffer_timer.function = bfin_framebuffer_timerfn ;        bfin_framebuffer_timer.expires = jiffies + 10 ;	add_timer(&bfin_framebuffer_timer);}static void bfin_framebuffer_timerfn(unsigned long data){	bfin_framebuffer_update(ycrcb_buffer1, ycrcb_buffer2);	bfin_framebuffer_timer_setup();}	static int bfin_fb_mmap(struct fb_info *info, struct vm_area_struct * vma){  /* we really dont need any map ... not sure how the smem_start will     end up in the kernel  */	int a;	a = ycrcb_buffer2;	*(ycrcb_buffer1 + 900900) = a>>24;	*(ycrcb_buffer1 + 900901) = a>>16;	*(ycrcb_buffer1 + 900902) = a>>8;	*(ycrcb_buffer1 + 900903) = a;	vma->vm_start  = (int)ycrcb_buffer1;	return (int)ycrcb_buffer1;}static void bfin_framebuffer_init(void *ycrcb_buffer1, void *ycrcb_buffer2){	/*unsigned char * ycrcb_ptr = ycrcb_buffer;	int i, j;		for(j = 0; j < (RGB_WIDTH * YCBCR_HEIGHT); j++)		{			*ycrcb_ptr++=0x80;			*ycrcb_ptr++=0x10;		}*/	char *dest1 = (void *)ycrcb_buffer1;	char *dest2 = (void *)ycrcb_buffer2;        int lines;                                                                                                                                                             	for ( lines = 0; lines < YCBCR_HEIGHT; lines++ )	{	        int offset = 0;		unsigned int code;	        int i;#ifdef CONFIG_NTSC		if((lines>=0 && lines<=2) || (lines>=265 && lines <=281))			offset = 0;		else if((lines>=3 && lines<=18) || (lines>=263 && lines<=264))			offset = 1;		else if(lines>=19 && lines<=262)			offset = 2;		else if(lines>=282 && lines<=524)			offset = 3;#else // CONFIG_PAL		if((lines>=1 && lines<=22) || (lines>=311 && lines<=312))			offset = 0;		else if(lines>=23 && lines<=310)			offset = 1;		else if((lines>=313 && lines<=335) || (lines>=624 && lines <=625))			offset = 2;		else if(lines>=336 && lines<=623)			offset = 3;#endif		else				printk("Frame buffer init error\n");		                                                                                                                                             	        // Output EAV code	        code = system_code_map[ offset ].eav;	        *dest1++ = (char) (code >> 24) & 0xff;	        *dest1++ = (char) (code >> 16) & 0xff;	        *dest1++ = (char) (code >> 8) & 0xff;	        *dest1++ = (char) (code) & 0xff;		*dest2++ = (char) (code >> 24) & 0xff;	        *dest2++ = (char) (code >> 16) & 0xff;	        *dest2++ = (char) (code >> 8) & 0xff;	        *dest2++ = (char) (code) & 0xff;	                                                                                                                                             	        // Output horizontal blanking	        for ( i = 0; i < HB_LENGTH/2; ++i )	        {	                *dest1++ = 0x80;	                *dest1++ = 0x10;			*dest2++ = 0x80;	                *dest2++ = 0x10;	        }	                                                                                                                                             	        // Output SAV	        code = system_code_map[ offset ].sav;	        *dest1++ = (char) (code >> 24) & 0xff;	        *dest1++ = (char) (code >> 16) & 0xff;	        *dest1++ = (char) (code >> 8) & 0xff;	        *dest1++ = (char) (code) & 0xff;		*dest2++ = (char) (code >> 24) & 0xff;	        *dest2++ = (char) (code >> 16) & 0xff;	        *dest2++ = (char) (code >> 8) & 0xff;	        *dest2++ = (char) (code) & 0xff;	                                                                                                                                             	        // Output empty horizontal data	        for ( i = 0; i <RGB_WIDTH; ++i )	        {	                *dest1++ = 0x80;	                *dest1++ = 0x10;			*dest2++ = 0x80;	                *dest2++ = 0x10;	        }        }}void bfin_framebuffer_update(unsigned char *ycrcb_buffer1, unsigned char *ycrcb_buffer2){	if (*(ycrcb_buffer1+900902))	{		*(ycrcb_buffer1+900902) = 0;		if (*(ycrcb_buffer1+900901) == 1)			descriptor.start_addr = (unsigned int *) ycrcb_buffer1;		else			descriptor.start_addr = (unsigned int *) ycrcb_buffer2;	}}	static void bfin_config_dma(void *ycrcb_buffer1){		descriptor.next_desc = (unsigned int *) &descriptor;	descriptor.start_addr = (unsigned int *) ycrcb_buffer1;	bfin_write_DMA1_1_NEXT_DESC_PTR((unsigned int *)&descriptor);	bfin_write_DMA1_1_START_ADDR(ycrcb_buffer1);	bfin_write_DMA1_1_X_COUNT(YCBCR_WIDTH/4);        bfin_write_DMA1_1_X_MODIFY(0x0004);        bfin_write_DMA1_1_Y_COUNT(YCBCR_HEIGHT);        bfin_write_DMA1_1_Y_MODIFY(0x0004);        bfin_write_DMA1_1_CONFIG(0x7419);#if 0        *pDMA1_1_START_ADDR       = ycrcb_buffer;        *pDMA1_1_X_COUNT          = YCBCR_WIDTH/2;        *pDMA1_1_X_MODIFY         = 0x0002;        *pDMA1_1_Y_COUNT          = YCBCR_HEIGHT;        *pDMA1_1_Y_MODIFY         = 0x0002;        *pDMA1_1_CONFIG           = 0x1015;#endif	}static void bfin_disable_dma(void){	bfin_write_DMA1_1_CONFIG(bfin_read_DMA1_1_CONFIG() & (~DMAEN));#if 0	*pDMA1_1_CONFIG		&= ~DMAEN;#endif}static void bfin_config_ppi(void){#ifdef CONFIG_BF537        *pPORTG_FER   = 0xFFFF; /* PPI[15:0]    */        *pPORTF_FER  |= 0x8380; /* PF.15 - PPI_CLK */        *pPORT_MUX   &= ~0x0E00;        *pPORT_MUX   |= 0x0100;#endif	bfin_write_PPI1_CONTROL(0x0182);//	bfin_write_PPI1_COUNT(720*2-1);//	bfin_write_PPI1_DELAY(122*2-1);        bfin_write_PPI1_FRAME(YCBCR_HEIGHT-1);}static void bfin_enable_ppi(void){	bfin_write_PPI1_CONTROL(bfin_read_PPI1_CONTROL() | PORT_EN);#if 0	*pPPI1_CONTROL		* matriz_y_i = malloc( sizeof(dma_img_dsc) * 2);|= PORT_EN;#endif}static void bfin_disable_ppi(void){	bfin_write_PPI1_CONTROL(bfin_read_PPI1_CONTROL() & (~PORT_EN));#if 0	*pPPI1_CONTROL		&= ~PORT_EN;#endif}static void Reset_ADV7179(void){	bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | RESET_ADV7179);	udelay(DELAY_RESET);	// generate reset pulse	bfin_write_FIO0_FLAG_C(RESET_ADV7179);	// clear bit to reset ADV7179 	udelay(DELAY_RESET);	bfin_write_FIO0_FLAG_S(RESET_ADV7179);	// set bit to re-enable ADV7179 	udelay(DELAY_RESET);#if 0	*pFIO0_DIR |= RESET_ADV7179;	udelay(DELAY_RESET);	// generate reset pulse	*pFIO0_FLAG_C = RESET_ADV7179;	// clear bit to reset ADV7179 	udelay(DELAY_RESET);	*pFIO0_FLAG_S = RESET_ADV7179;	// set bit to re-enable ADV7179 	udelay(DELAY_RESET);#endif}int __init bfin_ad7179_fb_init(void){	int ret = 0;		// configure RESET flag as output		Reset_ADV7179();	udelay(5 * (DELAY_RESET));	printk(KERN_NOTICE "bfin_ad7179_fb: initializing:\n");	//ycrcb_buffer1 = (unsigned char *)kmalloc(BFIN_FB_YCRCB_LEN+4, GFP_KERNEL);	//memset(ycrcb_buffer1, 0, BFIN_FB_YCRCB_LEN);	//ycrcb_buffer2 = (unsigned char *)kmalloc(BFIN_FB_YCRCB_LEN, GFP_KERNEL);	//memset(ycrcb_buffer2, 0, BFIN_FB_YCRCB_LEN);	bfin_ad7179_fb.screen_base = (void *)ycrcb_buffer1;	bfin_ad7179_fb_fix.smem_start = (int)ycrcb_buffer1;	if (!bfin_ad7179_fb.screen_base) {		printk("bfin_ad7179_fb: unable to map device\n");		ret = -ENOMEM;	}	bfin_ad7179_fb_defined.red.length   = 8;	bfin_ad7179_fb_defined.green.length = 8;	bfin_ad7179_fb_defined.blue.length  = 8;		bfin_ad7179_fb.fbops = &bfin_ad7179_fb_ops;	bfin_ad7179_fb.var = bfin_ad7179_fb_defined;	// our physical memory is dynamically allocated	bfin_ad7179_fb_fix.smem_start	= (int)ycrcb_buffer1;	bfin_ad7179_fb.fix = bfin_ad7179_fb_fix;	bfin_ad7179_fb.par = &bfin_par;	bfin_ad7179_fb.flags = FBINFO_DEFAULT;	if (register_framebuffer(&bfin_ad7179_fb) < 0) {		printk(KERN_ERR "bfin_ad7179_fb: unable to register framebuffer\n");		ret = -EINVAL;	}	printk(KERN_INFO "fb%d: %s frame buffer device\n",	       bfin_ad7179_fb.node, bfin_ad7179_fb.fix.id);	printk(KERN_INFO "fb memory address : 0x%p\n",ycrcb_buffer1);	return ret;}static int bfin_ad7179_fb_open(struct fb_info *info, int user){	bfin_ad7179_fb.screen_base = (void *)ycrcb_buffer1;	bfin_ad7179_fb_fix.smem_start = (int)ycrcb_buffer1;	if (!bfin_ad7179_fb.screen_base) {		printk("bfin_ad7179_fb: unable to map device\n");		return -ENOMEM;	}        bfin_framebuffer_init(ycrcb_buffer1, ycrcb_buffer2);	bfin_framebuffer_timer_setup(); 	bfin_config_ppi();	bfin_config_dma(ycrcb_buffer1);	bfin_enable_ppi();	return 0;}static int bfin_ad7179_fb_release(struct fb_info *info, int user){	del_timer(&bfin_framebuffer_timer);	bfin_disable_dma();	bfin_disable_ppi();	return 0;}static void __exit bfin_ad7179_fb_exit(void){	if(ycrcb_buffer1)                kfree(ycrcb_buffer1);	if(ycrcb_buffer2)                kfree(ycrcb_buffer2);	unregister_framebuffer(&bfin_ad7179_fb);}MODULE_LICENSE("GPL");module_init(bfin_ad7179_fb_init);module_exit(bfin_ad7179_fb_exit);

⌨️ 快捷键说明

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