summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-12 23:15:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-12 23:15:27 +0000
commitae38fd1e4c98588314a42097c5a5e77dcef23561 (patch)
treef9f10c203bb9e5fbad4810d1f8774c08dfad20ff /drivers/char
parent466a823d79f41d0713b272e48fd73e494b0588e0 (diff)
Merge with Linux 2.3.50.
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Config.in4
-rw-r--r--drivers/char/Makefile20
-rw-r--r--drivers/char/agp/agp.h1
-rw-r--r--drivers/char/agp/agpgart_be.c3
-rw-r--r--drivers/char/bttv.c1232
-rw-r--r--drivers/char/bttv.h165
-rw-r--r--drivers/char/console.c2
-rw-r--r--drivers/char/epca.c5
-rw-r--r--drivers/char/istallion.c4
-rw-r--r--drivers/char/msp3400.c41
-rw-r--r--drivers/char/ppdev.c10
-rw-r--r--drivers/char/pty.c5
-rw-r--r--drivers/char/sh-sci.c992
-rw-r--r--drivers/char/sh-sci.h196
-rw-r--r--drivers/char/stradis.c18
-rw-r--r--drivers/char/tda9855.c455
-rw-r--r--drivers/char/tda985x.c532
-rw-r--r--drivers/char/tty_io.c15
-rw-r--r--drivers/char/tuner.c5
-rw-r--r--drivers/char/videodev.c3
20 files changed, 2624 insertions, 1084 deletions
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index 11f10b785..920546763 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -197,7 +197,9 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
fi
comment 'Video Adapters'
- dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI
+ if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then
+ dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT
+ fi
dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate ' Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 9e3ffd93a..32c66c442 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -38,7 +38,7 @@ obj-y += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o
export-objs := busmouse.o console.o i2c-old.o keyboard.o sysrq.o \
misc.o pty.o random.o selection.o serial.o videodev.o \
- tty_io.o
+ tty_io.o bttv.o
KEYMAP =defkeymap.o
KEYBD =pc_keyb.o
@@ -61,6 +61,20 @@ ifeq ($(ARCH),arm)
SERIAL =
endif
+ifeq ($(ARCH),sh)
+ KEYMAP =
+ KEYBD =
+ CONSOLE =
+ SERIAL =
+ ifeq ($(CONFIG_SERIAL),y)
+ SERIAL = generic_serial.o sh-sci.o
+ else
+ ifeq ($(CONFIG_SERIAL),m)
+ SERIAL = sh-sci.o
+ endif
+ endif
+endif
+
ifeq ($(CONFIG_DECSTATION),y)
KEYBD =
SERIAL =
@@ -180,13 +194,11 @@ else
endif
endif
-obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda9855.o tea6300.o
+obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda985x.o tea6300.o
ifeq ($(CONFIG_VIDEO_BT848),y)
-L_I2C=y
L_TUNERS=y
else
ifeq ($(CONFIG_VIDEO_BT848),m)
- L_I2C=m
L_TUNERS=m
endif
endif
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 31f481065..21a638fe2 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -226,6 +226,7 @@ struct agp_bridge_data {
#define AMD_MMBASE 0x14
#define AMD_APSIZE 0xac
#define AMD_MODECNTL 0xb0
+#define AMD_MODECNTL2 0xb2
#define AMD_GARTENABLE 0x02 /* In mmio region (16-bit register) */
#define AMD_ATTBASE 0x04 /* In mmio region (32-bit register) */
#define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index c478395f8..fc4312f64 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -1449,6 +1449,9 @@ static int amd_irongate_configure(void)
/* Write the Sync register */
pci_write_config_byte(agp_bridge.dev, AMD_MODECNTL, 0x80);
+
+ /* Set indexing mode */
+ pci_write_config_byte(agp_bridge.dev, AMD_MODECNTL2, 0x02);
/* Write the enable register */
enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE);
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index c21198356..82f545ecc 100644
--- a/drivers/char/bttv.c
+++ b/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(card,"1-4i");
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 radio[BTTV_MAX];
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 @@ static unsigned int autoload = 1;
#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 @@ static inline unsigned long kvirt_to_pa(unsigned long adr)
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 @@ static void * rvmalloc(unsigned long size)
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 void rvfree(void * mem, unsigned long size)
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 @@ static int attach_inform(struct i2c_client *client)
}
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 @@ static int detach_inform(struct i2c_client *client)
{
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 @@ static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
{
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 @@ hauppauge_tuner[] =
{ 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 @@ static void init_PXC200(struct bttv *btv)
/* 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 @@ static struct VENDOR {
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 @@ struct tvcard
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 @@ static struct tvcard tvcards[] =
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 @@ static struct tvcard tvcards[] =
{ "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 @@ dump_eeprom(struct bttv *btv, int addr)
} 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 @@ extern inline void bt848_dma(struct bttv *btv, uint state)
}
-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 @@ static int set_pll(struct bttv *btv)
/* 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 @@ static int set_pll(struct bttv *btv)
{
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 @@ static void make_vbitab(struct bttv *btv)
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 @@ static void make_vbitab(struct bttv *btv)
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 @@ static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
*(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 @@ static int make_prisctab(struct bttv *btv, unsigned int *ro,
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 @@ static int make_prisctab(struct bttv *btv, unsigned int *ro,
}
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 @@ static int make_prisctab(struct bttv *btv, unsigned int *ro,
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 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
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 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
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 clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int
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 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
/* 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 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
{
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 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
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 inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc,
}
-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 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height,
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;
-
- xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth;
- hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
+ btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0;
+
+ 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;
+ }
- hdelay=tvn->hdelayx1+btv->win.cropx;
- hdelay=(hdelay*hactive)/btv->win.cropwidth;
- hdelay&=0x3fe;
+ inter = (oheight>tvn->sheight/2) ? 0 : 1;
- sr=((btv->win.cropheight>>inter)*512)/height-512;
+ /* 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 @@ static void bt848_set_winsize(struct bttv *btv)
{
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 @@ static void bt848_set_winsize(struct bttv *btv)
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 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
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 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
* 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 @@ static int bttv_open(struct video_device *dev, int flags)
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 @@ static void bttv_close(struct video_device *dev)
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 @@ static void bttv_close(struct video_device *dev)
*/
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 inline void bt848_sat_v(struct bttv *btv, unsigned long data)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
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 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
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 @@ static int do_bttv_mmap(struct bttv *btv, const char *adr, unsigned long size)
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 @@ static int vbi_open(struct video_device *dev, int flags)
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 @@ static void vbi_close(struct video_device *dev)
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 @@ static void init_tda9840(struct bttv *btv)
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 @@ static void idcard(int i)
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 @@ static void idcard(int i)
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 @@ static void idcard(int i)
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 @@ static void idcard(int i)
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 idcard(int i)
}
-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 @@ static void bt848_set_risc_jmps(struct bttv *btv)
/* 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 @@ static void bt848_set_risc_jmps(struct bttv *btv)
/* 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 @@ init_video_dev(struct bttv *btv)
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 @@ static int init_bt848(int i)
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 @@ static int init_bt848(int i)
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 @@ static int init_bt848(int i)
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 @@ static int init_bt848(int i)
/* 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 @@ static int init_bt848(int i)
/*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 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
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 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
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 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
/* 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 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
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 int find_bt848(void)
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 @@ static void release_bttv(void)
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 @@ static void release_bttv(void)
pci_write_config_byte(btv->dev, PCI_COMMAND, command);
/* unmap and free memory */
- if (btv->grisc)
- kfree((void *) btv->grisc);
-
- if (btv->risc_odd)
- kfree((void *) btv->risc_odd);
+ 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_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 @@ static void release_bttv(void)
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 @@ int init_bttv_cards(struct video_init *unused)
(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;
diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h
index 309e93e95..ab3d88ab5 100644
--- a/drivers/char/bttv.h
+++ b/drivers/char/bttv.h
@@ -21,45 +21,67 @@
#ifndef _BTTV_H_
#define _BTTV_H_
-#define BTTV_VERSION_CODE 0x00070d
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,21)
#include <linux/types.h>
#include <linux/wait.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
#include "audiochip.h"
#include "bt848.h"
+#define WAIT_QUEUE wait_queue_head_t
-/* experimental, interface might change */
-#ifndef VIDIOCSWIN2
-#define VIDIOCSWIN2 _IOW('v',28,struct video_window2)
-struct video_window2
-{
- __u16 palette; /* Palette (aka video format) in use */
- __u32 start; /* start address, relative to video_buffer.base */
- __u32 pitch;
- __u32 width;
- __u32 height;
- __u32 flags;
-
- struct video_clip *clips;
- int clipcount;
-};
-#endif
+/* returns card type,
+ for possible values see lines below beginning with #define BTTV_UNKNOWN
+ returns negative value if error ocurred
+*/
+extern int bttv_get_id(unsigned int card);
+/* sets GPOE register (BT848_GPIO_OUT_EN) to new value:
+ data | (current_GPOE_value & ~mask)
+ returns negative value if error ocurred
+*/
+extern int bttv_gpio_enable(unsigned int card,
+ unsigned long mask, unsigned long data);
+
+/* fills data with GPDATA register contents
+ returns negative value if error ocurred
+*/
+extern int bttv_read_gpio(unsigned int card, unsigned long *data);
+
+/* sets GPDATA register to new value:
+ (data & mask) | (current_GPDATA_value & ~mask)
+ returns negative value if error ocurred
+*/
+extern int bttv_write_gpio(unsigned int card,
+ unsigned long mask, unsigned long data);
+
+/* returns pointer to task queue which can be used as parameter to
+ interruptible_sleep_on
+ in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated
+ (wake_up_interruptible) and following call to the function bttv_read_gpio
+ should return new value of GPDATA,
+ returns NULL value if error ocurred or queue is not available
+ WARNING: because there is no buffer for GPIO data, one MUST
+ process data ASAP
+*/
+extern WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card);
-#define WAIT_QUEUE wait_queue_head_t
#ifndef O_NONCAP
#define O_NONCAP O_TRUNC
#endif
-#define MAX_GBUFFERS 2
+#define MAX_GBUFFERS 64
#define RISCMEM_LEN (32744*2)
#define VBI_MAXLINES 16
#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
#define BTTV_MAX_FBUF 0x208000
+#define I2C_CLIENTS_MAX 8
#ifdef __KERNEL__
@@ -69,17 +91,12 @@ struct bttv_window
ushort width, height;
ushort bpp, bpl;
ushort swidth, sheight;
- short cropx, cropy;
- ushort cropwidth, cropheight;
unsigned long vidadr;
ushort freq;
int norm;
int interlace;
int color_fmt;
ushort depth;
-
- int use_yuv;
- struct video_window2 win2;
};
struct bttv_pll_info {
@@ -89,7 +106,21 @@ struct bttv_pll_info {
unsigned int pll_current; /* Currently programmed ofreq */
};
-#define I2C_CLIENTS_MAX 8
+struct bttv_gbuf {
+ int stat;
+#define GBUFFER_UNUSED 0
+#define GBUFFER_GRABBING 1
+#define GBUFFER_DONE 2
+#define GBUFFER_ERROR 3
+
+ u16 width;
+ u16 height;
+ u16 fmt;
+
+ u32 *risc;
+ unsigned long ro;
+ unsigned long re;
+};
struct bttv
{
@@ -125,6 +156,7 @@ struct bttv
unsigned char *vbibuf;
struct bttv_window win;
+ int fb_color_ctl;
int type; /* card type */
int audio; /* audio mode */
int audio_chip; /* set to one of the chips supported by bttv.c */
@@ -141,34 +173,18 @@ struct bttv
WAIT_QUEUE capqe;
int vbip;
- u32 *risc_odd;
- u32 *risc_even;
- int cap;
+ u32 *risc_scr_odd;
+ u32 *risc_scr_even;
+ u32 risc_cap_odd;
+ u32 risc_cap_even;
+ int scr_on;
+ int vbi_on;
struct video_clip *cliprecs;
- struct gbuffer *ogbuffers;
- struct gbuffer *egbuffers;
- u16 gwidth, gheight, gfmt;
- u16 gwidth_next, gheight_next, gfmt_next;
- u32 *grisc;
-
- unsigned long gro;
- unsigned long gre;
- unsigned long gro_next;
- unsigned long gre_next;
-
- int grf,grf_next; /* frame numbers in grab queue */
- int frame_stat[MAX_GBUFFERS];
-#define GBUFFER_UNUSED 0
-#define GBUFFER_GRABBING 1
-#define GBUFFER_DONE 2
-
+ struct bttv_gbuf *gbuf;
+ int gqueue[MAX_GBUFFERS];
+ int gq_in,gq_out,gq_grab;
char *fbuffer;
- int gmode;
- int grabbing;
- int lastgrab;
- int grab;
- int grabcount;
struct bttv_pll_info pll;
unsigned int Fsc;
@@ -176,12 +192,12 @@ struct bttv
unsigned int last_field; /* number of last grabbed field */
int i2c_command;
int triton1;
+
+ WAIT_QUEUE gpioq;
+ int shutdown;
};
#endif
-/*The following should be done in more portable way. It depends on define
- of _ALPHA_BTTV in the Makefile.*/
-
#if defined(__powerpc__) /* big-endian */
extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
{
@@ -193,14 +209,9 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
#define btwrite(dat,adr) io_st_le32((unsigned *)(btv->bt848_mem+(adr)),(dat))
#define btread(adr) ld_le32((unsigned *)(btv->bt848_mem+(adr)))
#else
-#ifdef _ALPHA_BTTV
-#define btwrite(dat,adr) writel((dat),(char *) (btv->bt848_adr+(adr)))
-#define btread(adr) readl(btv->bt848_adr+(adr))
-#else
#define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr)))
#define btread(adr) readl(btv->bt848_mem+(adr))
#endif
-#endif
#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
@@ -243,10 +254,19 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
#define BTTV_PHOEBE_TVMAS 0x16
#define BTTV_MODTEC_205 0x17
#define BTTV_MAGICTVIEW061 0x18
-
+#define BTTV_VOBIS_BOOSTAR 0x19
+#define BTTV_HAUPPAUG_WCAM 0x1a
#define BTTV_MAXI 0x1b
#define BTTV_TERRATV 0x1c
#define BTTV_PXC200 0x1d
+#define BTTV_FLYVIDEO_98 0x1e
+#define BTTV_IPROTV 0x1f
+#define BTTV_INTEL_C_S_PCI 0x20
+#define BTTV_TERRATVALUE 0x21
+#define BTTV_WINFAST2000 0x22
+#define BTTV_CHRONOS_VS2 0x23
+#define BTTV_TYPHOON_TVIEW 0x24
+#define BTTV_PXELVWPLTVPRO 0x25
#define AUDIO_TUNER 0x00
@@ -279,27 +299,6 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
#define TDA9840_STADJ 0x03
#define TDA9840_TEST 0x04
-#define TDA9850_CON1 0x04
-#define TDA9850_CON2 0x05
-#define TDA9850_CON3 0x06
-#define TDA9850_CON4 0x07
-#define TDA9850_ALI1 0x08
-#define TDA9850_ALI2 0x09
-#define TDA9850_ALI3 0x0a
-
-#define TDA8425_VL 0x00
-#define TDA8425_VR 0x01
-#define TDA8425_BA 0x02
-#define TDA8425_TR 0x03
-#define TDA8425_S1 0x08
-
-#define TEA6300_VL 0x00 /* volume control left */
-#define TEA6300_VR 0x01 /* volume control right */
-#define TEA6300_BA 0x02 /* bass control */
-#define TEA6300_TR 0x03 /* treble control */
-#define TEA6300_FA 0x04 /* fader control */
-#define TEA6300_SW 0x05 /* mute and source switch */
-
#define PT2254_L_CHANEL 0x10
#define PT2254_R_CHANEL 0x08
#define PT2254_DBS_IN_2 0x400
@@ -309,3 +308,9 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
#define WINVIEW_PT2254_STROBE 0x80
#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/char/console.c b/drivers/char/console.c
index a1c9f3cf3..9d8bf6cb0 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -2564,7 +2564,7 @@ void __init con_init_devfs (void)
int i;
for (i = 0; i < console_driver.num; i++)
- tty_register_devfs (&console_driver, 0,
+ tty_register_devfs (&console_driver, DEVFS_FL_AOPEN_NOTIFY,
console_driver.minor_start + i);
}
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index e8de397bf..31cd5546c 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1545,13 +1545,14 @@ int __init init_module()
} /* End init_module */
#endif
-#ifdef MODULE
-/* -------------------- Begin cleanup_module ---------------------- */
#ifdef ENABLE_PCI
static struct pci_driver epca_driver;
#endif
+#ifdef MODULE
+/* -------------------- Begin cleanup_module ---------------------- */
+
void cleanup_module()
{ /* Begin cleanup_module */
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 0b1ab10e1..ad9452390 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -142,6 +142,8 @@ static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
*/
#define STLI_EISAPROBE 0
+static devfs_handle_t devfs_handle = NULL;
+
/*****************************************************************************/
/*
@@ -830,8 +832,6 @@ int init_module()
/*****************************************************************************/
-static devfs_handle_t devfs_handle = NULL;
-
void cleanup_module()
{
stlibrd_t *brdp;
diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c
index 2be8b2798..8de178bb6 100644
--- a/drivers/char/msp3400.c
+++ b/drivers/char/msp3400.c
@@ -480,7 +480,7 @@ static void msp3400c_setstereo(struct i2c_client *client, int mode)
break;
case VIDEO_SOUND_MONO:
if (msp->mode == MSP_MODE_AM_NICAM) {
- printk("msp3400: switching to AM mono\n");
+ dprintk("msp3400: switching to AM mono\n");
/* AM mono decoding is handled by tuner, not MSP chip */
/* so let's redirect sound from tuner via SCART */
/* volume prescale for SCART */
@@ -723,7 +723,7 @@ static int msp3400c_thread(void *data)
/* some time for the tuner to sync */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ schedule_timeout(HZ/5);
if (signal_pending(current))
goto done;
@@ -750,13 +750,15 @@ static int msp3400c_thread(void *data)
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/25);
+ schedule_timeout(HZ/10);
if (signal_pending(current))
goto done;
if (msp->restart)
msp->restart = 0;
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
+ if (val > 32768)
+ val -= 65536;
if (val1 < val)
val1 = val, max1 = this;
dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
@@ -785,13 +787,15 @@ static int msp3400c_thread(void *data)
msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/25);
+ schedule_timeout(HZ/10);
if (signal_pending(current))
goto done;
if (msp->restart)
goto restart;
val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
+ if (val > 32768)
+ val -= 65536;
if (val2 < val)
val2 = val, max2 = this;
dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
@@ -974,7 +978,7 @@ static int msp3410d_thread(void *data)
/* some time for the tuner to sync */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ schedule_timeout(HZ/5);
if (signal_pending(current))
goto done;
@@ -1041,10 +1045,9 @@ static int msp3410d_thread(void *data)
for (i = 0; modelist[i].name != NULL; i++)
if (modelist[i].retval == val)
break;
- if (debug)
- printk("msp3410: current mode: %s (0x%04x)\n",
- modelist[i].name ? modelist[i].name : "unknown",
- val);
+ dprintk("msp3410: current mode: %s (0x%04x)\n",
+ modelist[i].name ? modelist[i].name : "unknown",
+ val);
msp->main = modelist[i].main;
msp->second = modelist[i].second;
@@ -1242,6 +1245,7 @@ static int
msp3400c_mixer_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ struct i2c_client *client;
struct msp3400c *msp;
int i;
@@ -1249,12 +1253,17 @@ msp3400c_mixer_open(struct inode *inode, struct file *file)
for (i = 0; i < MSP3400_MAX; i++) {
msp = msps[i]->data;
if (msp->mixer_num == minor) {
- file->private_data = msps[i];
+ client = msps[i];
+ file->private_data = client;
break;
}
}
if (MSP3400_MAX == i)
return -ENODEV;
+
+ /* lock bttv in memory while the mixer is in use */
+ if (client->adapter->inc_use)
+ client->adapter->inc_use(client->adapter);
MOD_INC_USE_COUNT;
return 0;
@@ -1263,6 +1272,10 @@ msp3400c_mixer_open(struct inode *inode, struct file *file)
static int
msp3400c_mixer_release(struct inode *inode, struct file *file)
{
+ struct i2c_client *client = file->private_data;
+
+ if (client->adapter->inc_use)
+ client->adapter->inc_use(client->adapter);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -1274,10 +1287,10 @@ msp3400c_mixer_llseek(struct file *file, loff_t offset, int origin)
}
static struct file_operations msp3400c_mixer_fops = {
- llseek: msp3400c_mixer_llseek,
- ioctl: msp3400c_mixer_ioctl,
- open: msp3400c_mixer_open,
- release: msp3400c_mixer_release,
+ llseek: msp3400c_mixer_llseek,
+ ioctl: msp3400c_mixer_ioctl,
+ open: msp3400c_mixer_open,
+ release: msp3400c_mixer_release,
};
#endif
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index d73c09695..59853da1f 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -83,7 +83,7 @@ struct pp_struct {
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
-static inline void enable_irq (struct pp_struct *pp)
+static inline void pp_enable_irq (struct pp_struct *pp)
{
struct parport *port = pp->pdev->port;
port->ops->enable_irq (port);
@@ -144,7 +144,7 @@ static ssize_t pp_read (struct file * file, char * buf, size_t count,
}
kfree (kbuffer);
- enable_irq (pp);
+ pp_enable_irq (pp);
return bytes_read;
}
@@ -197,7 +197,7 @@ static ssize_t pp_write (struct file * file, const char * buf, size_t count,
}
kfree (kbuffer);
- enable_irq (pp);
+ pp_enable_irq (pp);
return bytes_written;
}
@@ -292,7 +292,7 @@ static int pp_ioctl(struct inode *inode, struct file *file,
/* For interrupt-reporting to work, we need to be
* informed of each interrupt. */
- enable_irq (pp);
+ pp_enable_irq (pp);
/* We may need to fix up the state machine. */
info = &pp->pdev->port->ieee1284;
@@ -441,7 +441,7 @@ static int pp_ioctl(struct inode *inode, struct file *file,
ret = -ENXIO;
break;
}
- enable_irq (pp);
+ pp_enable_irq (pp);
return ret;
case PPWCTLONIRQ:
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 77cdb7a51..8f25926e9 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -329,9 +329,10 @@ static int pty_open(struct tty_struct *tty, struct file * filp)
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
wake_up_interruptible(&pty->open_wait);
set_bit(TTY_THROTTLED, &tty->flags);
- /* register a slave for the master */
+ /* Register a slave for the master */
if (tty->driver.major == PTY_MASTER_MAJOR)
- tty_register_devfs(&tty->link->driver, DEVFS_FL_WAIT,
+ tty_register_devfs(&tty->link->driver,
+ DEVFS_FL_AUTO_OWNER | DEVFS_FL_WAIT,
tty->link->driver.minor_start +
MINOR(tty->device)-tty->driver.minor_start);
retval = 0;
diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c
new file mode 100644
index 000000000..827be953a
--- /dev/null
+++ b/drivers/char/sh-sci.c
@@ -0,0 +1,992 @@
+/* $Id: sh-sci.c,v 1.32 2000-03-05 13:56:18+09 gniibe Exp $
+ *
+ * linux/drivers/char/sh-sci.c
+ *
+ * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ *
+ * TTY code is based on sx.c (Specialix SX driver) by:
+ *
+ * (C) 1998 R.E.Wolff@BitWizard.nl
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#include "generic_serial.h"
+#include "sh-sci.h"
+
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+static void gdb_detach(void);
+#endif
+
+struct sci_port sci_ports[1];
+
+/* Function prototypes */
+static void sci_disable_tx_interrupts(void *ptr);
+static void sci_enable_tx_interrupts(void *ptr);
+static void sci_disable_rx_interrupts(void *ptr);
+static void sci_enable_rx_interrupts(void *ptr);
+static int sci_get_CD(void *ptr);
+static void sci_shutdown_port(void *ptr);
+static void sci_set_real_termios(void *ptr);
+static void sci_hungup(void *ptr);
+static void sci_close(void *ptr);
+static int sci_chars_in_buffer(void *ptr);
+static int sci_init_drivers(void);
+
+static struct tty_driver sci_driver, sci_callout_driver;
+
+#define SCI_NPORTS 1
+static struct tty_struct *sci_table[SCI_NPORTS] = { NULL, };
+static struct termios *sci_termios[2]; /* nomal, locked */
+
+int sci_refcount;
+int sci_debug = 0;
+
+#ifdef MODULE
+MODULE_PARM(sci_debug, "i");
+#endif
+
+static struct real_driver sci_real_driver = {
+ sci_disable_tx_interrupts,
+ sci_enable_tx_interrupts,
+ sci_disable_rx_interrupts,
+ sci_enable_rx_interrupts,
+ sci_get_CD,
+ sci_shutdown_port,
+ sci_set_real_termios,
+ sci_chars_in_buffer,
+ sci_close,
+ sci_hungup,
+ NULL
+};
+
+static void sci_setsignals(struct sci_port *port, int dtr, int rts)
+{
+ /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
+ /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
+ /* If you have signals for DTR and DCD, please implement here. */
+ ;
+}
+
+static int sci_getsignals(struct sci_port *port)
+{
+ /* This routine is used for geting signals of: DTR, DCD, DSR, RI,
+ and CTS/RTS */
+
+ return TIOCM_DTR|TIOCM_RTS|TIOCM_DSR;
+/*
+ (((o_stat & OP_DTR)?TIOCM_DTR:0) |
+ ((o_stat & OP_RTS)?TIOCM_RTS:0) |
+ ((i_stat & IP_CTS)?TIOCM_CTS:0) |
+ ((i_stat & IP_DCD)?TIOCM_CAR:0) |
+ ((i_stat & IP_DSR)?TIOCM_DSR:0) |
+ ((i_stat & IP_RI) ?TIOCM_RNG:0)
+*/
+}
+
+static void sci_set_baud(struct sci_port *port)
+{
+ int t;
+
+ switch (port->gs.baud) {
+ case 0:
+ t = -1;
+ break;
+ case 2400:
+ t = BPS_2400;
+ break;
+ case 4800:
+ t = BPS_4800;
+ break;
+ case 9600:
+ t = BPS_9600;
+ break;
+ case 19200:
+ t = BPS_19200;
+ break;
+ case 38400:
+ t = BPS_38400;
+ break;
+ default:
+ printk(KERN_INFO "sci: unsupported baud rate: %d, use 115200 instead.\n", port->gs.baud);
+ case 115200:
+ t = BPS_115200;
+ break;
+ }
+
+ if (t > 0) {
+ sci_setsignals (port, 1, -1);
+ ctrl_outb(t, SCBRR);
+ ctrl_outw(0xa400, RFCR); /* Refresh counter clear */
+ while (ctrl_inw(RFCR) < WAIT_RFCR_COUNTER)
+ ;
+ } else {
+ sci_setsignals (port, 0, -1);
+ }
+}
+
+static void sci_set_termios_cflag(struct sci_port *port)
+{
+ unsigned short status;
+ unsigned short smr_val=0;
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ unsigned short fcr_val=6; /* TFRST=1, RFRST=1 */
+#endif
+
+ do
+ status = ctrl_in(SC_SR);
+ while (!(status & SCI_TEND));
+
+ port->old_cflag = port->gs.tty->termios->c_cflag;
+
+ ctrl_out(0x00, SCSCR); /* TE=0, RE=0, CKE1=0 */
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ ctrl_out(fcr_val, SCFCR);
+ fcr_val = 0;
+#endif
+
+ if ((port->gs.tty->termios->c_cflag & CSIZE) == CS7)
+ smr_val |= 0x40;
+ if (C_PARENB(port->gs.tty))
+ smr_val |= 0x20;
+ if (C_PARODD(port->gs.tty))
+ smr_val |= 0x10;
+ if (C_CSTOPB(port->gs.tty))
+ smr_val |= 0x08;
+ ctrl_out(smr_val, SCSMR);
+
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ if (C_CRTSCTS(port->gs.tty))
+ fcr_val |= 0x08;
+ ctrl_out(fcr_val, SCFCR);
+#endif
+
+ sci_set_baud(port);
+ ctrl_out(SCSCR_INIT, SCSCR); /* TIE=0,RIE=0,TE=1,RE=1 */
+#if 0 /* defined(CONFIG_SH_SCIF_SERIAL) */
+ ctrl_outw(0x0080, SCSPTR); /* Set RTS = 1 */
+#endif
+ sci_enable_rx_interrupts(port);
+}
+
+static void sci_set_real_termios(void *ptr)
+{
+ struct sci_port *port = ptr;
+
+ if (port->old_cflag != port->gs.tty->termios->c_cflag)
+ sci_set_termios_cflag(port);
+
+ /* Tell line discipline whether we will do input cooking */
+ if (I_OTHER(port->gs.tty))
+ clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
+ else
+ set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
+
+/* Tell line discipline whether we will do output cooking.
+ * If OPOST is set and no other output flags are set then we can do output
+ * processing. Even if only *one* other flag in the O_OTHER group is set
+ * we do cooking in software.
+ */
+ if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty))
+ set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
+ else
+ clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
+}
+
+/* ********************************************************************** *
+ * the interrupt related routines *
+ * ********************************************************************** */
+
+static void sci_transmit_chars(struct sci_port *port)
+{
+ int count, i;
+ int txroom;
+ unsigned long flags;
+ unsigned short status;
+ unsigned short ctrl;
+ unsigned char c;
+
+ status = ctrl_in(SC_SR);
+ if (!(status & SCI_TD_E)) {
+ save_and_cli(flags);
+ ctrl = ctrl_in(SCSCR);
+ if (port->gs.xmit_cnt == 0) {
+ ctrl &= ~SCI_CTRL_FLAGS_TIE;
+ port->gs.flags &= ~GS_TX_INTEN;
+ } else
+ ctrl |= SCI_CTRL_FLAGS_TIE;
+ ctrl_out(ctrl, SCSCR);
+ restore_flags(flags);
+ return;
+ }
+
+ while (1) {
+ count = port->gs.xmit_cnt;
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ txroom = 16 - (ctrl_inw(SCFDR)>>8);
+#else
+ txroom = (ctrl_in(SC_SR)&SCI_TD_E)?1:0;
+#endif
+ if (count > txroom)
+ count = txroom;
+
+ /* Don't copy pas the end of the source buffer */
+ if (count > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
+ count = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
+
+ /* If for one reason or another, we can't copy more data, we're done! */
+ if (count == 0)
+ break;
+
+ for (i=0; i<count; i++) {
+ c = port->gs.xmit_buf[port->gs.xmit_tail + i];
+ ctrl_outb(c, SC_TDR);
+ }
+ ctrl_out(SCI_TD_E_CLEAR, SC_SR);
+
+ /* Update the kernel buffer end */
+ port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1);
+
+ /* This one last. (this is essential)
+ It would allow others to start putting more data into the buffer! */
+ port->gs.xmit_cnt -= count;
+ }
+
+ if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+ if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ port->gs.tty->ldisc.write_wakeup)
+ (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+ wake_up_interruptible(&port->gs.tty->write_wait);
+ }
+
+ save_and_cli(flags);
+ ctrl = ctrl_in(SCSCR);
+ if (port->gs.xmit_cnt == 0) {
+ ctrl &= ~SCI_CTRL_FLAGS_TIE;
+ port->gs.flags &= ~GS_TX_INTEN;
+ } else {
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ ctrl_in(SC_SR); /* Dummy read */
+ ctrl_out(SCI_TD_E_CLEAR, SC_SR);
+#endif
+ ctrl |= SCI_CTRL_FLAGS_TIE;
+ }
+ ctrl_out(ctrl, SCSCR);
+ restore_flags(flags);
+}
+
+static inline void sci_receive_chars(struct sci_port *port)
+{
+ int i, count;
+ struct tty_struct *tty;
+ int copied=0;
+ unsigned short status;
+
+ status = ctrl_in(SC_SR);
+ if (!(status & SCI_RD_F))
+ return;
+
+ tty = port->gs.tty;
+ while (1) {
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ count = ctrl_inw(SCFDR)&0x001f;
+#else
+ count = (ctrl_in(SC_SR)&SCI_RD_F)?1:0;
+#endif
+
+ /* Don't copy more bytes than there is room for in the buffer */
+ if (tty->flip.count + count > TTY_FLIPBUF_SIZE)
+ count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+ /* If for one reason or another, we can't copy more data, we're done! */
+ if (count == 0)
+ break;
+
+ for (i=0; i<count; i++)
+ tty->flip.char_buf_ptr[i] = ctrl_inb(SC_RDR);
+ ctrl_in(SC_SR); /* dummy read */
+ ctrl_out(SCI_RDRF_CLEAR, SC_SR);
+
+ memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count);
+
+ /* Update the kernel buffer end */
+ tty->flip.count += count;
+ tty->flip.char_buf_ptr += count;
+ tty->flip.flag_buf_ptr += count;
+
+ copied += count;
+ }
+
+ if (copied)
+ /* Tell the rest of the system the news. New characters! */
+ tty_flip_buffer_push(tty);
+}
+
+static void sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ struct sci_port *port = ptr;
+
+ if (port->gs.flags & GS_ACTIVE)
+ if (!(port->gs.flags & SCI_RX_THROTTLE))
+ sci_receive_chars(port);
+}
+
+static void sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ struct sci_port *port = ptr;
+
+ if (port->gs.flags & GS_ACTIVE)
+ if (port->gs.xmit_cnt) {
+ sci_transmit_chars(port);
+ }
+}
+
+static void sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
+{
+ /* Handle errors */
+ if (ctrl_in(SC_SR) & SCI_ERRORS)
+ ctrl_out(SCI_ERROR_CLEAR, SC_SR);
+
+ /* Kick the transmission */
+ sci_tx_interrupt(irq, ptr, regs);
+}
+
+/* ********************************************************************** *
+ * Here are the routines that actually *
+ * interface with the generic_serial driver *
+ * ********************************************************************** */
+
+static void sci_disable_tx_interrupts(void *ptr)
+{
+ unsigned long flags;
+ unsigned short ctrl;
+
+ /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
+ save_and_cli(flags);
+ ctrl = ctrl_in(SCSCR);
+ ctrl &= ~SCI_CTRL_FLAGS_TIE;
+ ctrl_out(ctrl, SCSCR);
+ restore_flags(flags);
+}
+
+static void sci_enable_tx_interrupts(void *ptr)
+{
+ struct sci_port *port = ptr;
+
+ disable_irq(SCI_TXI_IRQ);
+ sci_transmit_chars(port);
+ enable_irq(SCI_TXI_IRQ);
+}
+
+static void sci_disable_rx_interrupts(void * ptr)
+{
+ unsigned long flags;
+ unsigned short ctrl;
+
+ /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
+ save_and_cli(flags);
+ ctrl = ctrl_in(SCSCR);
+ ctrl &= ~SCI_CTRL_FLAGS_RIE;
+ ctrl_out(ctrl, SCSCR);
+ restore_flags(flags);
+}
+
+static void sci_enable_rx_interrupts(void * ptr)
+{
+ unsigned long flags;
+ unsigned short ctrl;
+
+ /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
+ save_and_cli(flags);
+ ctrl = ctrl_in(SCSCR);
+ ctrl |= SCI_CTRL_FLAGS_RIE;
+ ctrl_out(ctrl, SCSCR);
+ restore_flags(flags);
+}
+
+static int sci_get_CD(void * ptr)
+{
+ /* If you have signal for CD (Carrier Detect), please change here. */
+ return 1;
+}
+
+static int sci_chars_in_buffer(void * ptr)
+{
+#if defined(CONFIG_SH_SCIF_SERIAL)
+ return (ctrl_inw(SCFDR) >> 8) + ((ctrl_in(SC_SR) & SCI_TEND)? 0: 1);
+#else
+ return (ctrl_in(SC_SR) & SCI_TEND)? 0: 1;
+#endif
+}
+
+static void sci_shutdown_port(void * ptr)
+{
+ struct sci_port *port = ptr;
+
+ port->gs.flags &= ~ GS_ACTIVE;
+ if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL)
+ sci_setsignals(port, 0, 0);
+}
+
+/* ********************************************************************** *
+ * Here are the routines that actually *
+ * interface with the rest of the system *
+ * ********************************************************************** */
+
+static int sci_open(struct tty_struct * tty, struct file * filp)
+{
+ struct sci_port *port;
+ int retval, line;
+
+ line = MINOR(tty->device) - SCI_MINOR_START;
+
+ if ((line < 0) || (line >= SCI_NPORTS))
+ return -ENODEV;
+
+ port = &sci_ports[line];
+
+ tty->driver_data = port;
+ port->gs.tty = tty;
+ port->gs.count++;
+
+ /*
+ * Start up serial port
+ */
+ retval = gs_init_port(&port->gs);
+ if (retval) {
+ port->gs.count--;
+ return retval;
+ }
+
+ port->gs.flags |= GS_ACTIVE;
+ sci_setsignals(port, 1,1);
+
+ if (port->gs.count == 1) {
+ MOD_INC_USE_COUNT;
+ }
+
+ retval = block_til_ready(port, filp);
+
+ if (retval) {
+ MOD_DEC_USE_COUNT;
+ port->gs.count--;
+ return retval;
+ }
+
+ if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = port->gs.normal_termios;
+ else
+ *tty->termios = port->gs.callout_termios;
+ sci_set_real_termios(port);
+ }
+
+ sci_enable_rx_interrupts(port);
+
+ port->gs.session = current->session;
+ port->gs.pgrp = current->pgrp;
+
+ return 0;
+}
+
+static void sci_hungup(void *ptr)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static void sci_close(void *ptr)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static int sci_ioctl(struct tty_struct * tty, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int rc;
+ struct sci_port *port = tty->driver_data;
+ int ival;
+
+ rc = 0;
+ switch (cmd) {
+ case TIOCGSOFTCAR:
+ rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+ (unsigned int *) arg);
+ break;
+ case TIOCSSOFTCAR:
+ if ((rc = verify_area(VERIFY_READ, (void *) arg,
+ sizeof(int))) == 0) {
+ get_user(ival, (unsigned int *) arg);
+ tty->termios->c_cflag =
+ (tty->termios->c_cflag & ~CLOCAL) |
+ (ival ? CLOCAL : 0);
+ }
+ break;
+ case TIOCGSERIAL:
+ if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct))) == 0)
+ gs_getserial(&port->gs, (struct serial_struct *) arg);
+ break;
+ case TIOCSSERIAL:
+ if ((rc = verify_area(VERIFY_READ, (void *) arg,
+ sizeof(struct serial_struct))) == 0)
+ rc = gs_setserial(&port->gs,
+ (struct serial_struct *) arg);
+ break;
+ case TIOCMGET:
+ if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int))) == 0) {
+ ival = sci_getsignals(port);
+ put_user(ival, (unsigned int *) arg);
+ }
+ break;
+ case TIOCMBIS:
+ if ((rc = verify_area(VERIFY_READ, (void *) arg,
+ sizeof(unsigned int))) == 0) {
+ get_user(ival, (unsigned int *) arg);
+ sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
+ ((ival & TIOCM_RTS) ? 1 : -1));
+ }
+ break;
+ case TIOCMBIC:
+ if ((rc = verify_area(VERIFY_READ, (void *) arg,
+ sizeof(unsigned int))) == 0) {
+ get_user(ival, (unsigned int *) arg);
+ sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
+ ((ival & TIOCM_RTS) ? 0 : -1));
+ }
+ break;
+ case TIOCMSET:
+ if ((rc = verify_area(VERIFY_READ, (void *) arg,
+ sizeof(unsigned int))) == 0) {
+ get_user(ival, (unsigned int *)arg);
+ sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
+ ((ival & TIOCM_RTS) ? 1 : 0));
+ }
+ break;
+
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+
+ return rc;
+}
+
+static void sci_throttle(struct tty_struct * tty)
+{
+ struct sci_port *port = (struct sci_port *)tty->driver_data;
+
+ /* If the port is using any type of input flow
+ * control then throttle the port.
+ */
+ if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) )
+ port->gs.flags |= SCI_RX_THROTTLE;
+}
+
+static void sci_unthrottle(struct tty_struct * tty)
+{
+ struct sci_port *port = (struct sci_port *)tty->driver_data;
+
+ /* Always unthrottle even if flow control is not enabled on
+ * this port in case we disabled flow control while the port
+ * was throttled
+ */
+ port->gs.flags &= ~SCI_RX_THROTTLE;
+ return;
+}
+
+/* ********************************************************************** *
+ * Here are the initialization routines. *
+ * ********************************************************************** */
+
+static int sci_init_drivers(void)
+{
+ int error;
+ struct sci_port *port;
+
+ memset(&sci_driver, 0, sizeof(sci_driver));
+ sci_driver.magic = TTY_DRIVER_MAGIC;
+ sci_driver.driver_name = "serial";
+ sci_driver.name = "ttyS";
+ sci_driver.major = TTY_MAJOR;
+ sci_driver.minor_start = SCI_MINOR_START;
+ sci_driver.num = 1;
+ sci_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ sci_driver.subtype = SERIAL_TYPE_NORMAL;
+ sci_driver.init_termios = tty_std_termios;
+ sci_driver.init_termios.c_cflag =
+ B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ sci_driver.flags = TTY_DRIVER_REAL_RAW;
+ sci_driver.refcount = &sci_refcount;
+ sci_driver.table = sci_table;
+ sci_driver.termios = &sci_termios[0];
+ sci_driver.termios_locked = &sci_termios[1];
+ sci_termios[0] = sci_termios[1] = NULL;
+
+ sci_driver.open = sci_open;
+ sci_driver.close = gs_close;
+ sci_driver.write = gs_write;
+ sci_driver.put_char = gs_put_char;
+ sci_driver.flush_chars = gs_flush_chars;
+ sci_driver.write_room = gs_write_room;
+ sci_driver.chars_in_buffer = gs_chars_in_buffer;
+ sci_driver.flush_buffer = gs_flush_buffer;
+ sci_driver.ioctl = sci_ioctl;
+ sci_driver.throttle = sci_throttle;
+ sci_driver.unthrottle = sci_unthrottle;
+ sci_driver.set_termios = gs_set_termios;
+ sci_driver.stop = gs_stop;
+ sci_driver.start = gs_start;
+ sci_driver.hangup = gs_hangup;
+
+ sci_callout_driver = sci_driver;
+ sci_callout_driver.name = "cua";
+ sci_callout_driver.major = TTYAUX_MAJOR;
+ sci_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+ if ((error = tty_register_driver(&sci_driver))) {
+ printk(KERN_ERR "sci: Couldn't register SCI driver, error = %d\n",
+ error);
+ return 1;
+ }
+ if ((error = tty_register_driver(&sci_callout_driver))) {
+ tty_unregister_driver(&sci_driver);
+ printk(KERN_ERR "sci: Couldn't register SCI callout driver, error = %d\n",
+ error);
+ return 1;
+ }
+
+ port = &sci_ports[0];
+ port->gs.callout_termios = tty_std_termios;
+ port->gs.normal_termios = tty_std_termios;
+ port->gs.magic = SCI_MAGIC;
+ port->gs.close_delay = HZ/2;
+ port->gs.closing_wait = 30 * HZ;
+ port->gs.rd = &sci_real_driver;
+ init_waitqueue_head(&port->gs.open_wait);
+ init_waitqueue_head(&port->gs.close_wait);
+ port->old_cflag = 0;
+
+ return 0;
+}
+
+#ifdef MODULE
+#define sci_init init_module
+#else
+#define sci_init rs_init
+#endif
+
+int __init sci_init(void)
+{
+ struct sci_port *port;
+ int i;
+
+ for (i=SCI_ERI_IRQ; i<SCI_IRQ_END; i++)
+ set_ipr_data(i, SCI_IPR_OFFSET, SCI_PRIORITY);
+
+ port = &sci_ports[0];
+
+ if (request_irq(SCI_ERI_IRQ, sci_er_interrupt, SA_INTERRUPT,
+ "serial", port)) {
+ printk(KERN_ERR "sci: Cannot allocate error irq.\n");
+ return -ENODEV;
+ }
+ if (request_irq(SCI_RXI_IRQ, sci_rx_interrupt, SA_INTERRUPT,
+ "serial", port)) {
+ printk(KERN_ERR "sci: Cannot allocate rx irq.\n");
+ return -ENODEV;
+ }
+ if (request_irq(SCI_TXI_IRQ, sci_tx_interrupt, SA_INTERRUPT,
+ "serial", port)) {
+ printk(KERN_ERR "sci: Cannot allocate tx irq.\n");
+ return -ENODEV;
+ }
+ /* XXX: How about BRI interrupt?? */
+
+ sci_init_drivers();
+
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+ gdb_detach();
+#endif
+ return 0; /* Return -EIO when not detected */
+}
+
+#ifdef MODULE
+#undef func_enter
+#undef func_exit
+
+void cleanup_module(void)
+{
+ int i;
+
+ for (i=SCI_ERI_IRQ; i<SCI_TEI_IRQ; i++) /* XXX: irq_end?? */
+ free_irq(i, port);
+
+ tty_unregister_driver(&sci_driver);
+ tty_unregister_driver(&sci_callout_driver);
+}
+
+#include "generic_serial.c"
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+/*
+ * ------------------------------------------------------------
+ * Serial console driver for SH-3/SH-4 SCI (with no FIFO)
+ * ------------------------------------------------------------
+ */
+
+static inline void put_char(char c)
+{
+ unsigned long flags;
+ unsigned short status;
+
+ save_and_cli(flags);
+
+ do
+ status = ctrl_in(SC_SR);
+ while (!(status & SCI_TD_E));
+
+ ctrl_outb(c, SC_TDR);
+ ctrl_out(SCI_TD_E_CLEAR, SC_SR);
+
+ restore_flags(flags);
+}
+
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+static int in_gdb = 1;
+
+static inline void handle_error(void)
+{ /* Clear error flags */
+ ctrl_out(SCI_ERROR_CLEAR, SC_SR);
+}
+
+static inline int get_char(void)
+{
+ unsigned long flags;
+ unsigned short status;
+ int c;
+
+ save_and_cli(flags);
+ do {
+ status = ctrl_in(SC_SR);
+ if (status & SCI_ERRORS) {
+ handle_error();
+ continue;
+ }
+ } while (!(status & SCI_RD_F));
+ c = ctrl_inb(SC_RDR);
+ ctrl_out(SCI_RDRF_CLEAR, SC_SR);
+ restore_flags(flags);
+
+ return c;
+}
+
+/* Taken from sh-stub.c of GDB 4.18 */
+static const char hexchars[] = "0123456789abcdef";
+static char highhex(int x)
+{
+ return hexchars[(x >> 4) & 0xf];
+}
+
+static char lowhex(int x)
+{
+ return hexchars[x & 0xf];
+}
+
+static void gdb_detach(void)
+{
+ asm volatile("trapa #0xff");
+
+ if (in_gdb == 1) {
+ in_gdb = 0;
+ get_char();
+ put_char('\r');
+ put_char('\n');
+ }
+}
+#endif
+
+/* send the packet in buffer. The host get's one chance to read it.
+ This routine does not wait for a positive acknowledge. */
+
+static void
+put_string(const char *buffer, int count)
+{
+ int i;
+ const unsigned char *p = buffer;
+#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
+ int checksum;
+
+if (in_gdb) {
+ /* $<packet info>#<checksum>. */
+ do {
+ unsigned char c;
+ put_char('$');
+ put_char('O'); /* 'O'utput to console */
+ checksum = 'O';
+
+ for (i=0; i<count; i++) { /* Don't use run length encoding */
+ int h, l;
+
+ c = *p++;
+ h = highhex(c);
+ l = lowhex(c);
+ put_char(h);
+ put_char(l);
+ checksum += h + l;
+ }
+ put_char('#');
+ put_char(highhex(checksum));
+ put_char(lowhex(checksum));
+ } while (get_char() != '+');
+} else
+#endif
+ for (i=0; i<count; i++) {
+ if (*p == 10)
+ put_char('\r');
+ put_char(*p++);
+ }
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ */
+static void serial_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ put_string(s, count);
+}
+
+/*
+ * Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+ /* Not implemented yet */
+ return 0;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR, SCI_MINOR_START + c->index);
+}
+
+/*
+ * Setup initial baud/bits/parity. We do two things here:
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * Return non-zero if we didn't find a serial port.
+ */
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int cflag = CREAD | HUPCL | CLOCAL;
+ char *s;
+
+ if (options) {
+ baud = simple_strtoul(options, NULL, 10);
+ s = options;
+ while(*s >= '0' && *s <= '9')
+ s++;
+ if (*s) parity = *s++;
+ if (*s) bits = *s - '0';
+ }
+
+ /*
+ * Now construct a cflag setting.
+ */
+ switch (baud) {
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 38400:
+ cflag |= B38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ case 9600:
+ default:
+ cflag |= B9600;
+ break;
+ }
+ switch (bits) {
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
+ }
+ switch (parity) {
+ case 'o': case 'O':
+ cflag |= PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
+ }
+ co->cflag = cflag;
+
+ /* XXX: set baud, char, and parity here. */
+ return 0;
+}
+
+static struct console sercons = {
+ "ttyS",
+ serial_console_write,
+ NULL,
+ serial_console_device,
+ serial_console_wait_key,
+ NULL,
+ serial_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+/*
+ * Register console.
+ */
+
+void __init serial_console_init(void)
+{
+ register_console(&sercons);
+}
+#endif /* CONFIG_SERIAL_CONSOLE */
diff --git a/drivers/char/sh-sci.h b/drivers/char/sh-sci.h
new file mode 100644
index 000000000..9239e41d7
--- /dev/null
+++ b/drivers/char/sh-sci.h
@@ -0,0 +1,196 @@
+/* $Id: sh-sci.h,v 1.5 2000-03-05 13:54:32+09 gniibe Exp $
+ *
+ * linux/drivers/char/sh-sci.h
+ *
+ * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
+ * Copyright (C) 1999, 2000 Niibe Yutaka
+ * Copyright (C) 2000 Greg Banks
+ *
+ */
+#include <linux/config.h>
+
+#if defined(CONFIG_SH_SCI_SERIAL)
+#if defined(__sh3__)
+#define SCSMR (volatile unsigned char *)0xfffffe80
+#define SCBRR 0xfffffe82
+#define SCSCR (volatile unsigned char *)0xfffffe84
+#define SC_TDR 0xfffffe86
+#define SC_SR (volatile unsigned char *)0xfffffe88
+#define SC_RDR 0xfffffe8a
+#define SCSPTR 0xffffff7c
+
+#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
+
+#elif defined(__SH4__)
+Not yet.
+#endif
+
+#define SCI_TD_E 0x80
+#define SCI_RD_F 0x40
+#define SCI_ORER 0x20
+#define SCI_FER 0x10
+#define SCI_PER 0x08
+#define SCI_TEND 0x04
+
+#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
+#define SCI_TD_E_CLEAR 0x78
+#define SCI_RDRF_CLEAR 0xbc
+#define SCI_ERROR_CLEAR 0xc4
+
+#define SCI_CTRL_FLAGS_TIE 0x80
+#define SCI_CTRL_FLAGS_RIE 0x40
+#define SCI_CTRL_FLAGS_TE 0x20
+#define SCI_CTRL_FLAGS_RE 0x10
+/* TEIE=0x04 */
+#define SCI_CTRL_FLAGS_CKE1 0x02
+#define SCI_CTRL_FLAGS_CKE0 0x01
+
+#define RFCR 0xffffff74
+
+#define SCI_ERI_IRQ 23
+#define SCI_RXI_IRQ 24
+#define SCI_TXI_IRQ 25
+#define SCI_TEI_IRQ 26
+#define SCI_IRQ_END 27
+
+#define SCI_IPR_OFFSET (16+4)
+#endif
+
+#if defined(CONFIG_SH_SCIF_SERIAL)
+#if defined(__sh3__)
+#define SCSMR (volatile unsigned char *)0xA4000150
+#define SCBRR 0xA4000152
+#define SCSCR (volatile unsigned char *)0xA4000154
+#define SC_TDR 0xA4000156
+#define SC_SR (volatile unsigned short *)0xA4000158
+#define SC_RDR 0xA400015A
+#define SCFCR (volatile unsigned char *)0xA400015C
+#define SCFDR 0xA400015E
+#undef SCSPTR /* Is there any register for RTS?? */
+#undef SCLSR
+
+#define RFCR 0xffffff74
+
+#define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
+ /* 0x33 when external clock is used */
+#define SCI_IPR_OFFSET (64+4)
+
+#elif defined(__SH4__)
+#define SCSMR (volatile unsigned short *)0xFFE80000
+#define SCBRR 0xFFE80004
+#define SCSCR (volatile unsigned short *)0xFFE80008
+#define SC_TDR 0xFFE8000C
+#define SC_SR (volatile unsigned short *)0xFFE80010
+#define SC_RDR 0xFFE80014
+#define SCFCR (volatile unsigned short *)0xFFE80018
+#define SCFDR 0xFFE8001C
+#define SCSPTR 0xFFE80020
+#define SCLSR 0xFFE80024
+
+#define RFCR 0xFF800028
+
+#define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#define SCI_IPR_OFFSET (32+4)
+
+#endif
+
+#define SCI_ER 0x0080
+#define SCI_TEND 0x0040
+#define SCI_TD_E 0x0020
+#define SCI_BRK 0x0010
+#define SCI_FER 0x0008
+#define SCI_PER 0x0004
+#define SCI_RD_F 0x0002
+#define SCI_DR 0x0001
+
+#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ER | SCI_BRK)
+#define SCI_TD_E_CLEAR 0x00df
+#define SCI_TEND_CLEAR 0x00bf
+#define SCI_RDRF_CLEAR 0x00fc
+#define SCI_ERROR_CLEAR 0x0063
+
+#define SCI_CTRL_FLAGS_TIE 0x80
+#define SCI_CTRL_FLAGS_RIE 0x40
+#define SCI_CTRL_FLAGS_TE 0x20
+#define SCI_CTRL_FLAGS_RE 0x10
+#define SCI_CTRL_FLAGS_REIE 0x08
+#define SCI_CTRL_FLAGS_CKE1 0x02
+
+#if defined(__sh3__)
+#define SCI_ERI_IRQ 56
+#define SCI_RXI_IRQ 57
+#define SCI_BRI_IRQ 58
+#define SCI_TXI_IRQ 59
+#define SCI_IRQ_END 60
+#elif defined(__SH4__)
+#define SCI_ERI_IRQ 40
+#define SCI_RXI_IRQ 41
+#define SCI_BRI_IRQ 42
+#define SCI_TXI_IRQ 43
+#define SCI_IRQ_END 44
+#endif
+#endif
+
+#define SCI_PRIORITY 3
+
+#define SCI_MINOR_START 64
+#define SCI_RX_THROTTLE 0x0000001
+
+#define O_OTHER(tty) \
+ ((O_OLCUC(tty)) ||\
+ (O_ONLCR(tty)) ||\
+ (O_OCRNL(tty)) ||\
+ (O_ONOCR(tty)) ||\
+ (O_ONLRET(tty)) ||\
+ (O_OFILL(tty)) ||\
+ (O_OFDEL(tty)) ||\
+ (O_NLDLY(tty)) ||\
+ (O_CRDLY(tty)) ||\
+ (O_TABDLY(tty)) ||\
+ (O_BSDLY(tty)) ||\
+ (O_VTDLY(tty)) ||\
+ (O_FFDLY(tty)))
+
+#define I_OTHER(tty) \
+ ((I_INLCR(tty)) ||\
+ (I_IGNCR(tty)) ||\
+ (I_ICRNL(tty)) ||\
+ (I_IUCLC(tty)) ||\
+ (L_ISIG(tty)))
+
+#define SCI_MAGIC 0xbabeface
+
+struct sci_port {
+ struct gs_port gs;
+ unsigned int old_cflag;
+};
+
+#define WAIT_RFCR_COUNTER 200
+
+/*
+ * Values for the BitRate Register (SCBRR)
+ *
+ * The values are actually divisors for a frequency which can
+ * be internal to the SH3 (14.7456MHz) or derived from an external
+ * clock source. This driver assumes the internal clock is used;
+ * to support using an external clock source, config options or
+ * possibly command-line options would need to be added.
+ *
+ * Also, to support speeds below 2400 (why?) the lower 2 bits of
+ * the SCSMR register would also need to be set to non-zero values.
+ *
+ * -- Greg Banks 27Feb2000
+ */
+
+#if defined(__sh3__)
+#define BPS_2400 191
+#define BPS_4800 95
+#define BPS_9600 47
+#define BPS_19200 23
+#define BPS_38400 11
+#define BPS_115200 3
+#elif defined(__SH4__)
+/* Values for SH-4 please! */
+
+#define BPS_115200 8
+#endif
diff --git a/drivers/char/stradis.c b/drivers/char/stradis.c
index b63f35436..6d98f9323 100644
--- a/drivers/char/stradis.c
+++ b/drivers/char/stradis.c
@@ -28,6 +28,7 @@
#include <linux/major.h>
#include <linux/malloc.h>
#include <linux/mm.h>
+#include <linux/init.h>
#include <linux/poll.h>
#include <linux/pci.h>
#include <linux/signal.h>
@@ -2236,13 +2237,9 @@ static void release_saa(void)
}
}
-#ifdef MODULE
-int init_module(void)
-{
-#else
-int init_stradis_cards(struct video_init *unused)
+
+static int __init stradis_init (void)
{
-#endif
struct pci_dev *dev = NULL;
int result = 0, i;
@@ -2269,11 +2266,14 @@ int init_stradis_cards(struct video_init *unused)
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+
+static void __exit stradis_exit (void)
{
release_saa();
printk(KERN_INFO "stradis: module cleanup complete\n");
}
-#endif
+
+module_init(stradis_init);
+module_exit(stradis_exit);
+
diff --git a/drivers/char/tda9855.c b/drivers/char/tda9855.c
deleted file mode 100644
index dfdee66dc..000000000
--- a/drivers/char/tda9855.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * For the TDA9855 chip (afaik, only the Diamond DTV2000 has this)
- * This driver will not complain if used with a TDA9850 or any
- * other i2c device with the same address.
- *
- * Copyright (c) 1999 Steve VanDeBogart (vandebo@uclink.berkeley.edu)
- * This code is placed under the terms of the GNU General Public License
- * Based on tda8425.c by Greg Alexander (c) 1998
- *
- * TODO:
- * Fix channel change bug - sound goes out when changeing channels, mute
- * and unmote to fix.
- * Fine tune sound
- * Get rest of capabilities into video_audio struct...
- *
- * Revision: 0.1
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/malloc.h>
-#include <linux/videodev.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include "bttv.h"
-#include "audiochip.h"
-
-
-MODULE_PARM(debug,"i");
-static int debug = 0; /* insmod parameter */
-
-/* Addresses to scan */
-#define I2C_TDA9855_L 0xb4
-#define I2C_TDA9855_H 0xb6
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {
- I2C_TDA9855_L >> 1,
- I2C_TDA9855_H >> 1,
- I2C_CLIENT_END};
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static struct i2c_client_address_data addr_data = {
- normal_i2c, normal_i2c_range,
- probe, probe_range,
- ignore, ignore_range,
- force
-};
-
-struct tda9855 {
- int addr;
- int rvol, lvol;
- int bass, treble, sub;
- int c1, c2, c3;
- int a1, a2, a3;
-};
-
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-
-#define dprintk if (debug) printk
-
- /* subaddresses */
-#define TDA9855_VR 0x00 /* Volume, right */
-#define TDA9855_VL 0x01 /* Volume, left */
-#define TDA9855_BA 0x02 /* Bass */
-#define TDA9855_TR 0x03 /* Treble */
-#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */
-#define TDA9855_C1 0x05 /* Control 1 */
-#define TDA9855_C2 0x06 /* Control 2 */
-#define TDA9855_C3 0x07 /* Control 3 */
-#define TDA9855_A1 0x08 /* Alignmnet 1*/
-#define TDA9855_A2 0x09 /* Alignmnet 2*/
-#define TDA9855_A3 0x0a /* Alignmnet 3*/
- /* Masks for bits in subaddresses */
-/* VR */ /* VL */
-/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f)
- * in 1dB steps - mute is 0x27 */
-
-/* BA */
-/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19)
- * in .5dB steps - 0 is 0x0E */
-
-/* TR */
-/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb)
- * in 3dB steps - 0 is 0x7 */
-
-/* SW */
-/* 4 bits << 2 control subwoofer/surraound gain from -14db (0x1) to 14db (0xf)
- * in 3dB steps - mute is 0x0 */
-
-/* C1 */
-#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */
-#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */
-#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */
-#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
- /* Bits 0 to 3 select various combinations
- * of line in and line out, only the
- * interesting ones are defined */
-#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */
-#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */
-
-/* C2 */
-#define TDA9855_SAP 3<<6 /* Selects SAP output, mute if not received */
-#define TDA9855_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */
-#define TDA9855_MONO 0 /* Forces Mono output */
-#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */
-#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/
-#define TDA9855_LMU 1<<3 /* Mute at LOR and LOL */
-#define TDA9855_LINEAR 0 /* Linear Stereo */
-#define TDA9855_PSEUDO 1 /* Pseudo Stereo */
-#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */
-#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */
-#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/
-
-/* C3 */
-/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF)
- * in .5dB steps - 0 is 0x7 */
-
-/* A1 and A2 (read/write) */
-/* lower 5 bites are wideband and spectral expander alignment
- * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */
-#define TDA9855_STP 1<<5 /* Stereo Pilot/detect (read-only) */
-#define TDA9855_SAPP 1<<6 /* SAP Pilot/detect (read-only) */
-#define TDA9855_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/
-
-/* A3 */
-/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1),
- * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */
-/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2),
- * 1200ohm (0x1), 2100ohm (0x3) */
-#define TDA9855_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral) */
-
-
-/* Begin code */
-
-static int tda9855_write(struct i2c_client *client, int subaddr, int val)
-{
- unsigned char buffer[2];
-
- buffer[0] = subaddr;
- buffer[1] = val;
- if (2 != i2c_master_send(client,buffer,2)) {
- printk(KERN_WARNING "tda9855: I/O error, trying (write %d 0x%x)\n",
- subaddr, val);
- return -1;
- }
- return 0;
-}
-
-static int tda9855_read(struct i2c_client *client)
-{
- unsigned char buffer;
-
- if (1 != i2c_master_recv(client,&buffer,1)) {
- printk(KERN_WARNING "tda9855: I/O error, trying (read)\n");
- return -1;
- }
- return buffer;
-}
-
-static int tda9855_set(struct i2c_client *client)
-{
- struct tda9855 *t = client->data;
- unsigned char buf[16];
-
- dprintk(KERN_INFO "tda9855_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",t->rvol,t->lvol,t->bass,t->treble,t->sub,
- t->c1,t->c2,t->c3,t->a1,t->a2,t->a3);
- buf[0] = TDA9855_VR;
- buf[1] = t->rvol;
- buf[2] = t->lvol;
- buf[3] = t->bass;
- buf[4] = t->treble;
- buf[5] = t->sub;
- buf[6] = t->c1;
- buf[7] = t->c2;
- buf[8] = t->c3;
- buf[9] = t->a1;
- buf[10] = t->a2;
- buf[11] = t->a3;
- if (12 != i2c_master_send(client,buf,12)) {
- printk(KERN_WARNING "tda9855: I/O error, trying tda9855_set\n");
- return -1;
- }
- return 0;
-}
-
-static void do_tda9855_init(struct i2c_client *client)
-{
- struct tda9855 *t = client->data;
-
- t->rvol=0x6f; /* 0dB */
- t->lvol=0x6f; /* 0dB */
- t->bass=0x0e; /* 0dB */
- t->treble=(0x07 << 1); /* 0dB */
- t->sub=0x8 << 2; /* 0dB */
- t->c1=TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT;
- /* Set Mute, AVL, Loudness off, Internal sound */
- t->c2=TDA9855_STEREO | TDA9855_LINEAR; /* Set Stereo liner mode */
- t->c3=0x07; /* 0dB input gain */
- t->a1=0x10; /* Select nominal wideband expander */
- t->a2=0x10; /* Select nominal spectral expander and 30mV trigger */
- t->a3=0x3; /* Set: nominal timinig current, 420ohm AVL attack */
- tda9855_write(client, TDA9855_C1, TDA9855_MUTE); /* mute */
- tda9855_set(client);
-}
-
-/* *********************** *
- * i2c interface functions *
- * *********************** */
-
-static int tda9855_attach(struct i2c_adapter *adap, int addr,
- unsigned short flags, int kind)
-{
- struct tda9855 *t;
- struct i2c_client *client;
-
- client = kmalloc(sizeof *client,GFP_KERNEL);
- if (!client)
- return -ENOMEM;
- memcpy(client,&client_template,sizeof(struct i2c_client));
- client->adapter = adap;
- client->addr = addr;
-
- client->data = t = kmalloc(sizeof *t,GFP_KERNEL);
- if (!t)
- return -ENOMEM;
- memset(t,0,sizeof *t);
- do_tda9855_init(client);
- MOD_INC_USE_COUNT;
- strcpy(client->name,"TDA9855");
- printk(KERN_INFO "tda9855: init\n");
-
- i2c_attach_client(client);
- return 0;
-}
-
-static int tda9855_probe(struct i2c_adapter *adap)
-{
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
- return i2c_probe(adap, &addr_data, tda9855_attach);
- return 0;
-}
-
-static int tda9855_detach(struct i2c_client *client)
-{
- struct tda9855 *t = client->data;
-
- do_tda9855_init(client);
- i2c_detach_client(client);
-
- kfree(t);
- kfree(client);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int tda9855_command(struct i2c_client *client,
- unsigned int cmd, void *arg)
-{
- struct tda9855 *t = client->data;
-#if 0
- __u16 *sarg = arg;
-#endif
-
- switch (cmd) {
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
- case VIDIOCGAUDIO:
- {
- struct video_audio *va = arg;
- int left,right;
-
- va->flags |= VIDEO_AUDIO_VOLUME |
- VIDEO_AUDIO_BASS |
- VIDEO_AUDIO_TREBLE;
-
- /* min is 0x27 max is 0x7f, vstep is 2e8 */
- left = (t->lvol-0x27)*0x2e8;
- right = (t->rvol-0x27)*0x2e8;
- va->volume=MAX(left,right);
- va->balance=(32768*MIN(left,right))/
- (va->volume ? va->volume : 1);
- va->balance=(left<right)?
- (65535-va->balance) : va->balance;
- va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max is 0x19 */
- va->treble = ((t->treble>>1)-0x3)*0x1c71;
-
- va->mode = ((TDA9855_STP | TDA9855_SAPP) &
- tda9855_read(client)) >> 4;
- va->mode |= VIDEO_SOUND_MONO;
- break;
- }
- case VIDIOCSAUDIO:
- {
- struct video_audio *va = arg;
- int left,right;
-
- left = (MIN(65536 - va->balance,32768) *
- va->volume) / 32768;
- right = (MIN(va->balance,32768) *
- va->volume) / 32768;
- t->lvol = left/0x2e8+0x27;
- t->rvol = right/0x2e8+0x27;
- t->bass = va->bass/0xccc+0x6;
- t->treble = (va->treble/0x1c71+0x3)<<1;
- tda9855_write(client,TDA9855_VL,t->lvol);
- tda9855_write(client,TDA9855_VR,t->rvol);
- tda9855_write(client,TDA9855_BA, t->bass);
- tda9855_write(client,TDA9855_TR,t->treble);
-
- switch (va->mode) {
- case VIDEO_SOUND_MONO:
- t->c2= TDA9855_MONO | (t->c2 & 0x3f);
- break;
- case VIDEO_SOUND_STEREO:
- t->c2= TDA9855_STEREO | (t->c2 & 0x3f);
- break;
- case VIDEO_SOUND_LANG1:
- t->c2= TDA9855_SAP | (t->c2 & 0x3f);
- break;
- }
- tda9855_write(client,TDA9855_C2,t->c2);
- break;
- }
-
-#if 0
- /* --- old, obsolete interface --- */
- case AUDC_GET_VOLUME_LEFT:
- *sarg = (t->lvol-0x27)*0x2e8; /* min is 0x27 max is 0x7f, vstep is 2e8 */
- break;
- case AUDC_GET_VOLUME_RIGHT:
- *sarg = (t->rvol-0x27)*0x2e8;
- break;
- case AUDC_SET_VOLUME_LEFT:
- t->lvol = *sarg/0x2e8+0x27;
- break;
- case AUDC_SET_VOLUME_RIGHT:
- t->rvol = *sarg/0x2e8+0x27;
- break;
- case AUDC_GET_BASS:
- *sarg = (t->bass-0x6)*0xccc; /* min 0x6 max is 0x19 */
- break;
- case AUDC_SET_BASS:
- t->bass = *sarg/0xccc+0x6;
- tda9855_write(client,TDA9855_BA, t->bass);
- break;
- case AUDC_GET_TREBLE:
- *sarg = ((t->treble>>1)-0x3)*0x1c71;
- break;
- case AUDC_SET_TREBLE:
- t->treble = (*sarg/0x1c71+0x3)<<1;
- tda9855_write(client,TDA9855_TR,t->treble);
- break;
- case AUDC_GET_STEREO:
- *sarg = ((TDA9855_STP | TDA9855_SAPP) &
- tda9855_read(client)) >> 4;
- if(*sarg==0) *sarg=VIDEO_SOUND_MONO;
- break;
- case AUDC_SET_STEREO:
- if(*sarg==VIDEO_SOUND_MONO)
- t->c2= TDA9855_MONO | (t->c2 & 0x3f);
- /* Mask out the sap and stereo bits and set mono */
- else if(*sarg==VIDEO_SOUND_STEREO)
- t->c2= TDA9855_STEREO | (t->c2 & 0x3f);
- /* Mask out the sap and stereo bits and set stereo */
- else if(*sarg==VIDEO_SOUND_LANG2)
- t->c2= TDA9855_SAP | (t->c2 & 0x3f);
- /* Mask out the sap and stereo bits and set sap */
- tda9855_write(client,TDA9855_C2,t->c2);
- break;
- case AUDC_SET_INPUT:
- dprintk(KERN_INFO "tda9855: SET_INPUT with 0x%04x\n",*sarg);
- if((*sarg & (AUDIO_MUTE | AUDIO_OFF))!=0)
- t->c1|=TDA9855_MUTE;
- else
- t->c1= t->c1 & 0x7f; /* won't work --> (~TDA9855_MUTE); */
- if((*sarg & AUDIO_INTERN) == AUDIO_INTERN)
- t->c1=(t->c1 & ~0x7) | TDA9855_INT; /* 0x7 is a mask for the int/ext */
- if((*sarg & AUDIO_EXTERN) == AUDIO_EXTERN)
- t->c1=(t->c1 & ~0x7) | TDA9855_EXT; /* 0x7 is a mask for the int/ext */
- tda9855_write(client,TDA9855_C1,t->c1);
- break;
- case AUDC_SWITCH_MUTE:
- if((t->c1 & ~TDA9855_MUTE) == 0)
- t->c1|=TDA9855_MUTE;
- else
- t->c1&=~TDA9855_MUTE;
- tda9855_write(client,TDA9855_C1,t->c1);
- break;
-
-/* TDA9855 unsupported: */
-/* case AUDC_NEWCHANNEL:
- case AUDC_SET_RADIO:
- case AUDC_GET_DC:
-*/
-#endif
- default:
- /* nothing */
- }
- return 0;
-}
-
-
-static struct i2c_driver driver = {
- "i2c tda9855 driver",
- I2C_DRIVERID_TDA9855,
- I2C_DF_NOTIFY,
- tda9855_probe,
- tda9855_detach,
- tda9855_command,
-};
-
-static struct i2c_client client_template =
-{
- "(unset)", /* name */
- -1,
- 0,
- 0,
- NULL,
- &driver
-};
-
-#ifdef MODULE
-int init_module(void)
-#else
-int tda9855_init(void)
-#endif
-{
- i2c_add_driver(&driver);
- return 0;
-}
-
-#ifdef MODULE
-void cleanup_module(void)
-{
- i2c_del_driver(&driver);
-}
-#endif
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/char/tda985x.c b/drivers/char/tda985x.c
new file mode 100644
index 000000000..62bcf15ba
--- /dev/null
+++ b/drivers/char/tda985x.c
@@ -0,0 +1,532 @@
+/*
+ * For the TDA9850 and TDA9855 chips
+ * (The TDA9855 is used on the Diamond DTV2000 and the TDA9850 is used
+ * on STB cards. Other cards probably use these chips as well.)
+ * This driver will not complain if used with any
+ * other i2c device with the same address.
+ *
+ * Copyright (c) 1999 Gerd Knorr
+ * TDA9850 code and TDA9855.c merger by Eric Sandeen (eric_sandeen@bigfoot.com)
+ * This code is placed under the terms of the GNU General Public License
+ * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
+ * Which was based on tda8425.c by Greg Alexander (c) 1998
+ *
+ * OPTIONS:
+ * debug - set to 1 if you'd like to see debug messages
+ * chip - set to 9850 or 9855 to select your chip (default 9855)
+ *
+ * TODO:
+ * Fix channel change bug - sound goes out when changeing channels, mute
+ * and unmote to fix. - Is this still here?
+ * Fine tune sound
+ * Get rest of capabilities into video_audio struct...
+ *
+ * Revision: 0.4 - check for correct chip= insmod value
+ * also cleaned up comments a bit
+ * Revision: 0.3 - took out extraneous tda985x_write in tda985x_command
+ * Revision: 0.2 - added insmod option chip=
+ * Revision: 0.1 - original version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "bttv.h"
+#include "audiochip.h"
+
+MODULE_PARM(debug,"i");
+MODULE_PARM(chip,"i");
+MODULE_PARM_DESC(chip, "Type of chip to handle: 9850 or 9855");
+
+static int debug = 0; /* insmod parameter */
+static int chip = 9855; /* insmod parameter */
+
+/* Addresses to scan */
+#define I2C_TDA985x_L 0xb4
+#define I2C_TDA985x_H 0xb6
+static unsigned short normal_i2c[] = {I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {
+ I2C_TDA985x_L >> 1,
+ I2C_TDA985x_H >> 1,
+ I2C_CLIENT_END};
+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static struct i2c_client_address_data addr_data = {
+ normal_i2c, normal_i2c_range,
+ probe, probe_range,
+ ignore, ignore_range,
+ force
+};
+
+/* This is a superset of the TDA9850 and TDA9855 members */
+
+struct tda985x {
+ int addr;
+ int rvol, lvol;
+ int bass, treble, sub;
+ int c4, c5, c6, c7;
+ int a1, a2, a3;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+#define dprintk if (debug) printk
+
+/* The TDA9850 and TDA9855 are both made by Philips Semiconductor
+ * http://www.semiconductors.philips.com
+ * TDA9850: I2C-bus controlled BTSC stereo/SAP decoder
+ * TDA9855: I2C-bus controlled BTSC stereo/SAP decoder and audio processor
+ *
+ * The TDA9850 has more or less a subset of the functions that the TDA9855
+ * has. As a result, we can re-use many of these defines. Anything with
+ * TDA9855 is specific to that chip, anything with TDA9850 is specific
+ * to that chip, and anything with TDA985x is valid for either.
+ *
+ * To complicate things further, the TDA9850 uses labels C1 through C4
+ * for subaddresses 0x04 through 0x07, while the TDA9855 uses
+ * C1 through C3 for subadresses 0x05 through 0x07 - quite confusing.
+ * To help keep things straight, I have renamed the various C[1,4] labels
+ * to C[4,7] so that the numerical label matches the hex value of the
+ * subaddress for both chips. At least the A[1,3] labels line up. :)
+ */
+
+ /* subaddresses for TDA9855 */
+#define TDA9855_VR 0x00 /* Volume, right */
+#define TDA9855_VL 0x01 /* Volume, left */
+#define TDA9855_BA 0x02 /* Bass */
+#define TDA9855_TR 0x03 /* Treble */
+#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */
+
+ /* subaddresses for TDA9850 */
+#define TDA9850_C4 0x04 /* Control 1 for TDA9850 */
+
+ /* subaddesses for both chips */
+#define TDA985x_C5 0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */
+#define TDA985x_C6 0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */
+#define TDA985x_C7 0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */
+#define TDA985x_A1 0x08 /* Alignment 1 for both chips */
+#define TDA985x_A2 0x09 /* Alignment 2 for both chips */
+#define TDA985x_A3 0x0a /* Alignment 3 for both chips */
+
+ /* Masks for bits in TDA9855 subaddresses */
+/* 0x00 - VR in TDA9855 */
+/* 0x01 - VL in TDA9855 */
+/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f)
+ * in 1dB steps - mute is 0x27 */
+
+
+/* 0x02 - BA in TDA9855 */
+/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19)
+ * in .5dB steps - 0 is 0x0E */
+
+
+/* 0x03 - TR in TDA9855 */
+/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb)
+ * in 3dB steps - 0 is 0x7 */
+
+ /* Masks for bits in both chips' subaddresses */
+/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */
+/* Unique to TDA9855: */
+/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf)
+ * in 3dB steps - mute is 0x0 */
+
+/* Unique to TDA9850: */
+/* lower 4 bits control stereo noise threshold, over which stereo turns off
+ * set to values of 0x00 through 0x0f for Ster1 through Ster16 */
+
+
+/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/
+/* Unique to TDA9855: */
+#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */
+#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */
+#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */
+#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
+ /* Bits 0 to 3 select various combinations
+ * of line in and line out, only the
+ * interesting ones are defined */
+#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */
+#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */
+
+/* Unique to TDA9850: */
+/* lower 4 bits contol SAP noise threshold, over which SAP turns off
+ * set to values of 0x00 through 0x0f for SAP1 through SAP16 */
+
+
+/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */
+/* Common to TDA9855 and TDA9850: */
+#define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */
+#define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */
+#define TDA985x_MONO 0 /* Forces Mono output */
+#define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */
+
+/* Unique to TDA9855: */
+#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */
+#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/
+#define TDA9855_LINEAR 0 /* Linear Stereo */
+#define TDA9855_PSEUDO 1 /* Pseudo Stereo */
+#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */
+#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */
+#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/
+
+
+/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF)
+ * in .5dB steps - 0dB is 0x7 */
+
+
+/* 0x08, 0x09 - A1 and A2 (read/write) */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 5 bites are wideband and spectral expander alignment
+ * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */
+#define TDA985x_STP 1<<5 /* Stereo Pilot/detect (read-only) */
+#define TDA985x_SAPP 1<<6 /* SAP Pilot/detect (read-only) */
+#define TDA985x_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/
+
+
+/* 0x0a - A3 */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1),
+ * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */
+#define TDA985x_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral */
+
+/* Unique to TDA9855: */
+/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2),
+ * 1200ohm (0x1), 2100ohm (0x3) */
+
+
+/* Begin code */
+
+static int tda985x_write(struct i2c_client *client, int subaddr, int val)
+{
+ unsigned char buffer[2];
+ dprintk("In tda985x_write\n");
+ dprintk("Writing %d 0x%x\n", subaddr, val);
+ buffer[0] = subaddr;
+ buffer[1] = val;
+ if (2 != i2c_master_send(client,buffer,2)) {
+ printk(KERN_WARNING "tda985x: I/O error, trying (write %d 0x%x)\n",
+ subaddr, val);
+ return -1;
+ }
+ return 0;
+}
+
+static int tda985x_read(struct i2c_client *client)
+{
+ unsigned char buffer;
+ dprintk("In tda985x_read\n");
+ if (1 != i2c_master_recv(client,&buffer,1)) {
+ printk(KERN_WARNING "tda985x: I/O error, trying (read)\n");
+ return -1;
+ }
+ dprintk("Read 0x%02x\n", buffer);
+ return buffer;
+}
+
+static int tda985x_set(struct i2c_client *client)
+{
+ struct tda985x *t = client->data;
+ unsigned char buf[16];
+ dprintk("In tda985x_set\n");
+
+ if (chip == 9855)
+ {
+ dprintk(KERN_INFO
+ "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+ t->rvol,t->lvol,t->bass,t->treble,t->sub,
+ t->c5,t->c6,t->c7,t->a1,t->a2,t->a3);
+ buf[0] = TDA9855_VR;
+ buf[1] = t->rvol;
+ buf[2] = t->lvol;
+ buf[3] = t->bass;
+ buf[4] = t->treble;
+ buf[5] = t->sub;
+ buf[6] = t->c5;
+ buf[7] = t->c6;
+ buf[8] = t->c7;
+ buf[9] = t->a1;
+ buf[10] = t->a2;
+ buf[11] = t->a3;
+ if (12 != i2c_master_send(client,buf,12)) {
+ printk(KERN_WARNING "tda9855: I/O error, trying tda985x_set\n");
+ return -1;
+ }
+ }
+
+ else if (chip == 9850)
+ {
+ dprintk(KERN_INFO
+ "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+ t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3);
+ buf[0] = TDA9850_C4;
+ buf[1] = t->c4;
+ buf[2] = t->c5;
+ buf[3] = t->c6;
+ buf[4] = t->c7;
+ buf[5] = t->a1;
+ buf[6] = t->a2;
+ buf[7] = t->a3;
+ if (8 != i2c_master_send(client,buf,8)) {
+ printk(KERN_WARNING "tda9850: I/O error, trying tda985x_set\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void do_tda985x_init(struct i2c_client *client)
+{
+ struct tda985x *t = client->data;
+ dprintk("In tda985x_init\n");
+
+ if (chip == 9855)
+ {
+ printk("Using tda9855 options\n");
+ t->rvol = 0x6f; /* 0dB */
+ t->lvol = 0x6f; /* 0dB */
+ t->bass = 0x0e; /* 0dB */
+ t->treble = (0x07 << 1); /* 0dB */
+ t->sub = 0x8 << 2; /* 0dB */
+ t->c5 = TDA9855_MUTE | TDA9855_AVL |
+ TDA9855_LOUD | TDA9855_INT;
+ /* Set Mute, AVL, Loudness off, Internal sound */
+ t->c6 = TDA985x_STEREO | TDA9855_LINEAR |
+ TDA9855_TZCM | TDA9855_VZCM;
+ /* Stereo linear mode, also wait til zero crossings */
+ t->c7 = 0x07; /* 0dB input gain */
+ }
+
+ else if (chip == 9850)
+ {
+ printk("Using tda9850 options\n");
+ t->c4 = 0x08; /* Set stereo noise thresh to nominal */
+ t->c5 = 0x08; /* Set SAP noise threshold to nominal */
+ t->c6 = TDA985x_STEREO; /* Select Stereo mode for decoder */
+ t->c7 = 0x07; /* 0dB input gain */
+ }
+
+ /* The following is valid for both chip types */
+ t->a1 = 0x10; /* Select nominal wideband expander */
+ t->a2 = 0x10; /* Select nominal spectral expander and 30mV trigger */
+ t->a3 = 0x3; /* Set: nominal timing current, 420ohm AVL attack */
+
+ tda985x_set(client);
+}
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tda985x_attach(struct i2c_adapter *adap, int addr,
+ unsigned short flags, int kind)
+{
+ struct tda985x *t;
+ struct i2c_client *client;
+ dprintk("In tda985x_attach\n");
+ client = kmalloc(sizeof *client,GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+ memcpy(client,&client_template,sizeof(struct i2c_client));
+ client->adapter = adap;
+ client->addr = addr;
+
+ client->data = t = kmalloc(sizeof *t,GFP_KERNEL);
+ if (!t)
+ return -ENOMEM;
+ memset(t,0,sizeof *t);
+ do_tda985x_init(client);
+ MOD_INC_USE_COUNT;
+ strcpy(client->name,"TDA985x");
+ printk(KERN_INFO "tda985x: init\n");
+
+ i2c_attach_client(client);
+ return 0;
+}
+
+static int tda985x_probe(struct i2c_adapter *adap)
+{
+ if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ return i2c_probe(adap, &addr_data, tda985x_attach);
+ return 0;
+}
+
+static int tda985x_detach(struct i2c_client *client)
+{
+ struct tda985x *t = client->data;
+
+ do_tda985x_init(client);
+ i2c_detach_client(client);
+
+ kfree(t);
+ kfree(client);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int tda985x_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct tda985x *t = client->data;
+ dprintk("In tda985x_command...\n");
+#if 0
+ __u16 *sarg = arg;
+#endif
+
+ switch (cmd) {
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *va = arg;
+ dprintk("VIDIOCGAUDIO\n");
+ if (chip == 9855)
+ {
+ int left,right;
+
+ va->flags |= VIDEO_AUDIO_VOLUME |
+ VIDEO_AUDIO_BASS |
+ VIDEO_AUDIO_TREBLE;
+
+ /* min is 0x27 max is 0x7f, vstep is 2e8 */
+ left = (t->lvol-0x27)*0x2e8;
+ right = (t->rvol-0x27)*0x2e8;
+ va->volume=MAX(left,right);
+ va->balance=(32768*MIN(left,right))/
+ (va->volume ? va->volume : 1);
+ va->balance=(left<right)?
+ (65535-va->balance) : va->balance;
+ va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max 0x19 */
+ va->treble = ((t->treble>>1)-0x3)*0x1c71;
+ }
+
+ /* Valid for both chips: */
+ {
+ va->mode = ((TDA985x_STP | TDA985x_SAPP) &
+ tda985x_read(client)) >> 4;
+ /* Add mono mode regardless of SAP and stereo */
+ /* Allows forced mono */
+ va->mode |= VIDEO_SOUND_MONO;
+ }
+
+ break; /* VIDIOCGAUDIO case */
+ }
+
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio *va = arg;
+ dprintk("VIDEOCSAUDIO...\n");
+ if (chip == 9855)
+ {
+ int left,right;
+
+ left = (MIN(65536 - va->balance,32768) *
+ va->volume) / 32768;
+ right = (MIN(va->balance,32768) *
+ va->volume) / 32768;
+ t->lvol = left/0x2e8+0x27;
+ t->rvol = right/0x2e8+0x27;
+ t->bass = va->bass/0xccc+0x6;
+ t->treble = (va->treble/0x1c71+0x3)<<1;
+ tda985x_write(client,TDA9855_VL,t->lvol);
+ tda985x_write(client,TDA9855_VR,t->rvol);
+ tda985x_write(client,TDA9855_BA, t->bass);
+ tda985x_write(client,TDA9855_TR,t->treble);
+ }
+
+ /* The following is valid for both chips */
+
+ switch (va->mode) {
+ case VIDEO_SOUND_MONO:
+ dprintk("VIDEO_SOUND_MONO\n");
+ t->c6= TDA985x_MONO | (t->c6 & 0x3f);
+ tda985x_write(client,TDA985x_C6,t->c6);
+ break;
+ case VIDEO_SOUND_STEREO:
+ dprintk("VIDEO_SOUND_STEREO\n");
+ t->c6= TDA985x_STEREO | (t->c6 & 0x3f);
+ tda985x_write(client,TDA985x_C6,t->c6);
+ break;
+ case VIDEO_SOUND_LANG1:
+ dprintk("VIDEO_SOUND_LANG1\n");
+ t->c6= TDA985x_SAP | (t->c6 & 0x3f);
+ tda985x_write(client,TDA985x_C6,t->c6);
+ break;
+ } /* End of (va->mode) switch */
+
+ break;
+
+ } /* end of VIDEOCSAUDIO case */
+
+ default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
+
+ /* nothing */
+ dprintk("Default\n");
+
+ } /* end of (cmd) switch */
+
+ return 0;
+}
+
+
+static struct i2c_driver driver = {
+ "i2c tda985x driver",
+ I2C_DRIVERID_TDA9855, /* Get new one for TDA985x? */
+ I2C_DF_NOTIFY,
+ tda985x_probe,
+ tda985x_detach,
+ tda985x_command,
+};
+
+static struct i2c_client client_template =
+{
+ "(unset)", /* name */
+ -1,
+ 0,
+ 0,
+ NULL,
+ &driver
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int tda985x_init(void)
+#endif
+{
+ if ( (chip != 9850) && (chip != 9855) )
+ {
+ printk(KERN_ERR "tda985x: chip parameter must be 9850 or 9855\n");
+ return -EINVAL;
+ }
+ i2c_add_driver(&driver);
+ return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ i2c_del_driver(&driver);
+}
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 705d876b3..ed504dcfe 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1321,7 +1321,7 @@ retry_open:
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
minor -= driver->minor_start;
devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start));
- tty_register_devfs(&pts_driver[major], 0,
+ tty_register_devfs(&pts_driver[major], DEVFS_FL_NO_PERSISTENCE,
pts_driver[major].minor_start + minor);
noctty = 1;
goto init_dev_done;
@@ -2003,7 +2003,6 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
struct tty_struct tty;
char buf[32];
- flags |= DEVFS_FL_DEFAULT;
tty.driver = *driver;
tty.device = MKDEV (driver->major, minor);
switch (tty.device) {
@@ -2012,28 +2011,22 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
break;
default:
- flags |= DEVFS_FL_AUTO_OWNER;
break;
}
- if ((minor < driver->minor_start) ||
- (minor >= driver->minor_start + driver->num)) {
+ if ( (minor < driver->minor_start) ||
+ (minor >= driver->minor_start + driver->num) ) {
printk(KERN_ERR "Attempt to register invalid minor number "
"with devfs (%d:%d).\n", (int)driver->major,(int)minor);
return;
}
- if (driver->type == TTY_DRIVER_TYPE_CONSOLE) {
- flags |= DEVFS_FL_AOPEN_NOTIFY;
- flags &= ~DEVFS_FL_AUTO_OWNER;
- }
# ifdef CONFIG_UNIX98_PTYS
if ( (driver->major >= UNIX98_PTY_SLAVE_MAJOR) &&
(driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) ) {
- flags &= ~DEVFS_FL_AUTO_OWNER;
uid = current->uid;
gid = current->gid;
}
# endif
- devfs_register (NULL, tty_name (&tty, buf), 0, flags,
+ devfs_register (NULL, tty_name (&tty, buf), 0,flags | DEVFS_FL_DEFAULT,
driver->major, minor, mode, uid, gid,
&tty_fops, NULL);
#endif /* CONFIG_DEVFS_FS */
diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c
index 99dc750ee..dfea37d63 100644
--- a/drivers/char/tuner.c
+++ b/drivers/char/tuner.c
@@ -12,6 +12,7 @@
#include <linux/videodev.h>
#include "tuner.h"
+#include "audiochip.h"
/* Addresses to scan */
static unsigned short normal_i2c[] = {I2C_CLIENT_END};
@@ -334,6 +335,9 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->type,tuners[t->type].name);
strncpy(client->name, tuners[t->type].name, sizeof(client->name));
break;
+ case AUDC_SET_RADIO:
+ t->radio = 1;
+ break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -342,6 +346,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_channel *vc = arg;
+ t->radio = 0;
if (t->type == TUNER_PHILIPS_SECAM) {
t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0;
set_tv_freq(client,t->freq);
diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c
index cfcdbfcde..f0b1aaf4d 100644
--- a/drivers/char/videodev.c
+++ b/drivers/char/videodev.c
@@ -60,9 +60,6 @@ static struct video_init video_init_list[]={
{"i2c-tuner", i2c_tuner_init},
{"bttv", init_bttv_cards},
#endif
-#ifdef CONFIG_VIDEO_STRADIS
- {"stradis", init_stradis_cards},
-#endif
#ifdef CONFIG_VIDEO_BWQCAM
{"bw-qcam", init_bw_qcams},
#endif