patch-2.3.34 linux/drivers/char/bttv.c
Next file: linux/drivers/char/bttv.h
Previous file: linux/drivers/char/audiochip.h
Back to the patch index
Back to the overall index
- Lines: 3450
- Date:
Thu Dec 16 13:59:38 1999
- Orig file:
v2.3.33/linux/drivers/char/bttv.c
- Orig date:
Tue Nov 23 22:42:20 1999
diff -u --recursive --new-file v2.3.33/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
@@ -1,9 +1,9 @@
-
-/*
+/*
bttv - Bt848 frame grabber driver
Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
& Marcus Metzler (mocm@thp.uni-koeln.de)
+ (c) 1999 Gerd Knorr <kraxel@goldbach.in-berlin.de>
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
@@ -21,7 +21,6 @@
*/
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -41,43 +40,53 @@
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/interrupt.h>
-
-#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
#include <linux/vmalloc.h>
-#include <linux/videodev.h>
#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev.h>
+
+
#include "bttv.h"
#include "tuner.h"
-#define DEBUG(x) /* Debug driver */
-#define IDEBUG(x) /* Debug interrupt handler */
+#define DEBUG(x) /* Debug driver */
+#define IDEBUG(x) /* Debug interrupt handler */
+#define MIN(a,b) (((a)>(b))?(b):(a))
+#define MAX(a,b) (((a)>(b))?(a):(b))
/* Anybody who uses more than four? */
#define BTTV_MAX 4
-
static void bt848_set_risc_jmps(struct bttv *btv);
-static unsigned int vidmem=0; /* manually set video mem address */
-static int triton1=0;
-#ifndef USE_PLL
-/* 0=no pll, 1=28MHz, 2=34MHz */
-#define USE_PLL 0
-#endif
-#ifndef CARD_DEFAULT
-/* card type (see bttv.h) 0=autodetect */
-#define CARD_DEFAULT 0
-#endif
+static int bttv_num; /* number of Bt848s in use */
+static struct bttv bttvs[BTTV_MAX];
+
-static unsigned long remap[BTTV_MAX]; /* remap Bt848 */
+/* insmod args */
+MODULE_PARM(triton1,"i");
+MODULE_PARM(remap,"1-4i");
+MODULE_PARM(radio,"1-4i");
+MODULE_PARM(card,"1-4i");
+MODULE_PARM(pll,"1-4i");
+MODULE_PARM(bigendian,"i");
+MODULE_PARM(fieldnr,"i");
+
+#if defined(__sparc__) || defined(__powerpc__)
+static unsigned int bigendian=1;
+#else
+static unsigned int bigendian=0;
+#endif
+static int triton1=0;
+static unsigned long remap[BTTV_MAX];
static unsigned int radio[BTTV_MAX];
-static unsigned int card[BTTV_MAX] = { CARD_DEFAULT, CARD_DEFAULT,
- CARD_DEFAULT, CARD_DEFAULT };
-static unsigned int pll[BTTV_MAX] = { USE_PLL, USE_PLL, USE_PLL, USE_PLL };
+static unsigned int card[BTTV_MAX] = { 0, 0, 0, 0 };
+static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0};
+static unsigned int fieldnr = 0;
-static int bttv_num; /* number of Bt848s in use */
-static struct bttv bttvs[BTTV_MAX];
#define I2C_TIMING (0x7<<4)
#define I2C_DELAY 10
@@ -86,9 +95,9 @@
{ btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
#define I2C_GET() (btread(BT848_I2C)&1)
-#define EEPROM_WRITE_DELAY 20000
#define BURSTOFFSET 76
+
/*******************************/
/* Memory management functions */
/*******************************/
@@ -121,9 +130,8 @@
if (!pmd_none(*pmd)) {
ptep = pte_offset(pmd, adr);
pte = *ptep;
- /* Note; page_address will panic for us if the page is high */
if(pte_present(pte))
- ret = page_address(pte_page(pte))|(adr&(PAGE_SIZE-1));
+ ret = (page_address(pte_page(pte))|(adr&(PAGE_SIZE-1)));
}
}
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
@@ -205,12 +213,6 @@
}
}
-MODULE_PARM(vidmem,"i");
-MODULE_PARM(triton1,"i");
-MODULE_PARM(remap,"1-4i");
-MODULE_PARM(radio,"1-4i");
-MODULE_PARM(card,"1-4i");
-MODULE_PARM(pll,"1-4i");
/*
@@ -223,7 +225,7 @@
static int fbuffer_alloc(struct bttv *btv)
{
if(!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+ btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF);
else
printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n",
btv->nr);
@@ -236,194 +238,204 @@
/* ----------------------------------------------------------------------- */
/* I2C functions */
-/* software I2C functions */
-
-static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
+static void bttv_bit_setscl(void *data, int state)
{
- struct bttv *btv = (struct bttv*)bus->data;
- btwrite((ctrl<<1)|data, BT848_I2C);
- btread(BT848_I2C); /* flush buffers */
- udelay(I2C_DELAY);
+ struct bttv *btv = (struct bttv*)data;
+
+ if (state)
+ btv->i2c_state |= 0x02;
+ else
+ btv->i2c_state &= ~0x02;
+ btwrite(btv->i2c_state, BT848_I2C);
+ btread(BT848_I2C);
}
-static int i2c_getdataline(struct i2c_bus *bus)
+static void bttv_bit_setsda(void *data, int state)
{
- struct bttv *btv = (struct bttv*)bus->data;
- return btread(BT848_I2C)&1;
+ struct bttv *btv = (struct bttv*)data;
+
+ if (state)
+ btv->i2c_state |= 0x01;
+ else
+ btv->i2c_state &= ~0x01;
+ btwrite(btv->i2c_state, BT848_I2C);
+ btread(BT848_I2C);
}
-/* hardware I2C functions */
+static int bttv_bit_getscl(void *data)
+{
+ struct bttv *btv = (struct bttv*)data;
+ int state;
+
+ state = btread(BT848_I2C) & 0x02 ? 1 : 0;
+ return state;
+}
-/* read I2C */
-static int I2CRead(struct i2c_bus *bus, unsigned char addr)
+static int bttv_bit_getsda(void *data)
{
- u32 i;
- u32 stat;
- struct bttv *btv = (struct bttv*)bus->data;
-
- /* clear status bit ; BT848_INT_RACK is ro */
- btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
-
- btwrite(((addr & 0xff) << 24) | btv->i2c_command, BT848_I2C);
-
- /*
- * Timeout for I2CRead is 1 second (this should be enough, really!)
- */
- for (i=1000; i; i--)
- {
- stat=btread(BT848_INT_STAT);
- if (stat & BT848_INT_I2CDONE)
- break;
- mdelay(1);
- }
-
- if (!i)
- {
- printk(KERN_DEBUG "bttv%d: I2CRead timeout\n",
- btv->nr);
- return -1;
- }
- if (!(stat & BT848_INT_RACK))
- return -2;
-
- i=(btread(BT848_I2C)>>8)&0xff;
- return i;
+ struct bttv *btv = (struct bttv*)data;
+ int state;
+
+ state = btread(BT848_I2C) & 0x01;
+ return state;
}
-/* set both to write both bytes, reset it to write only b1 */
+static void bttv_inc_use(struct i2c_adapter *adap)
+{
+ MOD_INC_USE_COUNT;
+}
-static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1,
- unsigned char b2, int both)
+static void bttv_dec_use(struct i2c_adapter *adap)
{
- u32 i;
- u32 data;
- u32 stat;
- struct bttv *btv = (struct bttv*)bus->data;
-
- /* clear status bit; BT848_INT_RACK is ro */
- btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
-
- data=((addr & 0xff) << 24) | ((b1 & 0xff) << 16) | btv->i2c_command;
- if (both)
- {
- data|=((b2 & 0xff) << 8);
- data|=BT848_I2C_W3B;
- }
-
- btwrite(data, BT848_I2C);
+ MOD_DEC_USE_COUNT;
+}
- for (i=0x1000; i; i--)
- {
- stat=btread(BT848_INT_STAT);
- if (stat & BT848_INT_I2CDONE)
- break;
- mdelay(1);
- }
-
- if (!i)
- {
- printk(KERN_DEBUG "bttv%d: I2CWrite timeout\n",
- btv->nr);
- return -1;
+static void call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
+{
+ int i;
+
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (NULL == btv->i2c_clients[i])
+ continue;
+ if (NULL == btv->i2c_clients[i]->driver->command)
+ continue;
+ btv->i2c_clients[i]->driver->command(
+ btv->i2c_clients[i],cmd,arg);
}
- if (!(stat & BT848_INT_RACK))
- return -2;
-
- return 0;
}
-/* read EEPROM */
-static void readee(struct i2c_bus *bus, unsigned char *eedata)
+static int attach_inform(struct i2c_client *client)
{
- int i, k;
-
- if (I2CWrite(bus, 0xa0, 0, -1, 0)<0)
- {
- printk(KERN_WARNING "bttv: readee error\n");
- return;
- }
-
- for (i=0; i<256; i++)
- {
- k=I2CRead(bus, 0xa1);
- if (k<0)
- {
- printk(KERN_WARNING "bttv: readee error\n");
+ struct bttv *btv = (struct bttv*)client->adapter->data;
+ int i;
+
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (btv->i2c_clients[i] == NULL ||
+ btv->i2c_clients[i]->driver->id == client->driver->id) {
+ btv->i2c_clients[i] = client;
break;
}
- eedata[i]=k;
}
+ if (btv->tuner_type != -1)
+ call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
+ printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name);
+ return 0;
}
-/* write EEPROM */
-static void writeee(struct i2c_bus *bus, unsigned char *eedata)
+static int detach_inform(struct i2c_client *client)
{
+ struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
-
- for (i=0; i<256; i++)
- {
- if (I2CWrite(bus, 0xa0, i, eedata[i], 1)<0)
- {
- printk(KERN_WARNING "bttv: writeee error (%d)\n", i);
+
+ printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name);
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (NULL != btv->i2c_clients[i] &&
+ btv->i2c_clients[i]->driver->id == client->driver->id) {
+ btv->i2c_clients[i] = NULL;
break;
}
- udelay(EEPROM_WRITE_DELAY);
}
+ return 0;
}
-static void attach_inform(struct i2c_bus *bus, int id)
+static struct i2c_algo_bit_data i2c_algo_template = {
+ NULL,
+ bttv_bit_setsda,
+ bttv_bit_setscl,
+ bttv_bit_getsda,
+ bttv_bit_getscl,
+ 10, 10, 100,
+};
+
+static struct i2c_adapter i2c_adap_template = {
+ "bt848",
+ I2C_HW_B_BT848,
+ NULL,
+ NULL,
+ bttv_inc_use,
+ bttv_dec_use,
+ attach_inform,
+ detach_inform,
+ NULL,
+};
+
+static struct i2c_client i2c_client_template = {
+ "bttv internal",
+ -1,
+ 0,
+ 0,
+ NULL,
+ NULL
+};
+
+static int init_bttv_i2c(struct bttv *btv)
{
- struct bttv *btv = (struct bttv*)bus->data;
-
- switch (id)
- {
- case I2C_DRIVERID_MSP3400:
- btv->have_msp3400 = 1;
- break;
- case I2C_DRIVERID_TUNER:
- btv->have_tuner = 1;
- if (btv->tuner_type != -1)
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_TUNER,
- TUNER_SET_TYPE,&btv->tuner_type);
- break;
- }
+ /* i2c bit_adapter */
+ memcpy(&btv->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter));
+ memcpy(&btv->i2c_algo, &i2c_algo_template, sizeof(struct i2c_algo_bit_data));
+ memcpy(&btv->i2c_client, &i2c_client_template, sizeof(struct i2c_client));
+
+ sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name),
+ " #%d", btv->nr);
+ btv->i2c_algo.data = btv;
+ btv->i2c_adap.data = 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);
+
+ return i2c_bit_add_bus(&btv->i2c_adap);
}
-static void detach_inform(struct i2c_bus *bus, int id)
+/* read I2C */
+static int I2CRead(struct bttv *btv, unsigned char addr)
{
- struct bttv *btv = (struct bttv*)bus->data;
+ unsigned char buffer = 0;
- switch (id)
- {
- case I2C_DRIVERID_MSP3400:
- btv->have_msp3400 = 0;
- break;
- case I2C_DRIVERID_TUNER:
- btv->have_tuner = 0;
- break;
+ btv->i2c_client.addr = addr >> 1;
+ if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
+ printk("bttv%d: i2c read 0x%x: error\n",btv->nr,addr);
+ return -1;
}
+ printk("bttv%d: i2c read 0x%x: %d\n",btv->nr,addr,buffer);
+ return buffer;
}
-static struct i2c_bus bttv_i2c_bus_template =
+/* write I2C */
+static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+ unsigned char b2, int both)
{
- "bt848",
- I2C_BUSID_BT848,
- NULL,
+ unsigned char buffer[2];
+ int bytes = both ? 2 : 1;
+
+ btv->i2c_client.addr = addr >> 1;
+ buffer[0] = b1;
+ buffer[1] = b2;
+ if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
+ return -1;
+ return 0;
+}
+
+/* read EEPROM */
+static void readee(struct bttv *btv, unsigned char *eedata)
+{
+ int i;
+
+ if (I2CWrite(btv, 0xa0, 0, -1, 0)<0) {
+ printk(KERN_WARNING "bttv: readee error\n");
+ return;
+ }
+ btv->i2c_client.addr = 0xa0 >> 1;
+ for (i=0; i<256; i+=16) {
+ if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) {
+ printk(KERN_WARNING "bttv: readee error\n");
+ break;
+ }
+ }
+}
-#if LINUX_VERSION_CODE >= 0x020100
- SPIN_LOCK_UNLOCKED,
-#endif
- attach_inform,
- detach_inform,
-
- i2c_setlines,
- i2c_getdataline,
- I2CRead,
- I2CWrite,
-};
-
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
@@ -439,7 +451,7 @@
{ TUNER_ABSENT, "External" },
{ TUNER_ABSENT, "Unspecified" },
{ TUNER_ABSENT, "Philips FI1216" },
- { TUNER_ABSENT, "Philips FI1216MF" },
+ { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FI1236" },
{ TUNER_ABSENT, "Philips FI1246" },
{ TUNER_ABSENT, "Philips FI1256" },
@@ -462,11 +474,9 @@
};
static void
-hauppauge_eeprom(struct i2c_bus *bus)
+hauppauge_eeprom(struct bttv *btv)
{
- struct bttv *btv = (struct bttv*)bus->data;
-
- readee(bus, eeprom_data);
+ readee(btv, eeprom_data);
if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
{
btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
@@ -488,76 +498,214 @@
/* btaor(0, ~32, BT848_GPIO_OUT_EN); */
}
-/* ----------------------------------------------------------------------- */
+/* Imagenation L-Model PXC200 Framegrabber */
+/* This is basically the same procedure as
+ * used by Alessandro Rubini in his pxc200
+ * driver, but using BTTV functions */
+static void init_PXC200(struct bttv *btv)
+{
+ int tmp;
+
+ /* Initialise GPIO-connevted stuff */
+ btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */
+ btwrite(0,BT848_GPIO_DATA);
+ udelay(3);
+ btwrite(1<<13,BT848_GPIO_DATA);
+ /* GPIO inputs are pulled up, so no need to drive
+ * reset pin any longer */
+ btwrite(0,BT848_GPIO_OUT_EN);
+
+
+ /* Initialise MAX517 DAC */
+ printk(KERN_INFO "Setting DAC reference voltage level ...\n");
+ I2CWrite(btv,0x5E,0,0x80,1);
+
+ /* Initialise 12C508 PIC */
+ /* The I2CWrite and I2CRead commmands are actually to the
+ * same chips - but the R/W bit is included in the address
+ * argument so the numbers are different */
+
+ printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
+
+ tmp=I2CWrite(btv,0x1E,0x08,0,1);
+ printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x09,0,1);
+ printk(KERN_INFO "I2C Write(0x09) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x0a,0,1);
+ printk(KERN_INFO "I2C Write(0x0a) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x0b,0,1);
+ printk(KERN_INFO "I2C Write(0x0b) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x0c,0,1);
+ printk(KERN_INFO "I2C Write(0x0c) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x0d,0,1);
+ printk(KERN_INFO "I2C Write(0x0d) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x01,0,1);
+ printk(KERN_INFO "I2C Write(0x01) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x02,0,1);
+ printk(KERN_INFO "I2C Write(0x02) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x03,0,1);
+ printk(KERN_INFO "I2C Write(0x03) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x04,0,1);
+ printk(KERN_INFO "I2C Write(0x04) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x05,0,1);
+ printk(KERN_INFO "I2C Write(0x05) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x06,0,1);
+ printk(KERN_INFO "I2C Write(0x06) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+ tmp=I2CWrite(btv,0x1E,0x00,0,1);
+ printk(KERN_INFO "I2C Write(0x00) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F));
+
+ printk(KERN_INFO "PXC200 Initialised.\n");
+}
+
+/* ----------------------------------------------------------------------- */
struct tvcard
{
+ char *name;
int video_inputs;
int audio_inputs;
int tuner;
int svhs;
u32 gpiomask;
u32 muxsel[8];
- u32 audiomux[6]; /* Tuner, Radio, internal, external, mute, stereo */
- u32 gpiomask2; /* GPIO MUX mask */
+ u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */
+ u32 gpiomask2; /* GPIO MUX mask */
+
+ /* look for these i2c audio chips */
+ int msp34xx:1;
+ int tda8425:1;
+ int tda9840:1;
+ int tda985x:1;
+ int tea63xx:1;
};
static struct tvcard tvcards[] =
{
- /* default */
- { 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
- /* MIRO */
- { 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},
- /* Hauppauge */
- { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
- /* STB */
- { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},
- /* Intel??? */
- { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
- /* Diamond DTV2000 */
- { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
- /* AVerMedia TVPhone */
- { 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
- /* Matrix Vision MV-Delta */
- { 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0}},
- /* Fly Video II */
- { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},
- {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
- /* TurboTV */
- { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
- /* Newer Hauppauge (bt878) */
- { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
- /* MIRO PCTV pro */
- { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
- /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
- { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
- /* AVerMedia TVCapture 98 */
- { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
- /* Aimslab VHX */
- { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
- /* Zoltrix TV-Max */
- { 3, 1, 0, 2, 0x00000f, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0x8}},
- /* Pixelview PlayTV (bt878) */
- { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
- /* "Leadtek WinView 601", */
- { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}},
- /* AVEC Intercapture */
- { 3, 2, 0, 2, 0, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0}},
- /* LifeView FlyKit w/o Tuner */
- { 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}},
- /* CEI Raffles Card */
- { 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0}},
- /* Lucky Star Image World ConferenceTV */
- {3, 1, 0, 2, 16777215, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4}},
- /* Phoebe Tv Master + FM */
- { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0}},
- /* Modular Technology MM205 PCTV, bt878 */
- { 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 }},
- /* Magic TView CPH061 (bt878) */
- { 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0, 0, 0, 0}},
+ /* 0x00 */
+ { "unknown",
+ 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0,
+ 1,1,1,1,0 },
+ { "MIRO PCTV",
+ 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0,
+ 1,1,1,1,0 },
+ { "Hauppauge old",
+ 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 1,1,0,1,0 },
+ { "STB",
+ 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0,
+ 0,1,1,1,1 },
+
+ { "Intel",
+ 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 1,1,1,1,0 },
+ { "Diamond DTV2000",
+ 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0,
+ 1,1,1,1,0 },
+ { "AVerMedia TVPhone",
+ 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0},0,
+ 1,1,1,1,0 },
+ { "MATRIX-Vision MV-Delta",
+ 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0,
+ 1,1,1,1,0 },
+
+ /* 0x08 */
+ { "Fly Video II",
+ 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},
+ { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0,
+ 1,1,1,1,0 },
+ { "TurboTV",
+ 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0,
+ 1,1,1,1,0 },
+ { "Hauppauge new (bt878)",
+ 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 1,1,0,1,0 },
+ { "MIRO PCTV pro",
+ 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0,
+ 1,1,1,1,0 },
+
+ { "ADS Technologies Channel Surfer TV",
+ 3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0,
+ 1,1,1,1,0 },
+ { "AVerMedia TVCapture 98",
+ 3, 1, 4, 0, 15, { 2, 3, 1, 0, 0}, { 13, 14, 11, 7, 0, 0},0,
+ 1,1,1,1,0 },
+ { "Aimslab VHX",
+ 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 1,1,1,1,0 },
+ { "Zoltrix TV-Max",
+ 3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0,
+ 1,1,1,1,0 },
+
+ /* 0x10 */
+ { "Pixelview PlayTV (bt878)",
+ 3, 1, 0, 2, 0x01e000, { 2, 0, 1, 1},
+ { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0,
+ 1,1,1,1,0 },
+ { "Leadtek WinView 601",
+ 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0},
+ { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0,
+ 1,1,1,1,0 },
+ { "AVEC Intercapture",
+ 3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0,
+ 1,1,1,1,0 },
+ { "LifeView FlyKit w/o Tuner",
+ 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0,
+ 0,0,0,0,0 },
+
+ { "CEI Raffles Card",
+ 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0,
+ 1,1,1,1,0 },
+ { "Lucky Star Image World ConferenceTV",
+ 3, 1, 0, 2, 16777215, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0,
+ 1,1,1,1,0 },
+ { "Phoebe Tv Master + FM",
+ 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0,
+ 1,1,1,1,0 },
+ { "Modular Technology MM205 PCTV, bt878",
+ 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0,
+ 1,1,1,1,0 },
+
+ /* 0x18 */
+ { "Magic TView CPH061 (bt878)",
+ 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0, 0, 0, 0},0,
+ 1,1,1,1,0 },
+ { "Terratec/Vobis TV-Boostar",
+ 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0,
+ 1,1,1,1,0 },
+ { "Newer Hauppauge WinCam (bt878)",
+ 4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 1,1,1,1,0 },
+ { "MAXI TV Video PCI2",
+ 3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0,
+ 1,1,1,1,0 },
+
+ { "Terratec TerraTV+",
+ 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1},
+ { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0,
+ 1,1,1,1,0 },
+ { "Imagenation PXC200",
+ 5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0,
+ 1,1,1,1,0 },
+ { "FlyVideo 98",
+ 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1},
+ { 0, 0x8dff00, 0x800, 0x400, 0x8dff00, 0 },0,
+ 1,1,1,1,0 },
+ { "iProTV",
+ 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0,
+ 1,1,1,1,0 },
+
+ /* 0x20 */
+ { "Intel Create and Share PCI",
+ 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0,
+ 1,1,1,1,0 },
+ { "Askey/Typhoon/Anubis Magic TView",
+ 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0,
+ 1,1,1,1,0 },
};
-#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
+#define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard))
+
+/* ----------------------------------------------------------------------- */
static void audio(struct bttv *btv, int mode)
{
@@ -585,17 +733,13 @@
break;
}
/* if audio mute or not in H-lock, turn audio off */
- if ((btv->audio&AUDIO_MUTE)
-#if 0
- ||
- (!btv->radio && !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
-#endif
- )
+ if ((btv->audio&AUDIO_MUTE))
mode=AUDIO_OFF;
- if ((mode == 0) && (btv->radio))
- mode = 1;
+ if ((mode == AUDIO_TUNER) && (btv->radio))
+ mode = AUDIO_RADIO;
btaor(tvcards[btv->type].audiomux[mode],
~tvcards[btv->type].gpiomask, BT848_GPIO_DATA);
+ call_i2c_clients(btv,AUDC_SET_INPUT,&(mode));
}
@@ -697,7 +841,7 @@
}
while(time_before(jiffies,tv));
- for (i=0; i<10; i++)
+ for (i=0; i<100; i++)
{
if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
btwrite(0,BT848_DSTATUS);
@@ -743,15 +887,7 @@
~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);
}
-/*
- * Set the registers for the size we have specified. Don't bother
- * trying to understand this without the BT848 manual in front of
- * you [AC].
- *
- * PS: The manual is free for download in .pdf format from
- * www.brooktree.com - nicely done those folks.
- */
-
+
struct tvnorm
{
u32 Fsc;
@@ -768,29 +904,14 @@
/* PAL-BDGHI */
/* max. active video is actually 922, but 924 is divisible by 4 and 3! */
/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
-#ifdef VIDEODAT
{ 35468950,
924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
1135, 186, 924, 0x20, 255},
-#else
- { 35468950,
- 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 1135, 186, 924, 0x20, 255},
-#endif
-/*
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 944, 186, 922, 0x20, 255},
-*/
+
/* NTSC */
{ 28636363,
768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
910, 128, 910, 0x1a, 144},
-/*
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
-*/
#if 0
/* SECAM EAST */
{ 35468950,
@@ -889,8 +1010,10 @@
unsigned long bpl=1024; /* bytes per line */
unsigned long vadr=(unsigned long) vbuf;
- *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
- *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
+ *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(ro++)=cpu_to_le32(0);
+ *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(re++)=cpu_to_le32(0);
/* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY
is 2 and without separate VBI grabbing.
@@ -913,7 +1036,6 @@
return 0;
}
-
static int make_prisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re,
unsigned int *vbuf, unsigned short width,
@@ -962,8 +1084,10 @@
cradr=cbadr+csize;
inter = (height>btv->win.cropheight/2) ? 1 : 0;
- *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(ro++)=0;
- *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(re++)=0;
+ *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
+ *(ro++)=0;
+ *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
+ *(re++)=0;
for (line=0; line < (height<<(1^inter)); line++)
{
@@ -1005,7 +1129,7 @@
vadr+=bl;
if((rcmd&(15<<28))==BT848_RISC_WRITE123)
{
- *((*rp)++)=cpu_to_le32(kvirt_to_bus(cbadr));
+ *((*rp)++)=(kvirt_to_bus(cbadr));
cbadr+=blcb;
*((*rp)++)=cpu_to_le32(kvirt_to_bus(cradr));
cradr+=blcr;
@@ -1045,8 +1169,10 @@
inter = (height>btv->win.cropheight/2) ? 1 : 0;
bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
- *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
- *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
+ *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(ro++)=cpu_to_le32(0);
+ *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(re++)=cpu_to_le32(0);
for (line=0; line < (height<<(1^inter)); line++)
{
@@ -1059,7 +1185,7 @@
if (bpl<=bl)
{
*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
- BT848_RISC_EOL|bpl);
+ BT848_RISC_EOL|bpl);
*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
vadr+=bpl;
}
@@ -1156,18 +1282,28 @@
unsigned long adr;
unsigned char *clipmap, cbit, lastbit, outofmem;
+ if (btv->win.use_yuv) {
+ /* yuv-to-offscreen (BT848_COLOR_FMT_YUY2) */
+ bpp = 2;
+ bpl = btv->win.win2.pitch;
+ adr = btv->win.vidadr + btv->win.win2.start;
+ } else {
+ bpp=btv->win.bpp;
+ if (bpp==15) /* handle 15bpp as 16bpp in calculations */
+ bpp++;
+ bpl=btv->win.bpl;
+ adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
+ }
inter=(btv->win.interlace&1)^1;
- bpp=btv->win.bpp;
- if (bpp==15) /* handle 15bpp as 16bpp in calculations */
- bpp++;
- bpl=btv->win.bpl;
- ro=btv->risc_odd;
- re=btv->risc_even;
- if((width=btv->win.width)>1023)
+ width=btv->win.width;
+ height=btv->win.height;
+ if(width > 1023)
width = 1023; /* sanity check */
- if((height=btv->win.height)>625)
+ if(height > 625)
height = 625; /* sanity check */
- adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
+ ro=btv->risc_odd;
+ re=btv->risc_even;
+
if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {
/* can't clip, don't generate any risc code */
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
@@ -1186,17 +1322,21 @@
/* clip against viewing window AND screen
so we do not have to rely on the user program
*/
- clip_draw_rectangle(clipmap,(btv->win.x+width>btv->win.swidth) ?
- (btv->win.swidth-btv->win.x) : width, 0, 1024, 768);
- clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?
- (btv->win.sheight-btv->win.y) : height,1024,768);
- if (btv->win.x<0)
- clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);
- if (btv->win.y<0)
- clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
+ if (!btv->win.use_yuv) {
+ clip_draw_rectangle(clipmap,(btv->win.x+width>btv->win.swidth) ?
+ (btv->win.swidth-btv->win.x) : width, 0, 1024, 768);
+ clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?
+ (btv->win.sheight-btv->win.y) : height,1024,768);
+ if (btv->win.x<0)
+ clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);
+ if (btv->win.y<0)
+ clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
+ }
- *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
- *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
+ *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(ro++)=cpu_to_le32(0);
+ *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+ *(re++)=cpu_to_le32(0);
/* translate bitmap to risc code */
for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)
@@ -1216,8 +1356,9 @@
if (!lastbit) {
*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|flags|len);
*((*rp)++)=cpu_to_le32(adr + bpp * sx);
- } else
+ } else {
*((*rp)++)=cpu_to_le32(BT848_RISC_SKIP|flags|len);
+ }
lastbit=cbit;
sx += dx;
dx = 1;
@@ -1230,6 +1371,7 @@
if ((!inter)||(line&1))
adr+=bpl;
}
+
vfree(clipmap);
/* outofmem flag relies on the following code to discard extra data */
*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
@@ -1238,6 +1380,15 @@
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
}
+/*
+ * Set the registers for the size we have specified. Don't bother
+ * trying to understand this without the BT848 manual in front of
+ * you [AC].
+ *
+ * PS: The manual is free for download in .pdf format from
+ * www.brooktree.com - nicely done those folks.
+ */
+
/* set geometry for even/odd frames
just if you are wondering:
handling of even and odd frames will be separated, e.g. for grabbing
@@ -1266,7 +1417,8 @@
}
-static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt, int pllset)
+static void bt848_set_geo(struct bttv *btv, u16 width, u16 height,
+ u16 fmt, int pllset)
{
u16 vscale, hscale;
u32 xsf, sr;
@@ -1279,7 +1431,7 @@
if (!width || !height)
return;
-
+
save_flags(flags);
cli();
@@ -1288,17 +1440,6 @@
btv->win.cropheight=tvn->sheight;
btv->win.cropwidth=tvn->swidth;
-/*
- if (btv->win.cropwidth>tvn->cropwidth)
- btv->win.cropwidth=tvn->cropwidth;
- if (btv->win.cropheight>tvn->cropheight)
- btv->win.cropheight=tvn->cropheight;
-
- if (width>btv->win.cropwidth)
- width=btv->win.cropwidth;
- if (height>btv->win.cropheight)
- height=btv->win.cropheight;
-*/
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
@@ -1306,27 +1447,28 @@
btwrite(1, BT848_VBI_PACK_DEL);
btv->pll.pll_ofreq = tvn->Fsc;
- if(pllset)
- set_pll(btv);
+ if (pllset)
+ set_pll(btv);
btwrite(fmt, BT848_COLOR_FMT);
-#ifdef __sparc__
- if(fmt == BT848_COLOR_FMT_RGB32 ||
- fmt == BT848_COLOR_FMT_RGB24) {
+ if (bigendian &&
+ fmt == BT848_COLOR_FMT_RGB32) {
btwrite((BT848_COLOR_CTL_GAMMA |
- BT848_COLOR_CTL_WSWAP_ODD |
- BT848_COLOR_CTL_WSWAP_EVEN |
- BT848_COLOR_CTL_BSWAP_ODD |
- BT848_COLOR_CTL_BSWAP_EVEN),
- BT848_COLOR_CTL);
- } else if(fmt == BT848_COLOR_FMT_RGB16 ||
- fmt == BT848_COLOR_FMT_RGB15) {
- btwrite((BT848_COLOR_CTL_GAMMA |
- BT848_COLOR_CTL_BSWAP_ODD |
- BT848_COLOR_CTL_BSWAP_EVEN),
- BT848_COLOR_CTL);
- }
-#endif
+ BT848_COLOR_CTL_WSWAP_ODD |
+ BT848_COLOR_CTL_WSWAP_EVEN |
+ BT848_COLOR_CTL_BSWAP_ODD |
+ BT848_COLOR_CTL_BSWAP_EVEN),
+ BT848_COLOR_CTL);
+ } else if (bigendian &&
+ (fmt == BT848_COLOR_FMT_RGB16 ||
+ fmt == BT848_COLOR_FMT_RGB15)) {
+ btwrite((BT848_COLOR_CTL_GAMMA |
+ BT848_COLOR_CTL_BSWAP_ODD |
+ BT848_COLOR_CTL_BSWAP_EVEN),
+ BT848_COLOR_CTL);
+ } else {
+ btwrite(0x10, BT848_COLOR_CTL);
+ }
hactive=width;
vtc=0;
@@ -1350,18 +1492,18 @@
crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)|
((vactive>>4)&0x30)|((vdelay>>2)&0xc0);
vscale|= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0;
-
+
bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, vactive,
hdelay, vdelay, crop);
bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive,
hdelay, vdelay, crop);
-
+
restore_flags(flags);
}
int bpp2fmt[4] = {
- BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16,
+ BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16,
BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32
};
@@ -1369,9 +1511,14 @@
{
unsigned short format;
- btv->win.color_fmt = format =
- (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
- bpp2fmt[(btv->win.bpp-1)&3];
+ if (btv->win.use_yuv) {
+ /* yuv-to-offscreen */
+ format = BT848_COLOR_FMT_YUY2;
+ } else {
+ format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
+ bpp2fmt[(btv->win.bpp-1)&3];
+ }
+ btv->win.color_fmt = format;
/* RGB8 seems to be a 9x5x5 GRB color cube starting at
* color 16. Why the h... can't they even mention this in the
@@ -1385,45 +1532,39 @@
else
btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
- bt848_set_geo(btv, btv->win.width, btv->win.height, format, 1);
+ bt848_set_geo(btv, btv->win.width, btv->win.height, format,1);
}
/*
* Set TSA5522 synthesizer frequency in 1/16 Mhz steps
*/
+#if 0
static void set_freq(struct bttv *btv, unsigned short freq)
{
+ int naudio;
int fixme = freq; /* XXX */
-
+ /* int oldAudio = btv->audio; */
+
/* mute */
- if (btv->have_msp3400)
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_SWITCH_MUTE,0);
-
- /* switch channel */
- if (btv->have_tuner) {
- if (btv->radio) {
- i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
- TUNER_SET_RADIOFREQ,&fixme);
- } else {
- i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
- TUNER_SET_TVFREQ,&fixme);
- }
- }
+ AUDIO(AUDC_SWITCH_MUTE,0);
- if (btv->have_msp3400) {
- if (btv->radio) {
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_SET_RADIO,0);
- } else {
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_SET_TVNORM,&(btv->win.norm));
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_NEWCHANNEL,0);
- }
+ /* tune */
+ if (btv->radio) {
+ TUNER(TUNER_SET_RADIOFREQ,&fixme);
+ } else {
+ TUNER(TUNER_SET_TVFREQ,&fixme);
+ }
+
+ if (btv->radio) {
+ AUDIO(AUDC_SET_RADIO,0);
+ } else {
+ AUDIO(AUDC_SET_TVNORM,&(btv->win.norm));
+ AUDIO(AUDC_NEWCHANNEL,0);
}
}
+#endif
+
/*
* Grab into virtual memory.
@@ -1447,7 +1588,7 @@
* No grabbing past the end of the buffer!
*/
- if(mp->frame>1 || mp->frame <0)
+ if(mp->frame>(MAX_GBUFFERS-1) || mp->frame <0)
return -EINVAL;
if(mp->height <0 || mp->width <0)
@@ -1485,6 +1626,7 @@
re=ro+2048;
make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
/* bt848_set_risc_jmps(btv); */
+ cli();
btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
if (btv->grabbing) {
btv->gfmt_next=palette2fmt[mp->format];
@@ -1508,12 +1650,14 @@
}
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
}
+ sti();
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
/* interruptible_sleep_on(&btv->capq); */
return 0;
}
+
static long bttv_write(struct video_device *v, const char *buf, unsigned long count, int nonblock)
{
return -EINVAL;
@@ -1523,6 +1667,7 @@
{
struct bttv *btv= (struct bttv *)v;
int q,todo;
+
/* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */
todo=count;
while (todo && todo>(q=VBIBUF_SIZE-btv->vbip))
@@ -1569,18 +1714,17 @@
static int bttv_open(struct video_device *dev, int flags)
{
struct bttv *btv = (struct bttv *)dev;
- int i, ret;
-
+ int i,ret;
+
ret = -EBUSY;
- down(&btv->lock);
- if (btv->user)
+ if (btv->user)
goto out_unlock;
-
- btv->fbuffer= (unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+
+ btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF);
ret = -ENOMEM;
- if (!btv->fbuffer)
+ if (!btv->fbuffer)
goto out_unlock;
- audio(btv, AUDIO_UNMUTE);
+
btv->grabbing = 0;
btv->grab = 0;
btv->lastgrab = 0;
@@ -1588,9 +1732,9 @@
btv->frame_stat[i] = GBUFFER_UNUSED;
btv->user++;
- up(&btv->lock);
+ up(&btv->lock);
MOD_INC_USE_COUNT;
- return 0;
+ return 0;
out_unlock:
up(&btv->lock);
@@ -1601,9 +1745,8 @@
{
struct bttv *btv=(struct bttv *)dev;
- down(&btv->lock);
+ down(&btv->lock);
btv->user--;
- audio(btv, AUDIO_INTERN);
btv->cap&=~3;
bt848_set_risc_jmps(btv);
@@ -1621,15 +1764,16 @@
* be sure its safe to free the buffer. We wait 5-6 fields
* which is more than sufficient to be sure.
*/
-
+
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ/10); /* Wait 1/10th of a second */
/*
* We have allowed it to drain.
*/
+
if(btv->fbuffer)
- rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);
+ rvfree((void *) btv->fbuffer, MAX_GBUFFERS*BTTV_MAX_FBUF);
btv->fbuffer=0;
up(&btv->lock);
MOD_DEC_USE_COUNT;
@@ -1680,6 +1824,7 @@
btaor(datahi, ~1, BT848_O_CONTROL);
}
+
/*
* ioctl routine
*/
@@ -1687,619 +1832,597 @@
static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
- unsigned char eedata[256];
struct bttv *btv=(struct bttv *)dev;
int i;
- switch (cmd)
- {
- case VIDIOCGCAP:
- {
- struct video_capability b;
- strcpy(b.name,btv->video_dev.name);
- b.type = VID_TYPE_CAPTURE|
- VID_TYPE_TUNER|
- VID_TYPE_TELETEXT|
- VID_TYPE_OVERLAY|
- VID_TYPE_CLIPPING|
- VID_TYPE_FRAMERAM|
- VID_TYPE_SCALES;
- b.channels = tvcards[btv->type].video_inputs;
- b.audios = tvcards[btv->type].audio_inputs;
- b.maxwidth = tvnorms[btv->win.norm].swidth;
- b.maxheight = tvnorms[btv->win.norm].sheight;
- b.minwidth = 32;
- b.minheight = 32;
- if(copy_to_user(arg,&b,sizeof(b)))
- return -EFAULT;
- return 0;
- }
- case VIDIOCGCHAN:
+ switch (cmd) {
+ case VIDIOCGCAP:
+ {
+ struct video_capability b;
+ strcpy(b.name,btv->video_dev.name);
+ b.type = VID_TYPE_CAPTURE|
+ ((tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) |
+ VID_TYPE_OVERLAY|
+ VID_TYPE_CLIPPING|
+ VID_TYPE_FRAMERAM|
+ VID_TYPE_SCALES;
+ b.channels = tvcards[btv->type].video_inputs;
+ b.audios = tvcards[btv->type].audio_inputs;
+ b.maxwidth = tvnorms[btv->win.norm].swidth;
+ b.maxheight = tvnorms[btv->win.norm].sheight;
+ b.minwidth = 32;
+ b.minheight = 32;
+ if(copy_to_user(arg,&b,sizeof(b)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGCHAN:
+ {
+ struct video_channel v;
+ if(copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+ v.flags=VIDEO_VC_AUDIO;
+ v.tuners=0;
+ v.type=VIDEO_TYPE_CAMERA;
+ v.norm = btv->win.norm;
+ if (v.channel>=tvcards[btv->type].video_inputs)
+ return -EINVAL;
+ if(v.channel==tvcards[btv->type].tuner)
{
- struct video_channel v;
- if(copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- v.flags=VIDEO_VC_AUDIO;
- v.tuners=0;
- v.type=VIDEO_TYPE_CAMERA;
- v.norm = btv->win.norm;
- if (v.channel>=tvcards[btv->type].video_inputs)
- return -EINVAL;
- if(v.channel==tvcards[btv->type].tuner)
- {
- strcpy(v.name,"Television");
- v.flags|=VIDEO_VC_TUNER;
- v.type=VIDEO_TYPE_TV;
- v.tuners=1;
- }
- else if(v.channel==tvcards[btv->type].svhs)
- strcpy(v.name,"S-Video");
- else
- sprintf(v.name,"Composite%d",v.channel);
-
- if(copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- return 0;
- }
- /*
- * Each channel has 1 tuner
- */
- case VIDIOCSCHAN:
- {
- struct video_channel v;
- if(copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
-
- if (v.channel>tvcards[btv->type].video_inputs)
- return -EINVAL;
- if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
- &&v.norm!=VIDEO_MODE_SECAM)
- return -EOPNOTSUPP;
- down(&btv->lock);
- bt848_muxsel(btv, v.channel);
+ strcpy(v.name,"Television");
+ v.flags|=VIDEO_VC_TUNER;
+ v.type=VIDEO_TYPE_TV;
+ v.tuners=1;
+ }
+ else if(v.channel==tvcards[btv->type].svhs)
+ strcpy(v.name,"S-Video");
+ else
+ sprintf(v.name,"Composite%d",v.channel);
+
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ /*
+ * Each channel has 1 tuner
+ */
+ case VIDIOCSCHAN:
+ {
+ struct video_channel v;
+ if(copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+
+ if (v.channel>tvcards[btv->type].video_inputs)
+ return -EINVAL;
+ if (v.norm > (sizeof(tvnorms)/sizeof(*tvnorms)))
+ return -EOPNOTSUPP;
+
+ call_i2c_clients(btv,cmd,&v);
+ down(&btv->lock);
+ bt848_muxsel(btv, v.channel);
+ btv->channel=v.channel;
+ if (btv->win.norm != v.norm) {
btv->win.norm = v.norm;
- make_vbitab(btv);
+ make_vbitab(btv);
bt848_set_winsize(btv);
- btv->channel=v.channel;
- up(&btv->lock);
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner v;
- if(copy_from_user(&v,arg,sizeof(v))!=0)
- return -EFAULT;
- if(v.tuner||btv->channel) /* Only tuner 0 */
- return -EINVAL;
- strcpy(v.name, "Television");
- v.rangelow=0;
- v.rangehigh=0xFFFFFFFF;
- v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
- if (btv->audio_chip == TDA9840) {
- v.flags |= VIDEO_AUDIO_VOLUME;
- v.mode = VIDEO_SOUND_MONO|VIDEO_SOUND_STEREO;
- v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;
- }
- if (btv->audio_chip == TDA9850) {
- unsigned char ALR1;
- ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
- if (ALR1 & 32)
- v.flags |= VIDEO_TUNER_STEREO_ON;
- }
- v.mode = btv->win.norm;
- v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
- if(copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- return 0;
}
- /* We have but one tuner */
- case VIDIOCSTUNER:
- {
- struct video_tuner v;
- if(copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- /* Only one channel has a tuner */
- if(v.tuner!=tvcards[btv->type].tuner)
- return -EINVAL;
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v,arg,sizeof(v))!=0)
+ return -EFAULT;
+ if(v.tuner||btv->channel) /* Only tuner 0 */
+ return -EINVAL;
+ strcpy(v.name, "Television");
+ v.rangelow=0;
+ v.rangehigh=0xFFFFFFFF;
+ v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+ v.mode = btv->win.norm;
+ v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
+ call_i2c_clients(btv,cmd,&v);
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ /* We have but one tuner */
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ /* Only one channel has a tuner */
+ if(v.tuner!=tvcards[btv->type].tuner)
+ return -EINVAL;
- if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC
- &&v.mode!=VIDEO_MODE_SECAM)
- return -EOPNOTSUPP;
- btv->win.norm = v.mode;
- down(&btv->lock);
- bt848_set_winsize(btv);
- up(&btv->lock);
- return 0;
- }
- case VIDIOCGPICT:
- {
- struct video_picture p=btv->picture;
- if(btv->win.depth==8)
- p.palette=VIDEO_PALETTE_HI240;
- if(btv->win.depth==15)
- p.palette=VIDEO_PALETTE_RGB555;
- if(btv->win.depth==16)
- p.palette=VIDEO_PALETTE_RGB565;
- if(btv->win.depth==24)
- p.palette=VIDEO_PALETTE_RGB24;
- if(btv->win.depth==32)
- p.palette=VIDEO_PALETTE_RGB32;
-
- if(copy_to_user(arg, &p, sizeof(p)))
- return -EFAULT;
- return 0;
- }
- case VIDIOCSPICT:
- {
- struct video_picture p;
- int format;
- if(copy_from_user(&p, arg,sizeof(p)))
- return -EFAULT;
- down(&btv->lock);
- /* We want -128 to 127 we get 0-65535 */
- bt848_bright(btv, (p.brightness>>8)-128);
- /* 0-511 for the colour */
- bt848_sat_u(btv, p.colour>>7);
- bt848_sat_v(btv, ((p.colour>>7)*201L)/237);
- /* -128 to 127 */
- bt848_hue(btv, (p.hue>>8)-128);
- /* 0-511 */
- bt848_contrast(btv, p.contrast>>7);
- btv->picture = p;
-
- /* set palette if bpp matches */
- if (p.palette < sizeof(palette2fmt)/sizeof(int)) {
- format = palette2fmt[p.palette];
- if (fmtbppx2[format&0x0f]/2 == btv->win.bpp)
- btv->win.color_fmt = format;
- }
+ if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC
+ &&v.mode!=VIDEO_MODE_SECAM)
+ return -EOPNOTSUPP;
+ call_i2c_clients(btv,cmd,&v);
+ if (btv->win.norm != v.mode) {
+ btv->win.norm = v.mode;
+ down(&btv->lock);
+ make_vbitab(btv);
+ bt848_set_winsize(btv);
up(&btv->lock);
- return 0;
}
- case VIDIOCSWIN:
- {
- struct video_window vw;
- struct video_clip *vcp = NULL;
- int on;
-
- if(copy_from_user(&vw,arg,sizeof(vw)))
- return -EFAULT;
-
- if(vw.flags || vw.width < 16 || vw.height < 16)
- {
- down(&btv->lock);
- bt848_cap(btv,0);
- up(&btv->lock);
- return -EINVAL;
- }
- if (btv->win.bpp < 4)
- { /* 32-bit align start and adjust width */
- int i = vw.x;
- vw.x = (vw.x + 3) & ~3;
- i = vw.x - i;
- vw.width -= i;
- }
+ return 0;
+ }
+ case VIDIOCGPICT:
+ {
+ struct video_picture p=btv->picture;
+ if(btv->win.depth==8)
+ p.palette=VIDEO_PALETTE_HI240;
+ if(btv->win.depth==15)
+ p.palette=VIDEO_PALETTE_RGB555;
+ if(btv->win.depth==16)
+ p.palette=VIDEO_PALETTE_RGB565;
+ if(btv->win.depth==24)
+ p.palette=VIDEO_PALETTE_RGB24;
+ if(btv->win.depth==32)
+ p.palette=VIDEO_PALETTE_RGB32;
- down(&btv->lock);
- btv->win.x=vw.x;
- btv->win.y=vw.y;
- btv->win.width=vw.width;
- btv->win.height=vw.height;
-
- if(btv->win.height>btv->win.cropheight/2)
- btv->win.interlace=1;
- else
- btv->win.interlace=0;
-
- on=(btv->cap&3);
+ if(copy_to_user(arg, &p, sizeof(p)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSPICT:
+ {
+ struct video_picture p;
+ if(copy_from_user(&p, arg,sizeof(p)))
+ return -EFAULT;
+ down(&btv->lock);
+ /* We want -128 to 127 we get 0-65535 */
+ bt848_bright(btv, (p.brightness>>8)-128);
+ /* 0-511 for the colour */
+ bt848_sat_u(btv, p.colour>>7);
+ bt848_sat_v(btv, ((p.colour>>7)*201L)/237);
+ /* -128 to 127 */
+ bt848_hue(btv, (p.hue>>8)-128);
+ /* 0-511 */
+ bt848_contrast(btv, p.contrast>>7);
+ btv->picture = p;
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCSWIN:
+ {
+ struct video_window vw;
+ struct video_clip *vcp = NULL;
+ int on;
+ if(copy_from_user(&vw,arg,sizeof(vw)))
+ return -EFAULT;
+
+ if(vw.flags || vw.width < 16 || vw.height < 16)
+ {
+ down(&btv->lock);
bt848_cap(btv,0);
- bt848_set_winsize(btv);
-
up(&btv->lock);
+ return -EINVAL;
+ }
+ if (btv->win.bpp < 4)
+ { /* adjust and align writes */
+ vw.x = (vw.x + 3) & ~3;
+ vw.width &= ~3;
+ }
+ down(&btv->lock);
+ btv->win.use_yuv=0;
+ btv->win.x=vw.x;
+ btv->win.y=vw.y;
+ btv->win.width=vw.width;
+ btv->win.height=vw.height;
- /*
- * Do any clips.
- */
- if(vw.clipcount<0) {
- if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL)
- return -ENOMEM;
- if(copy_from_user(vcp, vw.clips,
- VIDEO_CLIPMAP_SIZE)) {
- vfree(vcp);
- return -EFAULT;
- }
- } else if (vw.clipcount) {
- if((vcp=vmalloc(sizeof(struct video_clip)*
- (vw.clipcount))) == NULL)
- return -ENOMEM;
- if(copy_from_user(vcp,vw.clips,
- sizeof(struct video_clip)*
- vw.clipcount)) {
- vfree(vcp);
- return -EFAULT;
- }
+ on=(btv->cap&3);
+
+ bt848_cap(btv,0);
+ bt848_set_winsize(btv);
+ up(&btv->lock);
+
+ /*
+ * Do any clips.
+ */
+ if(vw.clipcount<0) {
+ if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL)
+ return -ENOMEM;
+ if(copy_from_user(vcp, vw.clips,
+ VIDEO_CLIPMAP_SIZE)) {
+ vfree(vcp);
+ return -EFAULT;
}
- down(&btv->lock);
- make_clip_tab(btv, vcp, vw.clipcount);
- if (vw.clipcount != 0)
+ } else if (vw.clipcount) {
+ if((vcp=vmalloc(sizeof(struct video_clip)*
+ (vw.clipcount))) == NULL)
+ return -ENOMEM;
+ if(copy_from_user(vcp,vw.clips,
+ sizeof(struct video_clip)*
+ vw.clipcount)) {
vfree(vcp);
- if(on && btv->win.vidadr!=0)
- bt848_cap(btv,1);
- up(&btv->lock);
- return 0;
- }
- case VIDIOCGWIN:
- {
- struct video_window vw;
- /* Oh for a COBOL move corresponding .. */
- vw.x=btv->win.x;
- vw.y=btv->win.y;
- vw.width=btv->win.width;
- vw.height=btv->win.height;
- vw.chromakey=0;
- vw.flags=0;
- if(btv->win.interlace)
- vw.flags|=VIDEO_WINDOW_INTERLACE;
- if(copy_to_user(arg,&vw,sizeof(vw)))
return -EFAULT;
- return 0;
+ }
}
- case VIDIOCCAPTURE:
- {
- int v;
- if(copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- if(v!=0 && (btv->win.vidadr==0 || btv->win.width==0
- || btv->win.height==0))
- return -EINVAL;
-
- down(&btv->lock);
- if(v==0)
- bt848_cap(btv,0);
- else
- bt848_cap(btv,1);
- up(&btv->lock);
+ down(&btv->lock);
+ make_clip_tab(btv, vcp, vw.clipcount);
+ if (vw.clipcount != 0)
+ vfree(vcp);
+ if(on && btv->win.vidadr!=0)
+ bt848_cap(btv,1);
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCSWIN2:
+ {
+ /* experimental -- right now it handles unclipped yuv data only */
+ struct video_window2 vo;
+ __u32 fbsize;
+ int on;
+
+ if(copy_from_user(&vo,arg,sizeof(vo)))
+ return -EFAULT;
- return 0;
- }
- case VIDIOCGFBUF:
- {
- struct video_buffer v;
- v.base=(void *)btv->win.vidadr;
- v.height=btv->win.sheight;
- v.width=btv->win.swidth;
- v.depth=btv->win.depth;
- v.bytesperline=btv->win.bpl;
- if(copy_to_user(arg, &v,sizeof(v)))
- return -EFAULT;
- return 0;
+ fbsize = btv->win.sheight * btv->win.bpl;
+ if (vo.start + vo.pitch*vo.height > fbsize)
+ return -EINVAL;
+ if (vo.palette != VIDEO_PALETTE_YUV422)
+ return -EINVAL;
+
+ down(&btv->lock);
+ btv->win.use_yuv=1;
+ memcpy(&btv->win.win2,&vo,sizeof(vo));
+ btv->win.width=vo.width;
+ btv->win.height=vo.height;
+
+ on=(btv->cap&3);
+ bt848_cap(btv,0);
+ bt848_set_winsize(btv);
+ make_clip_tab(btv, NULL, 0);
+ if(on && btv->win.vidadr!=0)
+ bt848_cap(btv,1);
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCGWIN:
+ {
+ struct video_window vw;
+ /* Oh for a COBOL move corresponding .. */
+ vw.x=btv->win.x;
+ vw.y=btv->win.y;
+ vw.width=btv->win.width;
+ vw.height=btv->win.height;
+ vw.chromakey=0;
+ vw.flags=0;
+ if(btv->win.interlace)
+ vw.flags|=VIDEO_WINDOW_INTERLACE;
+ if(copy_to_user(arg,&vw,sizeof(vw)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCCAPTURE:
+ {
+ int v;
+ if(copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+ if(btv->win.vidadr == 0)
+ return -EINVAL;
+ if (0 == btv->win.use_yuv && (btv->win.width==0 || btv->win.height==0))
+ return -EINVAL;
+ down(&btv->lock);
+ if(v==0)
+ bt848_cap(btv,0);
+ else
+ bt848_cap(btv,1);
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer v;
+ v.base=(void *)btv->win.vidadr;
+ v.height=btv->win.sheight;
+ v.width=btv->win.swidth;
+ v.depth=btv->win.depth;
+ v.bytesperline=btv->win.bpl;
+ if(copy_to_user(arg, &v,sizeof(v)))
+ return -EFAULT;
+ return 0;
- }
- case VIDIOCSFBUF:
- {
- struct video_buffer v;
-#if LINUX_VERSION_CODE >= 0x020100
- if(!capable(CAP_SYS_ADMIN)
- && !capable(CAP_SYS_RAWIO))
-#else
- if(!suser())
-#endif
- return -EPERM;
- if(copy_from_user(&v, arg,sizeof(v)))
- return -EFAULT;
- if(v.depth!=8 && v.depth!=15 && v.depth!=16 &&
- v.depth!=24 && v.depth!=32 && v.width > 16 &&
- v.height > 16 && v.bytesperline > 16)
- return -EINVAL;
- down(&btv->lock);
- if (v.base)
- btv->win.vidadr=(unsigned long)v.base;
- btv->win.sheight=v.height;
- btv->win.swidth=v.width;
- btv->win.bpp=((v.depth+7)&0x38)/8;
- btv->win.depth=v.depth;
- btv->win.bpl=v.bytesperline;
+ }
+ case VIDIOCSFBUF:
+ {
+ struct video_buffer v;
+ if(!capable(CAP_SYS_ADMIN) &&
+ !capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ if(copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+ if(v.depth!=8 && v.depth!=15 && v.depth!=16 &&
+ v.depth!=24 && v.depth!=32 && v.width > 16 &&
+ v.height > 16 && v.bytesperline > 16)
+ return -EINVAL;
+ down(&btv->lock);
+ if (v.base)
+ btv->win.vidadr=(unsigned long)v.base;
+ btv->win.sheight=v.height;
+ btv->win.swidth=v.width;
+ btv->win.bpp=((v.depth+7)&0x38)/8;
+ btv->win.depth=v.depth;
+ btv->win.bpl=v.bytesperline;
- DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
- v.base, v.width,v.height, btv->win.bpp, btv->win.bpl));
- bt848_set_winsize(btv);
- up(&btv->lock);
- return 0;
- }
- case VIDIOCKEY:
- {
- /* Will be handled higher up .. */
- return 0;
- }
- case VIDIOCGFREQ:
- {
- unsigned long v=btv->win.freq;
- if(copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- return 0;
+ DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
+ v.base, v.width,v.height, btv->win.bpp, btv->win.bpl));
+ bt848_set_winsize(btv);
+ up(&btv->lock);
+ return 0;
+ }
+ case VIDIOCKEY:
+ {
+ /* Will be handled higher up .. */
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ {
+ unsigned long v=btv->win.freq;
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSFREQ:
+ {
+ unsigned long v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ btv->win.freq=v;
+ call_i2c_clients(btv,cmd,&v);
+ return 0;
+ }
+
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+
+ v=btv->audio_dev;
+ v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);
+ v.flags|=VIDEO_AUDIO_MUTABLE;
+ strcpy(v.name,"TV");
+
+ v.mode = VIDEO_SOUND_MONO;
+ call_i2c_clients(btv,cmd,&v);
+
+ if (btv->type == BTTV_TERRATV) {
+ v.mode = VIDEO_SOUND_MONO;
+ v.mode |= VIDEO_SOUND_STEREO;
+ v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;
+
+ } else if (btv->audio_chip == TDA9840) {
+ /* begin of Horrible Hack <grin@tolna.net> */
+ v.flags|=VIDEO_AUDIO_VOLUME;
+ v.mode = VIDEO_SOUND_MONO;
+ v.mode |= VIDEO_SOUND_STEREO;
+ v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;
+ v.volume = 32768; /* fixme */
+ v.step = 4096;
}
- case VIDIOCSFREQ:
- {
- unsigned long v;
- if(copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
- btv->win.freq=v;
- set_freq(btv, btv->win.freq);
- return 0;
- }
-
- case VIDIOCGAUDIO:
- {
- struct video_audio v;
- v=btv->audio_dev;
- v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);
- v.flags|=VIDEO_AUDIO_MUTABLE;
- strcpy(v.name,"TV");
- if (btv->audio_chip == TDA9850) {
- unsigned char ALR1;
- ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
- v.mode = VIDEO_SOUND_MONO;
- v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;
- v.mode |= (ALR1 & 64) ? VIDEO_SOUND_LANG1:0;
- }
- if (btv->have_msp3400)
- {
- v.flags|=VIDEO_AUDIO_VOLUME |
- VIDEO_AUDIO_BASS |
- VIDEO_AUDIO_TREBLE;
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_VOLUME,&(v.volume));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_BASS,&(v.bass));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_TREBLE,&(v.treble));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_STEREO,&(v.mode));
- }
- else v.mode = VIDEO_SOUND_MONO;
- if(copy_to_user(arg,&v,sizeof(v)))
- return -EFAULT;
- return 0;
+
+#if 0
+#warning this should be handled by tda9855.c
+ else if (btv->audio_chip == TDA9850) {
+ unsigned char ALR1;
+ v.flags|=VIDEO_AUDIO_VOLUME;
+ ALR1 = I2CRead(btv, I2C_TDA9850|1);
+ v.mode = VIDEO_SOUND_MONO;
+ v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;
+ v.mode |= (ALR1 & 32) ? VIDEO_SOUND_LANG1:0;
+ v.volume = 32768; /* fixme */
+ v.step = 4096;
}
- case VIDIOCSAUDIO:
- {
- struct video_audio v;
- if(copy_from_user(&v,arg, sizeof(v)))
- return -EFAULT;
- down(&btv->lock);
- if(v.flags&VIDEO_AUDIO_MUTE)
- audio(btv, AUDIO_MUTE);
- /* One audio source per tuner */
- /* if(v.audio!=0) */
- /* ADSTech TV card has more than one */
- if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
- {
- up(&btv->lock);
- return -EINVAL;
- }
- bt848_muxsel(btv,v.audio);
- if(!(v.flags&VIDEO_AUDIO_MUTE))
- audio(btv, AUDIO_UNMUTE);
- if (btv->audio_chip == TDA9850) {
- unsigned char con3 = 0;
- if (v.mode & VIDEO_SOUND_LANG1)
- con3 = 0x80; /* sap */
- if (v.mode & VIDEO_SOUND_STEREO)
- con3 = 0x40; /* stereo */
- I2CWrite(&(btv->i2c), I2C_TDA9850,
- TDA9850_CON3, con3, 1);
- }
-
- /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
- if (btv->type == BTTV_WINVIEW_601) {
- int bits_out, loops, vol, data;
-
- /* 32 levels logarithmic */
- vol = 32 - ((v.volume>>11));
- /* units */
- bits_out = (PT2254_DBS_IN_2>>(vol%5));
- /* tens */
- bits_out |= (PT2254_DBS_IN_10>>(vol/5));
- bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL;
- data = btread(BT848_GPIO_DATA);
- data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
- WINVIEW_PT2254_STROBE);
- for (loops = 17; loops >= 0 ; loops--) {
- if (bits_out & (1<<loops))
- data |= WINVIEW_PT2254_DATA;
- else
- data &= ~WINVIEW_PT2254_DATA;
- btwrite(data, BT848_GPIO_DATA);
- udelay(5);
- data |= WINVIEW_PT2254_CLK;
- btwrite(data, BT848_GPIO_DATA);
- udelay(5);
- data &= ~WINVIEW_PT2254_CLK;
- btwrite(data, BT848_GPIO_DATA);
- }
- data |= WINVIEW_PT2254_STROBE;
- data &= ~WINVIEW_PT2254_DATA;
- btwrite(data, BT848_GPIO_DATA);
- udelay(10);
- data &= ~WINVIEW_PT2254_STROBE;
- btwrite(data, BT848_GPIO_DATA);
- }
- /* TEA 6320 Audio Support by Michael Wrighton
- mgw1@cec.wustl.edu */
- if (btv->audio_chip == TEA6320)
- {
- int vol;
- vol = v.volume >> 11;
- if (!(v.flags&VIDEO_AUDIO_MUTE))
- I2CWrite(&(btv->i2c), I2C_TEA6320,
- TEA6320_S, TEA6320_S_SB,1); /* at least Raffles card uses input B */
- else
- I2CWrite(&(btv->i2c), I2C_TEA6320,
- TEA6320_S, TEA6320_S_GMU,1);
- I2CWrite(&(btv->i2c), I2C_TEA6320,
- TEA6320_V, vol, 1);
- }
- if (btv->have_msp3400)
- {
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_VOLUME,&(v.volume));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_BASS,&(v.bass));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_TREBLE,&(v.treble));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_STEREO,&(v.mode));
- }
- btv->audio_dev=v;
+#endif
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+
+ if(copy_from_user(&v,arg, sizeof(v)))
+ return -EFAULT;
+ down(&btv->lock);
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ audio(btv, AUDIO_MUTE);
+ /* One audio source per tuner -- huh? <GA> */
+ if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs) {
up(&btv->lock);
- return 0;
+ return -EINVAL;
}
+ /* bt848_muxsel(btv,v.audio); */
+ if(!(v.flags&VIDEO_AUDIO_MUTE))
+ audio(btv, AUDIO_UNMUTE);
- case VIDIOCSYNC:
- if(copy_from_user((void *)&i,arg,sizeof(int)))
- return -EFAULT;
-/* if(i>1 || i<0)
- return -EINVAL;
-*/
- switch (btv->frame_stat[i]) {
- case GBUFFER_UNUSED:
- return -EINVAL;
- case GBUFFER_GRABBING:
- while(btv->frame_stat[i]==GBUFFER_GRABBING) {
- interruptible_sleep_on(&btv->capq);
- if(signal_pending(current))
- return -EINTR;
- }
- /* fall */
- case GBUFFER_DONE:
- btv->frame_stat[i] = GBUFFER_UNUSED;
- break;
- }
- return 0;
+ call_i2c_clients(btv,cmd,&v);
+
+ if (btv->type == BTTV_TERRATV) {
+ unsigned int con = 0;
+ btor(0x180000, BT848_GPIO_OUT_EN);
+ if (v.mode & VIDEO_SOUND_LANG2)
+ con = 0x080000;
+ if (v.mode & VIDEO_SOUND_STEREO)
+ con = 0x180000;
+ btaor(con, ~0x180000, BT848_GPIO_DATA);
+
+ } else if (btv->type == BTTV_WINVIEW_601) {
+ /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
+ int bits_out, loops, vol, data;
+
+ /* 32 levels logarithmic */
+ vol = 32 - ((v.volume>>11));
+ /* units */
+ bits_out = (PT2254_DBS_IN_2>>(vol%5));
+ /* tens */
+ bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+ bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL;
+ data = btread(BT848_GPIO_DATA);
+ data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+ WINVIEW_PT2254_STROBE);
+ for (loops = 17; loops >= 0 ; loops--) {
+ if (bits_out & (1<<loops))
+ data |= WINVIEW_PT2254_DATA;
+ else
+ data &= ~WINVIEW_PT2254_DATA;
+ btwrite(data, BT848_GPIO_DATA);
+ udelay(5);
+ data |= WINVIEW_PT2254_CLK;
+ btwrite(data, BT848_GPIO_DATA);
+ udelay(5);
+ data &= ~WINVIEW_PT2254_CLK;
+ btwrite(data, BT848_GPIO_DATA);
+ }
+ data |= WINVIEW_PT2254_STROBE;
+ data &= ~WINVIEW_PT2254_DATA;
+ btwrite(data, BT848_GPIO_DATA);
+ udelay(10);
+ data &= ~WINVIEW_PT2254_STROBE;
+ btwrite(data, BT848_GPIO_DATA);
- case BTTV_WRITEE:
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if(copy_from_user((void *) eedata, (void *) arg, 256))
- return -EFAULT;
- down(&btv->lock);
- writeee(&(btv->i2c), eedata);
- up(&btv->lock);
- return 0;
+#if 0
+#warning this should be handled by tda9855.c
+ } else if (btv->audio_chip == TDA9850) {
+ unsigned char con3 = 0;
+ if (v.mode & VIDEO_SOUND_LANG1)
+ con3 = 0x80; /* sap */
+ if (v.mode & VIDEO_SOUND_STEREO)
+ con3 = 0x40; /* stereo */
+ I2CWrite(btv, I2C_TDA9850,
+ TDA9850_CON3, con3, 1);
+ if (v.flags & VIDEO_AUDIO_VOLUME)
+ I2CWrite(btv, I2C_TDA9850,
+ TDA9850_CON4,
+ (v.volume>>12) & 15, 1);
+#endif
+ }
+ btv->audio_dev=v;
+ up(&btv->lock);
+ return 0;
+ }
- case BTTV_READEE:
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- down(&btv->lock);
- readee(&(btv->i2c), eedata);
- up(&btv->lock);
- if(copy_to_user((void *) arg, (void *) eedata, 256))
- return -EFAULT;
+ case VIDIOCSYNC:
+ if(copy_from_user((void *)&i,arg,sizeof(int)))
+ return -EFAULT;
+ switch (btv->frame_stat[i]) {
+ case GBUFFER_UNUSED:
+ return -EINVAL;
+ case GBUFFER_GRABBING:
+ while(btv->frame_stat[i]==GBUFFER_GRABBING) {
+ interruptible_sleep_on(&btv->capq);
+ if(signal_pending(current))
+ return -EINTR;
+ }
+ /* fall */
+ case GBUFFER_DONE:
+ btv->frame_stat[i] = GBUFFER_UNUSED;
break;
+ }
+ return 0;
- case BTTV_FIELDNR:
- if(copy_to_user((void *) arg, (void *) &btv->last_field,
- sizeof(btv->last_field)))
- return -EFAULT;
- break;
+ case BTTV_FIELDNR:
+ if(copy_to_user((void *) arg, (void *) &btv->last_field,
+ sizeof(btv->last_field)))
+ return -EFAULT;
+ break;
- case BTTV_PLLSET: {
- struct bttv_pll_info p;
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
- return -EFAULT;
- down(&btv->lock);
- btv->pll.pll_ifreq = p.pll_ifreq;
- btv->pll.pll_ofreq = p.pll_ofreq;
- btv->pll.pll_crystal = p.pll_crystal;
- up(&btv->lock);
- break;
- }
- case VIDIOCMCAPTURE:
- {
- struct video_mmap vm;
- int v;
- if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
- return -EFAULT;
- if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING)
- return -EBUSY;
- down(&btv->lock);
- v=vgrab(btv, &vm);
- up(&btv->lock);
- return v;
- }
+ case BTTV_PLLSET: {
+ struct bttv_pll_info p;
+ if(!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
+ return -EFAULT;
+ down(&btv->lock);
+ btv->pll.pll_ifreq = p.pll_ifreq;
+ btv->pll.pll_ofreq = p.pll_ofreq;
+ btv->pll.pll_crystal = p.pll_crystal;
+ up(&btv->lock);
+
+ break;
+ }
+
+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap vm;
+ int ret;
+ if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
+ return -EFAULT;
+ if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING)
+ return -EBUSY;
+ down(&btv->lock);
+ ret = vgrab(btv, &vm);
+ up(&btv->lock);
+ return ret;
+ }
- case VIDIOCGMBUF:
- {
- struct video_mbuf vm;
- memset(&vm, 0 , sizeof(vm));
- vm.size=BTTV_MAX_FBUF*2;
- vm.frames=2;
- vm.offsets[0]=0;
- vm.offsets[1]=BTTV_MAX_FBUF;
- if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
- return -EFAULT;
- return 0;
- }
+ case VIDIOCGMBUF:
+ {
+ struct video_mbuf vm;
+ memset(&vm, 0 , sizeof(vm));
+ vm.size=BTTV_MAX_FBUF*MAX_GBUFFERS;
+ vm.frames=MAX_GBUFFERS;
+ vm.offsets[0]=0;
+ vm.offsets[1]=BTTV_MAX_FBUF;
+ if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+ return -EFAULT;
+ return 0;
+ }
- case VIDIOCGUNIT:
- {
- struct video_unit vu;
- vu.video=btv->video_dev.minor;
- vu.vbi=btv->vbi_dev.minor;
- if(btv->radio_dev.minor!=-1)
- vu.radio=btv->radio_dev.minor;
- else
- vu.radio=VIDEO_NO_UNIT;
- vu.audio=VIDEO_NO_UNIT;
- if(btv->have_msp3400)
- {
- i2c_control_device(&(btv->i2c), I2C_DRIVERID_MSP3400,
- MSP_GET_UNIT, &vu.audio);
- }
- vu.teletext=VIDEO_NO_UNIT;
- if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
- return -EFAULT;
- return 0;
- }
+ case VIDIOCGUNIT:
+ {
+ struct video_unit vu;
+ vu.video=btv->video_dev.minor;
+ vu.vbi=btv->vbi_dev.minor;
+ if(btv->radio_dev.minor!=-1)
+ vu.radio=btv->radio_dev.minor;
+ else
+ vu.radio=VIDEO_NO_UNIT;
+ vu.audio=VIDEO_NO_UNIT;
+#if 0
+ AUDIO(AUDC_GET_UNIT, &vu.audio);
+#endif
+ vu.teletext=VIDEO_NO_UNIT;
+ if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
+ return -EFAULT;
+ return 0;
+ }
- case BTTV_BURST_ON:
- {
- tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
- tvnorms[0].hdelayx1=186-BURSTOFFSET;
- return 0;
- }
+ case BTTV_BURST_ON:
+ {
+ tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
+ tvnorms[0].hdelayx1=186-BURSTOFFSET;
+ tvnorms[2].scaledtwidth=1135-BURSTOFFSET-2;
+ tvnorms[2].hdelayx1=186-BURSTOFFSET;
+ return 0;
+ }
- case BTTV_BURST_OFF:
- {
- tvnorms[0].scaledtwidth=1135;
- tvnorms[0].hdelayx1=186;
- return 0;
- }
+ case BTTV_BURST_OFF:
+ {
+ tvnorms[0].scaledtwidth=1135;
+ tvnorms[0].hdelayx1=186;
+ tvnorms[2].scaledtwidth=1135;
+ tvnorms[2].hdelayx1=186;
+ return 0;
+ }
- case BTTV_VERSION:
- {
- return BTTV_VERSION_CODE;
- }
+ case BTTV_VERSION:
+ {
+ return BTTV_VERSION_CODE;
+ }
- case BTTV_PICNR:
- {
- /* return picture;*/
- return 0;
- }
+ case BTTV_PICNR:
+ {
+ /* return picture;*/
+ return 0;
+ }
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -2317,43 +2440,42 @@
* - remap_page_range is kind of inefficient for page by page remapping.
* But e.g. pte_alloc() does not work in modules ... :-(
*/
-
+
static int do_bttv_mmap(struct bttv *btv, const char *adr, unsigned long size)
{
unsigned long start=(unsigned long) adr;
- unsigned long page,pos;
+ unsigned long page,pos;
- if (size>2*BTTV_MAX_FBUF)
- return -EINVAL;
- if (!btv->fbuffer)
- {
- if(fbuffer_alloc(btv))
- return -EINVAL;
- }
- pos=(unsigned long) btv->fbuffer;
- while (size > 0)
- {
- page = kvirt_to_pa(pos);
- if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
- return -EAGAIN;
- start+=PAGE_SIZE;
- pos+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- return 0;
+ if (size>2*BTTV_MAX_FBUF)
+ return -EINVAL;
+ if (!btv->fbuffer) {
+ if(fbuffer_alloc(btv))
+ return -EINVAL;
+ }
+ pos=(unsigned long) btv->fbuffer;
+ while (size > 0) {
+ page = kvirt_to_pa(pos);
+ if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+ start+=PAGE_SIZE;
+ pos+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ return 0;
}
static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size)
{
- struct bttv *btv=(struct bttv *)dev;
- int r;
-
- down(&btv->lock);
- r=do_bttv_mmap(btv, adr, size);
- up(&btv->lock);
- return r;
+ struct bttv *btv=(struct bttv *)dev;
+ int r;
+
+ down(&btv->lock);
+ r=do_bttv_mmap(btv, adr, size);
+ up(&btv->lock);
+ return r;
}
+
static struct video_device bttv_template=
{
"UNSET",
@@ -2363,9 +2485,7 @@
bttv_close,
bttv_read,
bttv_write,
-#if LINUX_VERSION_CODE >= 0x020100
- NULL, /* poll */
-#endif
+ NULL,
bttv_ioctl,
bttv_mmap,
bttv_init_done,
@@ -2437,7 +2557,7 @@
{
struct bttv *btv=(struct bttv *)(dev-2);
- down(&btv->lock);
+ down(&btv->lock);
btv->vbip=VBIBUF_SIZE;
btv->cap|=0x0c;
bt848_set_risc_jmps(btv);
@@ -2451,7 +2571,7 @@
{
struct bttv *btv=(struct bttv *)(dev-2);
- down(&btv->lock);
+ down(&btv->lock);
btv->cap&=~0x0c;
bt848_set_risc_jmps(btv);
up(&btv->lock);
@@ -2459,10 +2579,36 @@
MOD_DEC_USE_COUNT;
}
-
static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
- return -EINVAL;
+ struct bttv *btv=(struct bttv *)dev;
+
+ switch (cmd) {
+ case VIDIOCGCAP:
+ {
+ struct video_capability b;
+ strcpy(b.name,btv->vbi_dev.name);
+ b.type = ((tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) |
+ VID_TYPE_TELETEXT;
+ b.channels = 0;
+ b.audios = 0;
+ b.maxwidth = 0;
+ b.maxheight = 0;
+ b.minwidth = 0;
+ b.minheight = 0;
+ if(copy_to_user(arg,&b,sizeof(b)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ case VIDIOCSFREQ:
+ return bttv_ioctl((struct video_device *)btv,cmd,arg);
+ case BTTV_VBISIZE:
+ /* make alevt happy :-) */
+ return VBIBUF_SIZE;
+ default:
+ return -EINVAL;
+ }
}
static struct video_device vbi_template=
@@ -2474,9 +2620,7 @@
vbi_close,
vbi_read,
bttv_write,
-#if LINUX_VERSION_CODE >= 0x020100
vbi_poll,
-#endif
vbi_ioctl,
NULL, /* no mmap yet */
bttv_init_done,
@@ -2490,17 +2634,16 @@
{
struct bttv *btv = (struct bttv *)(dev-1);
- down(&btv->lock);
+ down(&btv->lock);
if (btv->user)
goto busy_unlock;
btv->user++;
-
- set_freq(btv,400*16);
+
btv->radio = 1;
+ call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
bt848_muxsel(btv,0);
- audio(btv, AUDIO_UNMUTE);
up(&btv->lock);
-
+
MOD_INC_USE_COUNT;
return 0;
@@ -2512,11 +2655,10 @@
static void radio_close(struct video_device *dev)
{
struct bttv *btv=(struct bttv *)(dev-1);
-
+
down(&btv->lock);
btv->user--;
btv->radio = 0;
- /*audio(btv, AUDIO_MUTE);*/
up(&btv->lock);
MOD_DEC_USE_COUNT;
}
@@ -2595,9 +2737,7 @@
radio_close,
radio_read, /* just returns -EINVAL */
bttv_write, /* just returns -EINVAL */
-#if LINUX_VERSION_CODE >= 0x020100
NULL, /* no poll */
-#endif
radio_ioctl,
NULL, /* no mmap */
bttv_init_done, /* just returns 0 */
@@ -2607,7 +2747,6 @@
};
-
#define TRITON_PCON 0x50
#define TRITON_BUS_CONCURRENCY (1<<0)
#define TRITON_STREAMING (1<<1)
@@ -2623,79 +2762,69 @@
if (triton1)
triton1=BT848_INT_ETBF;
-
- if(pci_pci_problems&PCIPCI_FAIL)
- {
- printk(KERN_WARNING "bttv: This configuration is known to have PCI to PCI DMA problems\n");
- printk(KERN_WARNING "bttv: You may not be able to use overlay mode.\n");
- }
-
- while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev)))
+ while ((dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, dev)))
{
- unsigned char b;
- pci_read_config_byte(dev, 0x53, &b);
- DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
- DEBUG(printk("bufcon=0x%02x\n",b));
- }
+ /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
+ printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
+ }
+
+ while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82441, dev)))
+ {
+ unsigned char b;
+ pci_read_config_byte(dev, 0x53, &b);
+ DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
+ DEBUG(printk("bufcon=0x%02x\n",b));
+ }
while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev)))
{
-/* unsigned char b;
- unsigned char bo;*/
-
printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
triton1=BT848_INT_ETBF;
}
}
-static void init_tea6300(struct i2c_bus *bus)
+#if 0
+#warning please use tda8425.c instead
+static void init_tda8425(struct bttv *btv)
{
- I2CWrite(bus, I2C_TEA6300, TEA6300_VL, 0x35, 1); /* volume left 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6300_VR, 0x35, 1); /* volume right 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6300_BA, 0x07, 1); /* bass 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6300_TR, 0x07, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6300_FA, 0x0f, 1); /* fader off */
- I2CWrite(bus, I2C_TEA6300, TEA6300_SW, 0x01, 1); /* mute off input A */
+ I2CWrite(btv, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */
+ I2CWrite(btv, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */
+ I2CWrite(btv, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */
+ I2CWrite(btv, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */
+ I2CWrite(btv, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
}
+#endif
-static void init_tea6320(struct i2c_bus *bus)
+/* can tda9855.c handle this too maybe? */
+static void init_tda9840(struct bttv *btv)
{
- I2CWrite(bus, I2C_TEA6300, TEA6320_V, 0x28, 1); /* master volume */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FFL, 0x28, 1); /* volume left 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FFR, 0x28, 1); /* volume right 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FRL, 0x28, 1); /* volume rear left 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FRR, 0x28, 1); /* volume rear right 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_BA, 0x11, 1); /* bass 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_TR, 0x11, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_S, TEA6320_S_GMU, 1); /* mute off input A */
+ /* Horrible Hack */
+ I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */
+ /* 00 - mute
+ 10 - mono / averaged stereo
+ 2a - stereo
+ 12 - dual A
+ 1a - dual AB
+ 16 - dual BA
+ 1e - dual B
+ 7a - external */
}
-static void init_tda8425(struct i2c_bus *bus)
-{
- I2CWrite(bus, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
-}
-static void init_tda9840(struct i2c_bus *bus)
-{
- I2CWrite(bus, I2C_TDA9840, TDA9840_SW, 0x2A, 1); /* Sound mode switching */
-}
-
-static void init_tda9850(struct i2c_bus *bus)
+#if 0
+#warning this should be handled by tda9855.c
+static void init_tda9850(struct bttv *btv)
{
- I2CWrite(bus, I2C_TDA9850, TDA9850_CON1, 0x08, 1); /* noise threshold st */
- I2CWrite(bus, I2C_TDA9850, TDA9850_CON2, 0x08, 1); /* noise threshold sap */
- I2CWrite(bus, I2C_TDA9850, TDA9850_CON3, 0x40, 1); /* stereo mode */
- I2CWrite(bus, I2C_TDA9850, TDA9850_CON4, 0x07, 1); /* 0 dB input gain?*/
- I2CWrite(bus, I2C_TDA9850, TDA9850_ALI1, 0x10, 1); /* wideband alignment? */
- I2CWrite(bus, I2C_TDA9850, TDA9850_ALI2, 0x10, 1); /* spectral alignment? */
- I2CWrite(bus, I2C_TDA9850, TDA9850_ALI3, 0x03, 1);
+ I2CWrite(btv, I2C_TDA9850, TDA9850_CON1, 0x08, 1); /* noise threshold st */
+ I2CWrite(btv, I2C_TDA9850, TDA9850_CON2, 0x08, 1); /* noise threshold sap */
+ I2CWrite(btv, I2C_TDA9850, TDA9850_CON3, 0x40, 1); /* stereo mode */
+ I2CWrite(btv, I2C_TDA9850, TDA9850_CON4, 0x07, 1); /* 0 dB input gain?*/
+ I2CWrite(btv, I2C_TDA9850, TDA9850_ALI1, 0x10, 1); /* wideband alignment? */
+ I2CWrite(btv, I2C_TDA9850, TDA9850_ALI2, 0x10, 1); /* spectral alignment? */
+ I2CWrite(btv, I2C_TDA9850, TDA9850_ALI3, 0x03, 1);
}
-
-
+#endif
/* Figure out card and tuner type */
@@ -2707,180 +2836,119 @@
DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
/* Default the card to the user-selected one. */
- btv->type=card[i];
- btv->tuner_type=-1; /* use default tuner type */
+ if (card[i] >= 0 && card[i] < TVCARDS)
+ btv->type=card[i];
/* If we were asked to auto-detect, then do so!
Right now this will only recognize Miro, Hauppauge or STB
*/
if (btv->type == BTTV_UNKNOWN)
{
- if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
+ if (I2CRead(btv, I2C_HAUPEE)>=0)
{
if(btv->id>849)
btv->type=BTTV_HAUPPAUGE878;
else
btv->type=BTTV_HAUPPAUGE;
- } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
+ } else if (I2CRead(btv, I2C_STBEE)>=0) {
btv->type=BTTV_STB;
+
+#if 0 /* bad idea: 0xc0 is used for the tuner on _many_ boards */
+ } else if (I2CRead(btv, I2C_VHX)>=0) {
+ btv->type=BTTV_VHX;
+#endif
+
} else {
- if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
+ if (I2CRead(btv, 0x80)>=0) /* check for msp34xx */
btv->type = BTTV_MIROPRO;
else
- btv->type=BTTV_MIRO;
+ btv->type = BTTV_MIRO;
}
}
- /* board specific initialisations */
-
- switch(btv->type)
- {
- case BTTV_MIRO:
- case BTTV_MIROPRO:
- /* auto detect tuner for MIRO cards */
- btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
- break;
-
- case BTTV_HAUPPAUGE:
- case BTTV_HAUPPAUGE878:
- hauppauge_msp_reset(btv);
- hauppauge_eeprom(&(btv->i2c));
- if (btv->type == BTTV_HAUPPAUGE878) {
- /* all bt878 hauppauge boards use this ... */
- btv->pll.pll_ifreq=28636363;
- btv->pll.pll_crystal=BT848_IFORM_XT0;
- }
- break;
-
- case BTTV_CONFERENCETV:
- btv->tuner_type = 1;
- btv->pll.pll_ifreq=28636363;
- btv->pll.pll_crystal=BT848_IFORM_XT0;
- break;
-
- case BTTV_PIXVIEWPLAYTV:
- case BTTV_AVERMEDIA98:
- case BTTV_MODTEC_205:
- case BTTV_MAGICTVIEW061:
- btv->pll.pll_ifreq=28636363;
- btv->pll.pll_crystal=BT848_IFORM_XT0;
- break;
+ /* print which board we have found */
+ printk(KERN_INFO "bttv%d: model: ",btv->nr);
+
+ sprintf(btv->video_dev.name,"BT%d",btv->id);
+ if (btv->id==848 && btv->revision==0x12)
+ strcat(btv->video_dev.name,"A");
+ strcat(btv->video_dev.name,"(");
+ strcat(btv->video_dev.name, tvcards[btv->type].name);
+ strcat(btv->video_dev.name,")");
+ printk("%s\n",btv->video_dev.name);
+ /* board specific initialisations */
+ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
+ /* auto detect tuner for MIRO cards */
+ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+ }
+ if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
+ hauppauge_msp_reset(btv);
+ hauppauge_eeprom(btv);
+ }
+ if (btv->type == BTTV_MAXI) {
+ /* PHILIPS FI1216MK2 tuner (PAL/SECAM) */
+ btv->tuner_type=TUNER_PHILIPS_SECAM;
}
+
+ if (btv->type == BTTV_PXC200)
+ init_PXC200(btv);
+
+ if (btv->type == BTTV_CONFERENCETV)
+ btv->tuner_type = 1;
- if (btv->have_tuner && btv->tuner_type != -1)
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_TUNER,
- TUNER_SET_TYPE,&btv->tuner_type);
-
-
- if (I2CRead(&(btv->i2c), I2C_TDA9840) >=0)
- {
- btv->audio_chip = TDA9840;
- printk(KERN_INFO "bttv%d: audio chip: TDA9840\n", btv->nr);
- }
-
- if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
- {
- btv->audio_chip = TDA9850;
- printk(KERN_INFO "bttv%d: audio chip: TDA9850\n",btv->nr);
+ if (btv->type == BTTV_HAUPPAUGE878 ||
+ btv->type == BTTV_CONFERENCETV ||
+ btv->type == BTTV_PIXVIEWPLAYTV ||
+ btv->type == BTTV_AVERMEDIA98) {
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
}
- if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
- {
- btv->audio_chip = TDA8425;
- printk(KERN_INFO "bttv%d: audio chip: TDA8425\n",btv->nr);
- }
-
- switch(btv->audio_chip)
- {
- case TDA9850:
- init_tda9850(&(btv->i2c));
- break;
- case TDA9840:
- init_tda9840(&(btv->i2c));
- break;
- case TDA8425:
- init_tda8425(&(btv->i2c));
- break;
+ if (btv->tuner_type != -1)
+ call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
+
+ /* try to detect audio/fader chips */
+ if (tvcards[btv->type].msp34xx &&
+ I2CRead(btv, I2C_MSP3400) >=0) {
+ printk(KERN_INFO "bttv%d: audio chip: MSP34xx\n",i);
+ request_module("msp3400");
+ }
+
+ if (tvcards[btv->type].tda8425 &&
+ I2CRead(btv, I2C_TDA8425) >=0) {
+ printk(KERN_INFO "bttv%d: audio chip: TDA8425\n",i);
+ request_module("tda8425");
}
-
- if (I2CRead(&(btv->i2c), I2C_TEA6300) >=0)
- {
- if(btv->type==BTTV_AVEC_INTERCAP || btv->type==BTTV_CEI_RAFFLES)
- {
- printk(KERN_INFO "bttv%d: fader chip: TEA6320\n",btv->nr);
- btv->audio_chip = TEA6320;
- init_tea6320(&(btv->i2c));
- } else {
- printk(KERN_INFO "bttv%d: fader chip: TEA6300\n",btv->nr);
- btv->audio_chip = TEA6300;
- init_tea6300(&(btv->i2c));
- }
- } else
- printk(KERN_INFO "bttv%d: NO fader chip: TEA6300\n",btv->nr);
- printk(KERN_INFO "bttv%d: model: ",btv->nr);
+ if (tvcards[btv->type].tda9840 &&
+ I2CRead(btv, I2C_TDA9840) >=0) {
+ init_tda9840(btv);
+ printk(KERN_INFO "bttv%d: audio chip: TDA9840\n", i);
+ btv->audio_chip = TDA9840;
+ /* move this to a module too? */
+ init_tda9840(btv);
+ }
- sprintf(btv->video_dev.name,"BT%d",btv->id);
- switch (btv->type)
- {
- case BTTV_MIRO:
- case BTTV_MIROPRO:
- strcat(btv->video_dev.name,
- (btv->type == BTTV_MIRO) ? "(Miro)" : "(Miro pro)");
- break;
- case BTTV_HAUPPAUGE:
- strcat(btv->video_dev.name,"(Hauppauge old)");
- break;
- case BTTV_HAUPPAUGE878:
- strcat(btv->video_dev.name,"(Hauppauge new)");
- break;
- case BTTV_STB:
- strcat(btv->video_dev.name,"(STB)");
- break;
- case BTTV_INTEL:
- strcat(btv->video_dev.name,"(Intel)");
- break;
- case BTTV_DIAMOND:
- strcat(btv->video_dev.name,"(Diamond)");
- break;
- case BTTV_AVERMEDIA:
- strcat(btv->video_dev.name,"(AVerMedia)");
- break;
- case BTTV_MATRIX_VISION:
- strcat(btv->video_dev.name,"(MATRIX-Vision)");
- break;
- case BTTV_AVERMEDIA98:
- strcat(btv->video_dev.name,"(AVerMedia TVCapture 98)");
- break;
- case BTTV_VHX:
- strcpy(btv->video_dev.name,"(Aimslab-VHX)");
- break;
- case BTTV_WINVIEW_601:
- strcpy(btv->video_dev.name,"(Leadtek WinView 601)");
- break;
- case BTTV_AVEC_INTERCAP:
- strcpy(btv->video_dev.name,"(AVEC Intercapture)");
- break;
- case BTTV_CEI_RAFFLES:
- strcpy(btv->video_dev.name,"(CEI Raffles Card)");
- break;
- case BTTV_CONFERENCETV:
- strcpy(btv->video_dev.name,"(Image World ConferenceTV)");
- break;
- case BTTV_PHOEBE_TVMAS:
- strcpy(btv->video_dev.name,"(Phoebe TV Master)");
- break;
- case BTTV_MODTEC_205:
- strcpy(btv->video_dev.name,"(Modtec MM205)");
- break;
+ if (tvcards[btv->type].tda985x &&
+ I2CRead(btv, I2C_TDA9850) >=0) {
+ printk(KERN_INFO "bttv%d: audio chip: TDA985x\n",i);
+ request_module("tda9855");
}
- printk("%s\n",btv->video_dev.name);
- audio(btv, AUDIO_INTERN);
-}
+ if (tvcards[btv->type].tea63xx &&
+ I2CRead(btv, I2C_TEA6300)) {
+ printk(KERN_INFO "bttv%d: fader chip: TEA63xx\n",i);
+ request_module("tea6300");
+ }
+
+ if (tvcards[btv->type].tuner != -1) {
+ request_module("tuner");
+ }
+
+ audio(btv, AUDIO_MUTE);
+}
static void bt848_set_risc_jmps(struct bttv *btv)
@@ -2888,18 +2956,19 @@
int flags=btv->cap;
/* Sync to start of odd field */
- btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE);
- btv->risc_jmp[1]=0;
+ btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC
+ |BT848_FIFO_STATUS_VRE);
+ btv->risc_jmp[1]=cpu_to_le32(0);
/* Jump to odd vbi sub */
- btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0x5<<20));
+ btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20));
if (flags&8)
btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd));
else
btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));
/* Jump to odd sub */
- btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0x6<<20));
+ btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20));
if (flags&2)
btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_odd));
else
@@ -2907,8 +2976,9 @@
/* Sync to start of even field */
- btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO);
- btv->risc_jmp[7]=0;
+ btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC
+ |BT848_FIFO_STATUS_VRO);
+ btv->risc_jmp[7]=cpu_to_le32(0);
/* Jump to even vbi sub */
btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP);
@@ -2927,7 +2997,7 @@
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp));
- /* enable capturing */
+ /* enable cpaturing and DMA */
btaor(flags, ~0x0f, BT848_CAP_CTL);
if (flags&0x0f)
bt848_dma(btv, 3);
@@ -2935,13 +3005,52 @@
bt848_dma(btv, 0);
}
+static int
+init_video_dev(struct bttv *btv)
+{
+ int num = btv - bttvs;
+
+ memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
+ memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
+ memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
+
+ idcard(num);
+
+ if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
+ return -1;
+ if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0)
+ {
+ video_unregister_device(&btv->video_dev);
+ return -1;
+ }
+ if (radio[num])
+ {
+ if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0)
+ {
+ video_unregister_device(&btv->vbi_dev);
+ video_unregister_device(&btv->video_dev);
+ return -1;
+ }
+ }
+ return 1;
+}
+
static int init_bt848(int i)
{
struct bttv *btv = &bttvs[i];
btv->user=0;
-
- init_MUTEX(&btv->lock);
+ init_MUTEX(&btv->lock);
+
+#if 0
+ /* dump current state of the gpio registers before changing them,
+ * might help to make a new card work */
+ printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n",
+ i,
+ btread(BT848_GPIO_OUT_EN),
+ btread(BT848_GPIO_DATA),
+ btread(BT848_GPIO_REG_INP));
+#endif
/* reset the bt848 */
btwrite(0, BT848_SRESET);
@@ -2964,6 +3073,7 @@
btv->win.bpl=1024*btv->win.bpp;
btv->win.swidth=1024;
btv->win.sheight=768;
+ btv->win.vidadr=0;
btv->cap=0;
btv->gmode=0;
@@ -2977,17 +3087,10 @@
btv->grab=0;
btv->lastgrab=0;
btv->field=btv->last_field=0;
- /* cevans - prevents panic if initialization bails due to memory
- * alloc failures!
- */
- btv->video_dev.minor = -1;
- btv->vbi_dev.minor = -1;
- btv->radio_dev.minor = -1;
/* i2c */
- memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
- sprintf(btv->i2c.name,"bt848-%d",i);
- btv->i2c.data = btv;
+ btv->tuner_type=-1;
+ init_bttv_i2c(btv);
if (!(btv->risc_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
return -1;
@@ -3017,14 +3120,14 @@
bt848_set_winsize(btv);
/* btwrite(0, BT848_TDEC); */
- btwrite(0x10, BT848_COLOR_CTL);
+ btwrite(0x10, BT848_COLOR_CTL);
btwrite(0x00, BT848_CAP_CTL);
btwrite(0xac, BT848_GPIO_DMA_CTL);
/* select direct input */
btwrite(0x00, BT848_GPIO_REG_INP);
- btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_PAL_BDGHI,
+ btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_AUTO,
BT848_IFORM);
btwrite(0xd8, BT848_CONTRAST_LO);
@@ -3053,7 +3156,7 @@
btwrite(btv->triton1|
/*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
- BT848_INT_VSYNC|
+ (fieldnr ? BT848_INT_VSYNC : 0)|
BT848_INT_SCERR|
BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
BT848_INT_FMTCHG|BT848_INT_HLOCK,
@@ -3065,30 +3168,7 @@
/*
* Now add the template and register the device unit.
*/
-
- memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
- memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
- memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
-
- idcard(i);
-
- if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
- return -1;
- if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0)
- {
- video_unregister_device(&btv->video_dev);
- return -1;
- }
- if (radio[i])
- {
- if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0)
- {
- video_unregister_device(&btv->vbi_dev);
- video_unregister_device(&btv->video_dev);
- return -1;
- }
- }
- i2c_register_bus(&btv->i2c);
+ init_video_dev(btv);
return 0;
}
@@ -3110,7 +3190,8 @@
if (!astat)
return;
btwrite(astat,BT848_INT_STAT);
- IDEBUG(printk ("bttv%d: astat %08x stat %08x\n", btv->nr, astat, stat));
+ IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat));
+ IDEBUG(printk ("bttv%d: stat %08x\n", btv->nr, stat));
/* get device status bits */
dstat=btread(BT848_DSTATUS);
@@ -3133,7 +3214,7 @@
if (astat&BT848_INT_SCERR) {
IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
bt848_dma(btv, 0);
- bt848_dma(btv, 3);
+ bt848_dma(btv, 1);
wake_up_interruptible(&btv->vbiq);
wake_up_interruptible(&btv->capq);
@@ -3154,7 +3235,7 @@
/* captured full frame */
if (stat&(2<<28))
{
- wake_up_interruptible(&btv->capq);
+ /*wake_up_interruptible(&btv->capq);*/
btv->last_field=btv->field;
btv->grab++;
btv->frame_stat[btv->grf] = GBUFFER_DONE;
@@ -3170,14 +3251,14 @@
btv->risc_jmp[11]=cpu_to_le32(btv->gre);
bt848_set_geo(btv, btv->gwidth,
btv->gheight,
- btv->gfmt, 0);
+ btv->gfmt,0);
} else {
bt848_set_risc_jmps(btv);
btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
bt848_set_geo(btv, btv->win.width,
btv->win.height,
- btv->win.color_fmt, 0);
+ btv->win.color_fmt,0);
}
wake_up_interruptible(&btv->capq);
break;
@@ -3188,7 +3269,7 @@
btv->risc_jmp[11]=cpu_to_le32(btv->gre);
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
bt848_set_geo(btv, btv->gwidth, btv->gheight,
- btv->gfmt, 0);
+ btv->gfmt,0);
}
}
if (astat&BT848_INT_OCERR)
@@ -3255,6 +3336,9 @@
int result;
unsigned char command;
struct bttv *btv;
+#if defined(__powerpc__)
+ unsigned int cmd;
+#endif
btv=&bttvs[bttv_num];
btv->dev=dev;
@@ -3278,6 +3362,7 @@
else
btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
+ btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
bttv_num,btv->id, btv->revision);
@@ -3285,6 +3370,14 @@
printk("irq: %d, ",btv->irq);
printk("memory: 0x%lx.\n", btv->bt848_adr);
+#if defined(__powerpc__)
+ /* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
+ /* response on cards with no firmware is not enabled by OF */
+ pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+ cmd = (cmd | PCI_COMMAND_MEMORY );
+ pci_write_config_dword(dev, PCI_COMMAND, cmd);
+#endif
+
btv->pll.pll_crystal = 0;
btv->pll.pll_ifreq = 0;
btv->pll.pll_ofreq = 0;
@@ -3306,8 +3399,12 @@
break;
}
}
-
- btv->bt848_mem = ioremap(btv->bt848_adr, 0x1000);
+
+#ifdef __sparc__
+ btv->bt848_mem=(unsigned char *)btv->bt848_adr;
+#else
+ btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+#endif
/* clear interrupt mask */
btwrite(0, BT848_INT_MASK);
@@ -3393,10 +3490,9 @@
btwrite(0x0, BT848_GPIO_OUT_EN);
/* unregister i2c_bus */
- i2c_unregister_bus((&btv->i2c));
+ i2c_bit_del_bus(&btv->i2c_adap);
/* disable PCI bus-mastering */
-
pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
/* Should this be &=~ ?? */
command&=~PCI_COMMAND_MASTER;
@@ -3436,19 +3532,15 @@
}
#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-
int init_module(void)
-{
#else
int init_bttv_cards(struct video_init *unused)
-{
#endif
+{
int i;
handle_chipset();
- if (find_bt848()<0)
+ if (find_bt848()<=0)
return -EIO;
/* initialize Bt848s */
@@ -3465,7 +3557,6 @@
}
-
#ifdef MODULE
void cleanup_module(void)
@@ -3477,14 +3568,6 @@
/*
* Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
+ * c-basic-offset: 8
* End:
*/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)