2006-10-27 11:26:54 video frame display with ADV7179
ZC L (SINGAPORE)
Message: 15647 Hi All,
Now the "video frame capture with ADV7183" is done and it's time to continue on the output portion, especially for BF561_EZKIT without card extender, so that we can check the input frame. So, anybody using the driver for ppi1 for video out?
zhichien
QuoteReplyEditDelete
2006-10-28 21:34:38 RE: video frame display with ADV7179
Alex Pereira (BRAZIL)
Message: 15677 Me and a co-worker, sergio trofino, have worked in a device driver for adv7179 on ez-kit bf561. It's been posted in http://blackfin.uclinux.org/forum/message.php?msg_id=13193
Is it what you're looking for?
Alex
QuoteReplyEditDelete
2006-10-30 01:04:21 RE: video frame display with ADV7179
ZC L (SINGAPORE)
Message: 15688 Hi Alex,
Yes. It is the codes that I'm looking for but looks very different from the adv7183 driver that Laimonas has created(http://blackfin.uclinux.org/forum/message.php?msg_id=15308). Can you please guide me on how to combine the two source codes?
Thanks a lot.
zhichien
QuoteReplyEditDelete
2006-10-30 09:23:25 RE: video frame display with ADV7179
sima sima (UNITED STATES)
Message: 15717 hi
I used adv7181 and is successful to capture images from PPI0 to fb0,and 7171 can display them from fb0 to LCD,but I just used one buffer.I thought it was the same as two buffers ,I did it ,as a result just I thought
QuoteReplyEditDelete
2006-10-30 09:49:59 RE: video frame display with ADV7179
ZC L (SINGAPORE)
Message: 15719 Hi,
You working on BF533_EZKIT?
QuoteReplyEditDelete
2006-11-08 10:33:59 RE: video frame display with ADV7179
sui april (CHINA)
Message: 16175 Hi Alex,
After you finished the ADV7179 driver, have you done the test program for the ADV7179 application? i try to write the app program, but cannot call the function in the driver.
i hope your help. thank you very much
QuoteReplyEditDelete
2006-11-23 13:00:08 RE: video frame display with ADV7179
Alex Pereira (BRAZIL)
Message: 16787 zhichien,
sorry to answer too late. I just saw you message. I could help you implement this driver, as I already have it here.
The IC ADV7179 is quite the same as 7179 when we think about how to use it. But EZ-KIT 533 and 561 are a little different from each other. So, in EZ-KIT 561 you have to generate a reset pulse as follows in Reset_ADV7179 funciont. Say thank you to Sergio Trofino, the guy who found it.
First reset ADV7179 with PF using this funcition:
#define RESET_ADV7179 0x4000
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);
}
Then fix some mismacth functions name that appear when using 533 code in 561.
Alex
QuoteReplyEditDelete
2006-11-24 01:11:23 RE: video frame display with ADV7179
ZC L (SINGAPORE)
Message: 16806 Hi Alex,
Thanks for replying. Can you send me a copy of the codes? I found there is some undefined value. (Such as RGB_HEIGHT, YCBCR_WIDTH).
And may I know what should be displayed on the monitor?
Thank you.
QuoteReplyEditDelete
2006-11-26 13:03:05 RE: video frame display with ADV7179
Alex Pereira (BRAZIL)
Message: 16885 Here a copy of bfin_ad7179fb.h file:
/*
* linux/drivers/video/bfin_ad7179.h -- Analog Devices Blackfin + AD7179 video out chip
*
* Based on vga16fb.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)
*
* 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.
*/
#define CONFIG_NTSC
#define BLACK (0x01800180) /* black pixel pattern */
#define BLUE (0x296E29F0) /* blue pixel pattern */
#define RED (0x51F0515A) /* red pixel pattern */
#define MAGENTA (0x6ADE6ACA) /* magenta pixel pattern*/
#define GREEN (0x91229136) /* green pixel pattern */
#define CYAN (0xAA10AAA6) /* cyan pixel pattern */
#define YELLOW (0xD292D210) /* yellow pixel pattern */
#define WHITE (0xFE80FE80) /* white pixel pattern */
#define true 1
#define false 0
struct system_code_type
{
unsigned int sav; /* Start of Active Video */
unsigned int eav; /* End of Active Video */
};
#ifdef CONFIG_NTSC
const struct system_code_type system_code_map[4] =
{
{ 0xFF0000EC, 0xFF0000F1 },
{ 0xFF0000AB, 0xFF0000B6 },
{ 0xFF000080, 0xFF00009D },
{ 0xFF0000C7, 0xFF0000DA }
};
#define FIELD1_VB_START 0
#define FIELD1_VB_END 18
#define FIELD1_AV_START 19
#define FIELD1_AV_END 262
#define FIELD2_VB_START 263
#define FIELD2_VB_END 281
#define FIELD2_AV_START 282
#define FIELD2_AV_END 524
#define HB_LENGTH 268
#define RGB_WIDTH 720
#define RGB_HEIGHT 480
#define YCBCR_WIDTH 1716
#define YCBCR_HEIGHT 525
#else /* CONFIG_PAL */
const struct system_code_type system_code_map[4] =
{
{ 0xFF0000AB, 0xFF0000B6 },
{ 0xFF000080, 0xFF00009D },
{ 0xFF0000EC, 0xFF0000F1 },
{ 0xFF0000C7, 0xFF0000DA }
};
#define FIELD1_VB_START 1
#define FIELD1_VB_END 22
#define FIELD1_AV_START 23
#define FIELD1_AV_END 310
#define FIELD2_VB_START 311
#define FIELD2_VB_END 335
#define FIELD2_AV_START 336
#define FIELD2_AV_END 623
#define FIELD2_VB2_START 624
#define FIELD2_VB2_END 625
#define HB_LENGTH 280
#define RGB_WIDTH 720
#define RGB_HEIGHT 576
#define YCBCR_WIDTH 1728
#define YCBCR_HEIGHT 625
#endif /* CONFIG_NTSL */
struct rgb_t{
unsigned char r,g,b;
} ;
struct ycrcb_t{
unsigned char Cb,y1,Cr,y2;
};
struct adv7179 {
unsigned char reg[128];
int norm;
int input;
int enable;
int bright;
int contrast;
int hue;
int sat;
};
#define I2C_ADV7179 0x54
#define RESET_ADV7179 0x4000
#define DELAY_RESET 40
=============================================
Here a copy of ad7179fb_main.c file:
/*
* 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 = 0, * ycrcb_buffer2 = 0;
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);
QuoteReplyEditDelete
2007-05-08 22:25:59 RE: video frame display with ADV7179
ZC L (SINGAPORE)
Message: 26065
Hi Alex,
It has been a long time since my last post. I finally got the AD7183 raw image. I'm wondering how the AD7179fb driver can take the raw image and display on the TV monitor?
Thanks a lot.
zhichien
QuoteReplyEditDelete
2008-06-17 13:27:50 RE: video frame display with ADV7179
Justin Wetherell (UNITED STATES)
Message: 57418
If anyone has more info on how to get an image from the ppi to the fb for the 561+Eval board, it'd be greatly appreciated.