Commit b405268b authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] v4l: bttv driver update

This updates the bttv driver.  It depends on the videobuf patch.

  * usual tv card list updates.
  * sysfs adaptions.
  * new, experimental i2c adapter code for bt878 chips
    (not used by default yet).
  * various minor fixes.
parent c9e80989
......@@ -282,13 +282,16 @@
#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
#define BT848_I2C 0x110
#define BT878_I2C_MODE (1<<7)
#define BT878_I2C_RATE (1<<6)
#define BT878_I2C_NOSTOP (1<<5)
#define BT878_I2C_NOSTART (1<<4)
#define BT848_I2C_DIV (0xf<<4)
#define BT848_I2C_SYNC (1<<3)
#define BT848_I2C_W3B (1<<2)
#define BT848_I2C_SCL (1<<1)
#define BT848_I2C_SDA (1<<0)
#define BT848_RISC_STRT_ADD 0x114
#define BT848_GPIO_OUT_EN 0x118
#define BT848_GPIO_REG_INP 0x11C
......
......@@ -44,39 +44,6 @@ MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
static int memcnt;
int btcx_riscmem_alloc(struct pci_dev *pci,
struct btcx_riscmem *risc,
unsigned int size)
{
u32 *cpu;
dma_addr_t dma;
cpu = pci_alloc_consistent(pci, size, &dma);
if (NULL == cpu)
return -ENOMEM;
memset(cpu,0,size);
#if 0
if (risc->cpu && risc->size < size) {
/* realloc (enlarge buffer) -- copy old stuff */
memcpy(cpu,risc->cpu,risc->size);
btcx_riscmem_free(pci,risc);
}
#else
BUG_ON(NULL != risc->cpu);
#endif
risc->cpu = cpu;
risc->dma = dma;
risc->size = size;
if (debug) {
memcnt++;
printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
}
return 0;
}
void btcx_riscmem_free(struct pci_dev *pci,
struct btcx_riscmem *risc)
{
......@@ -90,6 +57,31 @@ void btcx_riscmem_free(struct pci_dev *pci,
}
}
int btcx_riscmem_alloc(struct pci_dev *pci,
struct btcx_riscmem *risc,
unsigned int size)
{
u32 *cpu;
dma_addr_t dma;
if (NULL != risc->cpu && risc->size < size)
btcx_riscmem_free(pci,risc);
if (NULL == risc->cpu) {
cpu = pci_alloc_consistent(pci, size, &dma);
if (NULL == cpu)
return -ENOMEM;
risc->cpu = cpu;
risc->dma = dma;
risc->size = size;
if (debug) {
memcnt++;
printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
}
}
memset(risc->cpu,0,risc->size);
return 0;
}
/* ---------------------------------------------------------- */
/* screen overlay helpers */
......
This diff is collapsed.
This diff is collapsed.
......@@ -27,15 +27,23 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "bttvp.h"
static struct i2c_algo_bit_data bttv_i2c_algo_template;
static struct i2c_adapter bttv_i2c_adap_template;
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
static struct i2c_adapter bttv_i2c_adap_sw_template;
static struct i2c_adapter bttv_i2c_adap_hw_template;
static struct i2c_client bttv_i2c_client_template;
#ifndef I2C_PEC
static void bttv_inc_use(struct i2c_adapter *adap);
static void bttv_dec_use(struct i2c_adapter *adap);
#endif
static int attach_inform(struct i2c_client *client);
EXPORT_SYMBOL(bttv_get_cardinfo);
EXPORT_SYMBOL(bttv_get_pcidev);
EXPORT_SYMBOL(bttv_get_id);
......@@ -45,6 +53,11 @@ EXPORT_SYMBOL(bttv_write_gpio);
EXPORT_SYMBOL(bttv_get_gpio_queue);
EXPORT_SYMBOL(bttv_i2c_call);
static int i2c_debug = 0;
static int i2c_hw = 0;
MODULE_PARM(i2c_debug,"i");
MODULE_PARM(i2c_hw,"i");
/* ----------------------------------------------------------------------- */
/* Exported functions - for other modules which want to access the */
/* gpio ports (IR for example) */
......@@ -76,6 +89,7 @@ int bttv_get_id(unsigned int card)
return bttvs[card].type;
}
int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
{
struct bttv *btv;
......@@ -146,7 +160,7 @@ wait_queue_head_t* bttv_get_gpio_queue(unsigned int card)
/* ----------------------------------------------------------------------- */
/* I2C functions */
/* I2C functions - bitbanging adapter (software i2c) */
void bttv_bit_setscl(void *data, int state)
{
......@@ -190,6 +204,222 @@ static int bttv_bit_getsda(void *data)
return state;
}
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
.setsda = bttv_bit_setsda,
.setscl = bttv_bit_setscl,
.getsda = bttv_bit_getsda,
.getscl = bttv_bit_getscl,
.udelay = 16,
.mdelay = 10,
.timeout = 200,
};
static struct i2c_adapter bttv_i2c_adap_sw_template = {
#ifdef I2C_PEC
.owner = THIS_MODULE,
#else
.inc_use = bttv_inc_use,
.dec_use = bttv_dec_use,
#endif
#ifdef I2C_ADAP_CLASS_TV_ANALOG
.class = I2C_ADAP_CLASS_TV_ANALOG,
#endif
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
/* ----------------------------------------------------------------------- */
/* I2C functions - hardware i2c */
static int algo_control(struct i2c_adapter *adapter,
unsigned int cmd, unsigned long arg)
{
return 0;
}
static u32 functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL;
}
static int
bttv_i2c_wait_done(struct bttv *btv)
{
u32 stat;
int timeout;
timeout = jiffies + HZ/100 + 1; /* 10ms */
for (;;) {
stat = btread(BT848_INT_STAT);
if (stat & BT848_INT_I2CDONE)
break;
if (time_after(jiffies,timeout))
return -EIO;
udelay(10);
}
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
return ((stat & BT848_INT_RACK) ? 1 : 0);
}
#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\
BT848_I2C_SCL | BT848_I2C_SDA)
static int
bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
{
u32 xmit;
int retval,cnt;
/* start, address + first byte */
xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
if (msg->len > 1 || !last)
xmit |= BT878_I2C_NOSTOP;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
if (i2c_debug) {
printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
for (cnt = 1; cnt < msg->len; cnt++ ) {
/* following bytes */
xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
if (cnt < msg->len-1 || !last)
xmit |= BT878_I2C_NOSTOP;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
if (i2c_debug) {
printk(" %02x", msg->buf[cnt]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
}
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
printk(" ERR: %d\n",retval);
return retval;
}
static int
bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
{
u32 xmit;
u32 cnt;
int retval;
for(cnt = 0; cnt < msg->len; cnt++) {
xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
if (cnt < msg->len-1)
xmit |= BT848_I2C_W3B;
if (cnt < msg->len-1 || !last)
xmit |= BT878_I2C_NOSTOP;
if (cnt)
xmit |= BT878_I2C_NOSTART;
btwrite(xmit, BT848_I2C);
retval = bttv_i2c_wait_done(btv);
if (retval < 0)
goto err;
if (retval == 0)
goto eio;
msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
if (i2c_debug) {
if (!(xmit & BT878_I2C_NOSTART))
printk(" <R %02x", (msg->addr << 1) +1);
printk(" =%02x", msg->buf[cnt]);
if (!(xmit & BT878_I2C_NOSTOP))
printk(" >\n");
}
}
return msg->len;
eio:
retval = -EIO;
err:
if (i2c_debug)
printk(" ERR: %d\n",retval);
return retval;
}
int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
{
struct bttv *btv = i2c_get_adapdata(i2c_adap);
int retval = 0;
int i;
if (i2c_debug)
printk("bt-i2c:");
btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
for (i = 0 ; i < num; i++) {
if (msgs[i].flags & I2C_M_RD) {
/* read */
retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
if (retval < 0)
goto err;
} else {
/* write */
retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
if (retval < 0)
goto err;
}
}
return num;
err:
return retval;
}
static struct i2c_algorithm bttv_algo = {
.name = "bt878",
.id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.master_xfer = bttv_i2c_xfer,
.algo_control = algo_control,
.functionality = functionality,
};
static struct i2c_adapter bttv_i2c_adap_hw_template = {
#ifdef I2C_PEC
.owner = THIS_MODULE,
#else
.inc_use = bttv_inc_use,
.dec_use = bttv_dec_use,
#endif
#ifdef I2C_ADAP_CLASS_TV_ANALOG
.class = I2C_ADAP_CLASS_TV_ANALOG,
#endif
I2C_DEVNAME("bt878"),
.id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
.client_register = attach_inform,
};
/* ----------------------------------------------------------------------- */
/* I2C functions - common stuff */
#ifndef I2C_PEC
static void bttv_inc_use(struct i2c_adapter *adap)
{
MOD_INC_USE_COUNT;
}
static void bttv_dec_use(struct i2c_adapter *adap)
{
MOD_DEC_USE_COUNT;
}
#endif
static int attach_inform(struct i2c_client *client)
{
......@@ -221,24 +451,6 @@ void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg)
bttv_call_i2c_clients(&bttvs[card], cmd, arg);
}
static struct i2c_algo_bit_data bttv_i2c_algo_template = {
.setsda = bttv_bit_setsda,
.setscl = bttv_bit_setscl,
.getsda = bttv_bit_getsda,
.getscl = bttv_bit_getscl,
.udelay = 16,
.mdelay = 10,
.timeout = 200,
};
static struct i2c_adapter bttv_i2c_adap_template = {
.owner = THIS_MODULE,
.class = I2C_ADAP_CLASS_TV_ANALOG,
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
static struct i2c_client bttv_i2c_client_template = {
I2C_DEVNAME("bttv internal"),
.id = -1,
......@@ -308,28 +520,56 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
/* init + register i2c algo-bit adapter */
int __devinit init_bttv_i2c(struct bttv *btv)
{
memcpy(&btv->i2c_adap, &bttv_i2c_adap_template,
sizeof(struct i2c_adapter));
memcpy(&btv->i2c_algo, &bttv_i2c_algo_template,
sizeof(struct i2c_algo_bit_data));
int use_hw = (btv->id == 878) && i2c_hw;
memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(struct i2c_client));
sizeof(bttv_i2c_client_template));
if (use_hw) {
/* bt878 */
memcpy(&btv->i2c_adap, &bttv_i2c_adap_hw_template,
sizeof(bttv_i2c_adap_hw_template));
} else {
/* bt848 */
memcpy(&btv->i2c_adap, &bttv_i2c_adap_sw_template,
sizeof(bttv_i2c_adap_sw_template));
memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
sizeof(bttv_i2c_algo_bit_template));
btv->i2c_algo.data = btv;
btv->i2c_adap.algo_data = &btv->i2c_algo;
}
sprintf(btv->i2c_adap.name, "bt848 #%d", btv->nr);
btv->i2c_adap.dev.parent = &btv->dev->dev;
snprintf(btv->i2c_adap.name, sizeof(btv->i2c_adap.name),
"bt%d #%d [%s]", btv->id, btv->nr, use_hw ? "hw" : "sw");
btv->i2c_algo.data = btv;
i2c_set_adapdata(&btv->i2c_adap, btv);
btv->i2c_adap.algo_data = &btv->i2c_algo;
btv->i2c_client.adapter = &btv->i2c_adap;
bttv_bit_setscl(btv,1);
bttv_bit_setsda(btv,1);
btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
if (use_hw) {
btv->i2c_rc = i2c_add_adapter(&btv->i2c_adap);
} else {
bttv_bit_setscl(btv,1);
bttv_bit_setsda(btv,1);
btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
}
return btv->i2c_rc;
}
int __devexit fini_bttv_i2c(struct bttv *btv)
{
int use_hw = (btv->id == 878) && i2c_hw;
if (0 != btv->i2c_rc)
return 0;
if (use_hw) {
return i2c_del_adapter(&btv->i2c_adap);
} else {
return i2c_bit_del_bus(&btv->i2c_adap);
}
}
/*
* Local variables:
* c-basic-offset: 8
......
......@@ -33,6 +33,8 @@
#include "bttvp.h"
#define VCR_HACK_LINES 4
/* ---------------------------------------------------------- */
/* risc code generators */
......@@ -62,6 +64,9 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
/* scan lines */
sg = sglist;
for (line = 0; line < lines; line++) {
if ((btv->opt_vcr_hack) &&
(line >= (lines - VCR_HACK_LINES)))
continue;
while (offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
sg++;
......@@ -136,6 +141,9 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
usg = sglist;
vsg = sglist;
for (line = 0; line < ylines; line++) {
if ((btv->opt_vcr_hack) &&
(line >= (ylines - VCR_HACK_LINES)))
continue;
switch (vshift) {
case 0: chroma = 1; break;
case 1: chroma = !(line & 1); break;
......@@ -219,8 +227,10 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
instructions = (ov->nclips + 1) *
((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
instructions += 2;
if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) {
kfree(skips);
return rc;
}
/* sync instruction */
rp = risc->cpu;
......@@ -228,12 +238,18 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
*(rp++) = cpu_to_le32(0);
addr = (unsigned long)btv->fbuf.base;
addr += btv->fbuf.bytesperline * ov->w.top;
addr += ((btv->fbuf.depth+7) >> 3) * ov->w.left;
addr += btv->fbuf.fmt.bytesperline * ov->w.top;
addr += (fmt->depth >> 3) * ov->w.left;
/* scan lines */
for (maxy = -1, line = 0; line < ov->w.height;
line++, addr += btv->fbuf.bytesperline) {
line++, addr += btv->fbuf.fmt.bytesperline) {
if ((btv->opt_vcr_hack) &&
(line >= (ov->w.height - VCR_HACK_LINES)))
continue;
if ((line%2) == 0 && skip_even)
continue;
if ((line%2) == 1 && skip_odd)
if ((line%2) == 0 && skip_even)
continue;
if ((line%2) == 1 && skip_odd)
......
......@@ -87,7 +87,7 @@ static int vbi_buffer_prepare(struct file *file, struct videobuf_buffer *vb,
return -EINVAL;
if (STATE_NEEDS_INIT == buf->vb.state) {
if (0 != (rc = videobuf_iolock(btv->dev,&buf->vb)))
if (0 != (rc = videobuf_iolock(btv->dev, &buf->vb, NULL)))
goto fail;
if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines)))
goto fail;
......
......@@ -115,6 +115,8 @@
#define BTTV_XGUARD 0x67
#define BTTV_NEBULA_DIGITV 0x68
#define BTTV_PV143 0x69
#define BTTV_IVC100 0x6e
#define BTTV_IVC120 0x6f
/* i2c address list */
#define I2C_TSA5522 0xc2
......@@ -170,6 +172,9 @@ struct tvcard
unsigned int needs_tvaudio:1;
unsigned int msp34xx_alt:1;
/* flag: video pci function is unused */
unsigned int no_video;
/* other settings */
unsigned int pll;
#define PLL_NONE 0
......
......@@ -24,9 +24,8 @@
#ifndef _BTTVP_H_
#define _BTTVP_H_
#include <linux/version.h>
#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11)
#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,12)
#include <linux/types.h>
#include <linux/wait.h>
......@@ -34,9 +33,11 @@
#include <linux/i2c-algo-bit.h>
#include <linux/videodev.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
#include <linux/device.h>
#include <media/video-buf.h>
#include <media/audiochip.h>
#include <media/tuner.h>
......@@ -44,6 +45,9 @@
#include "bt848.h"
#include "bttv.h"
#include "btcx-risc.h"
#ifdef CONFIG_VIDEO_IR
#include "ir-common.h"
#endif
#ifdef __KERNEL__
......@@ -142,6 +146,9 @@ struct bttv_overlay {
struct bttv_fh {
struct bttv *btv;
int resources;
#ifdef VIDIOC_G_PRIORITY
enum v4l2_priority prio;
#endif
enum v4l2_buf_type type;
/* video capture */
......@@ -211,6 +218,12 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines);
extern struct videobuf_queue_ops bttv_vbi_qops;
/* ---------------------------------------------------------- */
/* bttv-input.c */
int bttv_input_init(struct bttv *btv);
void bttv_input_fini(struct bttv *btv);
void bttv_input_irq(struct bttv *btv);
/* ---------------------------------------------------------- */
/* bttv-driver.c */
......@@ -221,6 +234,7 @@ extern unsigned int bttv_debug;
extern unsigned int bttv_gpio;
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
extern int init_bttv_i2c(struct bttv *btv);
extern int fini_bttv_i2c(struct bttv *btv);
extern int pvr_boot(struct bttv *btv);
extern int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg);
......@@ -249,6 +263,18 @@ struct bttv_pll_info {
unsigned int pll_current; /* Currently programmed ofreq */
};
#ifdef CONFIG_VIDEO_IR
/* for gpio-connected remote control */
struct bttv_input {
struct input_dev dev;
struct ir_input_state ir;
char name[32];
char phys[32];
u32 mask_keycode;
u32 mask_keydown;
};
#endif
struct bttv {
/* pci device config */
struct pci_dev *dev;
......@@ -263,6 +289,7 @@ struct bttv {
unsigned int type; /* card type (pointer into tvcards[]) */
unsigned int tuner_type; /* tuner chip type */
unsigned int pinnacle_id;
unsigned int svhs;
struct bttv_pll_info pll;
int triton1;
......@@ -278,22 +305,31 @@ struct bttv {
int i2c_state, i2c_rc;
/* video4linux (1) */
struct video_device video_dev;
struct video_device radio_dev;
struct video_device vbi_dev;
struct video_device *video_dev;
struct video_device *radio_dev;
struct video_device *vbi_dev;
/* infrared remote */
int has_remote;
#ifdef CONFIG_VIDEO_IR
struct bttv_input *remote;
#endif
/* locking */
spinlock_t s_lock;
struct semaphore lock;
int resources;
struct semaphore reslock;
#ifdef VIDIOC_G_PRIORITY
struct v4l2_prio_state prio;
#endif
/* video state */
unsigned int input;
unsigned int audio;
unsigned long freq;
int tvnorm,hue,contrast,bright,saturation;
struct video_buffer fbuf;
struct v4l2_framebuffer fbuf;
unsigned int field_count;
/* various options */
......@@ -302,6 +338,7 @@ struct bttv {
int opt_automute;
int opt_chroma_agc;
int opt_adc_crush;
int opt_vcr_hack;
/* radio data/state */
int has_radio;
......@@ -329,6 +366,7 @@ struct bttv {
struct list_head capture; /* video capture queue */
struct list_head vcapture; /* vbi capture queue */
struct bttv_buffer_set curr; /* active buffers */
int new_input;
unsigned long cap_ctl;
unsigned long dma_on;
......
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