Commit 4a6f3f0e authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] Update the saa7146 driver core

 - fix WRITE_RPS0 and WRITE_RPS1 inlines, fix usage in mxb and budget
   drivers
 - export "saa7146_start_preview" and "saa7146_stop_preview" to allow
   drivers to start and stop video overlay (necessary for analog module
   support in the av7110 driver)
 - fix i2c implementation: some frontend drivers transfer a huge amount
   of firmware data (> 30kB), speed up the transmission by busy waiting
   between byte transfers for bigger transmissions
 - change ioctl function in various driver to accept a saa7146
   filehandle instead of a saa714 device structure
parent 2201b74f
...@@ -935,6 +935,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71 ...@@ -935,6 +935,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
static void program_capture_engine(struct saa7146_dev *dev, int planar) static void program_capture_engine(struct saa7146_dev *dev, int planar)
{ {
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
int count = 0;
unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_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; unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
......
...@@ -181,9 +181,10 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev) ...@@ -181,9 +181,10 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
/* this functions writes out the data-byte 'dword' to the i2c-device. /* this functions writes out the data-byte 'dword' to the i2c-device.
it returns 0 if ok, -1 if the transfer failed, -2 if the transfer it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
failed badly (e.g. address error) */ failed badly (e.g. address error) */
static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
{ {
u32 status = 0, mc2 = 0; u32 status = 0, mc2 = 0;
int trial = 0;
int timeout; int timeout;
/* write out i2c-command */ /* write out i2c-command */
...@@ -224,10 +225,13 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) ...@@ -224,10 +225,13 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword)
/* wait until we get a transfer done or error */ /* wait until we get a transfer done or error */
timeout = jiffies + HZ/100 + 1; /* 10ms */ timeout = jiffies + HZ/100 + 1; /* 10ms */
while(1) { while(1) {
/**
* first read usually delivers bogus results...
*/
saa7146_i2c_status(dev);
status = saa7146_i2c_status(dev); status = saa7146_i2c_status(dev);
if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { if ((status & 0x3) != 1)
break; break;
}
if (jiffies > timeout) { if (jiffies > timeout) {
/* this is normal when probing the bus /* this is normal when probing the bus
* (no answer from nonexisistant device...) * (no answer from nonexisistant device...)
...@@ -235,6 +239,9 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) ...@@ -235,6 +239,9 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword)
DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
return -EIO; return -EIO;
} }
if ((++trial < 20) && short_delay)
udelay(10);
else
my_wait(dev,1); my_wait(dev,1);
} }
} }
...@@ -277,6 +284,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i ...@@ -277,6 +284,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
u32* buffer = dev->d_i2c.cpu_addr; u32* buffer = dev->d_i2c.cpu_addr;
int err = 0; int err = 0;
int address_err = 0; int address_err = 0;
int short_delay = 0;
if (down_interruptible (&dev->i2c_lock)) if (down_interruptible (&dev->i2c_lock))
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -292,6 +300,8 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i ...@@ -292,6 +300,8 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
goto out; goto out;
} }
if (count > 3) short_delay = 1;
do { do {
/* reset the i2c-device if necessary */ /* reset the i2c-device if necessary */
err = saa7146_i2c_reset(dev); err = saa7146_i2c_reset(dev);
...@@ -302,7 +312,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i ...@@ -302,7 +312,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
/* write out the u32s one after another */ /* write out the u32s one after another */
for(i = 0; i < count; i++) { for(i = 0; i < count; i++) {
err = saa7146_i2c_writeout(dev, &buffer[i] ); err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
if ( 0 != err) { if ( 0 != err) {
/* this one is unsatisfying: some i2c slaves on some /* this one is unsatisfying: some i2c slaves on some
dvb cards don't acknowledge correctly, so the saa7146 dvb cards don't acknowledge correctly, so the saa7146
...@@ -357,7 +367,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i ...@@ -357,7 +367,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
if( 0 == dev->revision ) { if( 0 == dev->revision ) {
u32 zero = 0; u32 zero = 0;
saa7146_i2c_reset(dev); saa7146_i2c_reset(dev);
if( 0 != saa7146_i2c_writeout(dev, &zero)) { if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
INFO(("revision 0 error. this should never happen.\n")); INFO(("revision 0 error. this should never happen.\n"));
} }
} }
......
...@@ -9,6 +9,7 @@ static int vbi_workaround(struct saa7146_dev *dev) ...@@ -9,6 +9,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
u32 *cpu; u32 *cpu;
dma_addr_t dma_addr; dma_addr_t dma_addr;
int count = 0;
int i; int i;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
......
...@@ -220,7 +220,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) ...@@ -220,7 +220,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
} }
} }
static int start_preview(struct saa7146_fh *fh) int saa7146_start_preview(struct saa7146_fh *fh)
{ {
struct saa7146_dev *dev = fh->dev; struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
...@@ -266,12 +266,12 @@ static int start_preview(struct saa7146_fh *fh) ...@@ -266,12 +266,12 @@ static int start_preview(struct saa7146_fh *fh)
return 0; return 0;
} }
static int stop_preview(struct saa7146_fh *fh) int saa7146_stop_preview(struct saa7146_fh *fh)
{ {
struct saa7146_dev *dev = fh->dev; struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
DEB_EE(("saa7146.o: stop_preview()\n")); DEB_EE(("saa7146.o: saa7146_stop_preview()\n"));
/* check if overlay is running */ /* check if overlay is running */
if( 0 == vv->ov_data ) { if( 0 == vv->ov_data ) {
...@@ -333,8 +333,8 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) ...@@ -333,8 +333,8 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
if( vv->ov_data != NULL ) { if( vv->ov_data != NULL ) {
if( fh == vv->ov_data->fh) { if( fh == vv->ov_data->fh) {
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
stop_preview(fh); saa7146_stop_preview(fh);
start_preview(fh); saa7146_start_preview(fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
} }
} }
...@@ -522,8 +522,8 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) ...@@ -522,8 +522,8 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
if( 0 != vv->ov_data ) { if( 0 != vv->ov_data ) {
if( fh == vv->ov_data->fh ) { if( fh == vv->ov_data->fh ) {
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
stop_preview(fh); saa7146_stop_preview(fh);
start_preview(fh); saa7146_start_preview(fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
} }
} }
...@@ -747,12 +747,12 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -747,12 +747,12 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
DEB_D(("extension handles ioctl exclusive.\n")); DEB_D(("extension handles ioctl exclusive.\n"));
result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); result = dev->ext->ext_vv_data->ioctl(fh, cmd, arg);
return result; return result;
} }
if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
DEB_D(("extension handles ioctl before.\n")); DEB_D(("extension handles ioctl before.\n"));
result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); result = dev->ext->ext_vv_data->ioctl(fh, cmd, arg);
if( -EAGAIN != result ) { if( -EAGAIN != result ) {
return result; return result;
} }
...@@ -968,7 +968,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -968,7 +968,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
if( vv->ov_data != NULL ) { if( vv->ov_data != NULL ) {
ov_fh = vv->ov_data->fh; ov_fh = vv->ov_data->fh;
stop_preview(ov_fh); saa7146_stop_preview(ov_fh);
restart_overlay = 1; restart_overlay = 1;
} }
...@@ -983,7 +983,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -983,7 +983,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
} }
if( 0 != restart_overlay ) { if( 0 != restart_overlay ) {
start_preview(ov_fh); saa7146_start_preview(ov_fh);
} }
up(&dev->lock); up(&dev->lock);
...@@ -1013,7 +1013,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -1013,7 +1013,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
} }
} }
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
err = start_preview(fh); err = saa7146_start_preview(fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
} else { } else {
if( vv->ov_data != NULL ) { if( vv->ov_data != NULL ) {
...@@ -1022,7 +1022,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -1022,7 +1022,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
} }
} }
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
err = stop_preview(fh); err = saa7146_stop_preview(fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
} }
return err; return err;
...@@ -1287,7 +1287,7 @@ static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct f ...@@ -1287,7 +1287,7 @@ static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct f
if( 0 != vv->ov_data ) { if( 0 != vv->ov_data ) {
if( fh == vv->ov_data->fh ) { if( fh == vv->ov_data->fh ) {
spin_lock_irqsave(&dev->slock,flags); spin_lock_irqsave(&dev->slock,flags);
stop_preview(fh); saa7146_stop_preview(fh);
spin_unlock_irqrestore(&dev->slock,flags); spin_unlock_irqrestore(&dev->slock,flags);
} }
} }
...@@ -1331,7 +1331,7 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p ...@@ -1331,7 +1331,7 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p
if( vv->ov_data != NULL ) { if( vv->ov_data != NULL ) {
ov_fh = vv->ov_data->fh; ov_fh = vv->ov_data->fh;
stop_preview(ov_fh); saa7146_stop_preview(ov_fh);
restart_overlay = 1; restart_overlay = 1;
} }
...@@ -1343,7 +1343,7 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p ...@@ -1343,7 +1343,7 @@ static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *p
/* restart overlay if it was active before */ /* restart overlay if it was active before */
if( 0 != restart_overlay ) { if( 0 != restart_overlay ) {
start_preview(ov_fh); saa7146_start_preview(ov_fh);
} }
return ret; return ret;
...@@ -1360,3 +1360,6 @@ struct saa7146_use_ops saa7146_video_uops = { ...@@ -1360,3 +1360,6 @@ struct saa7146_use_ops saa7146_video_uops = {
}; };
EXPORT_SYMBOL_GPL(saa7146_video_uops); EXPORT_SYMBOL_GPL(saa7146_video_uops);
EXPORT_SYMBOL_GPL(saa7146_start_preview);
EXPORT_SYMBOL_GPL(saa7146_stop_preview);
...@@ -256,8 +256,9 @@ static struct saa7146_extension_ioctls ioctls[] = { ...@@ -256,8 +256,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
}; };
static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{ {
struct saa7146_dev *dev = fh->dev;
struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
/* /*
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
......
...@@ -165,6 +165,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ...@@ -165,6 +165,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
{ {
struct budget_patch *budget; struct budget_patch *budget;
int err; int err;
int count = 0;
if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
......
...@@ -246,8 +246,9 @@ int dpc_vbi_bypass(struct saa7146_dev* dev) ...@@ -246,8 +246,9 @@ int dpc_vbi_bypass(struct saa7146_dev* dev)
} }
#endif #endif
static int dpc_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{ {
struct saa7146_dev *dev = fh->dev;
struct dpc* dpc = (struct dpc*)dev->ext_priv; struct dpc* dpc = (struct dpc*)dev->ext_priv;
/* /*
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
......
...@@ -566,8 +566,9 @@ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) ...@@ -566,8 +566,9 @@ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl)
return 0; return 0;
} }
static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{ {
struct saa7146_dev *dev = fh->dev;
struct mxb* mxb = (struct mxb*)dev->ext_priv; struct mxb* mxb = (struct mxb*)dev->ext_priv;
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
......
...@@ -10,12 +10,10 @@ ...@@ -10,12 +10,10 @@
#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ #define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */
#define WRITE_RPS0(x) do { \ #define WRITE_RPS0(x) do { \
static int count = 0; \
dev->d_rps0.cpu_addr[ count++ ] = cpu_to_le32(x); \ dev->d_rps0.cpu_addr[ count++ ] = cpu_to_le32(x); \
} while (0); } while (0);
#define WRITE_RPS1(x) do { \ #define WRITE_RPS1(x) do { \
static int count = 0; \
dev->d_rps1.cpu_addr[ count++ ] = cpu_to_le32(x); \ dev->d_rps1.cpu_addr[ count++ ] = cpu_to_le32(x); \
} while (0); } while (0);
...@@ -166,7 +164,7 @@ struct saa7146_ext_vv ...@@ -166,7 +164,7 @@ struct saa7146_ext_vv
int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
struct saa7146_extension_ioctls *ioctls; struct saa7146_extension_ioctls *ioctls;
int (*ioctl)(struct saa7146_dev*, unsigned int cmd, void *arg); int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
}; };
struct saa7146_use_ops { struct saa7146_use_ops {
...@@ -201,6 +199,8 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); ...@@ -201,6 +199,8 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
/* from saa7146_video.c */ /* from saa7146_video.c */
extern struct saa7146_use_ops saa7146_video_uops; extern struct saa7146_use_ops saa7146_video_uops;
int saa7146_start_preview(struct saa7146_fh *fh);
int saa7146_stop_preview(struct saa7146_fh *fh);
/* from saa7146_vbi.c */ /* from saa7146_vbi.c */
extern struct saa7146_use_ops saa7146_vbi_uops; extern struct saa7146_use_ops saa7146_vbi_uops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment