patch-2.3.50 linux/drivers/char/bttv.c
Next file: linux/drivers/char/bttv.h
Previous file: linux/drivers/char/agp/agpgart_be.c
Back to the patch index
Back to the overall index
- Lines: 2052
- Date:
Mon Mar 6 15:32:30 2000
- Orig file:
v2.3.49/linux/drivers/char/bttv.c
- Orig date:
Thu Feb 10 17:11:07 2000
diff -u --recursive --new-file v2.3.49/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
@@ -3,7 +3,7 @@
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>
+ (c) 1999,2000 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
@@ -20,6 +20,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/config.h>
+#include <linux/version.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -40,27 +42,28 @@
#include <linux/types.h>
#include <linux/wrapper.h>
#include <linux/interrupt.h>
-#include <linux/version.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
-
+#ifdef LOCK_I2C_BUS
+# error INSTALL ERROR
+# error gcc uses the old, obsolete i2c.h include file. Please install the \
+ new i2c stack. Please install it by patching the kernel, otherwise \
+ gcc will not find the new header files.
+#endif
#include "bttv.h"
#include "tuner.h"
#define DEBUG(x) /* Debug driver */
-#define IDEBUG(x) /* Debug interrupt handler */
+#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 void bt848_set_risc_jmps(struct bttv *btv, int state);
static int bttv_num; /* number of Bt848s in use */
static struct bttv bttvs[BTTV_MAX];
@@ -74,7 +77,20 @@
MODULE_PARM(pll,"1-4i");
MODULE_PARM(bigendian,"i");
MODULE_PARM(fieldnr,"i");
+MODULE_PARM(verbose,"i");
+MODULE_PARM(debug,"i");
MODULE_PARM(autoload,"i");
+MODULE_PARM(gbuffers,"i");
+MODULE_PARM(gbufsize,"i");
+
+EXPORT_SYMBOL(bttv_get_id);
+EXPORT_SYMBOL(bttv_gpio_enable);
+EXPORT_SYMBOL(bttv_read_gpio);
+EXPORT_SYMBOL(bttv_write_gpio);
+EXPORT_SYMBOL(bttv_get_gpio_queue);
+
+MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards");
+MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
#if defined(__sparc__) || defined(__powerpc__)
static unsigned int bigendian=1;
@@ -87,7 +103,15 @@
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 unsigned int verbose = 1;
+static unsigned int debug = 0;
+static unsigned int gbuffers = 2;
+static unsigned int gbufsize = BTTV_MAX_FBUF;
+#ifdef MODULE
static unsigned int autoload = 1;
+#else
+static unsigned int autoload = 0;
+#endif
#define I2C_TIMING (0x7<<4)
@@ -100,6 +124,101 @@
#define BURSTOFFSET 76
+/* ----------------------------------------------------------------------- */
+/* Exported functions - for other modules which want to access the */
+/* gpio ports (IR for example) */
+/* see bttv.h for comments */
+
+int bttv_get_id(unsigned int card)
+{
+ if (card >= bttv_num) {
+ return -1;
+ }
+
+ return bttvs[card].type;
+}
+
+int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
+{
+ struct bttv *btv;
+
+ if (card >= bttv_num) {
+ return -EINVAL;
+ }
+
+ btv = &bttvs[card];
+ down(&btv->lock);
+ btaor(data, ~mask, BT848_GPIO_OUT_EN);
+ up(&btv->lock);
+
+ return 0;
+}
+
+int bttv_read_gpio(unsigned int card, unsigned long *data)
+{
+ struct bttv *btv;
+
+ if (card >= bttv_num) {
+ return -EINVAL;
+ }
+
+ btv = &bttvs[card];
+
+ if(btv->shutdown) {
+ return -ENODEV;
+ }
+
+ down(&btv->lock);
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+ because we set direct input on init */
+
+ *data = btread(BT848_GPIO_DATA);
+
+ up(&btv->lock);
+
+ return 0;
+}
+
+int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
+{
+ struct bttv *btv;
+
+ if (card >= bttv_num) {
+ return -EINVAL;
+ }
+
+ btv = &bttvs[card];
+
+ down(&btv->lock);
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+ because direct input is set on init */
+
+ btaor(data & mask, ~mask, BT848_GPIO_DATA);
+
+ up(&btv->lock);
+
+ return 0;
+}
+
+WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card)
+{
+ struct bttv *btv;
+
+ if (card >= bttv_num) {
+ return NULL;
+ }
+
+ btv = &bttvs[card];
+
+ if (bttvs[card].shutdown) {
+ return NULL;
+ }
+
+ return &btv->gpioq;
+}
+
/*******************************/
/* Memory management functions */
/*******************************/
@@ -176,11 +295,11 @@
return ret;
}
-static void * rvmalloc(unsigned long size)
+static void * rvmalloc(signed long size)
{
void * mem;
unsigned long adr, page;
-
+
mem=vmalloc(size);
if (mem)
{
@@ -197,7 +316,7 @@
return mem;
}
-static void rvfree(void * mem, unsigned long size)
+static void rvfree(void * mem, signed long size)
{
unsigned long adr, page;
@@ -227,7 +346,7 @@
static int fbuffer_alloc(struct bttv *btv)
{
if(!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF);
+ btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize);
else
printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n",
btv->nr);
@@ -320,7 +439,8 @@
}
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);
+ if (verbose)
+ printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name);
return 0;
}
@@ -328,8 +448,9 @@
{
struct bttv *btv = (struct bttv*)client->adapter->data;
int i;
-
- printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name);
+
+ if (verbose)
+ 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) {
@@ -395,19 +516,20 @@
{
unsigned char buffer = 0;
- if (NULL != probe_for)
+ if (verbose && NULL != probe_for)
printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ",
btv->nr,probe_for,addr);
btv->i2c_client.addr = addr >> 1;
if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
- if (NULL != probe_for)
- printk("not found\n");
- else
+ if (NULL != probe_for) {
+ if (verbose)
+ printk("not found\n");
+ } else
printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n",
btv->nr,addr);
return -1;
}
- if (NULL != probe_for)
+ if (verbose && NULL != probe_for)
printk("found\n");
return buffer;
}
@@ -481,31 +603,70 @@
{ TUNER_PHILIPS_PAL, "Philips FM1216" },
{ TUNER_ABSENT, "Philips FM1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FM1236" },
+ { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
+ { TUNER_ABSENT, "Philips FM1256" },
+ { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
+ { TUNER_ABSENT, "Samsung TCPN9082D" },
+ { TUNER_ABSENT, "Samsung TCPM9092P" },
+ { TUNER_TEMIC_PAL, "Temic 4006FH5" },
+ { TUNER_ABSENT, "Samsung TCPN9085D" },
+ { TUNER_ABSENT, "Samsung TCPB9085P" },
+ { TUNER_ABSENT, "Samsung TCPL9091P" },
+ { TUNER_ABSENT, "Temic 4039FR5" },
+ { TUNER_ABSENT, "Philips FQ1216 ME" },
+ { TUNER_TEMIC_PAL_I, "Temic 4066FY5" },
+ { TUNER_ABSENT, "Philips TD1536" },
+ { TUNER_ABSENT, "Philips TD1536D" },
+ { TUNER_ABSENT, "Philips FMR1236" },
+ { TUNER_ABSENT, "Philips FI1256MP" },
+ { TUNER_ABSENT, "Samsung TCPQ9091P" },
+ { TUNER_ABSENT, "Temic 4006FN5" },
+ { TUNER_ABSENT, "Temic 4009FR5" },
+ { TUNER_ABSENT, "Temic 4046FM5" },
};
static void
hauppauge_eeprom(struct bttv *btv)
{
- readee(btv, eeprom_data, 0xa0);
if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
{
btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
- printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr,
- hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
+ if (verbose)
+ printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr,
+ hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
}
}
static void
-hauppauge_msp_reset(struct bttv *btv)
+hauppauge_boot_msp34xx(struct bttv *btv)
{
- /* Reset the MSP on some Hauppauge cards */
+ int i;
+
+ /* reset/enable the MSP on some Hauppauge cards */
/* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
- /* Can this hurt cards without one? What about Miros with MSP? */
btaor(32, ~32, BT848_GPIO_OUT_EN);
btaor(0, ~32, BT848_GPIO_DATA);
udelay(2500);
btaor(32, ~32, BT848_GPIO_DATA);
- /* btaor(0, ~32, BT848_GPIO_OUT_EN); */
+
+ if (verbose)
+ printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr);
+
+ /* look if the msp3400 driver is already registered */
+ for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+ if (btv->i2c_clients[i] != NULL &&
+ btv->i2c_clients[i]->driver->id == I2C_DRIVERID_MSP3400) {
+ return;
+ }
+ }
+
+ /* if not: look for the chip ... */
+ if (I2CRead(btv, I2C_MSP3400, "MSP34xx")) {
+ /* ... if found re-register to trigger a i2c bus rescan, */
+ /* this time with the msp34xx chip activated */
+ i2c_bit_del_bus(&btv->i2c_adap);
+ i2c_bit_add_bus(&btv->i2c_adap);
+ }
}
@@ -528,7 +689,15 @@
/* GPIO inputs are pulled up, so no need to drive
* reset pin any longer */
btwrite(0,BT848_GPIO_OUT_EN);
-
+
+ /* we could/should try and reset/control the AD pots? but
+ right now we simply turned off the crushing. Without
+ this the AGC drifts drifts
+ remember the EN is reverse logic -->
+ setting BT848_ADC_AGC_EN disable the AGC
+ tboult@eecs.lehigh.edu
+ */
+ btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
/* Initialise MAX517 DAC */
printk(KERN_INFO "Setting DAC reference voltage level ...\n");
@@ -555,19 +724,34 @@
int id;
char *name;
} vendors[] = {
- { 0x0070, "Hauppauge" },
- { 0x144f, "Askey" },
+ { 0x0001, "ATI Technologies Inc" },
+ { 0x10b4, "STB Systems Inc" },
+ { 0x13eb, "Hauppauge Computer Works Inc" },
+ { 0x1461, "Avermedia" },
+ { 0x1850, "Chronos" },
+ { 0x1852, "Typhoon" },
+ { 0x3000, "Askey" },
+ { 0x3002, "Askey" },
+ { 0x6606, "Leadtek" },
{ -1, NULL }
};
static struct CARD {
- int id;
int vid;
+ int id;
int cardnr;
char *name;
} cards[] = {
- { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV Theater" },
- { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" },
+ { 0x0001, 0x1002, BTTV_HAUPPAUGE878, "TV Wonder" },
+ { 0x10b4, 0x2636, BTTV_HAUPPAUGE878, "???" },
+ { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV" },
+ { 0x1461, 0x0002, BTTV_AVERMEDIA98, "TVCapture 98" },
+ { 0x1850, 0x1851, BTTV_CHRONOS_VS2, "Video Shuttle II" },
+ { 0x1852, 0x1852, BTTV_TYPHOON_TVIEW, "TView TV/FM Tuner" },
+ { 0x3000, 0x14ff, BTTV_MAGICTVIEW061, "TView 99" },
+ { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" },
+ { 0x3002, 0x14ff, BTTV_PHOEBE_TVMAS, "TV Master" },
+ { 0x6606, 0x217d, BTTV_WINFAST2000, "WinFast TV 2000" },
{ -1, -1, -1, NULL }
};
@@ -594,7 +778,7 @@
static struct tvcard tvcards[] =
{
/* 0x00 */
- { "unknown",
+ { " *** UNKNOWN *** ",
3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0,
1,1,1,1,0 },
{ "MIRO PCTV",
@@ -614,7 +798,7 @@
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,
+ 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,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,
@@ -713,16 +897,32 @@
{ "Terratec TerraTValue",
3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0,
1,1,1,1,0 },
+ { "Leadtek WinFast 2000",
+ 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0},
+ { 0x621000,0x620100,0x621100,0x620000,0xE210000,0x620000},0,
+ 1,1,1,1,1 },
+ { "Chronos Video Shuttle II",
+ 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0,
+ 1,1,1,1,0 },
+
+ { "Typhoon TView TV/FM Tuner",
+ 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0,
+ 1,1,1,1,0 },
+ { "PixelView PlayTV pro",
+ 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 },
+ { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 }
};
#define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard))
static void
-dump_eeprom(struct bttv *btv, int addr)
+dump_eeprom(struct bttv *btv,int addr)
{
- int i,id1,id2,n1,n2;
+ int i;
+ if (verbose < 2)
+ return;
+ /* for debugging: dump eeprom to syslog */
printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr);
- readee(btv, eeprom_data,addr);
for (i = 0; i < 256;) {
printk(KERN_DEBUG " %02x:",i);
do {
@@ -730,35 +930,47 @@
} while (i % 16);
printk("\n");
}
- id1 = (eeprom_data[252] << 8) | (eeprom_data[253]);
- id2 = (eeprom_data[254] << 8) | (eeprom_data[255]);
- if (id1 != 0 && id1 != 0xffff &&
- id2 != 0 && id2 != 0xffff) {
- n1 = -1;
- n2 = -1;
- for (i = 0; vendors[i].id != -1; i++)
- if (vendors[i].id == id2)
- n2 = i;
- for (i = 0; cards[i].id != -1; i++)
- if (cards[i].id == id1 &&
- cards[i].vid == id2)
- n1 = i;
- if (n1 != -1 && n2 != -1) {
- printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n",
- cards[n1].name,id1,vendors[n2].name,id2);
- printk(KERN_INFO " => card=%d (%s)\n",
- cards[n1].cardnr,tvcards[cards[n1].cardnr].name);
-#if 1
- /* not yet, but that's the plan for autodetect... */
- btv->type = cards[n1].cardnr;
-#endif
- } else {
- printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n",
- (n1 != -1) ? cards[n1].name : "unknown", id1,
- (n2 != -1) ? vendors[n2].name : "unknown", id2);
- printk(KERN_INFO " please mail card type, id + vendor to ");
- printk(" kraxel@goldbach.in-berlin.de\n");
- }
+}
+
+static int
+idcard_eeprom(struct bttv *btv)
+{
+ int i,id1,id2,n1,n2;
+
+ id1 = (eeprom_data[254] << 8) | (eeprom_data[255]);
+ id2 = (eeprom_data[252] << 8) | (eeprom_data[253]);
+ if (id1 == 0 || id1 == 0xffff ||
+ id2 == 0 || id2 == 0xffff)
+ return -1;
+
+ /* look for the card */
+ n1 = -1; n2 = -1;
+ for (i = 0; vendors[i].id != -1; i++)
+ if (vendors[i].id == id2)
+ n2 = i;
+ for (i = 0; cards[i].id != -1; i++)
+ if (cards[i].id == id1 &&
+ cards[i].vid == id2)
+ n1 = i;
+
+ if (n1 != -1 && n2 != -1) {
+ /* found it */
+ printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n",
+ btv->nr,cards[n1].name,id1,vendors[n2].name,id2);
+ if (verbose)
+ printk(KERN_INFO "bttv%d: => card=%d (%s)\n",
+ btv->nr,cards[n1].cardnr,
+ tvcards[cards[n1].cardnr].name);
+ return cards[n1].cardnr;
+ } else {
+ /* 404 */
+ printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n",
+ btv->nr, "unknown", id1,
+ (n2 != -1) ? vendors[n2].name : "unknown", id2);
+ printk(KERN_INFO "please mail id + vendor, board name and "
+ "the correct card= insmod option to "
+ "kraxel@goldbach.in-berlin.de\n");
+ return -1;
}
}
@@ -810,21 +1022,6 @@
}
-static void bt848_cap(struct bttv *btv, uint state)
-{
- if (state)
- {
- btv->cap|=3;
- bt848_set_risc_jmps(btv);
- }
- else
- {
- btv->cap&=~3;
- bt848_set_risc_jmps(btv);
- }
-}
-
-
/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/
/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
@@ -885,9 +1082,10 @@
/* printk("bttv%d: PLL: no change required\n",btv->nr); */
return 1;
}
-
- printk("bttv%d: PLL: %d => %d ... ",btv->nr,
- btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+
+ if (verbose)
+ printk("bttv%d: PLL: %d => %d ... ",btv->nr,
+ btv->pll.pll_ifreq, btv->pll.pll_ofreq);
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
@@ -907,13 +1105,15 @@
{
btwrite(0x08,BT848_TGCTRL);
btv->pll.pll_current = btv->pll.pll_ofreq;
- printk("ok\n");
+ if (verbose)
+ printk("ok\n");
return 1;
}
mdelay(10);
}
btv->pll.pll_current = 0;
- printk("oops\n");
+ if (verbose)
+ printk("oops\n");
return -1;
}
@@ -1010,10 +1210,9 @@
unsigned int *po=(unsigned int *) btv->vbi_odd;
unsigned int *pe=(unsigned int *) btv->vbi_even;
- DEBUG(printk(KERN_DEBUG "vbiodd: 0x%lx\n",(long)btv->vbi_odd));
- DEBUG(printk(KERN_DEBUG "vbievn: 0x%lx\n",(long)btv->vbi_even));
- DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po));
- DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe));
+ if (debug)
+ printk("bttv%d: vbi: po=%08lx pe=%08lx\n",
+ btv->nr,virt_to_bus(po), virt_to_bus(pe));
*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
for (i=0; i<16; i++)
@@ -1036,11 +1235,11 @@
DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe));
}
-int fmtbppx2[16] = {
+static int fmtbppx2[16] = {
8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0
};
-int palette2fmt[] = {
+static int palette2fmt[] = {
0,
BT848_COLOR_FMT_Y8,
BT848_COLOR_FMT_RGB8,
@@ -1082,7 +1281,7 @@
*(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
*(ro++)=cpu_to_le32(kvirt_to_bus(vadr));
*(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
- *(re++)=cpu_to_le32(kvirt_to_bus(vadr+BTTV_MAX_FBUF/2));
+ *(re++)=cpu_to_le32(kvirt_to_bus(vadr+gbufsize/2));
vadr+=bpl;
}
@@ -1108,6 +1307,9 @@
unsigned long vadr=(unsigned long) vbuf;
int shift, csize;
+ if (debug)
+ printk("bttv%d: prisc: ro=%08lx re=%08lx\n",
+ btv->nr,virt_to_bus(ro), virt_to_bus(re));
switch(fmt)
{
@@ -1140,7 +1342,7 @@
}
cbadr=vadr+(width*height);
cradr=cbadr+csize;
- inter = (height>btv->win.cropheight/2) ? 1 : 0;
+ inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
*(ro++)=0;
@@ -1158,7 +1360,7 @@
if (inter)
rp= (line&1) ? &re : &ro;
else
- rp= (line>=height) ? &re : &ro;
+ rp= (line>=height) ? &ro : &re;
if(line&lmask)
@@ -1222,9 +1424,12 @@
return make_rawrisctab(btv, ro, re, vbuf);
if (palette>=VIDEO_PALETTE_PLANAR)
return make_prisctab(btv, ro, re, vbuf, width, height, palette);
-
-
- inter = (height>btv->win.cropheight/2) ? 1 : 0;
+
+ if (debug)
+ printk("bttv%d: vrisc: ro=%08lx re=%08lx\n",
+ btv->nr,virt_to_bus(ro), virt_to_bus(re));
+
+ inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;
bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
@@ -1237,7 +1442,7 @@
if (inter)
rp= (line&1) ? &re : &ro;
else
- rp= (line>=height) ? &re : &ro;
+ rp= (line>=height) ? &ro : &re;
bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
if (bpl<=bl)
@@ -1335,32 +1540,31 @@
static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
{
- int i, line, x, y, bpl, width, height, inter;
+ int i, line, x, y, bpl, width, height, inter, maxw;
unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len;
unsigned long adr;
- unsigned char *clipmap, cbit, lastbit, outofmem;
+ unsigned char *clipmap, *clipline, 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;
- }
+ /* take care: bpp != btv->win.bpp is allowed here */
+ bpp = fmtbppx2[btv->win.color_fmt&0xf]/2;
+ bpl=btv->win.bpl;
+ adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl;
inter=(btv->win.interlace&1)^1;
width=btv->win.width;
height=btv->win.height;
+ if (debug)
+ printk("bttv%d: make_clip: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
+ btv->nr,btv->picture.palette,width,height,bpl,bpp);
if(width > 1023)
width = 1023; /* sanity check */
if(height > 625)
height = 625; /* sanity check */
- ro=btv->risc_odd;
- re=btv->risc_even;
+ ro=btv->risc_scr_odd;
+ re=btv->risc_scr_even;
+
+ if (debug)
+ printk("bttv%d: clip: ro=%08lx re=%08lx\n",
+ btv->nr,virt_to_bus(ro), virt_to_bus(re));
if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {
/* can't clip, don't generate any risc code */
@@ -1380,16 +1584,15 @@
/* clip against viewing window AND screen
so we do not have to rely on the user program
*/
- 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));
- }
+ maxw = (bpl - btv->win.x * btv->win.bpp) / bpp;
+ clip_draw_rectangle(clipmap, (width > maxw) ? maxw : 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++)=cpu_to_le32(0);
@@ -1401,12 +1604,30 @@
{
y = line>>inter;
rp= (line&1) ? &re : &ro;
- lastbit=(clipmap[y<<7]&1);
- for(x=dx=1,sx=0; x<=width && !outofmem; x++) {
- cbit = (clipmap[(y<<7)+(x>>3)] & (1<<(x&7)));
- if (x < width && !lastbit == !cbit)
+ clipline = clipmap + (y<<7); /* running pointers ... */
+ lastbit = *clipline & 1;
+ for(x=dx=0,sx=0; x<=width && !outofmem;) {
+ if (0 == (x&7)) {
+ /* check bytes not bits if we can ... */
+ if (lastbit) {
+ while (0xff==*clipline && x<width-8) {
+ x += 8;
+ dx += 8;
+ clipline++;
+ }
+ } else {
+ while (0x00==*clipline && x<width-8) {
+ x += 8;
+ dx += 8;
+ clipline++;
+ }
+ }
+ }
+ cbit = *clipline & (1<<(x&7));
+ if (x < width && !lastbit == !cbit) {
dx++;
- else { /* generate the dma controller code */
+ } else {
+ /* generate the dma controller code */
len = dx * bpp;
flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
flags |= ((!sx) ? BT848_RISC_SOL : 0);
@@ -1420,11 +1641,14 @@
lastbit=cbit;
sx += dx;
dx = 1;
- if (ro - btv->risc_odd > RISCMEM_LEN/2 - 16)
+ if (ro - btv->risc_scr_odd>RISCMEM_LEN/2 - 16)
outofmem++;
- if (re - btv->risc_even > RISCMEM_LEN/2 - 16)
+ if (re - btv->risc_scr_even>RISCMEM_LEN/2 - 16)
outofmem++;
}
+ x++;
+ if (0 == (x&7))
+ clipline++;
}
if ((!inter)||(line&1))
adr+=bpl;
@@ -1475,29 +1699,25 @@
}
-static void bt848_set_geo(struct bttv *btv, u16 width, u16 height,
- u16 fmt, int no_irq_context)
+static void bt848_set_geo(struct bttv *btv,
+ int no_irq_context)
{
u16 vscale, hscale;
u32 xsf, sr;
- u16 hdelay, vdelay;
- u16 hactive, vactive;
+ u16 ewidth, eheight, owidth, oheight;
+ u16 format, bswap;
+ u16 hdelay;
+ u16 hactive;
u16 inter;
u8 crop, vtc;
struct tvnorm *tvn;
unsigned long flags;
- if (!width || !height)
- return;
-
save_flags(flags);
cli();
tvn=&tvnorms[btv->win.norm];
- btv->win.cropheight=tvn->sheight;
- btv->win.cropwidth=tvn->swidth;
-
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
@@ -1508,59 +1728,84 @@
if (no_irq_context)
set_pll(btv);
- btwrite(fmt, BT848_COLOR_FMT);
- 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 (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;
/* Some people say interpolation looks bad ... */
/* vtc = (hactive < 193) ? 2 : ((hactive < 385) ? 1 : 0); */
- btv->win.interlace = (height>btv->win.cropheight/2) ? 1 : 0;
- inter=(btv->win.interlace&1)^1;
- vdelay=btv->win.cropy+tvn->vdelay;
+ btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0;
- xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth;
- hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
-
- hdelay=tvn->hdelayx1+btv->win.cropx;
- hdelay=(hdelay*hactive)/btv->win.cropwidth;
- hdelay&=0x3fe;
+ if (0 == btv->risc_cap_odd &&
+ 0 == btv->risc_cap_even) {
+ /* overlay only */
+ owidth = btv->win.width;
+ oheight = btv->win.height;
+ ewidth = btv->win.width;
+ eheight = btv->win.height;
+ format = btv->win.color_fmt;
+ bswap = btv->fb_color_ctl;
+ } else if (-1 != btv->gq_grab &&
+ 0 == btv->risc_cap_odd &&
+ !btv->win.interlace &&
+ btv->scr_on) {
+ /* odd field -> overlay, even field -> capture */
+ owidth = btv->win.width;
+ oheight = btv->win.height;
+ ewidth = btv->gbuf[btv->gq_grab].width;
+ eheight = btv->gbuf[btv->gq_grab].height;
+ format = (btv->win.color_fmt & 0xf0) |
+ (btv->gbuf[btv->gq_grab].fmt & 0x0f);
+ bswap = btv->fb_color_ctl & 0x0a;
+ } else {
+ /* capture only */
+ owidth = btv->gbuf[btv->gq_grab].width;
+ oheight = btv->gbuf[btv->gq_grab].height;
+ ewidth = btv->gbuf[btv->gq_grab].width;
+ eheight = btv->gbuf[btv->gq_grab].height;
+ format = btv->gbuf[btv->gq_grab].fmt;
+ bswap = 0;
+ inter = (btv->win.height>tvn->sheight/2) ? 0 : 1;
+ }
- sr=((btv->win.cropheight>>inter)*512)/height-512;
+ inter = (oheight>tvn->sheight/2) ? 0 : 1;
+
+ /* odd field */
+ hactive=owidth;
+ xsf = (hactive*tvn->scaledtwidth)/tvn->swidth;
+ hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
+ hdelay = tvn->hdelayx1;
+ hdelay = (hdelay*hactive)/tvn->swidth;
+ hdelay &= 0x3fe;
+ sr=((tvn->sheight>>inter)*512)/oheight-512;
vscale=(0x10000UL-sr)&0x1fff;
- vactive=btv->win.cropheight;
crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)|
- ((vactive>>4)&0x30)|((vdelay>>2)&0xc0);
- vscale|= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0;
+ ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0);
+ vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0;
+ bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, tvn->sheight,
+ hdelay, tvn->vdelay, crop);
+
+ /* even field */
+ hactive=ewidth;
+ xsf = (hactive*tvn->scaledtwidth)/tvn->swidth;
+ hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
+ hdelay = tvn->hdelayx1;
+ hdelay = (hdelay*hactive)/tvn->swidth;
+ hdelay &= 0x3fe;
+ sr=((tvn->sheight>>inter)*512)/eheight-512;
+ vscale=(0x10000UL-sr)&0x1fff;
+ crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)|
+ ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0);
+ vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0;
+ bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, tvn->sheight,
+ hdelay, tvn->vdelay, crop);
- 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);
+ btwrite(format, BT848_COLOR_FMT);
+ btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
restore_flags(flags);
}
-int bpp2fmt[4] = {
+static int bpp2fmt[4] = {
BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16,
BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32
};
@@ -1569,14 +1814,31 @@
{
unsigned short format;
- if (btv->win.use_yuv) {
- /* yuv-to-offscreen */
- format = BT848_COLOR_FMT_YUY2;
+ if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) {
+ /* format set by VIDIOCSPICT */
+ format = palette2fmt[btv->picture.palette];
} else {
+ /* use default for the given color depth */
format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
bpp2fmt[(btv->win.bpp-1)&3];
}
btv->win.color_fmt = format;
+ if (bigendian &&
+ format == BT848_COLOR_FMT_RGB32) {
+ btv->fb_color_ctl =
+ BT848_COLOR_CTL_WSWAP_ODD |
+ BT848_COLOR_CTL_WSWAP_EVEN |
+ BT848_COLOR_CTL_BSWAP_ODD |
+ BT848_COLOR_CTL_BSWAP_EVEN;
+ } else if (bigendian &&
+ (format == BT848_COLOR_FMT_RGB16 ||
+ format == BT848_COLOR_FMT_RGB15)) {
+ btv->fb_color_ctl =
+ BT848_COLOR_CTL_BSWAP_ODD |
+ BT848_COLOR_CTL_BSWAP_EVEN;
+ } else {
+ btv->fb_color_ctl = 0;
+ }
/* RGB8 seems to be a 9x5x5 GRB color cube starting at
* color 16. Why the h... can't they even mention this in the
@@ -1590,38 +1852,8 @@
else
btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
- 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 */
- AUDIO(AUDC_SWITCH_MUTE,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);
- }
+ bt848_set_geo(btv,1);
}
-#endif
/*
@@ -1639,30 +1871,19 @@
if(fbuffer_alloc(btv))
return -ENOBUFS;
}
- if(btv->grabbing >= MAX_GBUFFERS)
- return -ENOBUFS;
-
- /*
- * No grabbing past the end of the buffer!
- */
-
- if(mp->frame>(MAX_GBUFFERS-1) || mp->frame <0)
+
+ if(mp->frame >= gbuffers || mp->frame < 0)
return -EINVAL;
+ if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED)
+ return -EBUSY;
if(mp->height <0 || mp->width <0)
return -EINVAL;
-
-/* This doesn´t work like this for NTSC anyway.
- So, better check the total image size ...
-*/
-/*
- if(mp->height>576 || mp->width>768+BURSTOFFSET)
- return -EINVAL;
-*/
if (mp->format >= PALETTEFMT_MAX)
return -EINVAL;
+
if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
- > BTTV_MAX_FBUF)
+ > gbufsize)
return -EINVAL;
if(-1 == palette2fmt[mp->format])
return -EINVAL;
@@ -1677,41 +1898,40 @@
* Ok load up the BT848
*/
- vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame);
-/* if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
- return -EAGAIN;*/
- ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
+ vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame);
+ ro=btv->gbuf[mp->frame].risc;
re=ro+2048;
make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
- /* bt848_set_risc_jmps(btv); */
+
+ if (debug)
+ printk("bttv%d: cap vgrab: queue %d\n",btv->nr,mp->frame);
cli();
- btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
- if (btv->grabbing) {
- btv->gfmt_next=palette2fmt[mp->format];
- btv->gwidth_next=mp->width;
- btv->gheight_next=mp->height;
- btv->gro_next=virt_to_bus(ro);
- btv->gre_next=virt_to_bus(re);
- btv->grf_next=mp->frame;
- } else {
- btv->gfmt=palette2fmt[mp->format];
- btv->gwidth=mp->width;
- btv->gheight=mp->height;
- btv->gro=virt_to_bus(ro);
- btv->gre=virt_to_bus(re);
- btv->grf=mp->frame;
- }
- if (!(btv->grabbing++)) {
+ btv->gbuf[mp->frame].stat = GBUFFER_GRABBING;
+ btv->gbuf[mp->frame].fmt = palette2fmt[mp->format];
+ btv->gbuf[mp->frame].width = mp->width;
+ btv->gbuf[mp->frame].height = mp->height;
+ btv->gbuf[mp->frame].ro = virt_to_bus(ro);
+ btv->gbuf[mp->frame].re = virt_to_bus(re);
+
+#if 1
+ if (mp->height <= tvnorms[btv->win.norm].sheight/2 &&
+ mp->format != VIDEO_PALETTE_RAW)
+ btv->gbuf[mp->frame].ro = 0;
+#endif
+
+ if (btv->gq_in == btv->gq_out) {
if(mp->format>=VIDEO_PALETTE_COMPONENT) {
btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
}
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
}
+ btv->gqueue[btv->gq_in++] = mp->frame;
+ btv->gq_in = btv->gq_in % MAX_GBUFFERS;
+
sti();
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
- /* interruptible_sleep_on(&btv->capq); */
return 0;
}
@@ -1787,16 +2007,16 @@
if (btv->user)
goto out_unlock;
- btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF);
+ btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize);
ret = -ENOMEM;
if (!btv->fbuffer)
goto out_unlock;
- btv->grabbing = 0;
- btv->grab = 0;
- btv->lastgrab = 0;
- for (i = 0; i < MAX_GBUFFERS; i++)
- btv->frame_stat[i] = GBUFFER_UNUSED;
+ btv->gq_in = 0;
+ btv->gq_out = 0;
+ btv->gq_grab = -1;
+ for (i = 0; i < gbuffers; i++)
+ btv->gbuf[i].stat = GBUFFER_UNUSED;
burst(0);
btv->user++;
@@ -1815,8 +2035,10 @@
down(&btv->lock);
btv->user--;
- btv->cap&=~3;
- bt848_set_risc_jmps(btv);
+ btv->scr_on = 0;
+ btv->risc_cap_odd = 0;
+ btv->risc_cap_even = 0;
+ bt848_set_risc_jmps(btv,-1);
/*
* A word of warning. At this point the chip
@@ -1841,7 +2063,7 @@
*/
if(btv->fbuffer)
- rvfree((void *) btv->fbuffer, MAX_GBUFFERS*BTTV_MAX_FBUF);
+ rvfree((void *) btv->fbuffer, gbuffers*gbufsize);
btv->fbuffer=0;
up(&btv->lock);
MOD_DEC_USE_COUNT;
@@ -1901,7 +2123,9 @@
static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
struct bttv *btv=(struct bttv *)dev;
- int i;
+ int i,ret;
+
+ if (debug) printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd);
switch (cmd) {
case VIDIOCGCAP:
@@ -2021,17 +2245,6 @@
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;
@@ -2041,6 +2254,8 @@
struct video_picture p;
if(copy_from_user(&p, arg,sizeof(p)))
return -EFAULT;
+ if (p.palette > PALETTEFMT_MAX)
+ return -EINVAL;
down(&btv->lock);
/* We want -128 to 127 we get 0-65535 */
bt848_bright(btv, (p.brightness>>8)-128);
@@ -2059,7 +2274,6 @@
{
struct video_window vw;
struct video_clip *vcp = NULL;
- int on;
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
@@ -2067,25 +2281,24 @@
if(vw.flags || vw.width < 16 || vw.height < 16)
{
down(&btv->lock);
- bt848_cap(btv,0);
+ btv->scr_on = 0;
+ bt848_set_risc_jmps(btv,-1);
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;
- on=(btv->cap&3);
-
- bt848_cap(btv,0);
+ bt848_set_risc_jmps(btv,0);
+
bt848_set_winsize(btv);
up(&btv->lock);
@@ -2115,39 +2328,7 @@
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;
-
- 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);
+ bt848_set_risc_jmps(btv,-1);
up(&btv->lock);
return 0;
}
@@ -2174,13 +2355,14 @@
return -EFAULT;
if(btv->win.vidadr == 0)
return -EINVAL;
- if (0 == btv->win.use_yuv && (btv->win.width==0 || btv->win.height==0))
+ if (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);
+ if (v == 1 && btv->win.vidadr != 0)
+ btv->scr_on = 1;
+ if (v == 0)
+ btv->scr_on = 0;
+ bt848_set_risc_jmps(btv,-1);
up(&btv->lock);
return 0;
}
@@ -2217,9 +2399,19 @@
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));
+
+ /* set sefault color format */
+ switch (btv->win.bpp) {
+ case 8: btv->picture.palette = VIDEO_PALETTE_HI240; break;
+ case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break;
+ case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break;
+ case 24: btv->picture.palette = VIDEO_PALETTE_RGB24; break;
+ case 32: btv->picture.palette = VIDEO_PALETTE_RGB32; break;
+ }
+
+ if (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;
@@ -2273,19 +2465,6 @@
v.step = 4096;
}
-#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;
- }
-#endif
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
return 0;
@@ -2354,23 +2533,8 @@
udelay(10);
data &= ~WINVIEW_PT2254_STROBE;
btwrite(data, BT848_GPIO_DATA);
-
-#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;
@@ -2379,19 +2543,27 @@
case VIDIOCSYNC:
if(copy_from_user((void *)&i,arg,sizeof(int)))
return -EFAULT;
- switch (btv->frame_stat[i]) {
+ if (i < 0 || i >= gbuffers)
+ return -EINVAL;
+ switch (btv->gbuf[i].stat) {
case GBUFFER_UNUSED:
return -EINVAL;
case GBUFFER_GRABBING:
- while(btv->frame_stat[i]==GBUFFER_GRABBING) {
+ while(btv->gbuf[i].stat==GBUFFER_GRABBING) {
+ if (debug)
+ printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i);
interruptible_sleep_on(&btv->capq);
if(signal_pending(current))
return -EINTR;
}
- /* fall */
+ /* fall throuth */
case GBUFFER_DONE:
- btv->frame_stat[i] = GBUFFER_UNUSED;
- break;
+ case GBUFFER_ERROR:
+ ret = (btv->gbuf[i].stat == GBUFFER_ERROR) ? -EIO : 0;
+ if (debug)
+ printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret);
+ btv->gbuf[i].stat = GBUFFER_UNUSED;
+ return ret;
}
return 0;
@@ -2422,8 +2594,6 @@
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);
@@ -2434,10 +2604,10 @@
{
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;
+ vm.size=gbufsize*gbuffers;
+ vm.frames=gbuffers;
+ for (i = 0; i < gbuffers; i++)
+ vm.offsets[i]=i*gbufsize;
if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
return -EFAULT;
return 0;
@@ -2510,7 +2680,7 @@
unsigned long start=(unsigned long) adr;
unsigned long page,pos;
- if (size>2*BTTV_MAX_FBUF)
+ if (size>gbuffers*gbufsize)
return -EINVAL;
if (!btv->fbuffer) {
if(fbuffer_alloc(btv))
@@ -2623,8 +2793,8 @@
down(&btv->lock);
btv->vbip=VBIBUF_SIZE;
- btv->cap|=0x0c;
- bt848_set_risc_jmps(btv);
+ btv->vbi_on = 1;
+ bt848_set_risc_jmps(btv,-1);
up(&btv->lock);
MOD_INC_USE_COUNT;
@@ -2636,8 +2806,8 @@
struct bttv *btv=(struct bttv *)(dev-2);
down(&btv->lock);
- btv->cap&=~0x0c;
- bt848_set_risc_jmps(btv);
+ btv->vbi_on = 0;
+ bt848_set_risc_jmps(btv,-1);
up(&btv->lock);
MOD_DEC_USE_COUNT;
@@ -2875,26 +3045,12 @@
7a - external */
}
-
-#if 0
-#warning this should be handled by tda9855.c
-static void init_tda9850(struct bttv *btv)
-{
- 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 */
static void idcard(int i)
{
struct bttv *btv = &bttvs[i];
+ int type,eeprom = 0;
btwrite(0, BT848_GPIO_OUT_EN);
DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
@@ -2903,40 +3059,36 @@
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_HAUPEE, "eeprom")>=0)
- {
- if(btv->id>849)
- btv->type=BTTV_HAUPPAUGE878;
- else
+ /* If we were asked to auto-detect, then do so! */
+ if (btv->type == BTTV_UNKNOWN) {
+
+ /* many bt878 cards have a eeprom @ 0xa0 => read ID
+ and try to identify it */
+ if (I2CRead(btv, I2C_HAUPEE, "eeprom") >= 0) {
+ eeprom = 0xa0;
+ readee(btv,eeprom_data,0xa0);
+ dump_eeprom(btv,0xa0); /* DEBUG */
+ type = idcard_eeprom(btv);
+ if (-1 != type) {
+ btv->type = type;
+ } else if (btv->id <= 849) {
+ /* for unknown bt848, assume old Hauppauge */
btv->type=BTTV_HAUPPAUGE;
+ }
+ /* STB cards have a eeprom @ 0xae */
} else if (I2CRead(btv, I2C_STBEE, "eeprom")>=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, 0x80, "msp3400")>=0) /* check for msp34xx */
+#if 0
+ /* check for msp34xx */
+ if (I2CRead(btv, 0x80, "msp3400")>=0)
btv->type = BTTV_MIROPRO;
else
- btv->type = BTTV_MIRO;
- }
- }
-
-#if 1
- /* DEBUG: dump eeprom content if available */
- if (I2CRead(btv, 0xa0, "eeprom")>=0) {
- dump_eeprom(btv,0xa0);
- }
+ btv->type = BTTV_MIRO;
#endif
+ }
/* print which board we have found */
printk(KERN_INFO "bttv%d: model: ",btv->nr);
@@ -2955,8 +3107,12 @@
btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
}
if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
- hauppauge_msp_reset(btv);
+ if (0xa0 != eeprom) {
+ eeprom = 0xa0;
+ readee(btv,eeprom_data,0xa0);
+ }
hauppauge_eeprom(btv);
+ hauppauge_boot_msp34xx(btv);
}
if (btv->type == BTTV_MAXI) {
/* PHILIPS FI1216MK2 tuner (PAL/SECAM) */
@@ -2973,7 +3129,11 @@
btv->type == BTTV_CONFERENCETV ||
btv->type == BTTV_PIXVIEWPLAYTV ||
btv->type == BTTV_AVERMEDIA98 ||
- btv->type == BTTV_MAGICTVIEW061) {
+ btv->type == BTTV_MAGICTVIEW061 ||
+ btv->type == BTTV_CHRONOS_VS2 ||
+ btv->type == BTTV_TYPHOON_TVIEW ||
+ btv->type == BTTV_PXELVWPLTVPRO ||
+ btv->type == BTTV_WINFAST2000) {
btv->pll.pll_ifreq=28636363;
btv->pll.pll_crystal=BT848_IFORM_XT0;
}
@@ -3005,7 +3165,7 @@
if (tvcards[btv->type].tda985x &&
I2CRead(btv, I2C_TDA9850, "TDA985x") >=0) {
if (autoload)
- request_module("tda9855");
+ request_module("tda985x");
}
if (tvcards[btv->type].tea63xx /* &&
@@ -3023,9 +3183,19 @@
}
-static void bt848_set_risc_jmps(struct bttv *btv)
+static void bt848_set_risc_jmps(struct bttv *btv, int flags)
{
- int flags=btv->cap;
+ if (-1 == flags) {
+ /* defaults */
+ flags = 0;
+ if (btv->scr_on)
+ flags |= 0x03;
+ if (btv->vbi_on)
+ flags |= 0x0c;
+ }
+
+ if (debug) printk("bttv%d: set_risc_jmp %08lx:",
+ btv->nr,virt_to_bus(btv->risc_jmp));
/* Sync to start of odd field */
btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC
@@ -3034,17 +3204,27 @@
/* Jump to odd vbi sub */
btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20));
- if (flags&8)
+ if (flags&8) {
+ if (debug) printk(" ev=%08lx",virt_to_bus(btv->vbi_odd));
btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd));
- else
+ } else {
+ if (debug) printk(" -----------");
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|(0xe<<20));
- if (flags&2)
- btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_odd));
- else
+ if (0 != btv->risc_cap_odd) {
+ if (debug) printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd);
+ flags |= 3;
+ btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd);
+ } else if (flags&2) {
+ if (debug) printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd));
+ btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd));
+ } else {
+ if (debug) printk(" -----------");
btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6));
+ }
/* Sync to start of even field */
@@ -3054,22 +3234,34 @@
/* Jump to even vbi sub */
btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP);
- if (flags&4)
+ if (flags&4) {
+ if (debug) printk(" ov=%08lx",virt_to_bus(btv->vbi_even));
btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even));
- else
+ } else {
+ if (debug) printk(" -----------");
btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));
+ }
/* Jump to even sub */
btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20));
- if (flags&1)
- btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_even));
- else
+ if (0 != btv->risc_cap_even) {
+ if (debug) printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even);
+ flags |= 3;
+ btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even);
+ } else if (flags&1) {
+ if (debug) printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even));
+ btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even));
+ } else {
+ if (debug) printk(" -----------");
btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12));
+ }
btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp));
/* enable cpaturing and DMA */
+ if (debug) printk(" flags=0x%x dma=%s\n",
+ flags,(flags&0x0f) ? "on" : "off");
btaor(flags, ~0x0f, BT848_CAP_CTL);
if (flags&0x0f)
bt848_dma(btv, 3);
@@ -3110,24 +3302,29 @@
static int init_bt848(int i)
{
struct bttv *btv = &bttvs[i];
+ int j;
btv->user=0;
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
+ if (verbose >= 2)
+ 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));
/* reset the bt848 */
btwrite(0, BT848_SRESET);
DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n",i,(unsigned long) btv->bt848_mem));
+ /* not registered yet */
+ btv->video_dev.minor = -1;
+ btv->radio_dev.minor = -1;
+ btv->vbi_dev.minor = -1;
+
/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */
btv->win.interlace=1;
@@ -3135,10 +3332,6 @@
btv->win.y=0;
btv->win.width=768; /* 640 */
btv->win.height=576; /* 480 */
- btv->win.cropwidth=768; /* 640 */
- btv->win.cropheight=576; /* 480 */
- btv->win.cropx=0;
- btv->win.cropy=0;
btv->win.bpp=2;
btv->win.depth=16;
btv->win.color_fmt=BT848_COLOR_FMT_RGB16;
@@ -3146,27 +3339,24 @@
btv->win.swidth=1024;
btv->win.sheight=768;
btv->win.vidadr=0;
- btv->cap=0;
+ btv->vbi_on=0;
+ btv->scr_on=0;
- btv->gmode=0;
- btv->risc_odd=0;
- btv->risc_even=0;
+ btv->risc_scr_odd=0;
+ btv->risc_scr_even=0;
+ btv->risc_cap_odd=0;
+ btv->risc_cap_even=0;
btv->risc_jmp=0;
btv->vbibuf=0;
- btv->grisc=0;
- btv->grabbing=0;
- btv->grabcount=0;
- btv->grab=0;
- btv->lastgrab=0;
btv->field=btv->last_field=0;
/* i2c */
btv->tuner_type=-1;
init_bttv_i2c(btv);
- if (!(btv->risc_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
+ if (!(btv->risc_scr_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
return -1;
- if (!(btv->risc_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
+ if (!(btv->risc_scr_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
return -1;
if (!(btv->risc_jmp =(unsigned int *) kmalloc(2048, GFP_KERNEL)))
return -1;
@@ -3180,9 +3370,13 @@
btv->vbibuf=(unsigned char *) vmalloc(VBIBUF_SIZE);
if (!btv->vbibuf)
return -1;
- if (!(btv->grisc=(unsigned int *) kmalloc(32768, GFP_KERNEL)))
+ if (!(btv->gbuf = kmalloc(sizeof(struct bttv_gbuf)*gbuffers,GFP_KERNEL)))
return -1;
-
+ for (j = 0; j < gbuffers; j++) {
+ if (!(btv->gbuf[j].risc = kmalloc(16384,GFP_KERNEL)))
+ return -1;
+ }
+
memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random
memory to the user */
@@ -3194,7 +3388,14 @@
/* btwrite(0, BT848_TDEC); */
btwrite(0x10, BT848_COLOR_CTL);
btwrite(0x00, BT848_CAP_CTL);
- btwrite(0xac, BT848_GPIO_DMA_CTL);
+ /* set planar and packed mode trigger points and */
+ /* set rising edge of inverted GPINTR pin as irq trigger */
+ btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
+ BT848_GPIO_DMA_CTL_PLTP1_16|
+ BT848_GPIO_DMA_CTL_PLTP23_16|
+ BT848_GPIO_DMA_CTL_GPINTC|
+ BT848_GPIO_DMA_CTL_GPINTI,
+ BT848_GPIO_DMA_CTL);
/* select direct input */
btwrite(0x00, BT848_GPIO_REG_INP);
@@ -3229,13 +3430,14 @@
/*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
(fieldnr ? BT848_INT_VSYNC : 0)|
+ BT848_INT_GPINT|
BT848_INT_SCERR|
BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
BT848_INT_FMTCHG|BT848_INT_HLOCK,
BT848_INT_MASK);
make_vbitab(btv);
- bt848_set_risc_jmps(btv);
+ bt848_set_risc_jmps(btv,-1);
/*
* Now add the template and register the device unit.
@@ -3262,12 +3464,17 @@
if (!astat)
return;
btwrite(astat,BT848_INT_STAT);
- IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat));
- IDEBUG(printk ("bttv%d: stat %08x\n", btv->nr, 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);
+ if (astat&BT848_INT_GPINT) {
+ IDEBUG(printk ("bttv%d: IRQ_GPINT\n", btv->nr));
+ wake_up_interruptible(&btv->gpioq);
+ }
+
if (astat&BT848_INT_FMTCHG)
{
IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr));
@@ -3283,13 +3490,21 @@
IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr));
btv->field++;
}
- if (astat&BT848_INT_SCERR) {
- IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
- bt848_dma(btv, 0);
- bt848_dma(btv, 1);
+ if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) {
+ printk("bttv%d: irq:%s%s risc_count=%08x\n",btv->nr,
+ (astat&BT848_INT_SCERR) ? " SCERR" : "",
+ (astat&BT848_INT_OCERR) ? " OCERR" : "",
+ btread(BT848_RISC_COUNT));
+ bt848_set_risc_jmps(btv,0);
+ btwrite(0, BT848_SRESET);
+ btwrite(virt_to_bus(btv->risc_jmp),
+ BT848_RISC_STRT_ADD);
+ bt848_set_geo(btv,0);
+ bt848_set_risc_jmps(btv,-1);
+#if 0
wake_up_interruptible(&btv->vbiq);
wake_up_interruptible(&btv->capq);
-
+#endif
}
if (astat&BT848_INT_RISCI)
{
@@ -3307,41 +3522,48 @@
/* captured full frame */
if (stat&(2<<28))
{
- /*wake_up_interruptible(&btv->capq);*/
btv->last_field=btv->field;
- btv->grab++;
- btv->frame_stat[btv->grf] = GBUFFER_DONE;
- if ((--btv->grabbing))
+ if (debug)
+ printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab);
+ btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE;
+ btv->gq_grab = -1;
+ if (btv->gq_in != btv->gq_out)
{
- btv->gfmt = btv->gfmt_next;
- btv->gwidth = btv->gwidth_next;
- btv->gheight = btv->gheight_next;
- btv->gro = btv->gro_next;
- btv->gre = btv->gre_next;
- btv->grf = btv->grf_next;
- btv->risc_jmp[5]=cpu_to_le32(btv->gro);
- btv->risc_jmp[11]=cpu_to_le32(btv->gre);
- bt848_set_geo(btv, btv->gwidth,
- btv->gheight,
- btv->gfmt,0);
+ btv->gq_grab = btv->gqueue[btv->gq_out++];
+ btv->gq_out = btv->gq_out % MAX_GBUFFERS;
+ if (debug)
+ printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab);
+ btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro;
+ btv->risc_cap_even = btv->gbuf[btv->gq_grab].re;
+ bt848_set_risc_jmps(btv,-1);
+ bt848_set_geo(btv,0);
+ btwrite(BT848_COLOR_CTL_GAMMA,
+ BT848_COLOR_CTL);
} else {
- bt848_set_risc_jmps(btv);
+ btv->risc_cap_odd = 0;
+ btv->risc_cap_even = 0;
+ bt848_set_risc_jmps(btv,-1);
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);
+ bt848_set_geo(btv,0);
+ btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA,
+ BT848_COLOR_CTL);
}
wake_up_interruptible(&btv->capq);
break;
}
if (stat&(8<<28))
{
- btv->risc_jmp[5]=cpu_to_le32(btv->gro);
- 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->gq_grab = btv->gqueue[btv->gq_out++];
+ btv->gq_out = btv->gq_out % MAX_GBUFFERS;
+ if (debug)
+ printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab);
+ btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro;
+ btv->risc_cap_even = btv->gbuf[btv->gq_grab].re;
+ bt848_set_risc_jmps(btv,-1);
+ bt848_set_geo(btv,0);
+ btwrite(BT848_COLOR_CTL_GAMMA,
+ BT848_COLOR_CTL);
}
}
if (astat&BT848_INT_OCERR)
@@ -3427,6 +3649,9 @@
init_waitqueue_head(&btv->capqe);
btv->vbip=VBIBUF_SIZE;
+ init_waitqueue_head(&btv->gpioq);
+ btv->shutdown=0;
+
btv->id=dev->device;
btv->irq=dev->irq;
btv->bt848_adr=dev->resource[0].start;
@@ -3544,15 +3769,17 @@
static void release_bttv(void)
{
u8 command;
- int i;
+ int i,j;
struct bttv *btv;
for (i=0;i<bttv_num; i++)
{
btv=&bttvs[i];
- /* turn off all capturing, DMA and IRQs */
+ /* unregister i2c_bus */
+ i2c_bit_del_bus(&btv->i2c_adap);
+ /* turn off all capturing, DMA and IRQs */
btand(~15, BT848_GPIO_DMA_CTL);
/* first disable interrupts before unmapping the memory! */
@@ -3560,9 +3787,6 @@
btwrite(0xffffffffUL,BT848_INT_STAT);
btwrite(0x0, BT848_GPIO_OUT_EN);
- /* unregister i2c_bus */
- i2c_bit_del_bus(&btv->i2c_adap);
-
/* disable PCI bus-mastering */
pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
/* Should this be &=~ ?? */
@@ -3570,14 +3794,17 @@
pci_write_config_byte(btv->dev, PCI_COMMAND, command);
/* unmap and free memory */
- if (btv->grisc)
- kfree((void *) btv->grisc);
+ for (j = 0; j < gbuffers; j++)
+ if (btv->gbuf[j].risc)
+ kfree(btv->gbuf[j].risc);
+ if (btv->gbuf)
+ kfree((void *) btv->gbuf);
- if (btv->risc_odd)
- kfree((void *) btv->risc_odd);
+ if (btv->risc_scr_odd)
+ kfree((void *) btv->risc_scr_odd);
- if (btv->risc_even)
- kfree((void *) btv->risc_even);
+ if (btv->risc_scr_even)
+ kfree((void *) btv->risc_scr_even);
DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp));
if (btv->risc_jmp)
@@ -3599,6 +3826,13 @@
video_unregister_device(&btv->vbi_dev);
if (radio[btv->nr] && btv->radio_dev.minor != -1)
video_unregister_device(&btv->radio_dev);
+
+ /* wake up any waiting processes
+ because shutdown flag is set, no new processes (in this queue)
+ are expected
+ */
+ btv->shutdown=1;
+ wake_up(&btv->gpioq);
}
}
@@ -3614,6 +3848,14 @@
(BTTV_VERSION_CODE >> 16) & 0xff,
(BTTV_VERSION_CODE >> 8) & 0xff,
BTTV_VERSION_CODE & 0xff);
+ if (gbuffers < 2 || gbuffers > MAX_GBUFFERS)
+ gbuffers = 2;
+ if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF)
+ gbufsize = BTTV_MAX_FBUF;
+ if (verbose)
+ printk(KERN_INFO "bttv: using %d buffers with %dk (%dk total) for capture\n",
+ gbuffers,gbufsize/1024,gbuffers*gbufsize/1024);
+
handle_chipset();
if (find_bt848()<=0)
return -EIO;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)