Commit 2b12289c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] v4l: bttv driver update

From: Gerd Knorr <kraxel@bytesex.org>

This patch updates the bttv driver.  Changes:

  (1) several card-specific tweaks.
  (2) make software vs. hardware i2c configurable per TV card.
  (3) reinitialize image parameters after chip reset.
  (4) make bttv quite by default on frame drops.
  (5) new insmod option: "debug_latency=1" to enable frame drop
      debug messages.

bttv is quite sensitive to irq latencies, especially when capturing both
video and vbi.  There are several reports about problems due to this, I don't
see that on my machines through.  (5) dumps a stracktrace if the driver
thinks the frame drop is is caused by high latencies as experiment, lets see
whenever that helps ...
parent ba2fab99
This diff is collapsed.
...@@ -59,6 +59,7 @@ static unsigned int gbufsize = 0x208000; ...@@ -59,6 +59,7 @@ static unsigned int gbufsize = 0x208000;
static int video_nr = -1; static int video_nr = -1;
static int radio_nr = -1; static int radio_nr = -1;
static int vbi_nr = -1; static int vbi_nr = -1;
static int debug_latency = 0;
static unsigned int fdsr = 0; static unsigned int fdsr = 0;
...@@ -98,6 +99,7 @@ MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); ...@@ -98,6 +99,7 @@ MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
MODULE_PARM(video_nr,"i"); MODULE_PARM(video_nr,"i");
MODULE_PARM(radio_nr,"i"); MODULE_PARM(radio_nr,"i");
MODULE_PARM(vbi_nr,"i"); MODULE_PARM(vbi_nr,"i");
MODULE_PARM(debug_latency,"i");
MODULE_PARM(fdsr,"i"); MODULE_PARM(fdsr,"i");
...@@ -795,6 +797,7 @@ static void bt848_bright(struct bttv *btv, int bright) ...@@ -795,6 +797,7 @@ static void bt848_bright(struct bttv *btv, int bright)
{ {
int value; int value;
// printk("bttv: set bright: %d\n",bright); // DEBUG
btv->bright = bright; btv->bright = bright;
/* We want -128 to 127 we get 0-65535 */ /* We want -128 to 127 we get 0-65535 */
...@@ -1048,6 +1051,11 @@ static void init_bt848(struct bttv *btv) ...@@ -1048,6 +1051,11 @@ static void init_bt848(struct bttv *btv)
btwrite(whitecrush_upper, BT848_WC_UP); btwrite(whitecrush_upper, BT848_WC_UP);
btwrite(whitecrush_lower, BT848_WC_DOWN); btwrite(whitecrush_lower, BT848_WC_DOWN);
bt848_bright(btv, btv->bright);
bt848_hue(btv, btv->hue);
bt848_contrast(btv, btv->contrast);
bt848_sat(btv, btv->saturation);
if (btv->opt_lumafilter) { if (btv->opt_lumafilter) {
btwrite(0, BT848_E_CONTROL); btwrite(0, BT848_E_CONTROL);
btwrite(0, BT848_O_CONTROL); btwrite(0, BT848_O_CONTROL);
...@@ -2170,13 +2178,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, ...@@ -2170,13 +2178,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
VID_TYPE_OVERLAY| VID_TYPE_OVERLAY|
VID_TYPE_CLIPPING| VID_TYPE_CLIPPING|
VID_TYPE_SCALES; VID_TYPE_SCALES;
cap->channels = bttv_tvcards[btv->c.type].video_inputs;
cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth;
cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;
cap->minwidth = 48; cap->minwidth = 48;
cap->minheight = 32; cap->minheight = 32;
} }
cap->channels = bttv_tvcards[btv->c.type].video_inputs;
cap->audios = bttv_tvcards[btv->c.type].audio_inputs;
return 0; return 0;
} }
...@@ -3155,10 +3163,27 @@ static struct video_device radio_template = ...@@ -3155,10 +3163,27 @@ static struct video_device radio_template =
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* irq handler */ /* irq handler */
static char *irq_name[] = { "FMTCHG", "VSYNC", "HSYNC", "OFLOW", "HLOCK", static char *irq_name[] = {
"VPRES", "6", "7", "I2CDONE", "GPINT", "10", "FMTCHG", // format change detected (525 vs. 625)
"RISCI", "FBUS", "FTRGT", "FDSR", "PPERR", "VSYNC", // vertical sync (new field)
"RIPERR", "PABORT", "OCERR", "SCERR" }; "HSYNC", // horizontal sync
"OFLOW", // chroma/luma AGC overflow
"HLOCK", // horizontal lock changed
"VPRES", // video presence changed
"6", "7",
"I2CDONE", // hw irc operation finished
"GPINT", // gpio port triggered irq
"10",
"RISCI", // risc instruction triggered irq
"FBUS", // pixel data fifo dropped data (high pci bus latencies)
"FTRGT", // pixel data fifo overrun
"FDSR", // fifo data stream resyncronisation
"PPERR", // parity error (data transfer)
"RIPERR", // parity error (read risc instructions)
"PABORT", // pci abort
"OCERR", // risc instruction error
"SCERR", // syncronisation error
};
static void bttv_print_irqbits(u32 print, u32 mark) static void bttv_print_irqbits(u32 print, u32 mark)
{ {
...@@ -3188,6 +3213,28 @@ static void bttv_print_riscaddr(struct bttv *btv) ...@@ -3188,6 +3213,28 @@ static void bttv_print_riscaddr(struct bttv *btv)
btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0); btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
} }
static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
{
printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
btv->c.nr,
(unsigned long)btv->main.dma,
(unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1],
(unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1],
(unsigned long)rc);
if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
printk("bttv%d: Oh, there (temporarely?) is no input signal. "
"Ok, then this is harmless, don't worry ;)",
btv->c.nr);
return;
}
printk("bttv%d: Uhm. Looks like we have unusual high IRQ latencies.\n",
btv->c.nr);
printk("bttv%d: Lets try to catch the culpit red-handed ...\n",
btv->c.nr);
dump_stack();
}
static int static int
bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set)
{ {
...@@ -3306,8 +3353,8 @@ static void bttv_irq_timeout(unsigned long data) ...@@ -3306,8 +3353,8 @@ static void bttv_irq_timeout(unsigned long data)
unsigned long flags; unsigned long flags;
if (bttv_verbose) { if (bttv_verbose) {
printk(KERN_INFO "bttv%d: timeout: irq=%d/%d, risc=%08x, ", printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
btv->c.nr, btv->irq_me, btv->irq_total, btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
btread(BT848_RISC_COUNT)); btread(BT848_RISC_COUNT));
bttv_print_irqbits(btread(BT848_INT_STAT),0); bttv_print_irqbits(btread(BT848_INT_STAT),0);
printk("\n"); printk("\n");
...@@ -3376,14 +3423,9 @@ bttv_irq_switch_fields(struct bttv *btv) ...@@ -3376,14 +3423,9 @@ bttv_irq_switch_fields(struct bttv *btv)
bttv_irq_next_set(btv, &new); bttv_irq_next_set(btv, &new);
rc = btread(BT848_RISC_COUNT); rc = btread(BT848_RISC_COUNT);
if (rc < btv->main.dma || rc > btv->main.dma + 0x100) { if (rc < btv->main.dma || rc > btv->main.dma + 0x100) {
if (1 /* irq_debug */) btv->framedrop++;
printk("bttv%d: skipped frame. no signal? high irq latency? " if (debug_latency)
"[main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", bttv_irq_debug_low_latency(btv, rc);
btv->c.nr,
(unsigned long)btv->main.dma,
(unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1],
(unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1],
(unsigned long)rc);
spin_unlock(&btv->s_lock); spin_unlock(&btv->s_lock);
return; return;
} }
...@@ -3870,11 +3912,6 @@ static int bttv_resume(struct pci_dev *pci_dev) ...@@ -3870,11 +3912,6 @@ static int bttv_resume(struct pci_dev *pci_dev)
gpio_inout(0xffffff, btv->state.gpio_enable); gpio_inout(0xffffff, btv->state.gpio_enable);
gpio_write(btv->state.gpio_data); gpio_write(btv->state.gpio_data);
bt848_bright(btv, btv->bright);
bt848_hue(btv, btv->hue);
bt848_contrast(btv, btv->contrast);
bt848_sat(btv, btv->saturation);
/* restart dma */ /* restart dma */
spin_lock_irqsave(&btv->s_lock,flags); spin_lock_irqsave(&btv->s_lock,flags);
btv->curr = btv->state.set; btv->curr = btv->state.set;
......
...@@ -414,12 +414,12 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) ...@@ -414,12 +414,12 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
/* init + register i2c algo-bit adapter */ /* init + register i2c algo-bit adapter */
int __devinit init_bttv_i2c(struct bttv *btv) int __devinit init_bttv_i2c(struct bttv *btv)
{ {
int use_hw = (btv->id == 878) && i2c_hw;
memcpy(&btv->i2c_client, &bttv_i2c_client_template, memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(bttv_i2c_client_template)); sizeof(bttv_i2c_client_template));
if (use_hw) { if (i2c_hw)
btv->use_i2c_hw = 1;
if (btv->use_i2c_hw) {
/* bt878 */ /* bt878 */
memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template, memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template,
sizeof(bttv_i2c_adap_hw_template)); sizeof(bttv_i2c_adap_hw_template));
...@@ -435,12 +435,13 @@ int __devinit init_bttv_i2c(struct bttv *btv) ...@@ -435,12 +435,13 @@ int __devinit init_bttv_i2c(struct bttv *btv)
btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
"bt%d #%d [%s]", btv->id, btv->c.nr, use_hw ? "hw" : "sw"); "bt%d #%d [%s]", btv->id, btv->c.nr,
btv->use_i2c_hw ? "hw" : "sw");
i2c_set_adapdata(&btv->c.i2c_adap, btv); i2c_set_adapdata(&btv->c.i2c_adap, btv);
btv->i2c_client.adapter = &btv->c.i2c_adap; btv->i2c_client.adapter = &btv->c.i2c_adap;
if (use_hw) { if (btv->use_i2c_hw) {
btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
} else { } else {
bttv_bit_setscl(btv,1); bttv_bit_setscl(btv,1);
...@@ -452,12 +453,10 @@ int __devinit init_bttv_i2c(struct bttv *btv) ...@@ -452,12 +453,10 @@ int __devinit init_bttv_i2c(struct bttv *btv)
int __devexit fini_bttv_i2c(struct bttv *btv) int __devexit fini_bttv_i2c(struct bttv *btv)
{ {
int use_hw = (btv->id == 878) && i2c_hw;
if (0 != btv->i2c_rc) if (0 != btv->i2c_rc)
return 0; return 0;
if (use_hw) { if (btv->use_i2c_hw) {
return i2c_del_adapter(&btv->c.i2c_adap); return i2c_del_adapter(&btv->c.i2c_adap);
} else { } else {
return i2c_bit_del_bus(&btv->c.i2c_adap); return i2c_bit_del_bus(&btv->c.i2c_adap);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define _BTTVP_H_ #define _BTTVP_H_
#include <linux/version.h> #include <linux/version.h>
#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,12) #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,14)
#include <linux/types.h> #include <linux/types.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -298,6 +298,7 @@ struct bttv { ...@@ -298,6 +298,7 @@ struct bttv {
struct bttv_pll_info pll; struct bttv_pll_info pll;
int triton1; int triton1;
int gpioirq; int gpioirq;
int use_i2c_hw;
/* old gpio interface */ /* old gpio interface */
wait_queue_head_t gpioq; wait_queue_head_t gpioq;
...@@ -384,9 +385,10 @@ struct bttv { ...@@ -384,9 +385,10 @@ struct bttv {
struct bttv_suspend_state state; struct bttv_suspend_state state;
/* stats */ /* stats */
unsigned int errors;
unsigned int framedrop;
unsigned int irq_total; unsigned int irq_total;
unsigned int irq_me; unsigned int irq_me;
unsigned int errors;
unsigned int users; unsigned int users;
struct bttv_fh init; struct bttv_fh init;
......
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