diff options
Diffstat (limited to 'drivers/char')
31 files changed, 1889 insertions, 674 deletions
diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 9df21affa..792832a30 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -50,6 +50,10 @@ if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then bool ' Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS fi tristate ' Specialix SX (and SI) card support' CONFIG_SX + tristate ' Specialix RIO system support' CONFIG_RIO + if [ "$CONFIG_RIO" != "n" ]; then + bool ' Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI + fi bool ' Stallion multiport serial support' CONFIG_STALDRV if [ "$CONFIG_STALDRV" = "y" ]; then tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION @@ -201,7 +205,7 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then fi comment 'Video Adapters' 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 + dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT $CONFIG_SOUND fi dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_ALL_PPC" = "y" ]; then diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 22deb4fad..f75dabd18 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -136,41 +136,38 @@ obj-$(CONFIG_SPECIALIX) += specialix.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o +# If either SX or RIO is in the kernel, generic_serial goes in the +# kernel, and the module is no longer required. The "in kernel" case +# is last to be able to override the module case.... This is an +# example of the new "makefile automatically figures out the +# dependencies".... -- REW -# If either is in the kernel, generic_serial goes in the kernel, and -# the module is no longer required. The "in kernel" case is last to be -# able to override the module case.... This is an example of the new -# "makefile automatically figures out the dependencies".... -- REW +GS=n +ifeq ($(CONFIG_RIO),m) + M_OBJS += generic_serial.o + MOD_SUB_DIRS += rio + GS = m +endif -GS = n ifeq ($(CONFIG_SX),m) GS = m + M_OBJS += sx.o endif -ifeq ($(CONFIG_RIO),m) - GS = m -endif -ifeq ($(CONFIG_SX),y) - GS = y -endif -ifeq ($(CONFIG_RIO),y) - GS = y -endif -obj-$(GS) += generic_serial.o - - - ifeq ($(CONFIG_RIO),y) -obj-y += rio/rio.o generic_serial.o -SUB_DIRS += rio -MOD_SUB_DIRS += rio -else - ifeq ($(CONFIG_RIO),m) - obj-m += generic_serial.o + L_OBJS += rio/rio.o generic_serial.o + SUB_DIRS += rio MOD_SUB_DIRS += rio - endif + GS = y endif +ifeq ($(CONFIG_SX),y) + L_OBJS += sx.o + GS = y +endif + +obj-$(GS) += generic_serial.o + obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o obj-$(CONFIG_PRINTER) += lp.o @@ -205,7 +202,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_MIXCOMWD) += mixcomwd.o obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o obj-$(CONFIG_ATARIMOUSE) += atarimouse.o -obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o +obj-$(CONFIG_ADBMOUSE) += adbmouse.o obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_WDT) += wdt.o obj-$(CONFIG_WDTPCI) += wdt_pci.o @@ -232,7 +229,8 @@ else endif endif -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda985x.o tea6300.o +obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \ + tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o ifeq ($(CONFIG_VIDEO_BT848),y) L_TUNERS=y else diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index f55f992d8..b17efd429 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -43,19 +43,13 @@ #include <linux/interrupt.h> #include <linux/kmod.h> #include <linux/vmalloc.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 <linux/init.h> #include "bttv.h" #include "tuner.h" -#define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ +#define DEBUG(x) /* Debug driver */ +#define IDEBUG(x) /* Debug interrupt handler */ #define MIN(a,b) (((a)>(b))?(b):(a)) #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -100,7 +94,7 @@ static int triton1=0; static unsigned long remap[BTTV_MAX]; 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 pll[BTTV_MAX] = { -1, -1, -1, -1}; static unsigned int fieldnr = 0; static unsigned int verbose = 1; static unsigned int debug = 0; @@ -473,7 +467,7 @@ static struct i2c_client i2c_client_template = { NULL }; -static int init_bttv_i2c(struct bttv *btv) +static int __init init_bttv_i2c(struct bttv *btv) { /* i2c bit_adapter */ memcpy(&btv->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); @@ -495,7 +489,7 @@ static int init_bttv_i2c(struct bttv *btv) } /* read I2C */ -static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +static int __init I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { unsigned char buffer = 0; @@ -520,7 +514,7 @@ static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) } /* write I2C */ -static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, +static int __init I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both) { unsigned char buffer[2]; @@ -537,7 +531,7 @@ static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, } /* read EEPROM */ -static void readee(struct bttv *btv, unsigned char *eedata, int addr) +static void __init readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; @@ -564,7 +558,7 @@ static struct HAUPPAUGE_TUNER int id; char *name; } -hauppauge_tuner[] = +hauppauge_tuner[] __initdata = { { TUNER_ABSENT, "" }, { TUNER_ABSENT, "External" }, @@ -612,8 +606,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Temic 4046FM5" }, }; -static void -hauppauge_eeprom(struct bttv *btv) +static void __init hauppauge_eeprom(struct bttv *btv) { if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { @@ -622,10 +615,11 @@ hauppauge_eeprom(struct bttv *btv) printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); } + + return; } -static void -hauppauge_boot_msp34xx(struct bttv *btv) +static void __init hauppauge_boot_msp34xx(struct bttv *btv) { int i; @@ -661,7 +655,7 @@ hauppauge_boot_msp34xx(struct bttv *btv) /* This is basically the same procedure as * used by Alessandro Rubini in his pxc200 * driver, but using BTTV functions */ -static void init_PXC200(struct bttv *btv) +static void __init init_PXC200(struct bttv *btv) { static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, @@ -711,21 +705,25 @@ static struct CARD { unsigned id; int cardnr; char *name; -} cards[] = { +} cards[] __initdata = { { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, - { 0x00031461, BTTV_AVERMEDIA98, "AVerMedia TVPhone98" }, + { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00041461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, + { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, + { 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" }, { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, + { 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" }, { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, { 0, -1, NULL } }; @@ -747,6 +745,13 @@ struct tvcard int tda9840:1; int tda985x:1; int tea63xx:1; + int tea64xx:1; + int tda7432:1; + int tda9875:1; + + /* other settings */ + int pll; + int tuner_type; }; static struct tvcard tvcards[] = @@ -754,149 +759,161 @@ static struct tvcard tvcards[] = /* 0x00 */ { " *** UNKNOWN *** ", 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MIRO PCTV", 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Hauppauge old", 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0 }, + 1,1,0,1,0,0,0,1, PLL_NONE, -1 }, { "STB", 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,1 }, + 0,1,1,1,1,0,0,1, PLL_NONE, -1 }, { "Intel", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 3, 1, 0, -1, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Diamond DTV2000", 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVerMedia TVPhone", 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MATRIX-Vision MV-Delta", 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x08 */ { "Fly Video II", 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "TurboTV", 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Hauppauge new (bt878)", 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0 }, + 1,1,0,1,0,0,0,1, PLL_28, -1 }, { "MIRO PCTV pro", 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "ADS Technologies Channel Surfer TV", 3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVerMedia TVCapture 98", 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Aimslab VHX", 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Zoltrix TV-Max", 3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x10 */ { "Pixelview PlayTV (bt878)", - 3, 1, 0, 2, 0x01e000, { 2, 0, 1, 1}, + 3, 1, 0, 2, 0x01fe00, { 2, 0, 1, 1}, { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Leadtek WinView 601", 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVEC Intercapture", 3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "LifeView FlyKit w/o Tuner", 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0, - 0,0,0,0,0 }, + 0,0,0,0,0,0,0,1, PLL_NONE, -1 }, { "CEI Raffles Card", 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Lucky Star Image World ConferenceTV", - 3, 1, 0, 2, 16777215, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, - 1,1,1,1,0 }, + 3, 1, 0, 2, 0x00fffe07, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, + 1,1,1,1,0,0,0,1, PLL_28, TUNER_PHILIPS_PAL_I }, { "Phoebe Tv Master + FM", 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Modular Technology MM205 PCTV, bt878", 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x18 */ { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Terratec/Vobis TV-Boostar", 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Newer Hauppauge WinCam (bt878)", 4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MAXI TV Video PCI2", 3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, TUNER_PHILIPS_SECAM }, { "Terratec TerraTV+", 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Imagenation PXC200", 5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "FlyVideo 98", 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "iProTV", 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x20 */ { "Intel Create and Share PCI", 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Terratec TerraTValue", - 3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0, - 1,1,1,1,0 }, + 3, 1, 0, 2, 0xffff00, { 2, 3, 1, 1}, + { 0x500, 0, 0x300, 0x900, 0x900},0, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "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 }, + 1,1,1,1,1,0,0,1, PLL_28, -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 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "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 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "PixelView PlayTV pro", 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 }, + { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0, + 0,0,0,0,0,0,0,1, PLL_28, -1 }, { "TView99 CPH063", - 3, 1, 0, 2, 0x551e00, { 2, 0, 1, 1}, - { 0x551400, 0x551200, 0, 0, 0x551200 }, 0,1,1,1,1,0 }, + 3, 1, 0, 2, 0x551e00, { 2, 3, 1, 1}, + { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, 0, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Pinnacle PCTV Rave", 3, 1, 0, 2, 0x03000F, { 2, 3, 1, 1}, { 2, 0, 0, 0, 1},0, - 1,1,1,1,0 }, - + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, + + /* 0x28 */ + { "STB2", + 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, + 0,1,1,1,0,1,1,1, PLL_NONE, -1 }, + { "AVerMedia TVPhone 98", + 3, 4, 0, 2, 4, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, + 1,1,1,1,0,0,0,1, PLL_28, 5 }, + { "ProVideo PV951", /* pic16c54 */ + 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, + 0,0,0,0,0,0,0,0, PLL_28, 1 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) -static void -dump_eeprom(struct bttv *btv,int addr) +static void __init dump_eeprom(struct bttv *btv,int addr) { int i; @@ -913,8 +930,7 @@ dump_eeprom(struct bttv *btv,int addr) } } -static int -idcard_eeprom(struct bttv *btv) +static int __init idcard_eeprom(struct bttv *btv) { unsigned id; int i,n; @@ -1477,6 +1493,10 @@ static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int unsigned char lmask, rmask, *p; int W, l, r; int i; + + if (debug) + printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y); + /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ if (x<0) { @@ -1497,10 +1517,10 @@ static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int w=1024-x; l=x>>3; - r=(x+w)>>3; + r=(x+w-1)>>3; W=r-l-1; lmask=lmaskt[x&7]; - rmask=rmaskt[(x+w)&7]; + rmask=rmaskt[(x+w-1)&7]; p=clipmap+128*y+l; if (W>0) @@ -1716,8 +1736,7 @@ static void bt848_set_geo(struct bttv *btv, struct tvnorm *tvn; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&btv->s_lock, flags); tvn=&tvnorms[btv->win.norm]; @@ -1771,7 +1790,7 @@ static void bt848_set_geo(struct bttv *btv, btwrite(format, BT848_COLOR_FMT); btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); - restore_flags(flags); + spin_unlock_irqrestore(&btv->s_lock, flags); } @@ -1835,6 +1854,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) { unsigned int *ro, *re; unsigned int *vbuf; + unsigned long flags; if(btv->fbuffer==NULL) { @@ -1870,7 +1890,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) if (debug) printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", btv->nr,mp->frame,mp->format,mp->width,mp->height); - cli(); + spin_lock_irqsave(&btv->s_lock, flags); btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; btv->gbuf[mp->frame].width = mp->width; @@ -1885,12 +1905,13 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) #endif if (btv->gq_in == btv->gq_out) { + btv->gq_start = 1; 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(); + spin_unlock_irqrestore(&btv->s_lock, flags); btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); return 0; @@ -1911,23 +1932,25 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + unsigned long flags; + if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) return -EFAULT; todo-=q; buf+=q; - cli(); + spin_lock_irqsave(&btv->s_lock, flags); if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - sti(); + spin_unlock_irqrestore(&btv->s_lock, flags); if(count==todo) return -EWOULDBLOCK; return count-todo; } + spin_unlock_irqrestore(&btv->s_lock, flags); interruptible_sleep_on(&btv->vbiq); - sti(); if(signal_pending(current)) { if(todo==count) @@ -1935,7 +1958,8 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in else return count-todo; } - } + } else + spin_unlock_irqrestore(&btv->s_lock, flags); } if (todo) { @@ -1958,7 +1982,7 @@ static void bt848_restart(struct bttv *btv) { if (verbose) printk("bttv%d: resetting chip\n",btv->nr); - btwrite(0xfffffUL, BT848_INT_STAT); + btwrite(~0x0UL, BT848_INT_STAT); btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_SRESET); btwrite(virt_to_bus(btv->risc_jmp+2), @@ -1984,6 +2008,8 @@ static int bttv_open(struct video_device *dev, int flags) int i,ret; ret = -EBUSY; + + MOD_INC_USE_COUNT; down(&btv->lock); if (btv->user) goto out_unlock; @@ -2005,11 +2031,11 @@ static int bttv_open(struct video_device *dev, int flags) set_pll(btv); btv->user++; up(&btv->lock); - MOD_INC_USE_COUNT; return 0; out_unlock: up(&btv->lock); + MOD_DEC_USE_COUNT; return ret; } @@ -2033,14 +2059,15 @@ static void bttv_close(struct video_device *dev) btread(BT848_I2C); /* This fixes the PCI posting delay */ - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + if (-1 != btv->gq_grab) { + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + } /* * We have allowed it to drain. @@ -2726,6 +2753,8 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + unsigned long flags; + if (btv->needs_restart) { down(&btv->lock); bt848_restart(btv); @@ -2736,18 +2765,18 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, todo-=q; buf+=q; - cli(); + spin_lock_irqsave(&btv->s_lock, flags); if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - sti(); + spin_unlock_irqrestore(&btv->s_lock, flags); if(count==todo) return -EWOULDBLOCK; return count-todo; } + spin_unlock_irqrestore(&btv->s_lock, flags); interruptible_sleep_on(&btv->vbiq); - sti(); if(signal_pending(current)) { if(todo==count) @@ -2755,7 +2784,8 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, else return count-todo; } - } + } else + spin_unlock_irqrestore(&btv->s_lock, flags); } if (todo) { @@ -2784,6 +2814,8 @@ static int vbi_open(struct video_device *dev, int flags) { struct bttv *btv=(struct bttv *)(dev-2); + MOD_INC_USE_COUNT; + down(&btv->lock); if (btv->needs_restart) bt848_restart(btv); @@ -2792,7 +2824,6 @@ static int vbi_open(struct video_device *dev, int flags) bt848_set_risc_jmps(btv,-1); up(&btv->lock); - MOD_INC_USE_COUNT; return 0; } @@ -2864,6 +2895,7 @@ static int radio_open(struct video_device *dev, int flags) struct bttv *btv = (struct bttv *)(dev-1); unsigned long v; + MOD_INC_USE_COUNT; down(&btv->lock); if (btv->user) goto busy_unlock; @@ -2876,11 +2908,11 @@ static int radio_open(struct video_device *dev, int flags) bt848_muxsel(btv,0); up(&btv->lock); - MOD_INC_USE_COUNT; return 0; busy_unlock: up(&btv->lock); + MOD_DEC_USE_COUNT; return -EBUSY; } @@ -2986,7 +3018,7 @@ static struct video_device radio_template= #define TRITON_PEER_CONCURRENCY (1<<3) -static void handle_chipset(void) +static void __init handle_chipset(void) { struct pci_dev *dev = NULL; @@ -3018,7 +3050,7 @@ static void handle_chipset(void) /* can tda9855.c handle this too maybe? */ -static void init_tda9840(struct bttv *btv) +static void __init init_tda9840(struct bttv *btv) { /* Horrible Hack */ I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */ @@ -3034,17 +3066,16 @@ static void init_tda9840(struct bttv *btv) /* Figure out card and tuner type */ -static void idcard(int i) +static void __init idcard(struct bttv *btv) { - 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))); + DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", btv->nr, btread(BT848_GPIO_DATA))); /* Default the card to the user-selected one. */ - if (card[i] >= 0 && card[i] < TVCARDS) - btv->type=card[i]; + if (card[btv->nr] >= 0 && card[btv->nr] < TVCARDS) + btv->type=card[btv->nr]; /* If we were asked to auto-detect, then do so! */ if (btv->type == BTTV_UNKNOWN) { @@ -3063,7 +3094,7 @@ static void idcard(int i) btv->type=BTTV_HAUPPAUGE; } - /* STB cards have a eeprom @ 0xae */ + /* STB cards have a eeprom @ 0xae (old bt848) */ } else if (I2CRead(btv, I2C_STBEE, "eeprom")>=0) { btv->type=BTTV_STB; } @@ -3078,20 +3109,20 @@ static void idcard(int i) } /* print which board we have found */ - printk(KERN_INFO "bttv%d: model: ",btv->nr); - sprintf(btv->video_dev.name,"BT%d%s(%.22s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", tvcards[btv->type].name); - printk("%s\n",btv->video_dev.name); + printk(KERN_INFO "bttv%d: model: %s\n",btv->nr,btv->video_dev.name); + /* board specific initialisations */ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { /* auto detect tuner for MIRO cards */ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; } if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) { + /* pick up some config infos from the eeprom */ if (0xa0 != eeprom) { eeprom = 0xa0; readee(btv,eeprom_data,0xa0); @@ -3099,32 +3130,42 @@ static void idcard(int i) hauppauge_eeprom(btv); hauppauge_boot_msp34xx(btv); } - if (btv->type == BTTV_MAXI) { - /* PHILIPS FI1216MK2 tuner (PAL/SECAM) */ - btv->tuner_type=TUNER_PHILIPS_SECAM; - } - if (btv->type == BTTV_PXC200) init_PXC200(btv); - - if (btv->type == BTTV_CONFERENCETV) - btv->tuner_type = 1; - - if (btv->type == BTTV_HAUPPAUGE878 || - btv->type == BTTV_CONFERENCETV || - btv->type == BTTV_PIXVIEWPLAYTV || - btv->type == BTTV_AVERMEDIA98 || - btv->type == BTTV_MAGICTVIEW061 || - btv->type == BTTV_MAGICTVIEW063 || - 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; - } - if (btv->tuner_type != -1) + + /* pll configuration */ + if (!(btv->id==848 && btv->revision==0x11)) { + /* defaults from card list */ + if (PLL_28 == tvcards[btv->type].pll) { + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + } + /* insmod options can override */ + switch (pll[btv->nr]) { + case 0: /* none */ + btv->pll.pll_crystal = 0; + btv->pll.pll_ifreq = 0; + btv->pll.pll_ofreq = 0; + break; + case 1: /* 28 MHz */ + btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal=BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ + btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal=BT848_IFORM_XT1; + break; + } + } + + + /* tuner configuration */ + if (-1 != tvcards[btv->type].tuner_type) + btv->tuner_type = tvcards[btv->type].tuner_type; + if (btv->tuner_type != -1) call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); /* try to detect audio/fader chips */ @@ -3154,12 +3195,28 @@ static void idcard(int i) request_module("tda985x"); } - if (tvcards[btv->type].tea63xx /* && - I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0 */) { + if (tvcards[btv->type].tda9875 && + I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { + if (autoload) + request_module("tda9875"); + } + + if (tvcards[btv->type].tda7432 && + I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { + if (autoload) + request_module("tda7432"); + } + + if (tvcards[btv->type].tea63xx) { if (autoload) request_module("tea6300"); } + if (tvcards[btv->type].tea64xx) { + if (autoload) + request_module("tea6420"); + } + if (tvcards[btv->type].tuner != -1) { if (autoload) request_module("tuner"); @@ -3171,6 +3228,10 @@ static void idcard(int i) static void bt848_set_risc_jmps(struct bttv *btv, int flags) { + unsigned long irq_flags; + + spin_lock_irqsave(&btv->s_lock, irq_flags); + if (-1 == flags) { /* defaults */ flags = 0; @@ -3242,7 +3303,11 @@ static void bt848_set_risc_jmps(struct bttv *btv, int flags) btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); } - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); + if (btv->gq_start) { + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); + } else { + 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 */ @@ -3253,18 +3318,17 @@ static void bt848_set_risc_jmps(struct bttv *btv, int flags) bt848_dma(btv, 3); else bt848_dma(btv, 0); + + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } -static int -init_video_dev(struct bttv *btv) +static int __init init_video_dev(struct bttv *btv) { - int num = btv - bttvs; - memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); - idcard(num); + idcard(btv); if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) return -1; @@ -3273,7 +3337,7 @@ init_video_dev(struct bttv *btv) video_unregister_device(&btv->video_dev); return -1; } - if (radio[num]) + if (radio[btv->nr]) { if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) { @@ -3285,9 +3349,8 @@ init_video_dev(struct bttv *btv) return 1; } -static int init_bt848(int i) +static int __init init_bt848(struct bttv *btv) { - struct bttv *btv = &bttvs[i]; int j; btv->user=0; @@ -3297,14 +3360,14 @@ static int init_bt848(int i) * might help to make a new card work */ if (verbose >= 2) printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", - i, + btv->nr, 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)); + DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem)); /* not registered yet */ btv->video_dev.minor = -1; @@ -3412,7 +3475,7 @@ static int init_bt848(int i) btwrite(0x00, BT848_O_SCLOOP); /* clear interrupt status */ - btwrite(0xfffffUL, BT848_INT_STAT); + btwrite(~0x0UL, BT848_INT_STAT); /* set interrupt mask */ btwrite(btv->triton1| @@ -3452,7 +3515,6 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) astat=stat&btread(BT848_INT_MASK); 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)); @@ -3561,6 +3623,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (stat&(8<<28)) { + btv->gq_start = 0; btv->gq_grab = btv->gqueue[btv->gq_out++]; btv->gq_out = btv->gq_out % MAX_GBUFFERS; if (debug) @@ -3613,7 +3676,9 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) { IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr)); } - + + btwrite(astat,BT848_INT_STAT); + count++; if (count > 10) printk (KERN_WARNING "bttv%d: irq loop %d\n", @@ -3633,7 +3698,76 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) * Scan for a Bt848 card, request the irq and map the io memory */ -int configure_bt848(struct pci_dev *dev, int bttv_num) +static void __init bttv_remove(struct pci_dev *pci_dev) +{ + u8 command; + int j; + struct bttv *btv = pci_dev->driver_data; + + /* 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! */ + btwrite(0, BT848_INT_MASK); + btwrite(~0x0UL,BT848_INT_STAT); + btwrite(0x0, BT848_GPIO_OUT_EN); + + /* disable PCI bus-mastering */ + pci_read_config_byte(btv->dev, PCI_COMMAND, &command); + /* Should this be &=~ ?? */ + command&=~PCI_COMMAND_MASTER; + pci_write_config_byte(btv->dev, PCI_COMMAND, command); + + /* unmap and free memory */ + 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_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) + kfree((void *) btv->risc_jmp); + + DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); + if (btv->vbibuf) + vfree((void *) btv->vbibuf); + + free_irq(btv->irq,btv); + DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); + if (btv->bt848_mem) + iounmap(btv->bt848_mem); + + if(btv->video_dev.minor!=-1) + video_unregister_device(&btv->video_dev); + if(btv->vbi_dev.minor!=-1) + video_unregister_device(&btv->vbi_dev); + if (radio[btv->nr] && btv->radio_dev.minor != -1) + video_unregister_device(&btv->radio_dev); + + release_mem_region(btv->bt848_adr, + pci_resource_len(btv->dev,0)); + /* 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); + + return; +} + + +static int __init bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int result; unsigned char command; @@ -3642,6 +3776,8 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) unsigned int cmd; #endif + printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); + btv=&bttvs[bttv_num]; btv->dev=dev; btv->nr = bttv_num; @@ -3657,15 +3793,15 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) btv->vbip=VBIBUF_SIZE; init_waitqueue_head(&btv->gpioq); + btv->s_lock = SPIN_LOCK_UNLOCKED; btv->shutdown=0; btv->id=dev->device; btv->irq=dev->irq; - btv->bt848_adr=pci_resource_start(dev, 0); - + btv->bt848_adr=pci_resource_start(dev, 0); if (pci_enable_device(dev)) return -EIO; - if (!request_mem_region(pci_resource_start(dev,0), + if (!request_mem_region(btv->bt848_adr, pci_resource_len(dev,0), "bttv")) { return -EBUSY; @@ -3689,29 +3825,7 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) cmd = (cmd | PCI_COMMAND_MEMORY ); pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif - - btv->pll.pll_crystal = 0; - btv->pll.pll_ifreq = 0; - btv->pll.pll_ofreq = 0; - btv->pll.pll_current = 0; - if (!(btv->id==848 && btv->revision==0x11)) { - switch (pll[btv->nr]) { - case 0: - /* off */ - break; - case 1: - /* 28 MHz crystal installed */ - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; - break; - case 2: - /* 35 MHz crystal installed */ - btv->pll.pll_ifreq=35468950; - btv->pll.pll_crystal=BT848_IFORM_XT1; - break; - } - } - + #ifdef __sparc__ btv->bt848_mem=(unsigned char *)btv->bt848_adr; #else @@ -3751,119 +3865,53 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) if (!(command&BT878_EN_TBFX)) { printk("bttv: 430FX compatibility could not be enabled\n"); + free_irq(btv->irq,btv); result = -1; goto fail; } } + + dev->driver_data = btv; + + if(init_bt848(btv) < 0) { + bttv_remove(dev); + return -EIO; + } + + bttv_num++; + return 0; fail: - release_mem_region(pci_resource_start(btv->dev,0), + release_mem_region(btv->bt848_adr, pci_resource_len(btv->dev,0)); return result; } -static int find_bt848(void) -{ - struct pci_dev *dev; - int result=0; - - bttv_num=0; - - pci_for_each_dev(dev) { - if (dev->vendor == PCI_VENDOR_ID_BROOKTREE) - if ((dev->device == PCI_DEVICE_ID_BT848)|| - (dev->device == PCI_DEVICE_ID_BT849)|| - (dev->device == PCI_DEVICE_ID_BT878)|| - (dev->device == PCI_DEVICE_ID_BT879)) - result=configure_bt848(dev,bttv_num++); - if (result) - return result; - } - if(bttv_num) - printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num); - return bttv_num; -} - -static void release_bttv(void) -{ - u8 command; - int i,j; - struct bttv *btv; - - for (i=0;i<bttv_num; i++) - { - btv=&bttvs[i]; - - /* 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! */ - btwrite(0, BT848_INT_MASK); - btwrite(0xffffffffUL,BT848_INT_STAT); - btwrite(0x0, BT848_GPIO_OUT_EN); - - /* disable PCI bus-mastering */ - pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - command&=~PCI_COMMAND_MASTER; - pci_write_config_byte(btv->dev, PCI_COMMAND, command); - - /* unmap and free memory */ - 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_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) - kfree((void *) btv->risc_jmp); - - DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); - if (btv->vbibuf) - vfree((void *) btv->vbibuf); - - - free_irq(btv->irq,btv); - DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); - if (btv->bt848_mem) - iounmap(btv->bt848_mem); +static struct pci_device_id bttv_pci_tbl[] __initdata = { + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; - if(btv->video_dev.minor!=-1) - video_unregister_device(&btv->video_dev); - if(btv->vbi_dev.minor!=-1) - video_unregister_device(&btv->vbi_dev); - if (radio[btv->nr] && btv->radio_dev.minor != -1) - video_unregister_device(&btv->radio_dev); +MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); - release_mem_region(pci_resource_start(btv->dev,0), - pci_resource_len(btv->dev,0)); - /* 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); - } -} +static struct pci_driver bttv_pci_driver = { + name:"bttv", + id_table:bttv_pci_tbl, + probe:bttv_probe, + remove:bttv_remove, +}; -#ifdef MODULE -int init_module(void) -#else -int init_bttv_cards(struct video_init *unused) -#endif +static int __init bttv_init_module(void) { - int i; + bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", (BTTV_VERSION_CODE >> 16) & 0xff, @@ -3878,31 +3926,18 @@ int init_bttv_cards(struct video_init *unused) gbuffers,gbufsize/1024,gbuffers*gbufsize/1024); handle_chipset(); - if (find_bt848()<=0) - return -EIO; - /* initialize Bt848s */ - for (i=0; i<bttv_num; i++) - { - if (init_bt848(i)<0) - { - release_bttv(); - return -EIO; - } - } - - return 0; + return pci_module_init(&bttv_pci_driver); } - -#ifdef MODULE - -void cleanup_module(void) +static void __exit bttv_cleanup_module(void) { - release_bttv(); + pci_unregister_driver(&bttv_pci_driver); + return; } -#endif +module_init(bttv_init_module); +module_exit(bttv_cleanup_module); /* * Local variables: diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index be929c6c9..3f4229fe8 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -1,4 +1,4 @@ -/* +/* bttv - Bt848 frame grabber driver Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,25) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,28) #include <linux/types.h> #include <linux/wait.h> @@ -143,6 +143,8 @@ struct bttv { int tuner_type; int channel; + + spinlock_t s_lock; unsigned int nr; unsigned short id; @@ -183,7 +185,7 @@ struct bttv { struct bttv_gbuf *gbuf; int gqueue[MAX_GBUFFERS]; - int gq_in,gq_out,gq_grab; + int gq_in,gq_out,gq_grab,gq_start; char *fbuffer; struct bttv_pll_info pll; @@ -272,7 +274,13 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) #define BTTV_PXELVWPLTVPRO 0x25 #define BTTV_MAGICTVIEW063 0x26 #define BTTV_PINNACLERAVE 0x27 +#define BTTV_STB2 0x28 +#define BTTV_AVPHONE98 0x29 +#define BTTV_PV951 0x2a +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 @@ -289,9 +297,11 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) #define TEA6300 0x04 #define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_TDA8425 0x82 #define I2C_TDA9840 0x84 #define I2C_TDA9850 0xb6 -#define I2C_TDA8425 0x82 +#define I2C_TDA9875 0xb0 #define I2C_HAUPEE 0xa0 #define I2C_STBEE 0xae #define I2C_VHX 0xc0 diff --git a/drivers/char/epca.c b/drivers/char/epca.c index dd94223bc..9238ae3eb 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -4080,9 +4080,10 @@ static struct pci_device_id epca_pci_tbl[] __initdata = { { PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem }, { PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx }, { PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj }, - { 0, }, /* terminate list */ + { 0, } }; +MODULE_DEVICE_TABLE(pci, epca_pci_tbl); int __init init_PCI (void) { /* Begin init_PCI */ diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 212525df7..dfe89b970 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -52,6 +52,10 @@ int gs_debug = 0; #define RS_EVENT_WRITE_WAKEUP 1 +#ifdef MODULE +MODULE_PARM(gs_debug, "i"); +#endif + #ifdef DEBUG static void my_hd (unsigned char *addr, int len) { @@ -209,12 +213,9 @@ int gs_write(struct tty_struct * tty, int from_user, if (!port || !port->xmit_buf || !tmp_buf) return -EIO; - /* printk ("from_user = %d.\n", from_user); */ save_flags(flags); if (from_user) { - /* printk ("Going into the semaphore\n"); */ down(&tmp_buf_sem); - /* printk ("got out of the semaphore\n"); */ while (1) { c = count; @@ -363,19 +364,14 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) func_exit(); return -EINVAL; /* This is an error which we don't know how to handle. */ } - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n"); rcib = gs_real_chars_in_buffer(port->tty); - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 2\n"); - if(rcib <= 0) { gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); func_exit(); return rv; } - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n"); - /* stop trying: now + twice the time it would normally take + seconds */ end_jiffies = jiffies; if (timeout != MAX_SCHEDULE_TIMEOUT) @@ -520,11 +516,10 @@ void gs_hangup(struct tty_struct *tty) func_enter (); tty = port->tty; - if (!tty) return; + if (!tty) + return; gs_shutdown_port (port); - - /* gs_flush_buffer (tty); */ port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE |GS_ACTIVE); port->tty = NULL; port->count = 0; @@ -576,7 +571,6 @@ int block_til_ready(void *port_, struct file * filp) else return -ERESTARTSYS; } - gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); /* @@ -599,7 +593,6 @@ int block_til_ready(void *port_, struct file * filp) } gs_dprintk (GS_DEBUG_BTR, "after subtype\n"); - /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. @@ -613,7 +606,6 @@ int block_til_ready(void *port_, struct file * filp) } gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); - if (port->flags & ASYNC_CALLOUT_ACTIVE) { if (port->normal_termios.c_cflag & CLOCAL) do_clocal = 1; @@ -622,8 +614,7 @@ int block_til_ready(void *port_, struct file * filp) do_clocal = 1; } - gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); - + gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -632,10 +623,10 @@ int block_til_ready(void *port_, struct file * filp) * exit, either normal or abnormal. */ retval = 0; + add_wait_queue(&port->open_wait, &wait); - + gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); - cli(); if (!tty_hung_up_p(filp)) port->count--; @@ -667,7 +658,7 @@ int block_til_ready(void *port_, struct file * filp) } gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", port->blocked_open); - current->state = TASK_RUNNING; + set_current_state (TASK_RUNNING); remove_wait_queue(&port->open_wait, &wait); if (!tty_hung_up_p(filp)) port->count++; @@ -687,10 +678,8 @@ void gs_close(struct tty_struct * tty, struct file * filp) struct gs_port *port; func_enter (); - port = (struct gs_port *) tty->driver_data; - gs_dprintk (GS_DEBUG_CLOSE, "tty=%p, port=%p port->tty=%p\n", - tty, port, port->tty); + port = (struct gs_port *) tty->driver_data; if(! port) { func_exit(); @@ -703,9 +692,7 @@ void gs_close(struct tty_struct * tty, struct file * filp) port->tty = tty; } - save_flags(flags); cli(); - if (tty_hung_up_p(filp)) { restore_flags(flags); port->rd->hungup (port); diff --git a/drivers/char/lp.c b/drivers/char/lp.c index fcf0644ff..90f034396 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -146,13 +146,6 @@ struct lp_struct lp_table[LP_NO]; static unsigned int lp_count = 0; -/* Test if printer is ready */ -#define LP_READY(status) ((status) & LP_PBUSY) -/* Test if the printer is not acking the strobe */ -#define LP_NO_ACKING(status) ((status) & LP_PACK) -/* Test if the printer has error conditions */ -#define LP_NO_ERROR(status) ((status) & LP_PERRORP) - #undef LP_DEBUG /* --- low-level port access ----------------------------------- */ @@ -265,6 +258,7 @@ static ssize_t lp_write(struct file * file, const char * buf, parport_set_timeout (lp_table[minor].dev, lp_table[minor].timeout); + if ((retv = lp_check_status (minor)) == 0) do { /* Write the data. */ written = parport_write (port, kbuf, copy_size); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 755c3b318..40e6c7ba6 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -231,9 +231,10 @@ static ssize_t read_kmem(struct file *file, char *buf, { unsigned long p = *ppos; ssize_t read = 0; - ssize_t virtr; + ssize_t virtr = 0; + char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ - if (p < (unsigned long) high_memory) { + if (p < (unsigned long) high_memory) { read = count; if (count > (unsigned long) high_memory - p) read = (unsigned long) high_memory - p; @@ -258,11 +259,27 @@ static ssize_t read_kmem(struct file *file, char *buf, count -= read; } - virtr = vread(buf, (char *)p, count); - if (virtr < 0) - return virtr; - *ppos += p + virtr; - return virtr + read; + kbuf = (char *)__get_free_page(GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + while (count > 0) { + int len = count; + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + len = vread(kbuf, (char *)p, len); + if (len && copy_to_user(buf, kbuf, len)) { + free_page((unsigned long)kbuf); + return -EFAULT; + } + count -= len; + buf += len; + virtr += len; + p += len; + } + free_page((unsigned long)kbuf); + *ppos = p; + return virtr + read; } /* diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c index 6b86db95b..f4252a071 100644 --- a/drivers/char/msp3400.c +++ b/drivers/char/msp3400.c @@ -871,7 +871,7 @@ static int msp3400c_thread(void *data) /* unmute */ msp3400c_setvolume(client, msp->left, msp->right); - if (msp->watch_stereo) + if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+5*HZ); if (debug) @@ -1086,7 +1086,7 @@ static int msp3410d_thread(void *data) msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->left, msp->right); - if (msp->watch_stereo) + if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+HZ); msp->active = 0; @@ -1236,7 +1236,7 @@ static int msp3400c_mixer_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev); - struct i2c_client *client = NULL; + struct i2c_client *client; struct msp3400c *msp; int i; @@ -1246,12 +1246,12 @@ msp3400c_mixer_open(struct inode *inode, struct file *file) if (msp->mixer_num == minor) { client = msps[i]; file->private_data = client; - goto match; + break; } } - return -ENODEV; + if (MSP3400_MAX == i) + return -ENODEV; -match: /* lock bttv in memory while the mixer is in use */ if (client->adapter->inc_use) client->adapter->inc_use(client->adapter); @@ -1265,8 +1265,8 @@ 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); + if (client->adapter->dec_use) + client->adapter->dec_use(client->adapter); MOD_DEC_USE_COUNT; return 0; } diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h index f51eeb0bb..3cf72f3e4 100644 --- a/drivers/char/rio/func.h +++ b/drivers/char/rio/func.h @@ -168,4 +168,6 @@ extern int rio_minor (kdev_t device); extern int rio_ismodem (kdev_t device); extern void rio_udelay (int usecs); +extern void rio_start_card_running (struct Host * HostP); + #endif /* __func_h_def */ diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index 6a155c1a6..12c47eae2 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h @@ -56,16 +56,16 @@ struct Host uchar Mode; /* Control stuff */ uchar Slot; /* Slot */ volatile caddr_t Caddr; /* KV address of DPRAM */ - volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ + volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ paddr_t PaddrP; /* Phys. address of DPRAM */ char Name[MAX_NAME_LEN]; /* The name of the host */ uint UniqueNum; /* host unique number */ - spinlock_t HostLock; /* Lock structure for MPX */ - /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ + spinlock_t HostLock; /* Lock structure for MPX */ + /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ /*struct lockb HostLock; *//* Lock structure for MPX */ uint WorkToBeDone; /* set to true each interrupt */ uint InIntr; /* Being serviced? */ - uint IntSrvDone; /* host's interrupt has been serviced */ + uint IntSrvDone;/* host's interrupt has been serviced */ int (*Copy)( caddr_t, caddr_t, int ); /* copy func */ struct timer_list timer; /* diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index 5a4ae63c1..3b6d2f3b1 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -47,7 +47,6 @@ struct ttystatics { #define SEM_SIGIGNORE 0x1234 - #ifdef DEBUG_SEM #define swait(a,b) printk ("waiting: " __FILE__ " line %d\n", __LINE__) #define ssignal(sem) printk ("signalling: " __FILE__ " line %d\n", __LINE__) diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 0adc6efed..625f7022b 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -109,108 +109,6 @@ of boards in rio.h. You'll have to allocate more majors if you need more than 512 ports.... */ -/* ************************************************************** */ -/* * This section can be removed when 2.0 becomes outdated.... * */ -/* ************************************************************** */ - -#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */ -#define TWO_ZERO -#else -#if LINUX_VERSION_CODE < 0x020209 /* less than 2.2.x */ -#warning "Please use a recent 2.2.x kernel. " -#endif -#endif - - -#ifdef TWO_ZERO - -/* Here is the section that makes the 2.2 compatible driver source - work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, - and provide for compatibility stuff here if possible. */ - -#include <linux/bios32.h> - -#define Get_user(a,b) a = get_user(b) -#define Put_user(a,b) 0,put_user(a,b) -#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) - -static inline int copy_from_user(void *to,const void *from, int c) -{ - memcpy_fromfs(to, from, c); - return 0; -} - -#define pci_present pcibios_present -#define pci_read_config_word pcibios_read_config_word -#define pci_read_config_dword pcibios_read_config_dword - -static inline unsigned char get_irq (unsigned char bus, unsigned char fn) -{ - unsigned char t; - pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t); - return t; -} - -static inline void *ioremap(unsigned long base, long length) -{ - if (base < 0x100000) return (void *)base; - return vremap (base, length); -} - -#define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x)) - -#define capable(x) suser() - -#define queue_task queue_task_irq_off -#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) -#define signal_pending(current) (current->signal & ~current->blocked) -#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) -#define time_after(t1,t2) (((long)t1-t2) > 0) - - -#define test_and_set_bit(nr, addr) set_bit(nr, addr) -#define test_and_clear_bit(nr, addr) clear_bit(nr, addr) - -/* Not yet implemented on 2.0 */ -#define ASYNC_SPD_SHI -1 -#define ASYNC_SPD_WARP -1 - - -/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it - to the "name" field that does exist. As long as the assignments are - done in the right order, there is nothing to worry about. */ -#define driver_name name - -/* Should be in a header somewhere. They are in tty.h on 2.2 */ -#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */ -#define TTY_HW_COOK_IN 15 /* in hardware - output and input */ - -/* The return type of a "close" routine. */ -#define INT void -#define NO_ERROR /* Nothing */ - -#else - -/* The 2.2.x compatibility section. */ -#include <asm/uaccess.h> - -#define Get_user(a,b) get_user(a,b) -#define Put_user(a,b) put_user(a,b) -#define get_irq(pdev) pdev->irq - -#define INT int -#define NO_ERROR 0 - -#define my_iounmap(x,b) (iounmap((char *)(b))) - -#endif - -/* ************************************************************** */ -/* * End of compatibility section.. * */ -/* ************************************************************** */ - - - /* Why the hell am I defining these here? */ #define RIO_TYPE_NORMAL 1 #define RIO_TYPE_CALLOUT 2 @@ -373,55 +271,15 @@ static struct real_driver rio_real_driver = { NULL }; - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ -#define DEBUG - -#ifdef DEBUG -#define rio_dprintk(f, str...) if (rio_debug & f) printk (str) -#else -#define rio_dprintk(f, str...) /* nothing */ -#endif - - -#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n") -#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n") - -#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \ - "(port %d)\n", port->line) - - - - /* * Firmware loader driver specific routines * */ static struct file_operations rio_fw_fops = { - NULL, /* lseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* select */ - rio_fw_ioctl, - NULL, /* mmap */ - rio_fw_open, -#ifndef TWO_ZERO - NULL, /* flush */ -#endif - rio_fw_release, - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ + ioctl: rio_fw_ioctl, + open: rio_fw_open, + release: rio_fw_release, }; struct miscdevice rio_fw_device = { @@ -446,11 +304,11 @@ static inline int rio_paranoia_check(struct rio_port const * port, KERN_ERR "rio: Warning: null rio port for device %s in %s\n"; if (!port) { - printk(badinfo, kdevname(device), routine); + printk (badinfo, kdevname(device), routine); return 1; } if (port->magic != RIO_MAGIC) { - printk(badmagic, kdevname(device), routine); + printk (badmagic, kdevname(device), routine); return 1; } @@ -468,15 +326,15 @@ void my_hd (void *ad, int len) unsigned char *addr = ad; for (i=0;i<len;i+=16) { - printk ("%08x ", (int) addr+i); + rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i); for (j=0;j<16;j++) { - printk ("%02x %s", addr[j+i], (j==7)?" ":""); + rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":""); } for (j=0;j<16;j++) { ch = addr[j+i]; - printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); + rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); } - printk ("\n"); + rio_dprintk (RIO_DEBUG_PARAM, "\n"); } } #else @@ -568,21 +426,26 @@ static int rio_set_real_termios (void *ptr) void rio_reset_interrupt (struct Host *HostP) { + func_enter(); + switch( HostP->Type ) { case RIO_AT: case RIO_MCA: case RIO_PCI: WBYTE(HostP->ResetInt , 0xff); } + + func_exit(); } static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs) { struct Host *HostP; + func_enter (); - HostP = &p->RIOHosts[(long)ptr]; - /* func_enter (); */ + HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */ + rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec); @@ -627,7 +490,7 @@ static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs) } } #endif - + rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); if (HostP->Ivec == irq) { /* Tell the card we've noticed the interrupt. */ rio_reset_interrupt (HostP); @@ -649,7 +512,7 @@ static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs) clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks); rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec); - /* func_exit (); */ + func_exit (); } @@ -657,7 +520,7 @@ static void rio_pollfunc (unsigned long data) { func_enter (); - rio_interrupt (0, (void *)data, NULL); + rio_interrupt (0, &p->RIOHosts[data], NULL); p->RIOHosts[data].timer.expires = jiffies + rio_poll; add_timer (&p->RIOHosts[data].timer); @@ -756,11 +619,11 @@ static void rio_shutdown_port (void * ptr) #if 0 port->gs.flags &= ~ GS_ACTIVE; if (!port->gs.tty) { - printk ("No tty.\n"); + rio_dprintk (RIO_DBUG_TTY, "No tty.\n"); return; } if (!port->gs.tty->termios) { - printk ("No termios.\n"); + rio_dprintk (RIO_DEBUG_TTY, "No termios.\n"); return; } if (port->gs.tty->termios->c_cflag & HUPCL) { @@ -1000,6 +863,8 @@ struct vpd_prom *get_VPD_PROM (struct Host *hp) if (rio_debug & RIO_DEBUG_PROBE) my_hd ((char *)&vpdp, 0x20); + + func_exit(); return &vpdp; } @@ -1099,7 +964,7 @@ static int rio_init_datastructures (void) /* However, the RIO driver allows users to configure their first RTA as the ports numbered 504-511. We therefore need to allocate the whole range. :-( -- REW */ - + #define RI_SZ sizeof(struct rio_info) #define HOST_SZ sizeof(struct Host) #define PORT_SZ sizeof(struct Port *) @@ -1138,11 +1003,20 @@ static int rio_init_datastructures (void) port->gs.close_delay = HZ/2; port->gs.closing_wait = 30 * HZ; port->gs.rd = &rio_real_driver; + + /* + * Initializing wait queue + */ + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); + } #else /* We could postpone initializing them to when they are configured. */ #endif + + if (rio_debug & RIO_DEBUG_INIT) { my_hd (&rio_real_driver, sizeof (rio_real_driver)); } @@ -1166,7 +1040,6 @@ static int rio_init_datastructures (void) } -#ifdef MODULE static void rio_release_drivers(void) { func_enter(); @@ -1176,7 +1049,6 @@ static void rio_release_drivers(void) tty_unregister_driver (&rio_driver); func_exit(); } -#endif #ifdef TWO_ZERO #define PDEV unsigned char pci_bus, unsigned pci_fun @@ -1213,7 +1085,7 @@ void fix_rio_pci (PDEV) unsigned int t; #define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x00260000 +#define CNTRL_REG_GOODVALUE 0x18260000 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; @@ -1294,7 +1166,6 @@ int rio_init(void) pci_read_config_dword (pdev, 0x2c, &tint); tshort = (tint >> 16) & 0xffff; rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); - /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ if (tshort != 0x0100) { rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort); @@ -1307,49 +1178,51 @@ int rio_init(void) hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = get_irq (pdev); - if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; - hp->Mode = RIO_PCI_DEFAULT_MODE; - + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + rio_reset_interrupt (hp); + rio_start_card_running (hp); + rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); - rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", - p->RIOHosts[p->RIONumHosts].UniqueNum); - -#if 1 - fix_rio_pci (pdev); -#endif - p->RIOLastPCISearch = RIO_SUCCESS; - p->RIONumHosts++; - found++; + rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n"); + WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); + p->RIOHosts[p->RIONumHosts].UniqueNum = + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); + rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", + p->RIOHosts[p->RIONumHosts].UniqueNum); + + fix_rio_pci (pdev); + p->RIOLastPCISearch = RIO_SUCCESS; + p->RIONumHosts++; + found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, + p->RIOHosts[p->RIONumHosts].Caddr); } - + #ifdef TWO_ZERO } /* We have two variants with the opening brace, so to prevent */ #else } /* Emacs from getting confused we have two closing braces too. */ #endif - /* Then look for the older PCI card.... : */ #ifndef TWO_ZERO + /* These older PCI cards have problems (only byte-mode access is supported), which makes them a bit awkward to support. They also have problems sharing interrupts. Be careful. @@ -1374,15 +1247,21 @@ int rio_init(void) hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = get_irq (pdev); - if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; - hp->Mode = RIO_PCI_DEFAULT_MODE; - - rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + + rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); + rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); + + rio_reset_interrupt (hp); + rio_start_card_running (hp); + rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, @@ -1425,11 +1304,15 @@ int rio_init(void) hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_AT; - hp->Copy = rio_pcicopy; + hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL + * -- YES! this is now a normal copy. Only the + * old PCI card uses the special PCI copy. + * Moreover, the ISA card will work with the + * special PCI copy anyway. -- REW */ hp->Mode = 0; vpdp = get_VPD_PROM (hp); - + rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n"); okboard = 0; if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || @@ -1460,11 +1343,21 @@ int rio_init(void) if (hp->Ivec) { int mode = SA_SHIRQ; if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;} - if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) { - printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); - hp->Ivec = 0; + rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode); + retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp); + rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); + if (retval) { + printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); + hp->Ivec = 0; } rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); + if (hp->Ivec != 0){ + rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); + hp->Mode |= RIO_PCI_INT_ENABLE; + } else + hp->Mode &= !RIO_PCI_INT_ENABLE; + rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); + rio_start_card_running (hp); } /* Init the timer "always" to make sure that it can safely be deleted when we unload... */ @@ -1481,7 +1374,7 @@ int rio_init(void) } if (found) { - printk (KERN_INFO "rio: total of %d boards detected.\n", found); + rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); if (misc_register(&rio_fw_device) < 0) { printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); @@ -1506,7 +1399,7 @@ void cleanup_module(void) for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) { RIOHostReset (hp->Type, hp->CardP, hp->Slot); if (hp->Ivec) { - free_irq (hp->Ivec, (void *)i); + free_irq (hp->Ivec, hp); rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); } /* It is safe/allowed to del_timer a non-active timer */ diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h index 5141355ea..c8b72bdce 100644 --- a/drivers/char/rio/rio_linux.h +++ b/drivers/char/rio/rio_linux.h @@ -23,13 +23,13 @@ * Version 1.0 -- July, 1999. * */ +#include <linux/config.h> #define RIO_NBOARDS 4 #define RIO_PORTSPERBOARD 128 #define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) #ifdef __KERNEL__ -#include <linux/config.h> #define RIO_MAGIC 0x12345678 @@ -160,3 +160,28 @@ static inline void *rio_memcpy_fromio (void *dest, void *source, int n) #define rio_memcpy_fromio memcpy_fromio #endif +#define DEBUG + + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ + +#ifdef DEBUG +#define rio_dprintk(f, str...) if (rio_debug & f) printk (str) +#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n") +#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n") +#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \ + "(port %d)\n", port->line) +#else +#define rio_dprintk(f, str...) /* nothing */ +#define func_enter() +#define func_exit() +#define func_enter2() +#endif + diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 7a06b0dc9..8168f2133 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -81,7 +81,6 @@ static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; #include "cmdblk.h" #include "route.h" - static uchar RIOAtVec2Ctrl[] = { @@ -113,6 +112,8 @@ struct DownLoad * rbp; { int offset; + func_enter (); + /* Linux doesn't allow you to disable interrupts during a "copyin". (Crash when a pagefault occurs). */ /* disable(oldspl); */ @@ -126,6 +127,7 @@ struct DownLoad * rbp; rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n")); p->RIOError.Error = HOST_FILE_TOO_LARGE; /* restore(oldspl); */ + func_exit (); return ENOMEM; } @@ -133,6 +135,7 @@ struct DownLoad * rbp; rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n")); p->RIOError.Error = BOOT_IN_PROGRESS; /* restore(oldspl); */ + func_exit (); return EBUSY; } @@ -160,6 +163,7 @@ struct DownLoad * rbp; rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n")); p->RIOError.Error = COPYIN_FAILED; /* restore(oldspl); */ + func_exit (); return EFAULT; } @@ -171,9 +175,61 @@ struct DownLoad * rbp; p->RIOBootCount = rbp->Count; /* restore(oldspl); */ + func_exit(); return 0; } +void rio_start_card_running (struct Host * HostP) +{ + func_enter (); + + switch ( HostP->Type ) { + case RIO_AT: + rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n")); + WBYTE(HostP->Control, + BOOT_FROM_RAM | EXTERNAL_BUS_ON + | HostP->Mode + | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); + break; + +#ifdef FUTURE_RELEASE + case RIO_MCA: + /* + ** MCA handles IRQ vectors differently, so we don't write + ** them to this register. + */ + rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n")); + WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); + break; + + case RIO_EISA: + /* + ** EISA is totally different and expects OUTBZs to turn it on. + */ + rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n"); + OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); + break; +#endif + + case RIO_PCI: + /* + ** PCI is much the same as MCA. Everything is once again memory + ** mapped, so we are writing to memory registers instead of io + ** ports. + */ + rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n")); + WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); + break; + default: + rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type)); + break; + } +/* + printk (KERN_INFO "Done with starting the card\n"); + func_exit (); +*/ + return; +} /* ** Load in the host boot code - load it directly onto all halted hosts @@ -206,6 +262,10 @@ register struct DownLoad *rbp; for ( host=0; host<p->RIONumHosts; host++ ) { rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host)); HostP = &p->RIOHosts[host]; + + rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", + HostP->Type, HostP->Mode, HostP->Ivec ) ); + if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) { rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host)); @@ -233,6 +293,7 @@ register struct DownLoad *rbp; if ( p->RIOConf.HostLoadBase < rbp->Count ) { rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n")); p->RIOError.Error = HOST_FILE_TOO_LARGE; + func_exit (); return EFBIG; } /* @@ -259,6 +320,7 @@ register struct DownLoad *rbp; if ( !DownCode ) { rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n")); p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; + func_exit (); return ENOMEM; } bzero(DownCode, rbp->Count); @@ -266,6 +328,7 @@ register struct DownLoad *rbp; if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) { rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); p->RIOError.Error = COPYIN_FAILED; + func_exit (); return EFAULT; } @@ -276,6 +339,7 @@ register struct DownLoad *rbp; else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) { rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); p->RIOError.Error = COPYIN_FAILED; + func_exit (); return EFAULT; } @@ -405,47 +469,8 @@ register struct DownLoad *rbp; rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec ) ); - switch ( HostP->Type ) { - case RIO_AT: - rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n")); - WBYTE(HostP->Control, - BOOT_FROM_RAM | EXTERNAL_BUS_ON - | HostP->Mode - | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); - break; + rio_start_card_running(HostP); -#ifdef FUTURE_RELEASE - case RIO_MCA: - /* - ** MCA handles IRQ vectors differently, so we don't write - ** them to this register. - */ - rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n")); - WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); - break; - - case RIO_EISA: - /* - ** EISA is totally different and expects OUTBZs to turn it on. - */ - rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n"); - OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); - break; -#endif - - case RIO_PCI: - /* - ** PCI is much the same as MCA. Everything is once again memory - ** mapped, so we are writing to memory registers instead of io - ** ports. - */ - rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n")); - WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); - break; - default: - rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type)); - break; - } rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n")); /* @@ -453,9 +478,10 @@ register struct DownLoad *rbp; ** pointer: */ for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&& - (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { + (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR))); delay(HostP, HUNDRED_MS); + } /* @@ -613,6 +639,7 @@ register struct DownLoad *rbp; p->RIOSystemUp++; rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec)); + func_exit (); return 0; } diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 6f2e43da0..835d815d3 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -43,7 +43,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include <asm/string.h> #include <asm/semaphore.h> - #include <linux/termios.h> #include <linux/serial.h> diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 27b46398a..fa68646d5 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -201,6 +201,8 @@ int su; int retval = 0; unsigned long flags; + func_enter (); + /* Confuse teh compiler to think that we've initialized these */ Host=0; PortP = NULL; @@ -1776,6 +1778,8 @@ RIO_DEBUG_CTRL, if (su) } rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd)); p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; + + func_exit (); return EINVAL; } diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 72e8632cd..59cfdedd5 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -1414,7 +1414,7 @@ struct rio_info * p; (int)p->RIOHosts, sizeof(struct Host) ) ); for( host=0; host<RIO_HOSTS; host++ ) { - p->RIOHosts[host].HostLock = SPIN_LOCK_UNLOCKED; /* Let the first guy takes it */ + spin_lock_init (&p->RIOHosts[host].HostLock); p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */ } /* diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 3e7236b19..cda417f3f 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -89,7 +89,6 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; #include "list.h" #include "sam.h" - #if 0 static void ttyseth_pv(struct Port *, struct ttystatics *, struct termios *sg, int); @@ -154,13 +153,21 @@ riotopen(struct tty_struct * tty, struct file * filp) unsigned long flags; int retval = 0; + func_enter (); + + /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close + is going to oops. + */ + tty->driver_data = NULL; + SysPort = rio_minor (tty->device); Modem = rio_ismodem (tty->device); if ( p->RIOFailed ) { rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n")); pseterr(ENXIO); - return 0; + func_exit (); + return -ENXIO; } rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n", @@ -176,22 +183,24 @@ riotopen(struct tty_struct * tty, struct file * filp) if (SysPort >= RIO_PORTS) { /* out of range ? */ rio_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort)); pseterr(ENXIO); - return 0; + func_exit(); + return -ENXIO; } /* ** Grab pointer to the port stucture */ PortP = p->RIOPortp[SysPort]; /* Get control struc */ - + rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP); if ( !PortP->Mapped ) { /* we aren't mapped yet! */ /* ** The system doesn't know which RTA this port ** corresponds to. */ rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n")); + func_exit (); pseterr(ENXIO); - return 0; + return -ENXIO; } tty->driver_data = PortP; @@ -209,7 +218,8 @@ riotopen(struct tty_struct * tty, struct file * filp) if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) { rio_dprint(RIO_DEBUG_TTY, ("Host not running\n")); pseterr(ENXIO); - return 0; + func_exit (); + return -ENXIO; } /* @@ -224,12 +234,14 @@ riotopen(struct tty_struct * tty, struct file * filp) do { if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n")); + func_exit (); return -EINTR; } if (repeat_this -- <= 0) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); RIOPreemptiveCmd(p, PortP, FCLOSE ); pseterr(EINTR); + func_exit (); return -EIO; } } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); @@ -237,6 +249,7 @@ riotopen(struct tty_struct * tty, struct file * filp) } else { rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); pseterr(ENXIO); + func_exit (); return 0; } } @@ -249,6 +262,7 @@ riotopen(struct tty_struct * tty, struct file * filp) while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { if (!PortP->WaitUntilBooted) { rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); + func_exit (); return -ENXIO; } @@ -258,10 +272,12 @@ riotopen(struct tty_struct * tty, struct file * filp) */ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n")); + func_exit (); return -EINTR; } if (repeat_this -- <= 0) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); + func_exit (); return -EIO; } } @@ -276,8 +292,10 @@ riotopen(struct tty_struct * tty, struct file * filp) } #if 0 retval = gs_init_port(&PortP->gs); - if (retval) - return retval; + if (retval){ + func_exit (); + return retval; + } #endif /* @@ -306,6 +324,7 @@ riotopen(struct tty_struct * tty, struct file * filp) rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n")); rio_spin_unlock_irqrestore(&PortP->portSem, flags); retval = -ENXIO; + func_exit (); return retval; } @@ -375,6 +394,7 @@ riotopen(struct tty_struct * tty, struct file * filp) if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n")); RIOPreemptiveCmd(p, PortP, FCLOSE ); + func_exit (); return -EINTR; } rio_spin_lock_irqsave(&PortP->portSem, flags); @@ -425,6 +445,7 @@ bombout: tp->tm.c_state &= ~WOPEN; PortP->State &= ~RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit (); return -EINTR; } } @@ -462,6 +483,7 @@ bombout: rio_spin_unlock_irqrestore(&PortP->portSem, flags); rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n")); + func_exit (); return 0; } diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h index 13821a982..eddf86278 100644 --- a/drivers/char/rio/unixrup.h +++ b/drivers/char/rio/unixrup.h @@ -49,7 +49,7 @@ struct UnixRup uint Id; /* Id number */ uint BaseSysPort; /* SysPort of first tty on this RTA */ uint ModTypes; /* Modules on this RTA */ - spinlock_t RupLock; /* Lock structure for MPX */ + spinlock_t RupLock; /* Lock structure for MPX */ /* struct lockb RupLock; */ /* Lock structure for MPX */ }; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index bb9da9018..bfe700219 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -762,7 +762,7 @@ EXPORT_NO_SYMBOLS; static void rtc_dropped_irq(unsigned long data) { - printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq); + unsigned long freq; spin_lock_irq (&rtc_lock); @@ -773,8 +773,13 @@ static void rtc_dropped_irq(unsigned long data) rtc_irq_data += ((rtc_freq/HZ)<<8); rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ + + freq = rtc_freq; + spin_unlock_irq(&rtc_lock); + printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", freq); + /* Now we have new data */ wake_up_interruptible(&rtc_wait); diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c index 8ab735cdc..05bfcb607 100644 --- a/drivers/char/sh-sci.c +++ b/drivers/char/sh-sci.c @@ -189,10 +189,35 @@ static void sci_set_termios_cflag(struct sci_port *port) ctrl_out(smr_val, SCSMR); #if defined(CONFIG_SH_SCIF_SERIAL) +#if defined(__sh3__) + { /* For SH7709, SH7709A, SH7729 */ + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ + ctrl_outw(data&0x0fcf, SCPCR); + } +#endif if (C_CRTSCTS(port->gs.tty)) fcr_val |= 0x08; - else + else { +#if defined(__sh3__) + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP4MD1,0, + Set SCP6MD1,0 = {01} (output) */ + ctrl_outw((data&0x0fcf)|0x1000, SCPCR); + + data = ctrl_inb(SCPDR); + /* Set /RTS2 (bit6) = 0 */ + ctrl_outb(data&0xbf, SCPDR); +#elif defined(__SH4__) ctrl_outw(0x0080, SCSPTR); /* Set RTS = 1 */ +#endif + } ctrl_out(fcr_val, SCFCR); #endif @@ -721,7 +746,7 @@ int __init sci_init(void) int i; for (i=SCI_ERI_IRQ; i<SCI_IRQ_END; i++) - set_ipr_data(i, SCI_IPR_OFFSET, SCI_PRIORITY); + set_ipr_data(i, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); port = &sci_ports[0]; @@ -789,6 +814,7 @@ static inline void put_char(char c) while (!(status & SCI_TD_E)); ctrl_outb(c, SC_TDR); + ctrl_in(SC_SR); /* Dummy read */ ctrl_out(SCI_TD_E_CLEAR, SC_SR); restore_flags(flags); @@ -817,6 +843,7 @@ static inline int get_char(void) } } while (!(status & SCI_RD_F)); c = ctrl_inb(SC_RDR); + ctrl_in(SC_SR); /* Dummy read */ ctrl_out(SCI_RDRF_CLEAR, SC_SR); restore_flags(flags); diff --git a/drivers/char/sh-sci.h b/drivers/char/sh-sci.h index 2a736f4c9..f501951ec 100644 --- a/drivers/char/sh-sci.h +++ b/drivers/char/sh-sci.h @@ -56,7 +56,8 @@ #define SCI_TEI_IRQ 26 #define SCI_IRQ_END 27 -#define SCI_IPR_OFFSET (16+4) +#define SCI_IPR_ADDR INTC_IPRB +#define SCI_IPR_POS 1 #endif #if defined(CONFIG_SH_SCIF_SERIAL) @@ -69,12 +70,16 @@ #define SC_RDR 0xA400015A #define SCFCR (volatile unsigned char *)0xA400015C #define SCFDR 0xA400015E -#undef SCSPTR /* Is there any register for RTS?? */ + +#undef SCSPTR /* SH7709 doesn't have SCSPTR */ +#define SCPCR 0xA4000116 /* Instead, it has SCPCR and SCPDR */ +#define SCPDR 0xA4000136 #undef SCLSR #define SCSCR_INIT 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ /* 0x33 when external clock is used */ -#define SCI_IPR_OFFSET (64+4) +#define SCI_IPR_ADDR INTC_IPRE +#define SCI_IPR_POS 1 #elif defined(__SH4__) #define SCSMR (volatile unsigned short *)0xFFE80000 @@ -89,7 +94,8 @@ #define SCLSR 0xFFE80024 #define SCSCR_INIT 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -#define SCI_IPR_OFFSET (32+4) +#define SCI_IPR_ADDR INTC_IPRC +#define SCI_IPR_POS 1 #endif @@ -187,8 +193,17 @@ struct sci_port { * -- Greg Banks 27Feb2000 */ +/* + * XXX: Well, this is not relevant... + * Should we have config option for peripheral clock? + * Or we get the value from time.c. + */ #if defined(__sh3__) -#define PCLK 14745600 +#if defined(CONFIG_CPU_SUBTYPE_SH7709) +#define PCLK 33333333 +#else +#define PCLK 14745600 /* Isn't it 15MHz? */ +#endif #elif defined(__SH4__) #define PCLK 33333333 #endif diff --git a/drivers/char/sx.c b/drivers/char/sx.c index adfe3c69d..24a4948b5 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1079,7 +1079,7 @@ inline void sx_receive_chars (struct sx_port *port) struct tty_struct *tty; int copied=0; - /* func_enter2 (); */ + func_enter2 (); tty = port->gs.tty; while (1) { rx_op = sx_read_channel_byte (port, hi_rxopos); @@ -1134,7 +1134,7 @@ inline void sx_receive_chars (struct sx_port *port) /* tty_schedule_flip (tty); */ } - /* func_exit (); */ + func_exit (); } /* Inlined: it is called only once. Remove the inline if you add another @@ -2343,6 +2343,12 @@ static int sx_init_portstructs (int nboards, int nports) #ifdef NEW_WRITE_LOCKING port->gs.port_write_sem = MUTEX; #endif + /* + * Initializing wait queue + */ + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); + port++; } } diff --git a/drivers/char/tda7432.c b/drivers/char/tda7432.c new file mode 100644 index 000000000..488091310 --- /dev/null +++ b/drivers/char/tda7432.c @@ -0,0 +1,505 @@ +/* + * For the STS-Thompson TDA7432 audio processor chip + * + * Handles audio functions: volume, balance, tone, loudness + * This driver will not complain if used with any + * other i2c device with the same address. + * + * Copyright (c) 2000 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 + * set to 2 if you'd like to be inundated with debug messages + * + * loudness - set between 0 and 15 for varying degrees of loudness effect + * + * TODO: + * Implement tone controls + * + * Revision: 0.3 - Fixed silly reversed volume controls. :) + * Revision: 0.2 - Cleaned up #defines + * fixed volume control + * Added I2C_DRIVERID_TDA7432 + * added loudness insmod control + * Revision: 0.1 - initial 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" + +/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ +#ifndef I2C_DRIVERID_TDA7432 + #define I2C_DRIVERID_TDA7432 27 +#endif + + +MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>"); +MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip"); + +MODULE_PARM(debug,"i"); +MODULE_PARM(loudness,"i"); +static int loudness = 0; /* disable loudness by default */ +static int debug = 0; /* insmod parameter */ + + +/* Address to scan (I2C address of this chip) */ +static unsigned short normal_i2c[] = { + I2C_TDA7432 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {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 +}; + +/* Structure of address and subaddresses for the tda7432 */ + +struct tda7432 { + int addr; + int input; + int volume; + int tone; + int lf, lr, rf, rr; + int loud; +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define dprintk if (debug) printk +#define d2printk if (debug > 1) printk + +/* The TDA7432 is made by STS-Thompson + * http://www.st.com + * http://us.st.com/stonline/books/pdf/docs/4056.pdf + * + * TDA7432: I2C-bus controlled basic audio processor + * + * The TDA7432 controls basic audio functions like volume, balance, + * and tone control (including loudness). It also has four channel + * output (for front and rear). Since most vidcap cards probably + * don't have 4 channel output, this driver will set front & rear + * together (no independent control). + */ + + /* Subaddresses for TDA7432 */ + +#define TDA7432_IN 0x00 /* Input select */ +#define TDA7432_VL 0x01 /* Volume */ +#define TDA7432_TN 0x02 /* Bass, Treble (Tone) */ +#define TDA7432_LF 0x03 /* Attenuation LF (Left Front) */ +#define TDA7432_LR 0x04 /* Attenuation LR (Left Rear) */ +#define TDA7432_RF 0x05 /* Attenuation RF (Right Front) */ +#define TDA7432_RR 0x06 /* Attenuation RR (Right Rear) */ +#define TDA7432_LD 0x07 /* Loudness */ + + + /* Masks for bits in TDA7432 subaddresses */ + +/* Many of these not used - just for documentation */ + +/* Subaddress 0x00 - Input selection and bass control */ + +/* Bits 0,1,2 control input: + * 0x00 - Stereo input + * 0x02 - Mono input + * 0x03 - Mute + * Mono probably isn't used - I'm guessing only the stereo + * input is connected on most cards, so we'll set it to stereo. + * + * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut + * Bit 4 controls bass range: 0/1 is extended/standard bass range + * + * Highest 3 bits not used + */ + +#define TDA7432_STEREO_IN 0 +#define TDA7432_MONO_IN 2 /* Probably won't be used */ +#define TDA7432_MUTE 3 /* Probably won't be used */ +#define TDA7432_BASS_SYM 1 << 3 +#define TDA7432_BASS_NORM 1 << 4 + +/* Subaddress 0x01 - Volume */ + +/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps + * Recommended maximum is +20 dB + * + * +32dB: 0x00 + * +20dB: 0x0c + * 0dB: 0x20 + * -79dB: 0x6f + * + * MSB (bit 7) controls loudness: 1/0 is loudness on/off + */ + +#define TDA7432_VOL_0DB 0x20 +#define TDA7432_LD_ON 1 << 7 + + +/* Subaddress 0x02 - Tone control */ + +/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB + * 0x0 is 14dB, 0x7 is 0dB + * + * Bit 3 controls treble attenuation/gain (sign) + * 1 = gain (+) + * 0 = attenuation (-) + * + * Bits 4,5,6 control absolute bass gain from 0dB to 14dB + * (This is only true for normal base range, set in 0x00) + * 0x0 << 4 is 14dB, 0x7 is 0dB + * + * Bit 7 controls bass attenuation/gain (sign) + * 1 << 7 = gain (+) + * 0 << 7 = attenuation (-) + * + * Example: + * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble + */ + +#define TDA7432_TREBLE_0DB 0xf +#define TDA7432_TREBLE 7 +#define TDA7432_TREBLE_GAIN 1 << 3 +#define TDA7432_BASS_0DB 0xf << 4 +#define TDA7432_BASS 7 << 4 +#define TDA7432_BASS_GAIN 1 << 7 + + +/* Subaddress 0x03 - Left Front attenuation */ +/* Subaddress 0x04 - Left Rear attenuation */ +/* Subaddress 0x05 - Right Front attenuation */ +/* Subaddress 0x06 - Right Rear attenuation */ + +/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB + * in 1.5dB steps. + * + * 0x00 is 0dB + * 0x1f is -37.5dB + * + * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) + * We'll use the mute on the input, though (above) + * Bits 6,7 unused + */ + +#define TDA7432_ATTEN_0DB 0x00 + + +/* Subaddress 0x07 - Loudness Control */ + +/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps + * when bit 4 is NOT set + * + * 0x0 is 0dB + * 0xf is -15dB + * + * If bit 4 is set, then there is a flat attenuation according to + * the lower 4 bits, as above. + * + * Bits 5,6,7 unused + */ + + + +/* Begin code */ + +static int tda7432_write(struct i2c_client *client, int subaddr, int val) +{ + unsigned char buffer[2]; + d2printk("tda7432: In tda7432_write\n"); + dprintk("tda7432: Writing %d 0x%x\n", subaddr, val); + buffer[0] = subaddr; + buffer[1] = val; + if (2 != i2c_master_send(client,buffer,2)) { + printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n", + subaddr, val); + return -1; + } + return 0; +} + +/* I don't think we ever actually _read_ the chip... */ +#if 0 +static int tda7432_read(struct i2c_client *client) +{ + unsigned char buffer; + d2printk("tda7432: In tda7432_read\n"); + if (1 != i2c_master_recv(client,&buffer,1)) { + printk(KERN_WARNING "tda7432: I/O error, trying (read)\n"); + return -1; + } + dprintk("tda7432: Read 0x%02x\n", buffer); + return buffer; +} +#endif + +static int tda7432_set(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + unsigned char buf[16]; + d2printk("tda7432: In tda7432_set\n"); + + dprintk(KERN_INFO + "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + t->input,t->volume,t->tone,t->lf,t->lr,t->rf,t->rr,t->loud); + buf[0] = TDA7432_IN; + buf[1] = t->input; + buf[2] = t->volume; + buf[3] = t->tone; + buf[4] = t->lf; + buf[5] = t->lr; + buf[6] = t->rf; + buf[7] = t->rr; + buf[8] = t->loud; + if (9 != i2c_master_send(client,buf,9)) { + printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n"); + return -1; + } + + return 0; +} + +static void do_tda7432_init(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + d2printk("tda7432: In tda7432_init\n"); + + t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ + TDA7432_BASS_SYM | /* Symmetric bass cut */ + TDA7432_BASS_NORM; /* Normal bass range */ + t->volume = TDA7432_VOL_0DB; /* 0dB Volume */ + if (loudness) /* Turn loudness on? */ + t->volume |= TDA7432_LD_ON; + t->tone = TDA7432_TREBLE_0DB | /* 0dB Treble */ + TDA7432_BASS_0DB; /* 0dB Bass */ + t->lf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->lr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->rf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->loud = loudness; /* insmod parameter */ + + tda7432_set(client); +} + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda7432_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tda7432 *t; + struct i2c_client *client; + d2printk("tda7432: In tda7432_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_tda7432_init(client); + MOD_INC_USE_COUNT; + strcpy(client->name,"TDA7432"); + printk(KERN_INFO "tda7432: init\n"); + + i2c_attach_client(client); + return 0; +} + +static int tda7432_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tda7432_attach); + return 0; +} + +static int tda7432_detach(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + + do_tda7432_init(client); + i2c_detach_client(client); + + kfree(t); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int tda7432_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tda7432 *t = client->data; + d2printk("tda7432: In tda7432_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... */ + + /* Query card - scale from TDA7432 settings to V4L settings */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + dprintk("tda7432: VIDIOCGAUDIO\n"); + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + + /* Master volume control + * V4L volume is min 0, max 65535 + * TDA7432 Volume: + * Min (-79dB) is 0x6f + * Max (+20dB) is 0x07 + * (Mask out bit 7 of vol - it's for the loudness setting) + */ + + va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630; + + /* Balance depends on L,R attenuation + * V4L balance is 0 to 65535, middle is 32768 + * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f + * to scale up to V4L numbers, mult by 1057 + * attenuation exists for lf, lr, rf, rr + * we use only lf and rf (front channels) + */ + + if ( (t->lf) < (t->rf) ) + /* right is attenuated, balance shifted left */ + va->balance = (32768 - 1057*(t->rf)); + else + /* left is attenuated, balance shifted right */ + va->balance = (32768 + 1057*(t->lf)); + + /* Bass/treble */ + va->bass = 32768; /* brain hurts... set to middle for now */ + va->treble = 32768; /* brain hurts... set to middle for now */ + + break; /* VIDIOCGAUDIO case */ + } + + /* Set card - scale from V4L settings to TDA7432 settings */ + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + dprintk("tda7432: VIDEOCSAUDIO\n"); + + t->volume = 0x6f - ( (va->volume)/630 ); + + if (loudness) /* Turn on the loudness bit */ + t->volume |= TDA7432_LD_ON; + + if (va->balance < 32768) { + /* shifted to left, attenuate right */ + t->rr = (32768 - va->balance)/1057; + t->rf = t->rr; + } + else { + /* shifted to right, attenuate left */ + t->lf = (va->balance - 32768)/1057; + t->lr = t->lf; + } + + /* t->tone = 0xff; */ /* Brain hurts - no tone control for now... */ + + tda7432_write(client,TDA7432_VL, t->volume); + /* tda7432_write(client,TDA7432_TN, t->tone); */ + tda7432_write(client,TDA7432_LF, t->lf); + tda7432_write(client,TDA7432_LR, t->lr); + tda7432_write(client,TDA7432_RF, t->rf); + tda7432_write(client,TDA7432_RR, t->rr); + + break; + + } /* end of VIDEOCSAUDIO case */ + + default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ + + /* nothing */ + d2printk("tda7432: Default\n"); + + } /* end of (cmd) switch */ + + return 0; +} + + +static struct i2c_driver driver = { + "i2c tda7432 driver", + I2C_DRIVERID_TDA7432, + I2C_DF_NOTIFY, + tda7432_probe, + tda7432_detach, + tda7432_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tda7432_init(void) +#endif +{ + + if ( (loudness < 0) || (loudness > 15) ) + { + printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\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/tda8425.c b/drivers/char/tda8425.c index 73df0b4ac..a1dec22eb 100644 --- a/drivers/char/tda8425.c +++ b/drivers/char/tda8425.c @@ -31,7 +31,6 @@ #include "audiochip.h" /* Addresses to scan */ -#define I2C_TDA8425 0x82 static unsigned short normal_i2c[] = { I2C_TDA8425 >> 1, I2C_CLIENT_END}; diff --git a/drivers/char/tda985x.c b/drivers/char/tda985x.c index 62bcf15ba..73fb9bd52 100644 --- a/drivers/char/tda985x.c +++ b/drivers/char/tda985x.c @@ -13,6 +13,7 @@ * * OPTIONS: * debug - set to 1 if you'd like to see debug messages + * - set to 2 if you'd like to be flooded with debug messages * chip - set to 9850 or 9855 to select your chip (default 9855) * * TODO: @@ -20,7 +21,8 @@ * and unmote to fix. - Is this still here? * Fine tune sound * Get rest of capabilities into video_audio struct... - * + * + * Revision 0.5 - cleaned up debugging messages, added debug level=2 * 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 @@ -55,9 +57,10 @@ static int chip = 9855; /* insmod parameter */ #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}; + 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 }; @@ -84,6 +87,7 @@ static struct i2c_driver driver; static struct i2c_client client_template; #define dprintk if (debug) printk +#define d2printk if (debug == 2) printk /* The TDA9850 and TDA9855 are both made by Philips Semiconductor * http://www.semiconductors.philips.com @@ -154,9 +158,9 @@ static struct i2c_client client_template; #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 */ + /* 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) */ @@ -213,8 +217,8 @@ static struct i2c_client client_template; 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); + d2printk("tda985x: In tda985x_write\n"); + dprintk("tda985x: Writing %d 0x%x\n", subaddr, val); buffer[0] = subaddr; buffer[1] = val; if (2 != i2c_master_send(client,buffer,2)) { @@ -228,12 +232,12 @@ static int tda985x_write(struct i2c_client *client, int subaddr, int val) static int tda985x_read(struct i2c_client *client) { unsigned char buffer; - dprintk("In tda985x_read\n"); + d2printk("tda985x: 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); + dprintk("tda985x: Read 0x%02x\n", buffer); return buffer; } @@ -241,12 +245,12 @@ static int tda985x_set(struct i2c_client *client) { struct tda985x *t = client->data; unsigned char buf[16]; - dprintk("In tda985x_set\n"); + d2printk("tda985x: 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", + "tda985x: 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; @@ -262,7 +266,7 @@ static int tda985x_set(struct i2c_client *client) 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"); + printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); return -1; } } @@ -270,7 +274,7 @@ static int tda985x_set(struct i2c_client *client) else if (chip == 9850) { dprintk(KERN_INFO - "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + "tda986x: 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; @@ -281,7 +285,7 @@ static int tda985x_set(struct i2c_client *client) 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"); + printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); return -1; } } @@ -292,11 +296,11 @@ static int tda985x_set(struct i2c_client *client) static void do_tda985x_init(struct i2c_client *client) { struct tda985x *t = client->data; - dprintk("In tda985x_init\n"); + d2printk("tda985x: In tda985x_init\n"); if (chip == 9855) { - printk("Using tda9855 options\n"); + printk("tda985x: Using tda9855 options\n"); t->rvol = 0x6f; /* 0dB */ t->lvol = 0x6f; /* 0dB */ t->bass = 0x0e; /* 0dB */ @@ -313,7 +317,7 @@ static void do_tda985x_init(struct i2c_client *client) else if (chip == 9850) { - printk("Using tda9850 options\n"); + printk("tda985x: 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 */ @@ -337,7 +341,7 @@ static int tda985x_attach(struct i2c_adapter *adap, int addr, { struct tda985x *t; struct i2c_client *client; - dprintk("In tda985x_attach\n"); + d2printk("tda985x: In tda985x_attach\n"); client = kmalloc(sizeof *client,GFP_KERNEL); if (!client) return -ENOMEM; @@ -382,7 +386,7 @@ static int tda985x_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tda985x *t = client->data; - dprintk("In tda985x_command...\n"); + d2printk("tda985x: In tda985x_command\n"); #if 0 __u16 *sarg = arg; #endif @@ -394,7 +398,7 @@ static int tda985x_command(struct i2c_client *client, case VIDIOCGAUDIO: { struct video_audio *va = arg; - dprintk("VIDIOCGAUDIO\n"); + dprintk("tda985x: VIDIOCGAUDIO\n"); if (chip == 9855) { int left,right; @@ -430,7 +434,7 @@ static int tda985x_command(struct i2c_client *client, case VIDIOCSAUDIO: { struct video_audio *va = arg; - dprintk("VIDEOCSAUDIO...\n"); + dprintk("tda985x: VIDEOCSAUDIO\n"); if (chip == 9855) { int left,right; @@ -453,17 +457,17 @@ static int tda985x_command(struct i2c_client *client, switch (va->mode) { case VIDEO_SOUND_MONO: - dprintk("VIDEO_SOUND_MONO\n"); + dprintk("tda985x: 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"); + dprintk("tda985x: 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"); + dprintk("tda985x: VIDEO_SOUND_LANG1\n"); t->c6= TDA985x_SAP | (t->c6 & 0x3f); tda985x_write(client,TDA985x_C6,t->c6); break; @@ -476,7 +480,7 @@ static int tda985x_command(struct i2c_client *client, default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ /* nothing */ - dprintk("Default\n"); + d2printk("tda985x: Default\n"); } /* end of (cmd) switch */ diff --git a/drivers/char/tda9875.c b/drivers/char/tda9875.c new file mode 100644 index 000000000..da3ceebfe --- /dev/null +++ b/drivers/char/tda9875.c @@ -0,0 +1,371 @@ +/* + * For the TDA9875 chip + * (The TDA9875 is used on the Diamond DTV2000 french version + * 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) 2000 Guillamue Delvit based on Gerd Knorr source and + * Eric Sandeen + * 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 + * + * 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" + +/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ +#ifndef I2C_DRIVERID_TDA9875 + #define I2C_DRIVERID_TDA9875 28 +#endif + + +MODULE_PARM(debug,"i"); + +static int debug = 0; /* insmod parameter */ + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { + I2C_TDA9875 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {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 TDA9875 */ +struct tda9875 { + int mode; + int rvol, lvol; + int bass, treble; +}; + + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define dprintk if (debug) printk + +/* The TDA9875 is made by Philips Semiconductor + * http://www.semiconductors.philips.com + * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator + * + */ + + /* subaddresses for TDA9875 */ +#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ +#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ +#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ +#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ + +#define TDA9875_CH1V 0x0c /*Chanel 1 volume (mute)*/ +#define TDA9875_CH2V 0x0d /*Chanel 2 volume (mute)*/ +#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ +#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ + +#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ +#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ +#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ +#define TDA9875_MVL 0x1a /* Main volume gauche */ +#define TDA9875_MVR 0x1b /* Main volume droite */ +#define TDA9875_MBA 0x1d /* Main Basse */ +#define TDA9875_MTR 0x1e /* Main treble */ +#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ +#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ +#define TDA9875_AVR 0x21 /* Auxilary volume droite */ +#define TDA9875_ABA 0x22 /* Auxilary Basse */ +#define TDA9875_ATR 0x23 /* Auxilary treble */ + +#define TDA9875_MSR 0x02 /* Monitor select register */ +#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ +#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ +#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ +#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ +#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ +#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ +#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ +#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ +#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ + +/* values */ +#define TDA9875_MUTE_ON 0xff /* general mute */ +#define TDA9875_MUTE_OFF 0xcc /* general no mute */ + + + +/* Begin code */ + +static int tda9875_write(struct i2c_client *client, int subaddr, int val) +{ + unsigned char buffer[2]; + dprintk("In tda9875_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 "tda9875: I/O error, trying (write %d 0x%x)\n", + subaddr, val); + return -1; + } + return 0; +} + +#if 0 +static int tda9875_read(struct i2c_client *client) +{ + unsigned char buffer; + dprintk("In tda9875_read\n"); + if (1 != i2c_master_recv(client,&buffer,1)) { + printk(KERN_WARNING "tda9875: I/O error, trying (read)\n"); + return -1; + } + dprintk("Read 0x%02x\n", buffer); + return buffer; +} +#endif + +static void tda9875_set(struct i2c_client *client) +{ + struct tda9875 *tda = client->data; + + dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble); + tda9875_write(client, TDA9875_MVL, tda->lvol / 600 - 84); + tda9875_write(client, TDA9875_MVR, tda->rvol / 600 -84); + tda9875_write(client, TDA9875_MBA, tda->bass / 2340 -12); + tda9875_write(client, TDA9875_MTR, tda->treble / 2621 -12); +} + +static void do_tda9875_init(struct i2c_client *client) +{ + struct tda9875 *t = client->data; + dprintk("In tda9875_init\n"); + tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ + tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ + tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ + tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ + tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ + tda9875_write(client, TDA9875_C2MSB, 0x00 ); /*Car2(NICAM) MSB XMHz*/ + tda9875_write(client, TDA9875_C2MIB, 0x00 ); /*Car2(NICAM) MIB XMHz*/ + tda9875_write(client, TDA9875_C2LSB, 0x00 ); /*Car2(NICAM) LSB XMHz*/ + tda9875_write(client, TDA9875_DCR, 0x00 ); /*Demod config 0x00*/ + tda9875_write(client, TDA9875_DEEM, 0x44 ); /*DE-Emph 0b0100 0100*/ + tda9875_write(client, TDA9875_FMAT, 0x00 ); /*FM Matrix reg 0x00*/ + tda9875_write(client, TDA9875_SC1, 0x00 ); /* SCART 1 (SC1)*/ + tda9875_write(client, TDA9875_SC2, 0x01 ); /* SCART 2 (sc2)*/ + + tda9875_write(client, TDA9875_CH1V, 0x10 ); /* Chanel volume 1 mute*/ + tda9875_write(client, TDA9875_CH2V, 0x10 ); /* Chanel volume 2 mute */ + tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ + tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ + tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ + tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ + tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ + tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ + tda9875_write(client, TDA9875_MBA, 0x00 ); /* Main Bass Main 0dB*/ + tda9875_write(client, TDA9875_MTR, 0x00 ); /* Main Treble Main 0dB*/ + tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ + tda9875_write(client, TDA9875_AVL, 0x00 ); /* Vol Aux left 0dB*/ + tda9875_write(client, TDA9875_AVR, 0x00 ); /* Vol Aux right 0dB*/ + tda9875_write(client, TDA9875_ABA, 0x00 ); /* Aux Bass Main 0dB*/ + tda9875_write(client, TDA9875_ATR, 0x00 ); /* Aux Aigus Main 0dB*/ + + tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ + + t->mode=AUDIO_MUTE; + t->lvol=t->rvol =51000; /* 0dB */ + t->bass=30420; /* 0dB */ + t->treble=34073; /* 0dB */ + tda9875_set(client); + +} + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda9875_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tda9875 *t; + struct i2c_client *client; + dprintk("In tda9875_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_tda9875_init(client); + MOD_INC_USE_COUNT; + strcpy(client->name,"TDA9875"); + printk(KERN_INFO "tda9875: init\n"); + + i2c_attach_client(client); + return 0; +} + +static int tda9875_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tda9875_attach); + return 0; +} + +static int tda9875_detach(struct i2c_client *client) +{ + struct tda9875 *t = client->data; + + do_tda9875_init(client); + i2c_detach_client(client); + + kfree(t); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int tda9875_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tda9875 *t = client->data; + + dprintk("In tda9875_command...\n"); + + 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; + + dprintk("VIDIOCGAUDIO\n"); + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + + /* min is -84 max is 24 */ + left = (t->lvol+85)*600; + right = (t->rvol+85)*600; + 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+13)*2340; /* min -12 max +15 */ + va->treble = (t->treble+13)*2621;/* min -12 max +12 */ + + va->mode |= VIDEO_SOUND_MONO; + + + break; /* VIDIOCGAUDIO case */ + } + + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + int left,right; + + dprintk("VIDEOCSAUDIO...\n"); + left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + right = (MIN(va->balance,32768) * + va->volume) / 32768; + t->lvol = left/600-84; + t->rvol = right/600-84; + t->bass = va->bass/2340-12; + t->treble = va->treble/2621-12; + tda9875_set(client); + + 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 tda9875 driver", + I2C_DRIVERID_TDA9875, /* Get new one for TDA9875 */ + I2C_DF_NOTIFY, + tda9875_probe, + tda9875_detach, + tda9875_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tda9875_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/tea6420.c b/drivers/char/tea6420.c new file mode 100644 index 000000000..231ed9e4e --- /dev/null +++ b/drivers/char/tea6420.c @@ -0,0 +1,268 @@ +/* + * for the TEA6420 chip (only found on 3DFX (STB) TV/FM cards to the best + * of my knowledge) + * Copyright (C) 2000 Dave Stuart <justdave@ynn.com> + * This code is placed under the terms of the GNU General Public License + * Code liberally copied from tea6300 by . . . + * + * Copyright (c) 1998 Greg Alexander <galexand@acm.org> + * This code is placed under the terms of the GNU General Public License + * Code liberally copied from msp3400.c, which is by Gerd Knorr + * + */ + +#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" + + +/* Addresses to scan */ +#define I2C_TEA6420 0x98 +static unsigned short normal_i2c[] = { + I2C_TEA6420 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {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 +}; + + +MODULE_PARM(debug,"i"); +static int debug = 0; /* insmod parameter */ + +#define dprintk if (debug) printk + + +struct tea6420 { + int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ + int stereo; +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define TEA6420_S_SA 0x00 /* stereo A input */ +#define TEA6420_S_SB 0x01 /* stereo B */ +#define TEA6420_S_SC 0x02 /* stereo C */ +#define TEA6420_S_SD 0x03 /* stereo D */ +#define TEA6420_S_SE 0x04 /* stereo E */ +#define TEA6420_S_GMU 0x05 /* general mute */ + + +/* ******************************** * + * functions for talking to TEA6420 * + * ******************************** */ + +static int tea6420_write(struct i2c_client *client, int val) +{ + unsigned char buffer[2]; + int result; + +/* buffer[0] = addr; */ + buffer[0] = val; + result = i2c_master_send(client,buffer,1); + if (1 != result) { + printk(KERN_WARNING "tea6420: I/O error, trying (write +0x%x) result = %d\n", val, result); + return -1; + } + return 0; +} + + +static void do_tea6420_init(struct i2c_client *client) +{ + struct tea6420 *tea = client->data; + + tea->mode=AUDIO_OFF; + tea->stereo=1; + tea6420_write(client, TEA6420_S_GMU); /* mute */ +} + +static void tea6420_audio(struct i2c_client *client, int mode) +{ + struct tea6420 *tea = client->data; + + /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ + dprintk(KERN_DEBUG "tea6420_audio:%d (T,R,E,I,O)\n",mode); + tea->mode=mode; + if (mode==AUDIO_OFF) { /* just mute it */ + tea6420_write(client, TEA6420_S_GMU); + return; + } + switch(mode) { + case AUDIO_TUNER: + tea6420_write(client, TEA6420_S_SA); + break; + case AUDIO_RADIO: + tea6420_write(client, TEA6420_S_SB); + break; + case AUDIO_EXTERN: + tea6420_write(client, TEA6420_S_SC); + break; + } +} + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tea6420_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tea6420 *tea; + 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 = tea = kmalloc(sizeof *tea,GFP_KERNEL); + if (!tea) + return -ENOMEM; + memset(tea,0,sizeof *tea); + do_tea6420_init(client); + + MOD_INC_USE_COUNT; + strcpy(client->name,"TEA6420"); + printk(KERN_INFO "tea6420: initialized\n"); + + i2c_attach_client(client); + return 0; +} + +static int tea6420_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tea6420_attach); + return 0; +} + +static int tea6420_detach(struct i2c_client *client) +{ + struct tea6420 *tea = client->data; + + do_tea6420_init(client); + i2c_detach_client(client); + + kfree(tea); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int +tea6420_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + __u16 *sarg = arg; + + switch (cmd) { + case AUDC_SET_RADIO: + tea6420_audio(client,AUDIO_RADIO); + break; + case AUDC_SET_INPUT: + tea6420_audio(client,*sarg); + break; + + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; +/* va->volume=MAX(tea->left,tea->right); + va->balance=(32768*MIN(tea->left,tea->right))/ + (va->volume ? va->volume : 1); + va->balance=(tea->left<tea->right)? + (65535-va->balance) : va->balance; + va->bass = tea->bass; + va->treble = tea->treble; +*/ break; + } + case VIDIOCSAUDIO: + { + +/* tea->left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + tea->right = (MIN(va->balance,32768) * + va->volume) / 32768; + tea->bass = va->bass; + tea->treble = va->treble; + tea6420_set(client); +*/ break; + } + +default: + /* nothing */ + } + return 0; +} + +static struct i2c_driver driver = { + "i2c tea6420 driver", + I2C_DRIVERID_TEA6420, + I2C_DF_NOTIFY, + tea6420_probe, + tea6420_detach, + tea6420_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tea6420_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/tty_io.c b/drivers/char/tty_io.c index f922c7b71..1516d985e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -146,8 +146,8 @@ extern long vme_scc_console_init(void); extern int serial167_init(void); extern long serial167_console_init(void); #endif -#ifdef CONFIG_8xx -extern console_8xx_init(void); +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) +extern void console_8xx_init(void); extern int rs_8xx_init(void); #endif /* CONFIG_8xx */ #ifdef CONFIG_SGI_SERIAL @@ -2197,7 +2197,7 @@ void __init console_init(void) con_init(); #endif #ifdef CONFIG_SERIAL_CONSOLE -#ifdef CONFIG_8xx +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); #elif defined(CONFIG_SERIAL) serial_console_init(); @@ -2346,7 +2346,7 @@ void __init tty_init(void) #ifdef CONFIG_RIO rio_init(); #endif -#ifdef CONFIG_8xx +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) rs_8xx_init(); #endif /* CONFIG_8xx */ pty_init(); diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index 364ae8e69..618f02f85 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -41,7 +41,6 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; #ifdef CONFIG_VIDEO_BT848 -extern int init_bttv_cards(struct video_init *); extern int i2c_tuner_init(struct video_init *); #endif #ifdef CONFIG_VIDEO_BWQCAM @@ -59,9 +58,8 @@ extern int init_zoran_cards(struct video_init *); static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_BT848 - {"i2c-tuner", i2c_tuner_init}, - {"bttv", init_bttv_cards}, -#endif + {"i2c-tuner", i2c_tuner_init}, +#endif #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, #endif |