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 | |
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')
21 files changed, 1520 insertions, 958 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 diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig index 5aba59f9e..edbec1c88 100644 --- a/linux/drivers/media/dvb/Kconfig +++ b/linux/drivers/media/dvb/Kconfig @@ -35,7 +35,8 @@ source "drivers/media/dvb/frontends/Kconfig" comment "Supported DVB Adapters" depends on DVB -source "drivers/media/dvb/av7110/Kconfig" +source "drivers/media/dvb/ttpci/Kconfig" +source "drivers/media/dvb/ttpci-budget/Kconfig" endmenu diff --git a/linux/drivers/media/dvb/Makefile b/linux/drivers/media/dvb/Makefile index 3290afb80..d23a404bf 100644 --- a/linux/drivers/media/dvb/Makefile +++ b/linux/drivers/media/dvb/Makefile @@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ av7110/ +obj-y := dvb-core/ frontends/ ttpci/ ttpci-budget/ diff --git a/linux/drivers/media/dvb/av7110/Kconfig b/linux/drivers/media/dvb/ttpci-budget/Kconfig index 93270f079..3c4d43d41 100644 --- a/linux/drivers/media/dvb/av7110/Kconfig +++ b/linux/drivers/media/dvb/ttpci-budget/Kconfig @@ -1,13 +1,12 @@ config DVB_AV7110 - tristate "SAA7146 based AV7110 and Nova/Budget PCI cards" + tristate "SAA7146 based AV7110 PCI cards" depends on VIDEO_DEV && DVB_CORE help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. - Simple cards like so called Budget- or Nova-PCI cards are - supported as well as fullfeatured cards with onboard MPEG2 - decoder. + This driver only supports the fullfeatured cards with + onboard MPEG2 decoder. Say Y if you own such a card and want to use it. diff --git a/linux/drivers/media/dvb/ttpci-budget/Makefile b/linux/drivers/media/dvb/ttpci-budget/Makefile new file mode 100644 index 000000000..11c671d1b --- /dev/null +++ b/linux/drivers/media/dvb/ttpci-budget/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the kernel AV7110 DVB device driver +# + +dvb-ttpci-budget-objs := budget.o + +obj-$(CONFIG_DVB_BUDGET) += dvb-ttpci-budget.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -I$(src)/../../common/ -I$(src)/../../common/saa7146 diff --git a/linux/drivers/media/dvb/ttpci-budget/budget.c b/linux/drivers/media/dvb/ttpci-budget/budget.c new file mode 100644 index 000000000..b50b1d4ad --- /dev/null +++ b/linux/drivers/media/dvb/ttpci-budget/budget.c @@ -0,0 +1,739 @@ +/* + * budget.c: driver for the SAA7146 based Nova/Budget DVB cards + * + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org/dvb/ + */ + +#include "dvb_i2c.h" +#include "dvb_frontend.h" +#include "dvbdev.h" +#include "demux.h" +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_filter.h" +#include "dvb_net.h" + +#include "saa7146.h" + +static int budget_debug = 0; +#if 1 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + #define KBUILD_MODNAME budget +#endif +#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_MODNAME),__FUNCTION__) +#define DEB_S(x) if (0!=(budget_debug&0x01)) { DEBUG_PROLOG; printk x; } /* simple debug messages */ +#define DEB_D(x) if (0!=(budget_debug&0x02)) { DEBUG_PROLOG; printk x; } /* more detailed debug messages */ +#define DEB_EE(x) if (0!=(budget_debug&0x04)) { DEBUG_PROLOG; printk x; } /* print enter and exit of functions */ +#else +#define DEB_S(x) +#define DEB_D(x) +#define DEB_EE(x) +#endif + +int budget_num = 0; + +/* place to store all the necessary device information */ +typedef struct budget_s { + + /* devices */ + struct dvb_device dvb_dev; + dvb_net_t dvb_net; + + struct saa7146_dev *dev; + + struct dvb_i2c_bus *i2c_bus; + struct card_info *card_type; + + unsigned char *grabbing; + struct saa7146_pgtable pt; + + struct tasklet_struct fidb_tasklet; + + dmxdev_t dmxdev; + struct dvb_demux demux; + char demux_id[16]; + + dmx_frontend_t hw_frontend; + dmx_frontend_t mem_frontend; + + int fe_synced; + struct semaphore pid_mutex; + + int tsf; + u32 ttbp; + int feeding; + + int registered; + + struct dvb_adapter *dvb_adapter; +} budget_t; + +/**************************************************************************** + * General helper functions + ****************************************************************************/ + +/* this is videobuf_vmalloc_to_sg() from video-buf.c */ +struct scatterlist* +vmalloc_to_sg(unsigned char *virt, int nr_pages) +{ + struct scatterlist *sglist; + struct page *pg; + int i; + + sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL); + if (NULL == sglist) + return NULL; + memset(sglist,0,sizeof(struct scatterlist)*nr_pages); + for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { + pg = vmalloc_to_page(virt); + if (NULL == pg) + goto err; + if (PageHighMem(pg)) + BUG(); + sglist[i].page = pg; + sglist[i].length = PAGE_SIZE; + } + return sglist; + + err: + kfree(sglist); + return NULL; +} + + +static inline void ddelay(int i) +{ + current->state=TASK_INTERRUPTIBLE; + schedule_timeout((HZ*i)/100); +} + +/**************************************************************************** + * TT budget / WinTV Nova + ****************************************************************************/ + +static int +TTBStop(budget_t *budget) +{ + DEB_EE(("budget: %p\n",budget)); + + if (--budget->feeding) + return budget->feeding; + + saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off + IER_DISABLE(budget->dev, MASK_07); + return 0; +} + +#define TS_WIDTH (4*188) +#define TS_HEIGHT (1024/4) +#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) + +static int +TTBStart(budget_t *budget) +{ + struct saa7146_dev *dev=budget->dev; + + DEB_EE(("budget: %p\n",budget)); + + if (budget->feeding) + return ++budget->feeding; + + saa7146_write(dev, MC1, MASK_20); // DMA3 off + + memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); + + saa7146_write(dev, PCI_BT_V1, 0x001c0000); + + budget->tsf=0; + budget->ttbp=0; + saa7146_write(dev, DD1_INIT, 0x02000680); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + saa7146_write(dev, BRS_CTRL, 0x60000000); + saa7146_write(dev, MC2, (MASK_08 | MASK_24)); + mdelay(10); + + saa7146_write(dev, BASE_ODD3, 0); + saa7146_write(dev, BASE_EVEN3, TS_WIDTH*TS_HEIGHT/2); + saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT); + saa7146_write(dev, BASE_PAGE3, budget->pt.dma |ME1|0xb0); + saa7146_write(dev, PITCH3, TS_WIDTH); + + saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT/2)<<16)|TS_WIDTH); + saa7146_write(dev, MC2, (MASK_04 | MASK_20)); + + saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on + + // FIDB + IER_ENABLE(budget->dev, MASK_07); + + return ++budget->feeding; +} + +static +void fidbirq (unsigned long data) +{ + struct budget_s *budget = (struct budget_s*) data; + u8 *mem=(u8 *)(budget->grabbing); + int num; + u32 dmapos; + + DEB_EE(("budget: %p\n",budget)); + + dmapos=saa7146_read(budget->dev, PCI_VDP3); + dmapos-=(dmapos%188); + + if (dmapos>=TS_BUFLEN) { + DEB_S(("bogus dmapos value ignored, budget: %p\n",budget)); + return; + } + + if (budget->tsf) { + mem+=budget->ttbp; + if (dmapos<0x20000) { + num=1024-budget->ttbp/188; + budget->ttbp=0; + } else { + num=(dmapos - budget->ttbp)/188; + budget->ttbp=dmapos; + } + } else { + if (budget->ttbp>1000*188 && budget->ttbp<1024*188) { + if (budget->feeding) + dvb_dmx_swfilter_packets(&budget->demux, + mem+budget->ttbp, + 1024- budget->ttbp / 188); + } + num=dmapos/188; + budget->ttbp=dmapos; + } + + budget->tsf^=1; + saa7146_write(budget->dev, DD1_INIT, 0x02000600|(budget->tsf ? 0x40:0x80)); + saa7146_write(budget->dev, MC2, + (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + // FIXME: use bottom half or tasklet + if (budget->feeding && mem[0]==0x47) + dvb_dmx_swfilter_packets(&budget->demux, mem, num); +} + +inline static void +Set22K(budget_t *budget, int state) +{ + struct saa7146_dev *dev=budget->dev; + DEB_EE(("budget: %p\n",budget)); + saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); +} + + +/* Diseqc functions only for TT Budget card */ +/* taken from the Skyvision DVB driver by + Ralph Metzler <rjkm@metzlerbros.de> */ + +inline static void +DiseqcSendBit(budget_t *budget, int data) +{ + struct saa7146_dev *dev=budget->dev; + DEB_EE(("budget: %p\n",budget)); + + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); + udelay(data ? 500 : 1000); + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + udelay(data ? 1000 : 500); +} + +static void +DiseqcSendByte(budget_t *budget, int data) +{ + struct saa7146_dev *dev=budget->dev; + int i, par=1, d; + + DEB_EE(("budget: %p\n",budget)); + + for (i=7; i>=0; i--) + { + d=(data>>i)&1; + par^=d; + DiseqcSendBit(budget, d); + } + DiseqcSendBit(budget, par); +} + +inline static int +SendDiSEqCMsg(budget_t *budget, int len, u8 *msg, int burst) +{ + struct saa7146_dev *dev=budget->dev; + int i; + + DEB_EE(("budget: %p\n",budget)); + + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + mdelay(16); + + for (i=0; i<len; i++) + DiseqcSendByte(budget, msg[i]); + + mdelay(16); + + if (burst!=-1) { + if (burst) + DiseqcSendByte(budget, 0xff); + else { + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); + udelay(12500); + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); + } + ddelay(2); + } + + return 0; +} + +/**************************************************************************** + * DVB API SECTION + ****************************************************************************/ + +static int +budget_start_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + budget_t *budget = (budget_t *) demux->priv; + + DEB_EE(("budget: %p\n",budget)); + + if (!demux->dmx.frontend) + return -EINVAL; + + return TTBStart(budget); +} + +static int +budget_stop_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + budget_t *budget = (budget_t *) demux->priv; + + DEB_EE(("budget: %p\n",budget)); + + return TTBStop(budget); +} + +/****************************************************************************** + * SEC device file operations + ******************************************************************************/ + +static +int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + budget_t *budget = fe->before_after_data; + + DEB_EE(("budget: %p\n",budget)); + + switch (cmd) { + case FE_SET_TONE: + switch ((fe_sec_tone_mode_t) arg) { + case SEC_TONE_ON: + Set22K (budget, 1); + break; + case SEC_TONE_OFF: + Set22K (budget, 0); + break; + default: + return -EINVAL; + }; + break; + + case FE_DISEQC_SEND_MASTER_CMD: + { + struct dvb_diseqc_master_cmd *cmd = arg; + + SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); + break; + } + + case FE_DISEQC_SEND_BURST: + SendDiSEqCMsg (budget, 0, NULL, (int) arg); + break; + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + +static +int budget_register(budget_t *budget) +{ + int ret; + dmx_frontend_t *dvbfront=&budget->hw_frontend; + struct dvb_demux *dvbdemux=&budget->demux; + + DEB_EE(("budget: %p\n",budget)); + + if (budget->registered) + return -1; + + budget->registered=1; + + /* init DiSEqC stuff */ + dvb_add_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL, budget); + + memcpy(budget->demux_id, "demux0_0", 9); + budget->demux_id[7]=budget->dvb_adapter->num+0x30; + dvbdemux->priv=(void *) budget; + + dvbdemux->filternum=256; + dvbdemux->feednum=256; + dvbdemux->start_feed=budget_start_feed; + dvbdemux->stop_feed=budget_stop_feed; + dvbdemux->write_to_decoder=NULL; + + dvbdemux->dmx.vendor="CIM"; + dvbdemux->dmx.model="sw"; + dvbdemux->dmx.id=budget->demux_id; + dvbdemux->dmx.capabilities=(DMX_TS_FILTERING| + DMX_SECTION_FILTERING| + DMX_MEMORY_BASED_FILTERING); + + dvb_dmx_init(&budget->demux); + + dvbfront->id="hw_frontend"; + dvbfront->vendor="VLSI"; + dvbfront->model="DVB Frontend"; + dvbfront->source=DMX_FRONTEND_0; + + budget->dmxdev.filternum=256; + budget->dmxdev.demux=&dvbdemux->dmx; + budget->dmxdev.capabilities=0; + + dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter); + + ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, + &budget->hw_frontend); + if (ret<0) + return ret; + + budget->mem_frontend.id="mem_frontend"; + budget->mem_frontend.vendor="memory"; + budget->mem_frontend.model="sw"; + budget->mem_frontend.source=DMX_MEMORY_FE; + ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, + &budget->mem_frontend); + if (ret<0) + return ret; + + ret=dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, + &budget->hw_frontend); + if (ret<0) + return ret; + + budget->dvb_net.card_num=budget->dvb_adapter->num; + dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); + + return 0; +} + + +static void +dvb_unregister(budget_t *budget) +{ + struct dvb_demux *dvbdemux=&budget->demux; + + DEB_EE(("budget: %p\n",budget)); + + if (!budget->registered) + return; + + dvb_net_release(&budget->dvb_net); + + dvbdemux->dmx.close(&dvbdemux->dmx); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend); + + dvb_dmxdev_release(&budget->dmxdev); + dvb_dmx_release(&budget->demux); + dvb_remove_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL); +} + +static +int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) +{ + struct saa7146_dev *dev = i2c->data; + return saa7146_i2c_transfer(dev, msgs, num, 6); +} + +/**************************************************************************** + * INITIALIZATION + ****************************************************************************/ + +int budget_preinit(struct saa7146_dev* dev) +{ + DEB_EE(("dev: %p\n",dev)); + return 0; +} + +struct card_info { + int type; + char *name; +}; + +#define DVB_CARD_TT_BUDGET 0 +#define DVB_CARD_TT_BUDGET_CI 1 +#define DVB_CARD_KNC1 2 + +static struct card_info ttbs = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-S PCI" }; +static struct card_info ttbc = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-C PCI" }; +static struct card_info ttbt = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-T PCI" }; +static struct card_info ttbci = { DVB_CARD_TT_BUDGET_CI, "TT-Budget/WinTV-NOVA-CI PCI" }; +static struct card_info satel = { DVB_CARD_TT_BUDGET, "SATELCO Multimedia PCI"}; +static struct card_info knc1 = { DVB_CARD_KNC1, "KNC1 DVB-S" }; + +static struct saa7146_sub_info sub_data[] = { + { 0x1131, 0x4f56 }, + { 0x13c2, 0x1003 }, + { 0x13c2, 0x1004 }, + { 0x13c2, 0x1005 }, + { 0x13c2, 0x100c }, + { 0x13c2, 0x1013 }, + { 0xffff, 0xffff }, +}; + +struct card_match { + struct saa7146_sub_info *sub; /* Subsystem IDs or PCI_ANY_ID */ + struct card_info *card; +}; + +static struct card_match match_data[] = { + { &sub_data[ 0], &knc1 }, + { &sub_data[ 1], &ttbs }, + { &sub_data[ 2], &ttbc }, + { &sub_data[ 3], &ttbt }, + { &sub_data[ 4], &ttbci }, + { &sub_data[ 5], &satel }, + { &sub_data[ 6], NULL }, +}; + + +int budget_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned int subdevice) +{ + budget_t *budget; + int i = 0; + + DEB_EE(("dev: %p\n",dev)); + + for(i = 0;;i++) { + if( 0xffff == match_data[i].sub->subvendor ) { + printk(KERN_ERR "dvb: device subvendor:0x%04x, subdevice:0x%04x is not a known dvb card.\n",subvendor,subdevice); + return -ENODEV; + } + if( subvendor == match_data[i].sub->subvendor && subdevice == match_data[i].sub->subdevice ) { + break; + } + } + + if (!(budget = kmalloc (sizeof (struct budget_s), GFP_KERNEL))) { + printk ("%s: out of memory!\n", __FUNCTION__); + return -ENOMEM; + } + memset(budget, 0, sizeof(budget_t)); + budget->card_type = match_data[i].card; + + (budget_t*)dev->ext_priv = budget; + + return 0; +} + +static +int budget_attach (struct saa7146_dev* dev) +{ + budget_t *budget = (budget_t*)dev->ext_priv; + struct scatterlist *slist = NULL; + int slen = 0; + int length = TS_WIDTH*TS_HEIGHT; + int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; + int ret = 0; + + DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + + budget->dev=(struct saa7146_dev *)dev; + dvb_register_adapter(&budget->dvb_adapter, budget->card_type->name); + + saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200); + budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, budget->dvb_adapter, 0); + + if (!budget->i2c_bus) { + dvb_unregister_adapter (budget->dvb_adapter); + return -ENOMEM; + } + + budget->grabbing = vmalloc(length); + if (!budget->grabbing) { + printk(KERN_ERR "dvb: vmalloc() failed.\n"); + ret = -ENOMEM; + goto err; + } + + if (!(slist = vmalloc_to_sg(budget->grabbing, pages))) { + printk(KERN_ERR "dvb: vmalloc_to_sg() failed.\n"); + ret = -ENOMEM; + goto err; + } + + if (saa7146_pgtable_alloc(dev->pci, &budget->pt)) { + printk(KERN_ERR "dvb: saa7146_pgtable_alloc() failed.\n"); + ret = -ENOMEM; + goto err; + } + + slen = pci_map_sg(dev->pci,slist,pages,PCI_DMA_FROMDEVICE); + saa7146_pgtable_build_single(dev->pci, &budget->pt, slist, slen); + + saa7146_write(dev, PCI_BT_V1, 0x1c00101f); + /* set dd1 stream a & b */ + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, DD1_INIT, 0x02000000); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + /* upload all */ + saa7146_write(dev, MC2, 0x077c077c); + saa7146_write(dev, GPIO_CTRL, 0x000000); + + tasklet_init (&budget->fidb_tasklet, fidbirq, (unsigned long) budget); + + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); /* frontend power on */ + + budget_register(budget); + + printk(KERN_INFO "budget: found budget-%d.\n",budget_num); + budget_num++; + return 0; + +err: + if( NULL != budget->grabbing ) { + vfree(budget->grabbing); + } + if( NULL != slist ) { + kfree(slist); + } + dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id); + dvb_unregister_adapter (budget->dvb_adapter); + return ret; +} + +static +int budget_detach (struct saa7146_dev* saa) +{ + budget_t *budget = (budget_t*)saa->ext_priv; + DEB_EE(("budget: %p\n",budget)); + + dvb_unregister(budget); + dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id); + dvb_unregister_adapter (budget->dvb_adapter); + + saa7146_pgtable_free(saa->pci, &budget->pt); + vfree(budget->grabbing); + kfree (budget); + + saa->ext_priv = NULL; + budget_num--; + + return 0; +} + + +static +void budget_irq(struct saa7146_dev* dev, u32 *isr) +{ + budget_t *budget = (budget_t*)dev->ext_priv; + + DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + + if (*isr & MASK_07) + tasklet_schedule (&budget->fidb_tasklet); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) +static +void budget_inc_use(struct saa7146_dev* adap) +{ + MOD_INC_USE_COUNT; +} + +static +void budget_dec_use(struct saa7146_dev* adap) +{ + MOD_DEC_USE_COUNT; +} +#endif + +static +struct saa7146_extension budget_extension = { + .name = "budget dvb\0", + .devices = &sub_data[0], + .module = THIS_MODULE, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + .inc_use = budget_inc_use, + .dec_use = budget_dec_use, +#endif + .preinit = budget_preinit, + .probe = budget_probe, + .attach = budget_attach, + .detach = budget_detach, + + .irq_mask = MASK_07, + .irq_func = budget_irq, +}; + + +static +int __init budget_init(void) +{ + DEB_EE((".\n")); + + if (saa7146_register_extension(&budget_extension)) + return -ENODEV; + + return 0; +} + + +static +void __exit budget_exit(void) +{ + DEB_EE((".\n")); + + if (saa7146_unregister_extension(&budget_extension)) + printk(KERN_ERR "dvb: extension deregistration failed.\n"); +} + +module_init(budget_init); +module_exit(budget_exit); + +MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by " + "Siemens, Technotrend, Hauppauge"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(budget_debug,"i"); diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig new file mode 100644 index 000000000..cf8fe5251 --- /dev/null +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -0,0 +1,9 @@ +config DVB_BUDGET + tristate "SAA7146 based Nova/Budget PCI cards" + depends on VIDEO_DEV && DVB_CORE + help + Support for simple SAA7146 based DVB cards + (so called Budget- or Nova-PCI cards) without onboard + MPEG2 decoder. + + Say Y if you own such a card and want to use it. diff --git a/linux/drivers/media/dvb/av7110/Makefile b/linux/drivers/media/dvb/ttpci/Makefile index 5a9fd0c0c..5a9fd0c0c 100644 --- a/linux/drivers/media/dvb/av7110/Makefile +++ b/linux/drivers/media/dvb/ttpci/Makefile diff --git a/linux/drivers/media/dvb/av7110/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 77ccc15db..f196ec210 100644 --- a/linux/drivers/media/dvb/av7110/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -1,6 +1,5 @@ /* * av7110.c: driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB) - * and Nova/Budget DVB cards * * Copyright (C) 1999-2002 Ralph Metzler * & Marcus Metzler for convergence integrated media GmbH @@ -121,21 +120,9 @@ static inline void ddelay(int i) /**************************************************************************** - * GPIO and DEBI functions + * DEBI functions ****************************************************************************/ -inline static void -setgpio(av7110_t *av7110, int port, u32 data) -{ - struct saa7146_dev *dev = av7110->dev; - u32 val = 0; - - val=saa7146_read(dev,GPIO_CTRL); - val&=~(0xff << (8*(port))); - val|=(data)<<(8*(port)); - saa7146_write(dev, GPIO_CTRL, val); -} - /* This DEBI code is based on the Stradis driver by Nathan Laredo <laredo@gnu.org> */ @@ -311,7 +298,7 @@ reset_arm(av7110_t *av7110) { DEB_EE(("av7110: %p\n",av7110)); - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ IER_DISABLE(av7110->dev, (MASK_19 | MASK_03)); @@ -320,7 +307,7 @@ reset_arm(av7110_t *av7110) saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); mdelay(800); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); mdelay(800); ARM_ResetMailBox(av7110); @@ -703,84 +690,6 @@ ring_buffer_put(ring_buffer_t *db, u8 *buf, int len) } #endif - -/**************************************************************************** - * TT budget / WinTV Nova - ****************************************************************************/ - -static int -TTBStop(av7110_t *av7110) -{ - DEB_EE(("av7110: %p\n",av7110)); - - if (--av7110->feeding) - return av7110->feeding; - saa7146_write(av7110->dev, MC1, MASK_20); // DMA3 off - -// saa7146_write(av7110->dev, MC1, MASK_28); // RPS0 off - - IER_DISABLE(av7110->dev, (MASK_07 | MASK_10)); -/* - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_10 ); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER)& ~MASK_07); -*/ - return 0; -} - -#define TS_WIDTH (4*188) -#define TS_HEIGHT (1024/4) -#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) - -static int -TTBStart(av7110_t *av7110) -{ - struct saa7146_dev *dev=av7110->dev; - - DEB_EE(("av7110: %p\n",av7110)); - - //printk ("function : %s\n", __FUNCTION__); - if (av7110->feeding) - return ++av7110->feeding; - - saa7146_write(dev, MC1, MASK_20); // DMA3 off - - memset(av7110->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); - - saa7146_write(dev, PCI_BT_V1, 0x001c0000); - - av7110->tsf=0; - av7110->ttbp=0; - saa7146_write(dev, DD1_INIT, 0x02000680); - saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - - saa7146_write(dev, BRS_CTRL, 0x60000000); - saa7146_write(dev, MC2, (MASK_08 | MASK_24)); - mdelay(10); - - saa7146_write(dev, BASE_ODD3, 0); - saa7146_write(dev, BASE_EVEN3, TS_WIDTH*TS_HEIGHT/2); - saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT); - saa7146_write(dev, BASE_PAGE3, av7110->pt.dma |ME1|0xb0); - saa7146_write(dev, PITCH3, TS_WIDTH); - - saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT/2)<<16)|TS_WIDTH); - saa7146_write(dev, MC2, (MASK_04 | MASK_20)); - - // VPE - IER_ENABLE(av7110->dev, MASK_10); -// saa7146_write(dev, IER, saa7146_read(saa->mem, IER)|MASK_10); - - saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on - - // FIDB - IER_ENABLE(av7110->dev, MASK_07); -// saa7146_write(dev, IER, saa7146_read(saa->mem, IER)|MASK_07); - - return ++av7110->feeding; -} - /** * Hack! we save the last av7110 ptr. This should be ok, since * you rarely will use more then one IR control. @@ -928,86 +837,6 @@ u8 pshead[0x26] = { }; -static void vpeirq (unsigned long data) -{ - //printk("vpeirq %08x\n", saa7146_read(av7110->dev, PCI_VDP3)); -} - -#if 0 -static void fidbirq(struct saa7146_dev* saa, void *data) -{ - av7110_t *av7110=(av7110_t *) data; - u8 *mem; - - DEB_EE(("av7110: %p\n",av7110)); - - mem=(av7110->tsf ? TS_HEIGHT*TS_WIDTH/2 :0)+(u8 *)av7110->grabbing; - - // FIXME: think of something better without busy waiting - if (av7110->tsf) - while (saa7146_read(av7110->dev, PCI_VDP3)>0x20000); - else - while (saa7146_read(av7110->dev, PCI_VDP3)<0x17800); - - av7110->tsf^=1; - saa7146_write(av7110->dev, DD1_INIT, 0x02000600|(av7110->tsf ? 0x40:0x80)); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - - // FIXME: use bottom half or tasklet - if (av7110->feeding && mem[0]==0x47) - dvb_dmx_swfilter_packets(&av7110->demux, mem, 512); -} -#else -static -void fidbirq (unsigned long data) -{ - struct av7110_s *av7110 = (struct av7110_s*) data; - u8 *mem=(u8 *)(av7110->grabbing); - int num; - u32 dmapos; - - DEB_EE(("av7110: %p\n",av7110)); - - dmapos=saa7146_read(av7110->dev, PCI_VDP3); - dmapos-=(dmapos%188); - - if (dmapos>=TS_BUFLEN) { - DEB_S(("bogus dmapos value ignored, av7110: %p\n",av7110)); - return; - } - - if (av7110->tsf) { - mem+=av7110->ttbp; - if (dmapos<0x20000) { - num=1024-av7110->ttbp/188; - av7110->ttbp=0; - } else { - num=(dmapos - av7110->ttbp)/188; - av7110->ttbp=dmapos; - } - } else { - if (av7110->ttbp>1000*188 && av7110->ttbp<1024*188) { - if (av7110->feeding) - dvb_dmx_swfilter_packets(&av7110->demux, - mem+av7110->ttbp, - 1024- av7110->ttbp / 188); - } - num=dmapos/188; - av7110->ttbp=dmapos; - } - - av7110->tsf^=1; - saa7146_write(av7110->dev, DD1_INIT, 0x02000600|(av7110->tsf ? 0x40:0x80)); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - - // FIXME: use bottom half or tasklet - if (av7110->feeding && mem[0]==0x47) - dvb_dmx_swfilter_packets(&av7110->demux, mem, num); -} -#endif - //#define DEBUG_TIMING inline static void print_time(char *s) @@ -2247,12 +2076,13 @@ bootcode[] = { static int bootarm(av7110_t *av7110) { + struct saa7146_dev *dev= av7110->dev; u32 ret; int i; DEB_EE(("av7110: %p\n",av7110)); - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ IER_DISABLE(av7110->dev, MASK_03|MASK_19); @@ -2282,15 +2112,15 @@ bootarm(av7110_t *av7110) /* boot */ DEB_D(("bootarm: load boot code\n")); - setgpio(av7110, ARM_IRQ_LINE, GPIO_IRQLO); - //setgpio(av7110, DEBI_DONE_LINE, GPIO_INPUT); - //setgpio(av7110, 3, GPIO_INPUT); + saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO); + //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); + //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); iwdebi(av7110, DEBISWAB, DPRAM_BASE, (u32) bootcode, sizeof(bootcode)); iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); wait_for_debi_done(av7110); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); current->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ); @@ -2299,7 +2129,7 @@ bootarm(av7110_t *av7110) if (load_dram(av7110, (u32 *)Root, sizeof(Root))<0) return -1; - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); mdelay(1); DEB_D(("bootarm: load dpram code\n")); @@ -2308,7 +2138,7 @@ bootarm(av7110_t *av7110) wait_for_debi_done(av7110); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); mdelay(800); //ARM_ClearIrq(av7110); @@ -2412,43 +2242,8 @@ inline static void Set22K(av7110_t *av7110, int state) { DEB_EE(("av7110: %p\n",av7110)); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) outcom(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0); - if (av7110->card_type->type==DVB_CARD_TT_BUDGET) - setgpio(av7110, 3, (state ? GPIO_OUTHI : GPIO_OUTLO)); -} - - -/* Diseqc functions only for TT Budget card */ -/* taken from the Skyvision DVB driver by - Ralph Metzler <rjkm@metzlerbros.de> */ - - -inline static void -DiseqcSendBit(av7110_t *av7110, int data) -{ - DEB_EE(("av7110: %p\n",av7110)); - - setgpio(av7110, 3, GPIO_OUTHI); - udelay(data ? 500 : 1000); - setgpio(av7110, 3, GPIO_OUTLO); - udelay(data ? 1000 : 500); -} - -static void -DiseqcSendByte(av7110_t *av7110, int data) -{ - int i, par=1, d; - - DEB_EE(("av7110: %p\n",av7110)); - - for (i=7; i>=0; i--) - { - d=(data>>i)&1; - par^=d; - DiseqcSendBit(av7110, d); - } - DiseqcSendBit(av7110, par); } inline static int @@ -2458,8 +2253,10 @@ SendDiSEqCMsg(av7110_t *av7110, int len, u8 *msg, int burst) DEB_EE(("av7110: %p\n",av7110)); +/* switch (av7110->card_type->type) { case DVB_CARD_TT_SIEMENS: +*/ { u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -2479,35 +2276,12 @@ SendDiSEqCMsg(av7110_t *av7110, int len, u8 *msg, int burst) buf[i+4]=msg[i]; SOutCommand(av7110, buf, 18); +/* break; } - - case DVB_CARD_TT_BUDGET: - setgpio(av7110, 3, GPIO_OUTLO); - - mdelay(16); - - for (i=0; i<len; i++) - DiseqcSendByte(av7110, msg[i]); - - mdelay(16); - - if (burst!=-1) { - if (burst) - DiseqcSendByte(av7110, 0xff); - else { - setgpio(av7110, 3, GPIO_OUTHI); - udelay(12500); - setgpio(av7110, 3, GPIO_OUTLO); - } - - ddelay(2); - } - - break; - default: return -1; +*/ } return 0; } @@ -3223,9 +2997,6 @@ av7110_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - return TTBStart(av7110); - if (feed->pid > 0x1fff) return -EINVAL; @@ -3282,9 +3053,6 @@ av7110_stop_feed(struct dvb_demux_feed *feed) DEB_EE(("av7110: %p\n",av7110)); - if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - return TTBStop(av7110); - if (feed->type == DMX_TYPE_TS) { if (feed->ts_type & TS_DECODER) { if (feed->pes_type >= DMX_TS_PES_OTHER || @@ -4221,14 +3989,13 @@ int av7110_register(av7110_t *av7110) av7110->registered=1; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_add_frontend_notifier (av7110->dvb_adapter, av7110_before_after_tune, av7110); /** * init DiSEqC stuff */ - if (av7110->card_type->type==DVB_CARD_TT_BUDGET || - av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_add_frontend_ioctls (av7110->dvb_adapter, av7110_diseqc_ioctl, NULL, av7110); @@ -4250,7 +4017,7 @@ int av7110_register(av7110_t *av7110) av7110->demux_id[7]=av7110->dvb_adapter->num+0x30; dvbdemux->priv=(void *) av7110; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { for (i=0; i<32; i++) av7110->handle2filter[i]=NULL; @@ -4280,35 +4047,7 @@ int av7110_register(av7110_t *av7110) av7110->dmxdev.capabilities=0; dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); - } - - if (av7110->card_type->type>=DVB_CARD_TT_BUDGET) { - dvbdemux->filternum=256; - dvbdemux->feednum=256; - dvbdemux->start_feed=av7110_start_feed; - dvbdemux->stop_feed=av7110_stop_feed; - dvbdemux->write_to_decoder=NULL; - - dvbdemux->dmx.vendor="CIM"; - dvbdemux->dmx.model="sw"; - dvbdemux->dmx.id=av7110->demux_id; - dvbdemux->dmx.capabilities=(DMX_TS_FILTERING| - DMX_SECTION_FILTERING| - DMX_MEMORY_BASED_FILTERING); - - dvb_dmx_init(&av7110->demux); - - dvbfront->id="hw_frontend"; - dvbfront->vendor="VLSI"; - dvbfront->model="DVB Frontend"; - dvbfront->source=DMX_FRONTEND_0; - - av7110->dmxdev.filternum=256; - av7110->dmxdev.demux=&dvbdemux->dmx; - av7110->dmxdev.capabilities=0; - - dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); - } +// } ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend); @@ -4329,7 +4068,7 @@ int av7110_register(av7110_t *av7110) if (ret<0) return ret; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { dvb_register_device(av7110->dvb_adapter, &av7110->video_dev, &dvbdev_video, av7110, DVB_DEVICE_VIDEO); dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev, @@ -4347,7 +4086,7 @@ int av7110_register(av7110_t *av7110) dvb_audio_write, av7110->audio_dev); #endif - } +// } av7110->dvb_net.card_num=av7110->dvb_adapter->num; dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); @@ -4375,14 +4114,14 @@ dvb_unregister(av7110_t *av7110) dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_remove_frontend_notifier (av7110->dvb_adapter, av7110_before_after_tune); dvb_remove_frontend_ioctls (av7110->dvb_adapter, av7110_diseqc_ioctl, NULL); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { dvb_unregister_device(av7110->audio_dev); dvb_unregister_device(av7110->video_dev); dvb_unregister_device(av7110->osd_dev); @@ -4390,7 +4129,7 @@ dvb_unregister(av7110_t *av7110) #ifdef USE_DVB_DSP dvb_unregister_dsp(av7110->dsp_dev); #endif - } +// } } static @@ -4423,32 +4162,25 @@ int av7110_preinit(struct saa7146_dev* dev) return 0; } -static struct card_info fs_1_5 = { DVB_CARD_TT_SIEMENS, "Siemens cable card PCI rev1.5" }; -static struct card_info fs_1_3 = { DVB_CARD_TT_SIEMENS, "Siemens/Technotrend/Hauppauge PCI rev1.3" }; -static struct card_info ttbs = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-S PCI" }; -static struct card_info ttbc = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-C PCI" }; -static struct card_info ttbt = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-T PCI" }; -static struct card_info ttbci = { DVB_CARD_TT_BUDGET_CI, "TT-Budget/WinTV-NOVA-CI PCI" }; -static struct card_info satel = { DVB_CARD_TT_BUDGET, "SATELCO Multimedia PCI"}; -static struct card_info unkwn = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev?(unknown0)?"}; -static struct card_info tt_1_6 = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev1.3 or 1.6" }; -static struct card_info tt_2_1 = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev2.1" }; -static struct card_info tt_t = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI DVB-T" }; -static struct card_info knc1 = { DVB_CARD_KNC1, "KNC1 DVB-S" }; +struct card_info { + char *name; +}; + +static char *fs_1_5 = { "Siemens cable card PCI rev1.5" }; +static char *fs_1_3 = { "Siemens/Technotrend/Hauppauge PCI rev1.3" }; +static char *unkwn = { "Technotrend/Hauppauge PCI rev?(unknown0)?"}; +static char *tt_1_6 = { "Technotrend/Hauppauge PCI rev1.3 or 1.6" }; +static char *tt_2_1 = { "Technotrend/Hauppauge PCI rev2.1" }; +static char *tt_t = { "Technotrend/Hauppauge PCI DVB-T" }; struct card_match { - struct saa7146_sub_info *sub; /* Subsystem ID's or PCI_ANY_ID */ - struct card_info *card; + struct saa7146_sub_info *sub; /* Subsystem IDs or PCI_ANY_ID */ + char **card; }; static struct saa7146_sub_info sub_data[] = { { 0x110a, 0xffff }, { 0x110a, 0x0000 }, - { 0x13c2, 0x1003 }, - { 0x13c2, 0x1004 }, - { 0x13c2, 0x1005 }, - { 0x13c2, 0x100c }, - { 0x13c2, 0x1013 }, { 0x13c2, 0x0000 }, { 0x13c2, 0x1002 }, { 0x13c2, 0x0001 }, @@ -4458,29 +4190,22 @@ static struct saa7146_sub_info sub_data[] = { { 0x13c2, 0x0006 }, { 0x13c2, 0x0008 }, { 0xffc2, 0x0000 }, - { 0x1131, 0x4f56 }, { 0xffff, 0xffff }, }; static struct card_match match_data[] = { { &sub_data[ 0], &fs_1_5 }, { &sub_data[ 1], &fs_1_5 }, - { &sub_data[ 2], &ttbs }, - { &sub_data[ 3], &ttbc }, - { &sub_data[ 4], &ttbt }, - { &sub_data[ 5], &ttbci }, - { &sub_data[ 6], &satel }, - { &sub_data[ 7], &fs_1_3 }, - { &sub_data[ 8], &unkwn }, - { &sub_data[ 9], &tt_1_6 }, - { &sub_data[10], &tt_2_1 }, - { &sub_data[11], &tt_2_1 }, - { &sub_data[12], &tt_2_1 }, - { &sub_data[13], &tt_1_6 }, - { &sub_data[14], &tt_t }, - { &sub_data[15], &unkwn }, - { &sub_data[16], &knc1 }, - { &sub_data[17], NULL }, + { &sub_data[ 2], &fs_1_3 }, + { &sub_data[ 3], &unkwn }, + { &sub_data[ 4], &tt_1_6 }, + { &sub_data[ 5], &tt_2_1 }, + { &sub_data[ 6], &tt_2_1 }, + { &sub_data[ 7], &tt_2_1 }, + { &sub_data[ 8], &tt_1_6 }, + { &sub_data[ 9], &tt_t }, + { &sub_data[10], &unkwn }, + { &sub_data[11], NULL }, }; @@ -4506,7 +4231,7 @@ int av7110_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned int s return -ENOMEM; } memset(av7110, 0, sizeof(av7110_t)); - av7110->card_type = match_data[i].card; + av7110->card_name = *match_data[i].card; (av7110_t*)dev->ext_priv = av7110; @@ -4517,56 +4242,33 @@ static int av7110_attach (struct saa7146_dev* dev) { av7110_t *av7110 = (av7110_t*)dev->ext_priv; - struct scatterlist *slist = NULL; - int slen = 0; - int length = TS_WIDTH*TS_HEIGHT; - int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; int ret = 0; DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); - saa7146_video_uops.init(dev); + if( 0 != saa7146_vv_init(dev)) { + ERR(("cannot init capture device. skipping.\n")); + return -1; + } + if( 0 != saa7146_register_device(&av7110->vd, dev, "av7710", VFL_TYPE_GRABBER)) { ERR(("cannot register capture device. skipping.\n")); + saa7146_vv_release(dev); return -1; } av7110->dev=(struct saa7146_dev *)dev; - dvb_register_adapter(&av7110->dvb_adapter, av7110->card_type->name); + dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name); saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200); av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, av7110->dvb_adapter, 0); if (!av7110->i2c_bus) { + saa7146_unregister_device(&av7110->vd, dev); + saa7146_vv_release(dev); dvb_unregister_adapter (av7110->dvb_adapter); return -ENOMEM; } - -// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - av7110->grabbing = vmalloc(length); - if (!av7110->grabbing) { - printk(KERN_ERR "dvb: vmalloc() failed.\n"); - ret = -ENOMEM; - goto err; - } - - if (!(slist = videobuf_vmalloc_to_sg(av7110->grabbing, pages))) { - printk(KERN_ERR "dvb: videobuf_vmalloc_to_sg() failed.\n"); - ret = -ENOMEM; - goto err; - } - - if (saa7146_pgtable_alloc(dev->pci, &av7110->pt)) { - printk(KERN_ERR "dvb: saa7146_pgtable_alloc() failed.\n"); - ret = -ENOMEM; - goto err; - } - - slen = pci_map_sg(dev->pci,slist,pages,PCI_DMA_FROMDEVICE); - saa7146_pgtable_build_single(dev->pci, &av7110->pt, slist, slen); - -// } - saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -4581,8 +4283,6 @@ int av7110_attach (struct saa7146_dev* dev) tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110); tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110); - tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110); - tasklet_init (&av7110->fidb_tasklet, fidbirq, (unsigned long) av7110); sema_init(&av7110->pid_mutex, 1); @@ -4640,23 +4340,18 @@ int av7110_attach (struct saa7146_dev* dev) /* handle different card types */ /* load firmware into AV7110 cards */ - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { bootarm(av7110); firmversion(av7110); if ((av7110->arm_app&0xffff)<0x2502) { printk("av7110: Warning, firmware version is too old. System might be unstable!!!\n"); } kernel_thread(arm_thread, (void *) av7110, 0); - } else { - saa7146_write(av7110->dev, DD1_INIT, 0x02000600); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - setgpio(av7110, 2, GPIO_OUTHI); /* frontend power on */ - } +// } SetVolume(av7110, 0xff, 0xff); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { VidMode(av7110, vidmode); /* remaining inits according to card and frontend type */ @@ -4693,11 +4388,11 @@ int av7110_attach (struct saa7146_dev* dev) outcom(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); outcom(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - //setgpio(av7110, 1, GPIO_OUTHI); // RGB on, SCART pin 16 - //setgpio(av7110, 3, GPIO_OUTLO); // SCARTpin 8 + //saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 + //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 av7110->adac_type = DVB_ADAC_NONE; } - } +// } av7110_setup_irc_config (av7110, 0); av7110_register(av7110); @@ -4707,12 +4402,9 @@ int av7110_attach (struct saa7146_dev* dev) return 0; err: - if( NULL != av7110->grabbing ) { - vfree(av7110->grabbing); - } - if( NULL != slist ) { - kfree(slist); - } + /* FIXME: error handling is totally bogus: memory does not get freed ... */ + saa7146_unregister_device(&av7110->vd, dev); + saa7146_vv_release(dev); dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); return ret; @@ -4747,11 +4439,6 @@ int av7110_detach (struct saa7146_dev* saa) pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); -// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - saa7146_pgtable_free(saa->pci, &av7110->pt); - vfree(av7110->grabbing); -// } - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); @@ -4776,12 +4463,6 @@ void av7110_irq(struct saa7146_dev* dev, u32 *isr) if (*isr & MASK_03) tasklet_schedule (&av7110->gpio_tasklet); - - if (*isr & MASK_10) - tasklet_schedule (&av7110->vpe_tasklet); - - if (*isr & MASK_07) - tasklet_schedule (&av7110->fidb_tasklet); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) @@ -4809,35 +4490,38 @@ struct saa7146_standard standard[] = { }; static -struct saa7146_extension av7110_extension = { - .name = "dvb\0", +struct saa7146_ext_vv av7110_vv_data = { .inputs = 1, .audios = 1, .capabilities = 0, - .flags = SAA7146_EXT_SWAP_ODD_EVEN, + .stds = &standard[0], + .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), + .std_callback = NULL, + + .ioctls = &ioctls[0], + .ioctl = av7110_ioctl, +}; + +static +struct saa7146_extension av7110_extension = { + .name = "dvb\0", + .devices = &sub_data[0], .module = THIS_MODULE, - + .ext_vv_data = &av7110_vv_data, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) .inc_use = av7110_inc_use, .dec_use = av7110_dec_use, #endif - .stds = &standard[0], - .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = NULL, - - .ioctls = &ioctls[0], - .preinit = av7110_preinit, .probe = av7110_probe, .attach = av7110_attach, .detach = av7110_detach, - .ioctl = av7110_ioctl, - .irq_mask = MASK_07|MASK_10|MASK_19|MASK_03, // |MASK_27, + .irq_mask = MASK_19|MASK_03, .irq_func = av7110_irq, }; diff --git a/linux/drivers/media/dvb/av7110/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h index a379a3fcd..d1eabe3ab 100644 --- a/linux/drivers/media/dvb/av7110/av7110.h +++ b/linux/drivers/media/dvb/ttpci/av7110.h @@ -11,7 +11,7 @@ #include <linux/devfs_fs_kernel.h> #endif -#include "saa7146.h" +#include "saa7146_vv.h" /* DEBI transfer mode defs */ @@ -39,11 +39,6 @@ #include "dvb_filter.h" #include "dvb_net.h" -#define DVB_CARD_TT_SIEMENS 0 -#define DVB_CARD_TT_BUDGET 1 -#define DVB_CARD_TT_BUDGET_CI 2 -#define DVB_CARD_KNC1 3 - typedef enum BOOTSTATES { BOOTSTATE_BUFFER_EMPTY = 0, @@ -51,16 +46,6 @@ typedef enum BOOTSTATES BOOTSTATE_BOOT_COMPLETE = 2 } BOOTSTATES; -typedef enum GPIO_MODE -{ - GPIO_INPUT = 0x00, - GPIO_IRQHI = 0x10, - GPIO_IRQLO = 0x20, - GPIO_IRQHL = 0x30, - GPIO_OUTLO = 0x40, - GPIO_OUTHI = 0x50 -} GPIO_MODE; - typedef enum { RP_None, AudioPES, @@ -111,14 +96,14 @@ typedef enum { // switch defines #define SB_GPIO 3 -#define SB_OFF GPIO_OUTLO //SlowBlank aus (TV-Mode) -#define SB_ON GPIO_INPUT //SlowBlank an (AV-Mode) -#define SB_WIDE GPIO_OUTHI //SlowBlank 6V (16/9-Mode) nicht realisiert +#define SB_OFF SAA7146_GPIO_OUTLO //SlowBlank aus (TV-Mode) +#define SB_ON SAA7146_GPIO_INPUT //SlowBlank an (AV-Mode) +#define SB_WIDE SAA7146_GPIO_OUTHI //SlowBlank 6V (16/9-Mode) nicht realisiert #define FB_GPIO 1 -#define FB_OFF GPIO_LO //FastBlank aus (CVBS-Mode) -#define FB_ON GPIO_OUTHI //FastBlank an (RGB-Mode) -#define FB_LOOP GPIO_INPUT //FastBlank der PC-Grafik durchschleifen +#define FB_OFF SAA7146_GPIO_LO //FastBlank aus (CVBS-Mode) +#define FB_ON SAA7146_GPIO_OUTHI //FastBlank an (RGB-Mode) +#define FB_LOOP SAA7146_GPIO_INPUT //FastBlank der PC-Grafik durchschleifen typedef enum VIDEOOUTPUTMODE { @@ -471,11 +456,6 @@ typedef struct p2t_s { struct dvb_demux_feed *feed; } p2t_t; -struct card_info { - int type; - char *name; -}; - /* place to store all the necessary device information */ typedef struct av7110_s { @@ -488,15 +468,10 @@ typedef struct av7110_s { struct saa7146_dev *dev; struct dvb_i2c_bus *i2c_bus; - struct card_info *card_type; - - unsigned char *grabbing; - struct saa7146_pgtable pt; + char *card_name; struct tasklet_struct debi_tasklet; struct tasklet_struct gpio_tasklet; - struct tasklet_struct vpe_tasklet; - struct tasklet_struct fidb_tasklet; int adac_type; /* audio DAC type */ #define DVB_ADAC_TI 0 @@ -586,11 +561,6 @@ typedef struct av7110_s { u8 *kbuf[2]; int sinfo; - int shsize; - int swsize; - - int tsf; - u32 ttbp; int feeding; int arm_errors; diff --git a/linux/drivers/media/dvb/av7110/av7110_firm.h b/linux/drivers/media/dvb/ttpci/av7110_firm.h index 5c93deb3d..5c93deb3d 100644 --- a/linux/drivers/media/dvb/av7110/av7110_firm.h +++ b/linux/drivers/media/dvb/ttpci/av7110_firm.h diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.c b/linux/drivers/media/dvb/ttpci/av7110_ipack.c index 3d16442e6..3d16442e6 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ipack.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ipack.c diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.h b/linux/drivers/media/dvb/ttpci/av7110_ipack.h index d1c995aff..d1c995aff 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ipack.h +++ b/linux/drivers/media/dvb/ttpci/av7110_ipack.h diff --git a/linux/drivers/media/dvb/av7110/av7110_ir.c b/linux/drivers/media/dvb/ttpci/av7110_ir.c index 4e89ed71f..4e89ed71f 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ir.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ir.c diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index ce8a4d9b4..2c25aa644 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -18,7 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <saa7146.h> +#include <saa7146_vv.h> #include "mxb.h" #include "tea6415c.h" @@ -176,6 +176,31 @@ struct mxb int cur_mute; /* current mute status */ }; +static int mxb_vbi_bypass(struct saa7146_dev* dev) +{ + struct mxb* mxb = (struct mxb*)dev->ext_priv; + s32 byte = 0x0; + int result = 0; + + DEB_EE(("dev:%p\n",dev)); + + /* switch bypass in saa7111a, this should be done in the + saa7111a driver of course... */ + if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) { + DEB_D(("could not read from saa7111a.\n")); + return -EFAULT; + } + byte = result; + byte &= 0xf0; + byte |= 0x0a; + + if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) { + DEB_D(("could not write to saa7111a.\n")); + return -EFAULT; + } + return 0; +} + /* this function gets called very early in the registration process of the extension. it has been reported that some devices need to enable the i2c-bus explicitly for example -- this can be done here. please @@ -357,6 +382,8 @@ static int mxb_init_done(struct saa7146_dev* dev) // i = VIDEO_MODE_PAL; // mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); + mxb_vbi_bypass(dev); + /* select a tuner type */ i = 5; mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE, &i); @@ -451,7 +478,7 @@ static int mxb_attach(struct saa7146_dev* dev) /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ - saa7146_video_uops.init(dev); + saa7146_vv_init(dev); if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; @@ -459,10 +486,8 @@ static int mxb_attach(struct saa7146_dev* dev) /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { - saa7146_vbi_uops.init(dev); if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { ERR(("cannot register vbi v4l2 device. skipping.\n")); - return -1; } } @@ -494,6 +519,7 @@ static int mxb_detach(struct saa7146_dev* dev) if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { saa7146_unregister_device(&mxb->vbi_dev,dev); } + saa7146_vv_release(dev); mxb_num--; @@ -503,31 +529,6 @@ static int mxb_detach(struct saa7146_dev* dev) return 0; } -static int mxb_vbi_bypass(struct saa7146_dev* dev) -{ - struct mxb* mxb = (struct mxb*)dev->ext_priv; - s32 byte = 0x0; - int result = 0; - - DEB_EE(("dev:%p\n",dev)); - - /* switch bypass in saa7111a, this should be done in the - saa7111a driver of course... */ - if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) { - DEB_D(("could not read from saa7111a.\n")); - return -EFAULT; - } - byte = result; - byte &= 0xf0; - byte |= 0x0a; - - if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) { - DEB_D(("could not write to saa7111a.\n")); - return -EFAULT; - } - return 0; -} - /* hack: this should go into saa711x */ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) { @@ -561,7 +562,8 @@ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - + struct saa7146_vv *vv = dev->vv_data; + switch(cmd) { case VIDIOC_ENUMINPUT: { @@ -909,7 +911,7 @@ static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); - dev->vbi_fieldcount = 0; + vv->vbi_fieldcount = 0; spin_unlock(&dev->slock); return 0; @@ -1017,33 +1019,34 @@ static struct saa7146_sub_info sub_data[] = { }; static -struct saa7146_extension extension = { - .name = MXB_IDENTIFIER, +struct saa7146_ext_vv vv_data = { .inputs = MXB_INPUTS, .audios = MXB_AUDIOS, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, - .flags = 0, - + .stds = &standard[0], + .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), + .std_callback = &std_callback, + .ioctls = &ioctls[0], + .ioctl = mxb_ioctl, +}; + +static +struct saa7146_extension extension = { + .name = MXB_IDENTIFIER, .devices = &sub_data[0], .module = THIS_MODULE, + .ext_vv_data = &vv_data, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) .inc_use = mxb_inc_use, .dec_use = mxb_dec_use, #endif - .stds = &standard[0], - .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = &std_callback, - - .ioctls = &ioctls[0], - .preinit = mxb_preinit, .probe = mxb_probe, .attach = mxb_attach, .detach = mxb_detach, - .ioctl = mxb_ioctl, .irq_mask = 0, .irq_func = NULL, |