?? bfin_ad7179fb_main.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 + -