diff options
author | Michael Hunold <devnull@localhost> | 2002-12-30 21:10:58 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2002-12-30 21:10:58 +0000 |
commit | d425bfb33eedb26e9878187a4f8506db80cee364 (patch) | |
tree | d85c70f34dcb9829043d9b22248a9b2693a1a361 /linux/drivers/media/common | |
parent | 4ac441dd0b30a80cdcf026cc2952cc547bf5dbad (diff) | |
download | mediapointer-dvb-s2-d425bfb33eedb26e9878187a4f8506db80cee364.tar.gz mediapointer-dvb-s2-d425bfb33eedb26e9878187a4f8506db80cee364.tar.bz2 |
Next chunk of big splitup / cleanup:
(tested on 2.4.18 and 2.5.53 -- the budget driver is
untested, Holger will test it the next week)
saa7146:
- completely separated the saa7146 driver into a core-driver (saa7146.o) and
a video/vbi part (saa7146_vv.o). this allows you to build the budget driver
without av7110 and videodev bloat (see below)
The following thinks have been approved by Holger Waechtler:
av7110 (now ttpci):
- for 2.5.x: removed the av7110 directory and put everything into ttpci.
- removed all budget card support from this driver
- compile and build fixes for the saa7146 changes
ttpci-budget (new):
- for 2.5.x: created a new ttpci-budget directory, added a new driver for
the budget cards
mxb:
- compile and build fixes for the saa7146 changes
Changed the build and compile files for both 2.5.x and build-2.4 of course...
Diffstat (limited to 'linux/drivers/media/common')
-rw-r--r-- | linux/drivers/media/common/saa7146.h | 306 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 47 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_fops.c | 139 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_hlp.c | 82 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_vbi.c | 69 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_video.c | 186 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_vv.h | 269 |
7 files changed, 623 insertions, 475 deletions
diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index b35b14672..81b06e9c7 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -17,13 +17,6 @@ from flaws in video-buf.c => Gerd Knorr */ #include <asm/io.h> /* for accessing devices */ #include <linux/stringify.h> -#include <linux/videodev2.h> -#include "video-buf.h" - -#define MAX_SAA7146_CAPTURE_BUFFERS 32 /* arbitrary */ - -#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ - #define SAA7146_VERSION_CODE KERNEL_VERSION(0,5,0) #define saa7146_write(sxy,adr,dat) writel((dat),(sxy->mem+(adr))) @@ -57,37 +50,29 @@ extern unsigned int saa7146_debug; saa7146_write(x, IER, saa7146_read(x, IER) | (y)); struct saa7146_dev; -struct saa7146_fh; -struct saa7146_standard; - -struct saa7146_extension_ioctls -{ - unsigned int cmd; - int flags; -}; +struct saa7146_extension; +struct saa7146_vv; struct saa7146_sub_info { unsigned int subvendor, subdevice; }; -#define SAA7146_EXCLUSIVE 0x1 -#define SAA7146_BEFORE 0x2 -#define SAA7146_AFTER 0x4 - -/* flags */ -#define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */ +/* saa7146 page table */ +struct saa7146_pgtable { + unsigned int size; + u32 *cpu; + dma_addr_t dma; + /* used for offsets for u,v planes for planar capture modes */ + unsigned long offset; +}; struct saa7146_extension { char name[32]; /* name of the device */ - int inputs; - int audios; - u32 capabilities; - - int flags; + struct saa7146_ext_vv *ext_vv_data; struct list_head item; - + /* pairs of subvendor and subdevice ids for supported devices, last entry 0xffff, 0xfff */ struct saa7146_sub_info *devices; @@ -98,13 +83,6 @@ struct saa7146_extension void (*inc_use)(struct saa7146_dev*); void (*dec_use)(struct saa7146_dev*); #endif - - /* additionally supported transmission standards */ - struct saa7146_standard *stds; - int num_stds; - int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); - - struct saa7146_extension_ioctls *ioctls; /* extension functions */ int (*preinit)(struct saa7146_dev*); @@ -113,106 +91,12 @@ struct saa7146_extension int (*attach)(struct saa7146_dev*); int (*detach)(struct saa7146_dev*); - int (*ioctl)(struct saa7146_dev*, unsigned int cmd, void *arg); - u32 irq_mask; /* mask to indicate, which irq-events are handled by the extension */ void (*irq_func)(struct saa7146_dev*, u32* irq_mask); }; -struct saa7146_video_dma { - u32 base_odd; - u32 base_even; - u32 prot_addr; - u32 pitch; - u32 base_page; - u32 num_line_byte; -}; - -struct saa7146_format { - char *name; - int pixelformat; - u32 trans; - u8 depth; - unsigned long flags; -}; - -struct saa7146_standard -{ - char *name; - v4l2_std_id id; - - int v_offset; - int v_field; - int v_calc; - - int h_offset; - int h_pixels; - int h_calc; - - int v_max_out; - int h_max_out; -}; - -/* saa7146 page table */ -struct saa7146_pgtable { - unsigned int size; - u32 *cpu; - dma_addr_t dma; - /* used for offsets for u,v planes for planar capture modes */ - unsigned long offset; -}; - -/* buffer for one video/vbi frame */ -struct saa7146_buf { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - /* saa7146 specific */ - struct v4l2_pix_format *fmt; - int (*activate)(struct saa7146_dev *dev, - struct saa7146_buf *buf, - struct saa7146_buf *next); - - /* page tables */ - struct saa7146_pgtable pt[3]; -}; - -struct saa7146_dmaqueue { - struct saa7146_dev *dev; - struct saa7146_buf *curr; - struct list_head queue; - struct timer_list timeout; -}; - -struct saa7146_overlay { - struct saa7146_fh *fh; - struct v4l2_window win; - struct v4l2_clip clips[16]; - int nclips; -}; - -/* per open data */ -struct saa7146_fh { - struct saa7146_dev *dev; - /* if this is a vbi or capture open */ - enum v4l2_buf_type type; - - /* video overlay */ - struct saa7146_overlay ov; - - /* video capture */ - struct videobuf_queue video_q; - struct v4l2_pix_format video_fmt; - - /* vbi capture */ - struct videobuf_queue vbi_q; - struct v4l2_vbi_format vbi_fmt; - struct timer_list vbi_read_timeout; -}; - struct saa7146_dev { - /* used for loadable modules */ struct module *module; struct list_head item; @@ -220,7 +104,6 @@ struct saa7146_dev /* different device locks */ spinlock_t slock; struct semaphore lock; - struct semaphore i2c_lock; unsigned char *mem; /* pointer to mapped IO memory */ int revision; /* chip revision; needed for bug-workarounds*/ @@ -232,147 +115,41 @@ struct saa7146_dev /* extension handling */ struct saa7146_extension *ext; /* indicates if handled by extension */ void *ext_priv; /* pointer for extension private use (most likely some private data) */ - int video_minor, vbi_minor; - void (*video_irq_done)(struct saa7146_dev *dev, unsigned long status); - void (*vbi_irq_done)(struct saa7146_dev *dev, unsigned long status); + /* per device video/vbi informations (if available) */ + struct saa7146_vv *vv_data; + void (*vv_callback)(struct saa7146_dev *dev, unsigned long status); /* i2c-stuff */ - u32 i2c_bitrate; - u32 *i2c_mem; /* pointer to i2c memory */ - wait_queue_head_t i2c_wq; - int i2c_op; + struct semaphore i2c_lock; + u32 i2c_bitrate; + u32 *i2c_mem; /* pointer to i2c memory */ + wait_queue_head_t i2c_wq; + int i2c_op; /* memories */ - u32 *clipping; /* pointer to clipping memory */ - u32 *rps0; - u32 *rps1; - - /* vbi capture */ - struct saa7146_dmaqueue vbi_q; - /* vbi workaround interrupt queue */ - wait_queue_head_t vbi_wq; - int vbi_fieldcount; - struct saa7146_fh *vbi_streaming; - - /* video overlay */ - struct v4l2_framebuffer ov_fb; - struct saa7146_format *ov_fmt; - struct saa7146_overlay *ov_data; - - /* video capture */ - struct saa7146_dmaqueue video_q; - struct saa7146_fh *streaming; - - /* common: fixme? shouldn't this be in saa7146_fh? - (this leads to a more complicated question: shall the driver - store the different settings (for example S_INPUT) for every open - and restore it appropriately, or should all settings be common for - all opens? currently, we do the latter, like all other - drivers do... */ - struct saa7146_standard *standard; - - int vflip; - int hflip; - int current_hps_source; - int current_hps_sync; - -}; - -struct saa7146_use_ops { - void (*init)(struct saa7146_dev *dev); - void(*open)(struct saa7146_dev *dev, struct saa7146_fh *fh); - void (*release)(struct saa7146_dev *dev, struct saa7146_fh *fh,struct file *file); - void (*irq_done)(struct saa7146_dev *dev, unsigned long status); - ssize_t (*read)(struct file *file, char *data, size_t count, loff_t *ppos); - int (*capture_begin)(struct saa7146_fh *fh); - int (*capture_end)(struct saa7146_fh *fh); + u32 *rps0; + u32 *rps1; }; -/* from saa7146_fops.c */ -int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type); -int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev); - /* from saa7146_i2c.c */ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num, int retries); -/* from saa7146_hlp.c */ -void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v); -void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next); -void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) ; - -void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sync); -void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); - /* from saa7146_core.c */ extern struct list_head saa7146_devices; extern struct semaphore saa7146_devices_lock; - int saa7146_register_extension(struct saa7146_extension*); int saa7146_unregister_extension(struct saa7146_extension*); struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); - -void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state); -void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi); -int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf); -void saa7146_buffer_timeout(unsigned long data); -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf); - int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt); void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt); void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length ); - -/* from saa7146_video.c */ -extern struct saa7146_use_ops saa7146_video_uops; - -/* from saa7146_vbi.c */ -extern struct saa7146_use_ops saa7146_vbi_uops; - -/* saa7146 source inputs */ -#define SAA7146_HPS_SOURCE_PORT_A 0x00 -#define SAA7146_HPS_SOURCE_PORT_B 0x01 -#define SAA7146_HPS_SOURCE_YPB_CPA 0x02 -#define SAA7146_HPS_SOURCE_YPA_CPB 0x03 - -/* sync inputs */ -#define SAA7146_HPS_SYNC_PORT_A 0x00 -#define SAA7146_HPS_SYNC_PORT_B 0x01 - -/* number of vertical active lines */ -#define V_ACTIVE_LINES_PAL 576 -#define V_ACTIVE_LINES_NTSC 480 -#define V_ACTIVE_LINES_SECAM 576 - -/* number of lines in a field for HPS to process */ -#define V_FIELD_PAL 288 -#define V_FIELD_NTSC 240 -#define V_FIELD_SECAM 288 - -/* number of lines of vertical offset before processing */ -#define V_OFFSET_PAL 0x17 -#define V_OFFSET_NTSC 0x16 -#define V_OFFSET_SECAM 0x14 - -/* number of horizontal pixels to process */ -#define H_PIXELS_PAL 680 -#define H_PIXELS_NTSC 708 -#define H_PIXELS_SECAM 720 - -/* horizontal offset of processing window */ -#define H_OFFSET_PAL 0x14 -#define H_OFFSET_NTSC 0x06 -#define H_OFFSET_SECAM 0x14 - -#define SAA7146_PAL_VALUES V_OFFSET_PAL, V_FIELD_PAL, V_ACTIVE_LINES_PAL, H_OFFSET_PAL, H_PIXELS_PAL, H_PIXELS_PAL+1, V_ACTIVE_LINES_PAL, 768 -#define SAA7146_NTSC_VALUES V_OFFSET_NTSC, V_FIELD_NTSC, V_ACTIVE_LINES_NTSC, H_OFFSET_NTSC, H_PIXELS_NTSC, H_PIXELS_NTSC+1, V_ACTIVE_LINES_NTSC, 640 -#define SAA7146_SECAM_VALUES V_OFFSET_SECAM, V_FIELD_SECAM, V_ACTIVE_LINES_SECAM, H_OFFSET_SECAM, H_PIXELS_SECAM, H_PIXELS_SECAM+1, V_ACTIVE_LINES_SECAM, 768 +void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data); /* some memory sizes */ -#define SAA7146_CLIPPING_MEM (14*PAGE_SIZE) -#define SAA7146_RPS_MEM ( 1*PAGE_SIZE) #define SAA7146_I2C_MEM ( 1*PAGE_SIZE) -#define SAA7146_DEBI_MEM ( 8*PAGE_SIZE) +#define SAA7146_RPS_MEM ( 1*PAGE_SIZE) /* some i2c constants */ #define SAA7146_I2C_TIMEOUT 100 /* i2c-timeout-value in ms */ @@ -383,11 +160,13 @@ extern struct saa7146_use_ops saa7146_vbi_uops; #define ME1 0x0000000800 #define PV1 0x0000000008 -/* some defines for the various clipping-modes */ -#define SAA7146_CLIPPING_RECT 0x4 -#define SAA7146_CLIPPING_RECT_INVERTED 0x5 -#define SAA7146_CLIPPING_MASK 0x6 -#define SAA7146_CLIPPING_MASK_INVERTED 0x7 +/* gpio defines */ +#define SAA7146_GPIO_INPUT 0x00 +#define SAA7146_GPIO_IRQHI 0x10 +#define SAA7146_GPIO_IRQLO 0x20 +#define SAA7146_GPIO_IRQHL 0x30 +#define SAA7146_GPIO_OUTLO 0x40 +#define SAA7146_GPIO_OUTHI 0x50 /* define for the register programming sequencer (rps) */ #define CMD_NOP 0x00000000 /* No operation */ @@ -415,29 +194,6 @@ extern struct saa7146_use_ops saa7146_vbi_uops; #define CMD_O_FID_A MASK_12 #define CMD_E_FID_A MASK_11 -/* output formats: each entry holds four informations */ -#define RGB08_COMPOSED 0x0217 /* composed is used in the sense of "not-planar" */ -/* this means: planar?=0, yuv2rgb-conversation-mode=2, dither=yes(=1), format-mode = 7 */ -#define RGB15_COMPOSED 0x0213 -#define RGB16_COMPOSED 0x0210 -#define RGB24_COMPOSED 0x0201 -#define RGB32_COMPOSED 0x0202 - -#define Y8 0x0006 -#define YUV411_COMPOSED 0x0003 -#define YUV422_COMPOSED 0x0000 -/* this means: planar?=1, yuv2rgb-conversion-mode=0, dither=no(=0), format-mode = b */ -#define YUV411_DECOMPOSED 0x100b -#define YUV422_DECOMPOSED 0x1009 -#define YUV420_DECOMPOSED 0x100a - -#define IS_PLANAR(x) (x & 0xf000) - -/* misc defines */ -#define SAA7146_NO_SWAP (0x0) -#define SAA7146_TWO_BYTE_SWAP (0x1) -#define SAA7146_FOUR_BYTE_SWAP (0x2) - /* Bit mask constants */ #define MASK_00 0x00000001 /* Mask value for bit 0 */ #define MASK_01 0x00000002 /* Mask value for bit 1 */ diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index 1ebb7ed36..1b4ca2222 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -116,9 +116,21 @@ void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *p } /********************************************************************************/ +/* gpio functions */ + +void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data) +{ + u32 val = 0; + + val=saa7146_read(dev,GPIO_CTRL); + val&=~(0xff << (8*(port))); + val|=(data)<<(8*(port)); + saa7146_write(dev, GPIO_CTRL, val); +} + +/********************************************************************************/ /* interrupt handler */ -/* FIXME: here are dependencies to the video and vbi code... */ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) { struct saa7146_dev *dev = (struct saa7146_dev*)dev_id; @@ -146,24 +158,16 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) } if (0 != (isr & (MASK_27))) { DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); - if( 0 != dev->video_irq_done ) { - dev->video_irq_done(dev,isr); + if( 0 != dev->vv_data && 0 != dev->vv_callback) { + dev->vv_callback(dev,isr); } isr &= ~MASK_27; } if (0 != (isr & (MASK_28))) { - u32 mc2 = saa7146_read(dev, MC2); - isr &= ~MASK_28; - if( 0 != (mc2 & MASK_15)) { - DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr)); - wake_up(&dev->vbi_wq); - saa7146_write(dev,MC2, MASK_31); - return; - } - DEB_INT(("irq: RPS1 (0x%08x).\n",isr)); - if( 0 != dev->vbi_irq_done ) { - dev->vbi_irq_done(dev,isr); + if( 0 != dev->vv_data && 0 != dev->vv_callback) { + dev->vv_callback(dev,isr); } + isr &= ~MASK_28; } if (0 != (isr & (MASK_16|MASK_17))) { u32 status = saa7146_read(dev, I2C_STATUS); @@ -427,14 +431,9 @@ static int config_a_device(struct pci_dev *pci) goto kmalloc_error_2; memset(dev->rps1, 0x0, SAA7146_RPS_MEM); - dev->clipping = (u32*)kmalloc(SAA7146_CLIPPING_MEM, GFP_KERNEL); - if( NULL == dev->clipping ) - goto kmalloc_error_3; - memset(dev->clipping, 0x0, SAA7146_CLIPPING_MEM); - dev->i2c_mem = (u32*)kmalloc(SAA7146_I2C_MEM, GFP_KERNEL); if( NULL == dev->i2c_mem ) - goto kmalloc_error_4; + goto kmalloc_error_3; memset(dev->i2c_mem, 0x00, SAA7146_I2C_MEM); /* the rest + print status message */ @@ -459,13 +458,8 @@ static int config_a_device(struct pci_dev *pci) dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); - dev->video_minor = -1; - dev->vbi_minor = -1; - return try_match_device_to_extension(dev); -kmalloc_error_4: - kfree( dev->clipping ); kmalloc_error_3: kfree( dev->rps1 ); kmalloc_error_2: @@ -494,7 +488,6 @@ static void unconfig_a_device(struct saa7146_dev* dev) /* free kernel memory */ kfree(dev->rps0 ); kfree(dev->rps1 ); - kfree(dev->clipping); kfree(dev->i2c_mem); iounmap(dev->mem); @@ -586,6 +579,8 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); EXPORT_SYMBOL_GPL(saa7146_pgtable_free); EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); +EXPORT_SYMBOL_GPL(saa7146_setgpio); + EXPORT_SYMBOL_GPL(saa7146_i2c_transfer); EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); EXPORT_SYMBOL_GPL(saa7146_debug); diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c index d8202c65f..594b6a379 100644 --- a/linux/drivers/media/common/saa7146_fops.c +++ b/linux/drivers/media/common/saa7146_fops.c @@ -1,9 +1,10 @@ -#include "saa7146.h" +#include "saa7146_vv.h" + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) #define KBUILD_MODNAME saa7146 #endif -#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vbi_minor != -1) +#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) /********************************************************************************/ /* common dma functions */ @@ -148,7 +149,7 @@ void saa7146_buffer_timeout(unsigned long data) /* file operations */ static -int video_open(struct inode *inode, struct file *file) +int fops_open(struct inode *inode, struct file *file) { unsigned int minor = minor(inode->i_rdev); struct saa7146_dev *h = NULL, *dev = NULL; @@ -165,11 +166,16 @@ int video_open(struct inode *inode, struct file *file) list_for_each(list,&saa7146_devices) { h = list_entry(list, struct saa7146_dev, item); - DEB_D(("trying: %p @ major %d,%d\n",h,h->video_minor,h->vbi_minor)); - if (h->video_minor == minor) { + if( NULL == h->vv_data ) { + DEB_D(("device %p has not registered video devices.\n",h)); + continue; + } + DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor)); + + if (h->vv_data->video_minor == minor) { dev = h; } - if (h->vbi_minor == minor) { + if (h->vv_data->vbi_minor == minor) { type = V4L2_BUF_TYPE_VBI_CAPTURE; dev = h; } @@ -212,10 +218,6 @@ int video_open(struct inode *inode, struct file *file) fh->dev = dev; fh->type = type; - /* FIXME: what's this? */ - dev->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; - dev->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; - saa7146_video_uops.open(dev,fh); if( 0 != BOARD_CAN_DO_VBI(dev) ) { saa7146_vbi_uops.open(dev,fh); @@ -230,7 +232,7 @@ out: return result; } -static int video_release(struct inode *inode, struct file *file) +static int fops_release(struct inode *inode, struct file *file) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -261,7 +263,7 @@ static int video_release(struct inode *inode, struct file *file) } int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg); -static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { /* DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg)); @@ -269,7 +271,7 @@ static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return video_usercopy(inode, file, cmd, arg, saa7146_video_do_ioctl); } -static int video_mmap(struct file *file, struct vm_area_struct * vma) +static int fops_mmap(struct file *file, struct vm_area_struct * vma) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -293,7 +295,7 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma) return videobuf_mmap_mapper(vma,q); } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -325,7 +327,7 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait return 0; } -static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) +static ssize_t fops_read(struct file *file, char *data, size_t count, loff_t *ppos) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -349,15 +351,39 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p static struct file_operations video_fops = { owner: THIS_MODULE, - open: video_open, - release: video_release, - read: video_read, - poll: video_poll, - mmap: video_mmap, - ioctl: video_ioctl, + open: fops_open, + release: fops_release, + read: fops_read, + poll: fops_poll, + mmap: fops_mmap, + ioctl: fops_ioctl, llseek: no_llseek, }; +void vv_callback(struct saa7146_dev *dev, unsigned long status) +{ + u32 isr = status; + + DEB_EE(("dev:%p, isr:0x%08x\n",dev,status)); + + if (0 != (isr & (MASK_27))) { + DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); + saa7146_video_uops.irq_done(dev,isr); + } + + if (0 != (isr & (MASK_28))) { + u32 mc2 = saa7146_read(dev, MC2); + if( 0 != (mc2 & MASK_15)) { + DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr)); + wake_up(&dev->vv_data->vbi_wq); + saa7146_write(dev,MC2, MASK_31); + return; + } + DEB_INT(("irq: RPS1 (0x%08x).\n",isr)); + saa7146_vbi_uops.irq_done(dev,isr); + } +} + static struct video_device device_template = { .hardware = VID_HARDWARE_SAA7146, @@ -365,9 +391,57 @@ static struct video_device device_template = .minor = -1, }; +int saa7146_vv_init(struct saa7146_dev* dev) +{ + struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL); + if( NULL == vv ) { + ERR(("out of memory. aborting.\n")); + return -1; + } + memset(vv, 0x0, sizeof(*vv)); + + DEB_EE(("dev:%p\n",dev)); + + vv->video_minor = -1; + vv->vbi_minor = -1; + + vv->clipping = (u32*)kmalloc(SAA7146_CLIPPING_MEM, GFP_KERNEL); + if( NULL == vv->clipping ) { + ERR(("out of memory. aborting.\n")); + kfree(vv); + return -1; + } + memset(vv->clipping, 0x0, SAA7146_CLIPPING_MEM); + + saa7146_video_uops.init(dev,vv); + saa7146_vbi_uops.init(dev,vv); + + dev->vv_data = vv; + dev->vv_callback = &vv_callback; + + return 0; +} + +int saa7146_vv_release(struct saa7146_dev* dev) +{ + struct saa7146_vv *vv = dev->vv_data; + + DEB_EE(("dev:%p\n",dev)); + + kfree(vv); + dev->vv_data = NULL; + dev->vv_callback = NULL; + + return 0; +} + int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type) { - *vid = device_template; + struct saa7146_vv *vv = dev->vv_data; + + DEB_EE(("dev:%p, name:'%s'\n",dev,name)); + + *vid = device_template; strncpy(vid->name, name, 32); vid->priv = dev; @@ -378,25 +452,29 @@ int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, c } if( VFL_TYPE_GRABBER == type ) { - dev->video_minor = vid->minor; + vv->video_minor = vid->minor; INFO(("%s: registered device video%d [v4l2]\n", dev->name,vid->minor & 0x1f)); } else { - dev->vbi_minor = vid->minor; + vv->vbi_minor = vid->minor; INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,vid->minor & 0x1f)); } + return 0; } int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev) { + struct saa7146_vv *vv = dev->vv_data; + + DEB_EE(("dev:%p\n",dev)); + if( VFL_TYPE_GRABBER == vid->type ) { - dev->video_minor = -1; - dev->video_irq_done = saa7146_video_uops.irq_done; + vv->video_minor = -1; } else { - dev->vbi_minor = -1; - dev->vbi_irq_done = saa7146_vbi_uops.irq_done; + vv->vbi_minor = -1; } video_unregister_device(vid); + return 0; } @@ -419,8 +497,9 @@ EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); EXPORT_SYMBOL_GPL(saa7146_register_device); EXPORT_SYMBOL_GPL(saa7146_unregister_device); +EXPORT_SYMBOL_GPL(saa7146_vv_init); +EXPORT_SYMBOL_GPL(saa7146_vv_release); + MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware"); MODULE_LICENSE("GPL"); - - diff --git a/linux/drivers/media/common/saa7146_hlp.c b/linux/drivers/media/common/saa7146_hlp.c index 618ad3514..e2bb66125 100644 --- a/linux/drivers/media/common/saa7146_hlp.c +++ b/linux/drivers/media/common/saa7146_hlp.c @@ -1,4 +1,5 @@ -#include "saa7146.h" +#include "saa7146_vv.h" + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) #define KBUILD_MODNAME saa7146 #endif @@ -31,12 +32,12 @@ void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync } static -void calculate_hxo_and_hyo(struct saa7146_dev *dev, u32* hps_h_scale, u32* hps_ctrl) +void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl) { int hyo = 0, hxo = 0; - hyo = dev->standard->v_offset; - hxo = dev->standard->h_offset; + hyo = vv->standard->v_offset; + hxo = vv->standard->h_offset; *hps_h_scale &= ~(MASK_B0 | 0xf00); *hps_h_scale |= (hxo << 0); @@ -358,11 +359,12 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh, struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field) { - int td_flip = dev->vflip; + struct saa7146_vv *vv = dev->vv_data; + u32 *clipping = vv->clipping; + int width = fh->ov.win.w.width; int height = fh->ov.win.w.height; int clipcount = fh->ov.nclips; - u32 *clipping = dev->clipping; u32 line_list[32]; u32 pixel_list[32]; @@ -378,7 +380,6 @@ void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_f memset(&pixel_list[0], 0x00, sizeof(u32)*32); memset(clipping, 0x00, SAA7146_CLIPPING_MEM); - /* fill the line and pixel-lists */ for(i = 0; i < clipcount; i++) { int l = 0, r = 0, t = 0, b = 0; @@ -400,7 +401,7 @@ void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_f if( y[i] < 0) { h[i] += y[i]; y[i] = 0; } - if( 0 != td_flip ) { + if( 0 != vv->vflip ) { y[i] = height - y[i] - h[i]; } @@ -549,25 +550,26 @@ void saa7146_set_clipping_rect(struct saa7146_dev *dev, struct saa7146_fh *fh) static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field) { - int flip_lr = dev->hflip; - int source = dev->current_hps_source; - int sync = dev->current_hps_sync; + struct saa7146_vv *vv = dev->vv_data; + + int source = vv->current_hps_source; + int sync = vv->current_hps_sync; u32 hps_v_scale = 0, hps_v_gain = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0; /* set vertical scale */ hps_v_scale = 0; /* all bits get set by the function-call */ hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/ - calculate_v_scale_registers(dev, field, dev->standard->v_calc, height, &hps_v_scale, &hps_v_gain); + calculate_v_scale_registers(dev, field, vv->standard->v_calc, height, &hps_v_scale, &hps_v_gain); /* set horizontal scale */ hps_ctrl = 0; hps_h_prescale = 0; /* all bits get set in the function */ hps_h_scale = 0; - calculate_h_scale_registers(dev, dev->standard->h_calc, width, flip_lr, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale); + calculate_h_scale_registers(dev, vv->standard->h_calc, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale); /* set hyo and hxo */ - calculate_hxo_and_hyo(dev, &hps_h_scale, &hps_ctrl); + calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl); calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl); /* write out new register contents */ @@ -585,16 +587,17 @@ void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field) { - int td_flip = dev->vflip; - int b_depth = dev->ov_fmt->depth; - int b_bpl = dev->ov_fb.fmt.bytesperline; - u32 base = (u32)dev->ov_fb.base; + struct saa7146_vv *vv = dev->vv_data; + + int b_depth = vv->ov_fmt->depth; + int b_bpl = vv->ov_fb.fmt.bytesperline; + u32 base = (u32)vv->ov_fb.base; struct saa7146_video_dma vdma1; /* calculate memory offsets for picture, look if we shall top-down-flip */ vdma1.pitch = 2*b_bpl; - if ( 0 == td_flip ) { + if ( 0 == vv->vflip ) { vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8)); vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2); vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2)); @@ -615,12 +618,12 @@ void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_heigh vdma1.pitch /= 2; } - if ( 0 != td_flip ) { + if ( 0 != vv->vflip ) { vdma1.pitch *= -1; } vdma1.base_page = 0; - vdma1.num_line_byte = (dev->standard->v_field<<16)+dev->standard->h_pixels; + vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels; saa7146_write_out_dma(dev, 1, &vdma1); } @@ -628,7 +631,7 @@ void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_heigh static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette) { - u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); + u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); /* call helper function */ calculate_output_format_register(dev,palette,&clip_format); @@ -653,6 +656,7 @@ void saa7146_set_picture_prop(struct saa7146_dev *dev, int brightness, int contr /* select input-source */ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync) { + struct saa7146_vv *vv = dev->vv_data; u32 hps_ctrl = 0; /* read old state */ @@ -665,8 +669,8 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy saa7146_write(dev, HPS_CTRL, hps_ctrl); saa7146_write(dev, MC2, (MASK_05 | MASK_21)); - dev->current_hps_source = source; - dev->current_hps_sync = sync; + vv->current_hps_source = source; + vv->current_hps_sync = sync; } /* write "data" to the gpio-pin "pin" */ @@ -690,6 +694,8 @@ void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data) /* reprogram hps, enable(1) / disable(0) video */ void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v) { + struct saa7146_vv *vv = dev->vv_data; + /* enable ? */ if( 0 == v) { /* disable video dma1 */ @@ -699,7 +705,7 @@ void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v) saa7146_set_window(dev, fh->ov.win.w.width, fh->ov.win.w.height, fh->ov.win.field); saa7146_set_position(dev, fh->ov.win.w.left, fh->ov.win.w.top, fh->ov.win.w.height, fh->ov.win.field); - saa7146_set_output_format(dev, dev->ov_fmt->trans); + saa7146_set_output_format(dev, vv->ov_fmt->trans); saa7146_set_clipping_rect(dev, fh); /* enable video dma1 */ @@ -708,6 +714,7 @@ void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v) void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) { + struct saa7146_vv *vv = dev->vv_data; int where = 0; if( which < 1 || which > 3) { @@ -717,7 +724,7 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi /* calculate starting address */ where = (which-1)*0x18; - if( 0 != (dev->ext->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { + if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { saa7146_write(dev, where, vdma->base_even); saa7146_write(dev, where+0x04, vdma->base_odd); } else { @@ -743,12 +750,11 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf) { + struct saa7146_vv *vv = dev->vv_data; struct saa7146_video_dma vdma1; struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); - int flip_td = dev->vflip; - int width = buf->fmt->width; int height = buf->fmt->height; enum v4l2_field field = buf->fmt->field; @@ -760,10 +766,10 @@ int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf width,height,v4l2_field_names[field],flags)); vdma1.pitch = (width*depth*2)/8; - vdma1.num_line_byte = ((dev->standard->v_field<<16) + dev->standard->h_pixels); + vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); vdma1.base_page = buf->pt[0].dma | ME1 | flags; - if( 0 != flip_td ) { + if( 0 != vv->vflip ) { vdma1.prot_addr = buf->pt[0].offset; vdma1.base_even = buf->pt[0].offset+(vdma1.pitch/2)*height; vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2); @@ -783,7 +789,7 @@ int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf vdma1.pitch /= 2; } - if( 0 != flip_td ) { + if( 0 != vv->vflip ) { vdma1.pitch *= -1; } @@ -794,14 +800,13 @@ int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf) { + struct saa7146_vv *vv = dev->vv_data; struct saa7146_video_dma vdma1; struct saa7146_video_dma vdma2; struct saa7146_video_dma vdma3; struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); - int flip_td = dev->vflip; - int width = buf->fmt->width; int height = buf->fmt->height; enum v4l2_field field = buf->fmt->field; @@ -816,7 +821,7 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf width,height,v4l2_field_names[field],flags)); vdma1.pitch = width*2; - vdma1.num_line_byte = ((dev->standard->v_field<<16) + dev->standard->h_pixels); + vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels); vdma1.base_page = buf->pt[0].dma | ME1 | flags; /* fscking saa7146! due to the "byte-swap bug", video-dma2 @@ -836,7 +841,7 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf most likely wrong, this version here only works for page-aligned buffers, modifications to the pagetable-functions are necessary...*/ - if( 0 != flip_td ) { + if( 0 != vv->vflip ) { vdma1.prot_addr = buf->pt[0].offset; vdma1.base_even = ((vdma1.pitch/2)*height)+buf->pt[0].offset; vdma1.base_odd = vdma1.base_even - (vdma1.pitch/2); @@ -884,7 +889,7 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf vdma3.pitch /= 2; } - if( 0 != flip_td ) { + if( 0 != vv->vflip ) { vdma1.pitch *= -1; vdma2.pitch *= -1; vdma3.pitch *= -1; @@ -900,10 +905,11 @@ int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf static void program_capture_engine(struct saa7146_dev *dev, int planar) { + struct saa7146_vv *vv = dev->vv_data; int count = 0; - unsigned long e_wait = dev->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; - unsigned long o_wait = dev->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; + unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; + unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; /* write beginning of rps-program */ count = 0; diff --git a/linux/drivers/media/common/saa7146_vbi.c b/linux/drivers/media/common/saa7146_vbi.c index 1b880ff9c..96ab61028 100644 --- a/linux/drivers/media/common/saa7146_vbi.c +++ b/linux/drivers/media/common/saa7146_vbi.c @@ -1,4 +1,5 @@ -#include "saa7146.h" +#include "saa7146_vv.h" + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) #define KBUILD_MODNAME saa7146 #endif @@ -8,6 +9,8 @@ static int vbi_pixel_to_capture = 720 * 2; static int vbi_workaround(struct saa7146_dev *dev) { + struct saa7146_vv *vv = dev->vv_data; + u32 *cpu; dma_addr_t dma_addr; @@ -88,7 +91,7 @@ int vbi_workaround(struct saa7146_dev *dev) IER_ENABLE(dev,MASK_28); /* prepare to wait to be woken up by the irq-handler */ - add_wait_queue(&dev->vbi_wq, &wait); + add_wait_queue(&vv->vbi_wq, &wait); current->state = TASK_INTERRUPTIBLE; /* start rps1 to enable workaround */ @@ -99,7 +102,7 @@ int vbi_workaround(struct saa7146_dev *dev) DEB_VBI(("brs bug workaround %d/1.\n",i)); - remove_wait_queue(&dev->vbi_wq, &wait); + remove_wait_queue(&vv->vbi_wq, &wait); current->state = TASK_RUNNING; /* disable rps1 irqs */ @@ -126,11 +129,13 @@ int vbi_workaround(struct saa7146_dev *dev) void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { + struct saa7146_vv *vv = dev->vv_data; + struct saa7146_video_dma vdma3; int count = 0; - unsigned long e_wait = dev->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; - unsigned long o_wait = dev->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; + unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; + unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; /* vdma3.base_even = (u32)dev->ov_fb.base+2048*70; @@ -196,12 +201,13 @@ int buffer_activate(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { + struct saa7146_vv *vv = dev->vv_data; buf->vb.state = STATE_ACTIVE; DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next)); saa7146_set_vbi_capture(dev,buf,next); - mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT); return 0; } @@ -277,10 +283,11 @@ void buffer_queue(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_VBI(("vb:%p\n",vb)); - saa7146_buffer_queue(dev,&dev->vbi_q,buf); + saa7146_buffer_queue(dev,&vv->vbi_q,buf); } static @@ -308,6 +315,7 @@ static void vbi_stop(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; DEB_VBI(("dev:%p, fh:%p\n",dev, fh)); @@ -322,7 +330,7 @@ void vbi_stop(struct saa7146_fh *fh) /* shut down dma 3 transfers */ saa7146_write(dev, MC1, MASK_20); - dev->vbi_streaming = NULL; + vv->vbi_streaming = NULL; spin_unlock_irqrestore(&dev->slock, flags); } @@ -338,21 +346,25 @@ void vbi_read_timeout(unsigned long data) } static -void vbi_init(struct saa7146_dev *dev) +void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv) { - INIT_LIST_HEAD(&dev->vbi_q.queue); + DEB_VBI(("dev:%p\n",dev)); + + INIT_LIST_HEAD(&vv->vbi_q.queue); - init_timer(&dev->vbi_q.timeout); - dev->vbi_q.timeout.function = saa7146_buffer_timeout; - dev->vbi_q.timeout.data = (unsigned long)(&dev->vbi_q); - dev->vbi_q.dev = dev; + init_timer(&vv->vbi_q.timeout); + vv->vbi_q.timeout.function = saa7146_buffer_timeout; + vv->vbi_q.timeout.data = (unsigned long)(&vv->vbi_q); + vv->vbi_q.dev = dev; - init_waitqueue_head(&dev->vbi_wq); + init_waitqueue_head(&vv->vbi_wq); } static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh) { + DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); + memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt)); fh->vbi_fmt.sampling_rate = 27000000; @@ -382,7 +394,10 @@ void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh) static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) { - if( fh == dev->vbi_streaming ) { + struct saa7146_vv *vv = dev->vv_data; + DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); + + if( fh == vv->vbi_streaming ) { vbi_stop(fh); } } @@ -390,18 +405,19 @@ void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) { + struct saa7146_vv *vv = dev->vv_data; spin_lock(&dev->slock); - if (dev->vbi_q.curr) { - DEB_VBI(("dev:%p, curr:%p\n",dev,dev->vbi_q.curr)); + if (vv->vbi_q.curr) { + DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr)); /* this must be += 2, one count for each field */ - dev->vbi_fieldcount+=2; - dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount; - saa7146_buffer_finish(dev,&dev->vbi_q,STATE_DONE); + vv->vbi_fieldcount+=2; + vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount; + saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE); } else { DEB_VBI(("dev:%p\n",dev)); } - saa7146_buffer_next(dev,&dev->vbi_q,1); + saa7146_buffer_next(dev,&vv->vbi_q,1); spin_unlock(&dev->slock); } @@ -411,18 +427,19 @@ ssize_t vbi_read(struct file *file, char *data, size_t count, loff_t *ppos) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; ssize_t ret = 0; DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); - if( NULL == dev->vbi_streaming ) { + if( NULL == vv->vbi_streaming ) { // fixme: check if dma3 is available // fixme: activate vbi engine here if necessary. (really?) - dev->vbi_streaming = fh; + vv->vbi_streaming = fh; } - if( fh != dev->vbi_streaming ) { - DEB_VBI(("open %p is already using vbi capture.",dev->vbi_streaming)); + if( fh != vv->vbi_streaming ) { + DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming)); return -EBUSY; } diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 2038e4748..8a2d83c98 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -1,4 +1,5 @@ -#include "saa7146.h" +#include "saa7146_vv.h" + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) #define KBUILD_MODNAME saa7146 #endif @@ -76,16 +77,17 @@ int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) static int try_win(struct saa7146_dev *dev, struct v4l2_window *win) { + struct saa7146_vv *vv = dev->vv_data; enum v4l2_field field; int maxw, maxh; DEB_EE(("dev:%p\n",dev)); - if (NULL == dev->ov_fb.base) { + if (NULL == vv->ov_fb.base) { DEB_D(("no fb base set.\n")); return -EINVAL; } - if (NULL == dev->ov_fmt) { + if (NULL == vv->ov_fmt) { DEB_D(("no fb fmt set.\n")); return -EINVAL; } @@ -99,8 +101,8 @@ int try_win(struct saa7146_dev *dev, struct v4l2_window *win) } field = win->field; - maxw = dev->standard->h_max_out; - maxh = dev->standard->v_max_out; + maxw = vv->standard->h_max_out; + maxh = vv->standard->v_max_out; if (V4L2_FIELD_ANY == field) { field = (win->w.height > maxh/2) @@ -133,6 +135,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; int err; switch (f->type) { @@ -150,8 +153,8 @@ int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) } field = f->fmt.pix.field; - maxw = dev->standard->h_max_out; - maxh = dev->standard->v_max_out; + maxw = vv->standard->h_max_out; + maxh = vv->standard->v_max_out; if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) @@ -197,6 +200,7 @@ static int start_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; int err = 0; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); @@ -208,8 +212,8 @@ int start_preview(struct saa7146_fh *fh) } /* check if overlay is running */ - if( 0 != dev->ov_data ) { - if( fh != dev->ov_data->fh ) { + if( 0 != vv->ov_data ) { + if( fh != vv->ov_data->fh ) { DEB_D(("overlay is running in another open.\n")); return -EAGAIN; } @@ -217,7 +221,7 @@ int start_preview(struct saa7146_fh *fh) return 0; } - if( 0 != dev->streaming ) { + if( 0 != vv->streaming ) { DEB_D(("streaming capture is active.\n")); return -EBUSY; } @@ -227,12 +231,12 @@ int start_preview(struct saa7146_fh *fh) return err; } - dev->ov_data = &fh->ov; + vv->ov_data = &fh->ov; DEB_D(("%dx%d+%d+%d %s field=%s\n", fh->ov.win.w.width,fh->ov.win.w.height, fh->ov.win.w.left,fh->ov.win.w.top, - dev->ov_fmt->name,v4l2_field_names[fh->ov.win.field])); + vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field])); saa7146_set_overlay(dev, fh, 1); @@ -243,21 +247,23 @@ static int stop_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + DEB_EE(("saa7146.o: stop_preview()\n")); /* check if overlay is running */ - if( 0 == dev->ov_data ) { + if( 0 == vv->ov_data ) { DEB_D(("overlay is not active.\n")); return 0; } - if( fh != dev->ov_data->fh ) { + if( fh != vv->ov_data->fh ) { DEB_D(("overlay is active, but for another open.\n")); return -EBUSY; } saa7146_set_overlay(dev, fh, 0); - dev->ov_data = NULL; + vv->ov_data = NULL; return 0; } @@ -266,6 +272,7 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; int err; @@ -273,7 +280,7 @@ int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh)); - if( fh == dev->streaming ) { + if( fh == vv->streaming ) { DEB_EE(("streaming capture is active")); return -EAGAIN; } @@ -302,8 +309,8 @@ int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) fh->ov.fh = fh; /* check if we have an active overlay */ - if( dev->ov_data != NULL ) { - if( fh == dev->ov_data->fh) { + if( vv->ov_data != NULL ) { + if( fh == vv->ov_data->fh) { spin_lock_irqsave(&dev->slock,flags); stop_preview(fh); start_preview(fh); @@ -381,6 +388,8 @@ static int get_control(struct saa7146_fh *fh, struct v4l2_control *c) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + const struct v4l2_queryctrl* ctrl; u32 value = 0; @@ -401,10 +410,10 @@ int get_control(struct saa7146_fh *fh, struct v4l2_control *c) c->value = 0x7f & (value >> 0); break; case V4L2_CID_VFLIP: - c->value = dev->vflip; + c->value = vv->vflip; break; case V4L2_CID_HFLIP: - c->value = dev->hflip; + c->value = vv->hflip; break; default: return -EINVAL; @@ -417,6 +426,8 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + const struct v4l2_queryctrl* ctrl; unsigned long flags; int restart_overlay = 0; @@ -467,19 +478,19 @@ int set_control(struct saa7146_fh *fh, struct v4l2_control *c) } case V4L2_CID_HFLIP: /* fixme: we can supfhrt changing VFLIP and HFLIP here... */ - if( 0 != dev->streaming ) { + if( 0 != vv->streaming ) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); return -EINVAL; } - dev->hflip = c->value; + vv->hflip = c->value; restart_overlay = 1; break; case V4L2_CID_VFLIP: - if( 0 != dev->streaming ) { + if( 0 != vv->streaming ) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); return -EINVAL; } - dev->vflip = c->value; + vv->vflip = c->value; restart_overlay = 1; break; default: { @@ -487,8 +498,8 @@ int set_control(struct saa7146_fh *fh, struct v4l2_control *c) } } if( 0 != restart_overlay ) { - if( 0 != dev->ov_data ) { - if( fh == dev->ov_data->fh ) { + if( 0 != vv->ov_data ) { + if( fh == vv->ov_data->fh ) { spin_lock_irqsave(&dev->slock,flags); stop_preview(fh); start_preview(fh); @@ -606,15 +617,16 @@ static int video_begin(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - if( fh == dev->streaming ) { + if( fh == vv->streaming ) { DEB_S(("already capturing.\n")); return 0; } - if( dev->streaming != 0 ) { + if( vv->streaming != 0 ) { DEB_S(("already capturing, but in another open.\n")); return -EBUSY; } @@ -630,7 +642,7 @@ int video_begin(struct saa7146_fh *fh) /* enable rps0 irqs */ IER_ENABLE(dev, MASK_27); - dev->streaming = fh; + vv->streaming = fh; spin_unlock_irqrestore(&dev->slock,flags); return 0; } @@ -639,11 +651,12 @@ static int video_end(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); - if( dev->streaming != fh ) { + if( vv->streaming != fh ) { DEB_S(("not capturing.\n")); return -EINVAL; } @@ -665,7 +678,7 @@ int video_end(struct saa7146_fh *fh) video-dma3, but video_end should not get called anyway ...*/ saa7146_write(dev, MC1, 0x00700000); - dev->streaming = NULL; + vv->streaming = NULL; spin_unlock_irqrestore(&dev->slock, flags); return 0; @@ -681,6 +694,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; int err = 0, result = 0, ee = 0; @@ -689,19 +703,19 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int struct videobuf_queue *q; /* check if extension handles the command */ - for(ee = 0; dev->ext->ioctls[ee].flags != 0; ee++) { - if( cmd == dev->ext->ioctls[ee].cmd ) + for(ee = 0; dev->ext->ext_vv_data->ioctls[ee].flags != 0; ee++) { + if( cmd == dev->ext->ext_vv_data->ioctls[ee].cmd ) break; } - if( 0 != (dev->ext->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { + if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { DEB_D(("extension handles ioctl exclusive.\n")); - result = dev->ext->ioctl(dev, cmd, arg); + result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); return result; } - if( 0 != (dev->ext->ioctls[ee].flags & SAA7146_BEFORE) ) { + if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { DEB_D(("extension handles ioctl before.\n")); - result = dev->ext->ioctl(dev, cmd, arg); + result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); if( -EAGAIN != result ) { return result; } @@ -742,7 +756,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities |= dev->ext->capabilities; + cap->capabilities |= dev->ext->ext_vv_data->capabilities; return 0; } case VIDIOC_G_FBUF: @@ -751,7 +765,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int DEB_EE(("VIDIOC_G_FBUF\n")); - *fb = dev->ov_fb; + *fb = vv->ov_fb; fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; return 0; } @@ -768,7 +782,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return -EPERM; } */ - if( 0 != dev->ov_data ) { + if( 0 != vv->ov_data ) { DEB_D(("VIDIOC_S_FBUF: overlay is active.\n")); return -EPERM; } @@ -780,11 +794,11 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } /* ok, accept it */ - dev->ov_fb = *fb; - dev->ov_fmt = fmt; - if (0 == dev->ov_fb.fmt.bytesperline) - dev->ov_fb.fmt.bytesperline = - dev->ov_fb.fmt.width*fmt->depth/8; + vv->ov_fb = *fb; + vv->ov_fmt = fmt; + if (0 == vv->ov_fb.fmt.bytesperline) + vv->ov_fb.fmt.bytesperline = + vv->ov_fb.fmt.width*fmt->depth/8; return 0; } case VIDIOC_ENUM_FMT: @@ -879,7 +893,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int { v4l2_std_id *id = arg; DEB_EE(("VIDIOC_G_STD\n")); - *id = dev->standard->id; + *id = vv->standard->id; return 0; } /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) @@ -890,9 +904,9 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int struct v4l2_standard *e = arg; if (e->index < 0 ) return -EINVAL; - if( e->index < dev->ext->num_stds ) { + if( e->index < dev->ext->ext_vv_data->num_stds ) { DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index)); - return v4l2_video_std_construct(e, dev->ext->stds[e->index].id, dev->ext->stds[e->index].name); + return v4l2_video_std_construct(e, dev->ext->ext_vv_data->stds[e->index].id, dev->ext->ext_vv_data->stds[e->index].name); } return -EINVAL; } @@ -906,25 +920,25 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int struct saa7146_fh *ov_fh = NULL; - if( 0 != dev->streaming ) { + if( 0 != vv->streaming ) { return -EBUSY; } down(&dev->lock); - if( dev->ov_data != NULL ) { - ov_fh = dev->ov_data->fh; + if( vv->ov_data != NULL ) { + ov_fh = vv->ov_data->fh; stop_preview(ov_fh); restart_overlay = 1; } - for(i = 0; i < dev->ext->num_stds; i++) - if (*id & dev->ext->stds[i].id) + for(i = 0; i < dev->ext->ext_vv_data->num_stds; i++) + if (*id & dev->ext->ext_vv_data->stds[i].id) break; - if (i != dev->ext->num_stds) { - dev->standard = &dev->ext->stds[i]; - if( NULL != dev->ext->std_callback ) - dev->ext->std_callback(dev, dev->standard); + if (i != dev->ext->ext_vv_data->num_stds) { + vv->standard = &dev->ext->ext_vv_data->stds[i]; + if( NULL != dev->ext->ext_vv_data->std_callback ) + dev->ext->ext_vv_data->std_callback(dev, vv->standard); found = 1; } @@ -938,7 +952,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int return -EINVAL; } - DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",dev->standard->name)); + DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name)); return 0; } case VIDIOC_OVERLAY: @@ -946,15 +960,15 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int int on = *(int *)arg; int err = 0; - if( NULL == dev->ov_fmt ) { + if( NULL == vv->ov_fmt ) { DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n")); return -EAGAIN; } DEB_D(("VIDIOC_OVERLAY on:%d\n",on)); if( 0 != on ) { - if( dev->ov_data != NULL ) { - if( fh != dev->ov_data->fh) { + if( vv->ov_data != NULL ) { + if( fh != vv->ov_data->fh) { return -EAGAIN; } } @@ -962,8 +976,8 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int err = start_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } else { - if( dev->ov_data != NULL ) { - if( fh != dev->ov_data->fh) { + if( vv->ov_data != NULL ) { + if( fh != vv->ov_data->fh) { return -EAGAIN; } } @@ -1049,10 +1063,12 @@ int buffer_activate (struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { + struct saa7146_vv *vv = dev->vv_data; + buf->vb.state = STATE_ACTIVE; saa7146_set_capture(dev,buf,next); - mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT); return 0; } @@ -1061,14 +1077,15 @@ int buffer_prepare(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; struct saa7146_buf *buf = (struct saa7146_buf *)vb; int size,err = 0; /* sanity checks */ if (fh->video_fmt.width < 64 || fh->video_fmt.height < 64 || - fh->video_fmt.width > dev->standard->h_max_out || - fh->video_fmt.height > dev->standard->v_max_out) { + fh->video_fmt.width > vv->standard->h_max_out || + fh->video_fmt.height > vv->standard->v_max_out) { DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height)); return -EINVAL; } @@ -1159,12 +1176,13 @@ void buffer_queue(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; /* */ struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_CAP(("vbuf:%p\n",vb)); - saa7146_buffer_queue(fh->dev,&fh->dev->video_q,buf); + saa7146_buffer_queue(fh->dev,&vv->video_q,buf); } @@ -1173,6 +1191,7 @@ void buffer_release(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; struct saa7146_buf *buf = (struct saa7146_buf *)vb; DEB_CAP(("vbuf:%p\n",vb)); @@ -1197,17 +1216,21 @@ struct saa7146_standard standard[] = { static -void video_init(struct saa7146_dev *dev) +void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) { - INIT_LIST_HEAD(&dev->video_q.queue); + INIT_LIST_HEAD(&vv->video_q.queue); - init_timer(&dev->video_q.timeout); - dev->video_q.timeout.function = saa7146_buffer_timeout; - dev->video_q.timeout.data = (unsigned long)(&dev->video_q); - dev->video_q.dev = dev; + init_timer(&vv->video_q.timeout); + vv->video_q.timeout.function = saa7146_buffer_timeout; + vv->video_q.timeout.data = (unsigned long)(&vv->video_q); + vv->video_q.dev = dev; /* set some default values */ - dev->standard = &standard[0]; + vv->standard = &standard[0]; + + /* FIXME: what's this? */ + vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; + vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; } @@ -1235,17 +1258,18 @@ void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh) static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) { + struct saa7146_vv *vv = dev->vv_data; unsigned long flags; - if( 0 != dev->ov_data ) { - if( fh == dev->ov_data->fh ) { + if( 0 != vv->ov_data ) { + if( fh == vv->ov_data->fh ) { spin_lock_irqsave(&dev->slock,flags); stop_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } } - if( fh == dev->streaming ) { + if( fh == vv->streaming ) { video_end(fh); } @@ -1256,7 +1280,8 @@ void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *fi static void video_irq_done(struct saa7146_dev *dev, unsigned long st) { - struct saa7146_dmaqueue *q = &dev->video_q; + struct saa7146_vv *vv = dev->vv_data; + struct saa7146_dmaqueue *q = &vv->video_q; spin_lock(&dev->slock); DEB_CAP(("called.\n")); @@ -1275,6 +1300,7 @@ ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; ssize_t ret = 0; DEB_EE(("called.\n")); @@ -1286,8 +1312,8 @@ ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) video_end(fh); /* restart overlay if it was active before */ - if( 0 != dev->ov_data) { - start_preview(dev->ov_data->fh); + if( 0 != vv->ov_data) { + start_preview(vv->ov_data->fh); } return ret; diff --git a/linux/drivers/media/common/saa7146_vv.h b/linux/drivers/media/common/saa7146_vv.h new file mode 100644 index 000000000..5a924bfd5 --- /dev/null +++ b/linux/drivers/media/common/saa7146_vv.h @@ -0,0 +1,269 @@ +#ifndef __SAA7146_VV__ +#define __SAA7146_VV__ + +#include "saa7146.h" + +#include <linux/videodev2.h> +#include "video-buf.h" + +#define MAX_SAA7146_CAPTURE_BUFFERS 32 /* arbitrary */ +#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ + +struct saa7146_video_dma { + u32 base_odd; + u32 base_even; + u32 prot_addr; + u32 pitch; + u32 base_page; + u32 num_line_byte; +}; + +struct saa7146_format { + char *name; + int pixelformat; + u32 trans; + u8 depth; + unsigned long flags; +}; + +struct saa7146_standard +{ + char *name; + v4l2_std_id id; + + int v_offset; + int v_field; + int v_calc; + + int h_offset; + int h_pixels; + int h_calc; + + int v_max_out; + int h_max_out; +}; + +/* buffer for one video/vbi frame */ +struct saa7146_buf { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* saa7146 specific */ + struct v4l2_pix_format *fmt; + int (*activate)(struct saa7146_dev *dev, + struct saa7146_buf *buf, + struct saa7146_buf *next); + + /* page tables */ + struct saa7146_pgtable pt[3]; +}; + +struct saa7146_dmaqueue { + struct saa7146_dev *dev; + struct saa7146_buf *curr; + struct list_head queue; + struct timer_list timeout; +}; + +struct saa7146_overlay { + struct saa7146_fh *fh; + struct v4l2_window win; + struct v4l2_clip clips[16]; + int nclips; +}; + +/* per open data */ +struct saa7146_fh { + struct saa7146_dev *dev; + /* if this is a vbi or capture open */ + enum v4l2_buf_type type; + + /* video overlay */ + struct saa7146_overlay ov; + + /* video capture */ + struct videobuf_queue video_q; + struct v4l2_pix_format video_fmt; + + /* vbi capture */ + struct videobuf_queue vbi_q; + struct v4l2_vbi_format vbi_fmt; + struct timer_list vbi_read_timeout; +}; + +struct saa7146_vv +{ + int vbi_minor; + + /* vbi capture */ + struct saa7146_dmaqueue vbi_q; + /* vbi workaround interrupt queue */ + wait_queue_head_t vbi_wq; + int vbi_fieldcount; + struct saa7146_fh *vbi_streaming; + + int video_minor; + + /* video overlay */ + struct v4l2_framebuffer ov_fb; + struct saa7146_format *ov_fmt; + struct saa7146_overlay *ov_data; + + /* video capture */ + struct saa7146_dmaqueue video_q; + struct saa7146_fh *streaming; + + /* common: fixme? shouldn't this be in saa7146_fh? + (this leads to a more complicated question: shall the driver + store the different settings (for example S_INPUT) for every open + and restore it appropriately, or should all settings be common for + all opens? currently, we do the latter, like all other + drivers do... */ + struct saa7146_standard *standard; + + int vflip; + int hflip; + int current_hps_source; + int current_hps_sync; + + u32 *clipping; /* pointer to clipping memory */ +}; + +#define SAA7146_EXCLUSIVE 0x1 +#define SAA7146_BEFORE 0x2 +#define SAA7146_AFTER 0x4 + +struct saa7146_extension_ioctls +{ + unsigned int cmd; + int flags; +}; + +/* flags */ +#define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */ + +struct saa7146_ext_vv +{ + /* informations about the video capabilities of the device */ + int inputs; + int audios; + u32 capabilities; + int flags; + + /* additionally supported transmission standards */ + struct saa7146_standard *stds; + int num_stds; + int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); + + struct saa7146_extension_ioctls *ioctls; + int (*ioctl)(struct saa7146_dev*, unsigned int cmd, void *arg); +}; + +struct saa7146_use_ops { + void (*init)(struct saa7146_dev *, struct saa7146_vv *); + void(*open)(struct saa7146_dev *, struct saa7146_fh *); + void (*release)(struct saa7146_dev *, struct saa7146_fh *,struct file *); + void (*irq_done)(struct saa7146_dev *, unsigned long status); + ssize_t (*read)(struct file *, char *, size_t, loff_t *); + int (*capture_begin)(struct saa7146_fh *); + int (*capture_end)(struct saa7146_fh *); +}; + +/* from saa7146_fops.c */ +int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type); +int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev); +void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state); +void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi); +int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf); +void saa7146_buffer_timeout(unsigned long data); +void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf); + +int saa7146_vv_init(struct saa7146_dev* dev); +int saa7146_vv_release(struct saa7146_dev* dev); + + +/* from saa7146_hlp.c */ +void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v); +void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next); +void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma) ; +void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sync); +void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); + +/* from saa7146_video.c */ +extern struct saa7146_use_ops saa7146_video_uops; + +/* from saa7146_vbi.c */ +extern struct saa7146_use_ops saa7146_vbi_uops; + +/* saa7146 source inputs */ +#define SAA7146_HPS_SOURCE_PORT_A 0x00 +#define SAA7146_HPS_SOURCE_PORT_B 0x01 +#define SAA7146_HPS_SOURCE_YPB_CPA 0x02 +#define SAA7146_HPS_SOURCE_YPA_CPB 0x03 + +/* sync inputs */ +#define SAA7146_HPS_SYNC_PORT_A 0x00 +#define SAA7146_HPS_SYNC_PORT_B 0x01 + +/* number of vertical active lines */ +#define V_ACTIVE_LINES_PAL 576 +#define V_ACTIVE_LINES_NTSC 480 +#define V_ACTIVE_LINES_SECAM 576 + +/* number of lines in a field for HPS to process */ +#define V_FIELD_PAL 288 +#define V_FIELD_NTSC 240 +#define V_FIELD_SECAM 288 + +/* number of lines of vertical offset before processing */ +#define V_OFFSET_PAL 0x17 +#define V_OFFSET_NTSC 0x16 +#define V_OFFSET_SECAM 0x14 + +/* number of horizontal pixels to process */ +#define H_PIXELS_PAL 680 +#define H_PIXELS_NTSC 708 +#define H_PIXELS_SECAM 720 + +/* horizontal offset of processing window */ +#define H_OFFSET_PAL 0x14 +#define H_OFFSET_NTSC 0x06 +#define H_OFFSET_SECAM 0x14 + +#define SAA7146_PAL_VALUES V_OFFSET_PAL, V_FIELD_PAL, V_ACTIVE_LINES_PAL, H_OFFSET_PAL, H_PIXELS_PAL, H_PIXELS_PAL+1, V_ACTIVE_LINES_PAL, 768 +#define SAA7146_NTSC_VALUES V_OFFSET_NTSC, V_FIELD_NTSC, V_ACTIVE_LINES_NTSC, H_OFFSET_NTSC, H_PIXELS_NTSC, H_PIXELS_NTSC+1, V_ACTIVE_LINES_NTSC, 640 +#define SAA7146_SECAM_VALUES V_OFFSET_SECAM, V_FIELD_SECAM, V_ACTIVE_LINES_SECAM, H_OFFSET_SECAM, H_PIXELS_SECAM, H_PIXELS_SECAM+1, V_ACTIVE_LINES_SECAM, 768 + +/* some memory sizes */ +#define SAA7146_CLIPPING_MEM (14*PAGE_SIZE) + +/* some defines for the various clipping-modes */ +#define SAA7146_CLIPPING_RECT 0x4 +#define SAA7146_CLIPPING_RECT_INVERTED 0x5 +#define SAA7146_CLIPPING_MASK 0x6 +#define SAA7146_CLIPPING_MASK_INVERTED 0x7 + +/* output formats: each entry holds four informations */ +#define RGB08_COMPOSED 0x0217 /* composed is used in the sense of "not-planar" */ +/* this means: planar?=0, yuv2rgb-conversation-mode=2, dither=yes(=1), format-mode = 7 */ +#define RGB15_COMPOSED 0x0213 +#define RGB16_COMPOSED 0x0210 +#define RGB24_COMPOSED 0x0201 +#define RGB32_COMPOSED 0x0202 + +#define Y8 0x0006 +#define YUV411_COMPOSED 0x0003 +#define YUV422_COMPOSED 0x0000 +/* this means: planar?=1, yuv2rgb-conversion-mode=0, dither=no(=0), format-mode = b */ +#define YUV411_DECOMPOSED 0x100b +#define YUV422_DECOMPOSED 0x1009 +#define YUV420_DECOMPOSED 0x100a + +#define IS_PLANAR(x) (x & 0xf000) + +/* misc defines */ +#define SAA7146_NO_SWAP (0x0) +#define SAA7146_TWO_BYTE_SWAP (0x1) +#define SAA7146_FOUR_BYTE_SWAP (0x2) + +#endif |