diff options
Diffstat (limited to 'drivers/char')
70 files changed, 4493 insertions, 999 deletions
diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 979f18ae0..04d20eb97 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -6,7 +6,7 @@ comment 'Character devices' bool 'Virtual terminal' CONFIG_VT if [ "$CONFIG_VT" = "y" ]; then - bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE + bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE fi tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL if [ "$CONFIG_SERIAL" = "y" ]; then @@ -22,103 +22,101 @@ if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then fi bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then - tristate 'Comtrol Rocketport support' CONFIG_ROCKETPORT - tristate 'Digiboard Intelligent Async Support' CONFIG_DIGIEPCA + tristate ' Comtrol Rocketport support' CONFIG_ROCKETPORT + tristate ' Digiboard Intelligent Async Support' CONFIG_DIGIEPCA if [ "$CONFIG_DIGIEPCA" = "n" ]; then - tristate 'Digiboard PC/Xx Support' CONFIG_DIGI + tristate ' Digiboard PC/Xx Support' CONFIG_DIGI fi - tristate 'Cyclades async mux support' CONFIG_CYCLADES + tristate ' Cyclades async mux support' CONFIG_CYCLADES if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then - bool ' Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR + bool ' Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR fi - bool 'Stallion multiport serial support' CONFIG_STALDRV + bool ' Stallion multiport serial support' CONFIG_STALDRV if [ "$CONFIG_STALDRV" = "y" ]; then - tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION - tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION + tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION + tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION fi - tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8 - tristate 'Computone IntelliPort Plus serial support' CONFIG_COMPUTONE - tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX + tristate ' SDL RISCom/8 card support' CONFIG_RISCOM8 + tristate ' Computone IntelliPort Plus serial support' CONFIG_COMPUTONE + tristate ' Specialix IO8+ card support' CONFIG_SPECIALIX if [ "$CONFIG_SPECIALIX" != "n" ]; then - bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS + bool ' Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS fi - tristate 'Specialix SX (and SI) card support' CONFIG_SX - tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL + tristate ' Specialix SX (and SI) card support' CONFIG_SX + tristate ' Hayes ESP serial port support' CONFIG_ESPSERIAL if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m + dep_tristate ' Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m fi - dep_tristate 'Microgate SyncLink card support' CONFIG_SYNCLINK m - dep_tristate 'HDLC line discipline support' CONFIG_N_HDLC m + dep_tristate ' Microgate SyncLink card support' CONFIG_SYNCLINK m + dep_tristate ' HDLC line discipline support' CONFIG_N_HDLC m fi bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then - int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 fi if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT - if [ "$CONFIG_PRINTER" != "n" ]; then - bool ' Support for console on line printer' CONFIG_LP_CONSOLE - fi - dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT + dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT + if [ "$CONFIG_PRINTER" != "n" ]; then + bool ' Support for console on line printer' CONFIG_LP_CONSOLE + fi + dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT fi mainmenu_option next_comment comment 'Mice' tristate 'Bus Mouse Support' CONFIG_BUSMOUSE if [ "$CONFIG_BUSMOUSE" != "n" ]; then - dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE - dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE - dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE - if [ "$CONFIG_ADB" = "y" ]; then - dep_tristate 'Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE - fi + dep_tristate ' ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE + dep_tristate ' Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE + dep_tristate ' Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE + if [ "$CONFIG_ADB" = "y" ]; then + dep_tristate ' Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE + fi fi tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE if [ "$CONFIG_MOUSE" != "n" ]; then - bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE - tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE - tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD + bool ' PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE + tristate ' C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE + tristate ' PC110 digitizer pad support' CONFIG_PC110_PAD fi endmenu tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE if [ "$CONFIG_QIC02_TAPE" != "n" ]; then - bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF - if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then - comment ' Edit configuration parameters in ./include/linux/tpqic02.h!' - else - comment ' Setting runtime QIC-02 configuration is done with qic02conf' - comment ' from the tpqic02-support package. It is available at' - comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/' - fi - dep_tristate 'Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV - dep_tristate ' Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN + bool ' Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF + if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then + comment ' Edit configuration parameters in ./include/linux/tpqic02.h!' + else + comment ' Setting runtime QIC-02 configuration is done with qic02conf' + comment ' from the tpqic02-support package. It is available at' + comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/' + fi fi +mainmenu_option next_comment +comment 'Watchdog Cards' bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then - mainmenu_option next_comment - comment 'Watchdog Cards' - bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT - tristate ' WDT Watchdog timer' CONFIG_WDT - if [ "$CONFIG_WDT" != "n" ]; then - bool ' WDT501 features' CONFIG_WDT_501 - if [ "$CONFIG_WDT_501" = "y" ]; then + bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT + tristate ' WDT Watchdog timer' CONFIG_WDT + if [ "$CONFIG_WDT" != "n" ]; then + bool ' WDT501 features' CONFIG_WDT_501 + if [ "$CONFIG_WDT_501" = "y" ]; then bool ' Fan Tachometer' CONFIG_WDT_501_FAN - fi - fi - tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG - tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG - tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT - endmenu + fi + fi + tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG + tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG + tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT fi +endmenu tristate '/dev/nvram support' CONFIG_NVRAM bool 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then - bool 'Tadpole ANA H8 Support' CONFIG_H8 + bool 'Tadpole ANA H8 Support' CONFIG_H8 fi mainmenu_option next_comment @@ -126,64 +124,76 @@ comment 'Video For Linux' tristate 'Video For Linux' CONFIG_VIDEO_DEV if [ "$CONFIG_VIDEO_DEV" != "n" ]; then - dep_tristate 'ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV - dep_tristate 'AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then - hex ' RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f - fi - dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then - hex ' RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c - fi - dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then - hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350 - fi - dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then - hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c - fi - dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV - dep_tristate 'TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then - hex ' Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590 - fi - if [ "$CONFIG_PCI" != "n" ]; then - dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV - fi - if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT - dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT - fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_SGI_IP22" = "y" ]; then - dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV - fi - fi - dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV - if [ "$CONFIG_PMAC" = "y" ]; then - dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV - fi - dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV - dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then - hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284 - fi - dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV - if [ "$CONFIG_PROC_FS" = "y" ]; then + dep_tristate ' I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT + comment 'Radio/Video Adapters' + dep_tristate ' ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV + dep_tristate ' AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then + hex ' RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f + fi + dep_tristate ' AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then + hex ' RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c + fi + dep_tristate ' Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then + hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350 + fi + if [ "$CONFIG_PCI" != "n" ]; then + dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV + fi + dep_tristate ' GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then + hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c + fi + dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV + dep_tristate ' Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV + if [ "$CONFIG_PMAC" = "y" ]; then + dep_tristate ' PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV + fi + if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate ' Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT + fi + fi + dep_tristate ' SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV + dep_tristate ' SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then + hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284 + fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_SGI" = "y" ]; then + dep_tristate ' SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV + fi + fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV + fi + dep_tristate ' TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then + hex ' Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590 + fi + dep_tristate ' Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_TRUST" = "y" ]; then + hex ' Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350 + fi + dep_tristate ' Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV + if [ "$CONFIG_PROC_FS" = "y" ]; then if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then - bool ' Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS + bool ' Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS fi - fi - if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then - hex ' Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316 - int ' Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500 - fi - dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV - if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then - hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c - fi - dep_tristate 'IIC on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT + fi + if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then + hex ' Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316 + int ' Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500 + fi + dep_tristate ' Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV + if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then + hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c + fi + dep_tristate ' Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV + dep_tristate ' Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN fi endmenu @@ -193,7 +203,7 @@ comment 'Joystick support' tristate 'Joystick support' CONFIG_JOYSTICK if [ "$CONFIG_JOYSTICK" != "n" ]; then - source drivers/char/joystick/Config.in + source drivers/char/joystick/Config.in fi endmenu @@ -206,15 +216,19 @@ mainmenu_option next_comment comment 'Ftape, the floppy tape device driver' tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE if [ "$CONFIG_FTAPE" != "n" ]; then - source drivers/char/ftape/Config.in + source drivers/char/ftape/Config.in fi endmenu if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM - if [ "$CONFIG_DRM" = "y" ]; then - dep_tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA m - fi + bool 'Direct Rendering Manager (XFree86 DRI support) (EXPERIMENTAL)' CONFIG_DRM + if [ "$CONFIG_DRM" = "y" ]; then + dep_tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA m + fi +fi + +if [ "$CONFIG_PCMCIA" != "n" ]; then + source drivers/char/pcmcia/Config.in fi endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 490ad02e3..e86c937a9 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -11,7 +11,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick +ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia # # This file contains the font map for the default (hardware) font @@ -277,7 +277,7 @@ O_OBJS += softdog.o else ifeq ($(CONFIG_SOFT_WATCHDOG),m) M_OBJS += softdog.o - endif + endif endif ifeq ($(CONFIG_PCWATCHDOG),y) @@ -338,6 +338,10 @@ endif ifeq ($(CONFIG_RTC),y) O_OBJS += rtc.o +else + ifeq ($(CONFIG_RTC),m) + M_OBJS += rtc.o + endif endif ifeq ($(CONFIG_NVRAM),y) @@ -378,16 +382,6 @@ else endif endif -ifeq ($(CONFIG_VIDEO_SAA5249),y) -O_OBJS += saa5249.o -L_I2C=y -else - ifeq ($(CONFIG_VIDEO_SAA5249),m) - M_OBJS += saa5249.o - M_I2C=y - endif -endif - ifeq ($(CONFIG_I2C_PARPORT),y) O_OBJS += i2c-parport.o L_I2C = y @@ -398,11 +392,13 @@ else endif endif -ifeq ($(CONFIG_VIDEO_BWQCAM),y) -O_OBJS += bw-qcam.o +ifeq ($(CONFIG_VIDEO_SAA5249),y) +O_OBJS += saa5249.o +L_I2C=y else - ifeq ($(CONFIG_VIDEO_BWQCAM),m) - M_OBJS += bw-qcam.o + ifeq ($(CONFIG_VIDEO_SAA5249),m) + M_OBJS += saa5249.o + M_I2C=y endif endif @@ -414,6 +410,14 @@ else endif endif +ifeq ($(CONFIG_VIDEO_BWQCAM),y) +O_OBJS += bw-qcam.o +else + ifeq ($(CONFIG_VIDEO_BWQCAM),m) + M_OBJS += bw-qcam.o + endif +endif + ifeq ($(CONFIG_VIDEO_ZORAN),y) O_OBJS += buz.o else @@ -462,13 +466,29 @@ else endif endif +ifeq ($(CONFIG_VIDEO_STRADIS),y) +O_OBJS += vino.o +else + ifeq ($(CONFIG_VIDEO_STRADIS),m) + M_OBJS += stradis.o + endif +endif + ifeq ($(CONFIG_RADIO_AZTECH),y) O_OBJS += radio-aztech.o else ifeq ($(CONFIG_RADIO_AZTECH),m) M_OBJS += radio-aztech.o endif -endif +endif + +ifeq ($(CONFIG_RADIO_RTRACK2),y) +O_OBJS += radio-rtrack2.o +else + ifeq ($(CONFIG_RADIO_RTRACK2),m) + M_OBJS += radio-rtrack2.o + endif +endif ifeq ($(CONFIG_RADIO_SF16FMI),y) O_OBJS += radio-sf16fmi.o @@ -476,23 +496,15 @@ else ifeq ($(CONFIG_RADIO_SF16FMI),m) M_OBJS += radio-sf16fmi.o endif -endif - -ifeq ($(CONFIG_RADIO_RTRACK),y) -O_OBJS += radio-aimslab.o -else - ifeq ($(CONFIG_RADIO_RTRACK),m) - M_OBJS += radio-aimslab.o - endif -endif +endif -ifeq ($(CONFIG_RADIO_RTRACK2),y) -O_OBJS += radio-rtrack2.o +ifeq ($(CONFIG_RADIO_CADET),y) +O_OBJS += radio-cadet.o else - ifeq ($(CONFIG_RADIO_RTRACK2),m) - M_OBJS += radio-rtrack2.o + ifeq ($(CONFIG_RADIO_CADET),m) + M_OBJS += radio-cadet.o endif -endif +endif ifeq ($(CONFIG_RADIO_TYPHOON),y) O_OBJS += radio-typhoon.o @@ -500,7 +512,23 @@ else ifeq ($(CONFIG_RADIO_TYPHOON),m) M_OBJS += radio-typhoon.o endif -endif +endif + +ifeq ($(CONFIG_RADIO_TERRATEC),y) +O_OBJS += radio-terratec.o +else + ifeq ($(CONFIG_RADIO_TERRATEC),m) + M_OBJS += radio-terratec.o + endif +endif + +ifeq ($(CONFIG_RADIO_RTRACK),y) +O_OBJS += radio-aimslab.o +else + ifeq ($(CONFIG_RADIO_RTRACK),m) + M_OBJS += radio-aimslab.o + endif +endif ifeq ($(CONFIG_RADIO_ZOLTRIX),y) O_OBJS += radio-zoltrix.o @@ -508,15 +536,7 @@ else ifeq ($(CONFIG_RADIO_ZOLTRIX),m) M_OBJS += radio-zoltrix.o endif -endif - -ifeq ($(CONFIG_RADIO_CADET),y) -O_OBJS += radio-cadet.o -else - ifeq ($(CONFIG_RADIO_CADET),m) - M_OBJS += radio-cadet.o - endif -endif +endif ifeq ($(CONFIG_RADIO_MIROPCM20),y) O_OBJS += radio-miropcm20.o @@ -532,13 +552,13 @@ else ifeq ($(CONFIG_RADIO_GEMTEK),m) M_OBJS += radio-gemtek.o endif -endif +endif -ifeq ($(CONFIG_RADIO_TERRATEC),y) -O_OBJS += radio-terratec.o +ifeq ($(CONFIG_RADIO_TRUST),y) +O_OBJS += radio-trust.o else - ifeq ($(CONFIG_RADIO_TERRATEC),m) - M_OBJS += radio-terratec.o + ifeq ($(CONFIG_RADIO_TRUST),m) + M_OBJS += radio-trust.o endif endif @@ -591,6 +611,15 @@ ifeq ($(CONFIG_DRM),y) MOD_SUB_DIRS += drm endif +ifeq ($(CONFIG_PCMCIA),y) + SUB_DIRS += pcmcia + MOD_IN_SUB_DIRS += pcmcia +else + ifeq ($(CONFIG_PCMCIA),m) + MOD_IN_SUB_DIRS += pcmcia + endif +endif + include $(TOPDIR)/Rules.make fastdep: diff --git a/drivers/char/README.computone b/drivers/char/README.computone index 51c3666b6..d12a4ac29 100644 --- a/drivers/char/README.computone +++ b/drivers/char/README.computone @@ -47,7 +47,7 @@ d) Run "make config" or "make menuconfig" or "make xconfig" e) Set address on ISA cards then: edit /usr/src/linux/drivers/char/ip2/ip2.h if needed or - edit /etc/conf.modules (or /etc/modules.conf) if needed (module). + edit /etc/modules.conf if needed (module). or both to match this setting. f) Run "make dep" g) Run "make modules" diff --git a/drivers/char/adbmouse.c b/drivers/char/adbmouse.c index 3fb2afea5..a33693c14 100644 --- a/drivers/char/adbmouse.c +++ b/drivers/char/adbmouse.c @@ -148,7 +148,7 @@ static struct busmouse adb_mouse = ADB_MOUSE_MINOR, "adbmouse", open_mouse, release_mouse, 7 }; -int __init adb_mouse_init(void) +static int __init adb_mouse_init(void) { #ifdef __powerpc__ if ((_machine != _MACH_chrp) && (_machine != _MACH_Pmac)) @@ -170,6 +170,8 @@ int __init adb_mouse_init(void) return msedev < 0 ? msedev : 0; } +#ifndef MODULE + /* * XXX this function is misnamed. * It is called if the kernel is booted with the adb_buttons=xxx @@ -193,15 +195,12 @@ static int __init adb_mouse_setup(char *str) __setup("adb_buttons=", adb_mouse_setup); -#ifdef MODULE -int init_module(void) -{ - return adb_mouse_init(); -} +#endif /* !MODULE */ -void cleanup_module(void) +static void __exit adb_mouse_cleanup(void) { unregister_busmouse(msedev); } -#endif +module_init(adb_mouse_init); +module_exit(adb_mouse_cleanup); diff --git a/drivers/char/amigamouse.c b/drivers/char/amigamouse.c index f3f0b372d..823ec88ea 100644 --- a/drivers/char/amigamouse.c +++ b/drivers/char/amigamouse.c @@ -183,7 +183,7 @@ static struct busmouse amigamouse = { AMIGAMOUSE_MINOR, "amigamouse", open_mouse, release_mouse, 7 }; -int __init amiga_mouse_init(void) +static int __init amiga_mouse_init(void) { if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) return -ENODEV; @@ -200,12 +200,10 @@ int __init amiga_mouse_init(void) return msedev < 0 ? msedev : 0; } -void __exit amiga_mouse_exit(void) +static void __exit amiga_mouse_exit(void) { unregister_busmouse(msedev); } -#ifdef MODULE -module_init(amiga_mouse_init) -module_exit(amiga_mouse_exit) -#endif +module_init(amiga_mouse_init); +module_exit(amiga_mouse_exit); diff --git a/drivers/char/atarimouse.c b/drivers/char/atarimouse.c index b831bd49c..a188320c2 100644 --- a/drivers/char/atarimouse.c +++ b/drivers/char/atarimouse.c @@ -76,7 +76,7 @@ static struct busmouse atarimouse = { ATARIMOUSE_MINOR, "atarimouse", open_mouse, release_mouse, 0 }; -int __init atari_mouse_init(void) +static int __init atari_mouse_init(void) { if (!MACH_IS_ATARI) return -ENODEV; @@ -89,42 +89,50 @@ int __init atari_mouse_init(void) } +#ifndef MODULE + #define MIN_THRESHOLD 1 #define MAX_THRESHOLD 20 /* more seems not reasonable... */ -void __init atari_mouse_setup( char *str, int *ints ) +static int __init atari_mouse_setup( char *str ) { + int ints[8]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] < 1) { - printk( "atari_mouse_setup: no arguments!\n" ); - return; + printk(KERN_ERR "atari_mouse_setup: no arguments!\n" ); + return 0; } else if (ints[0] > 2) { - printk( "atari_mouse_setup: too many arguments\n" ); + printk(KERN_WARNING "atari_mouse_setup: too many arguments\n" ); } if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD) - printk( "atari_mouse_setup: bad threshold value (ignored)\n" ); + printk(KERN_WARNING "atari_mouse_setup: bad threshold value (ignored)\n" ); else { mouse_threshold[0] = ints[1]; mouse_threshold[1] = ints[1]; if (ints[0] > 1) { if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD) - printk("atari_mouse_setup: bad threshold value (ignored)\n" ); + printk(KERN_WARNING "atari_mouse_setup: bad threshold value (ignored)\n" ); else mouse_threshold[1] = ints[2]; } } - -} -#ifdef MODULE -int init_module(void) -{ - return atari_mouse_init(); + return 1; } -void cleanup_module(void) +__setup("atarimouse=",atari_mouse_setup); + +#endif /* !MODULE */ + +static void __exit atari_mouse_cleanup (void) { unregister_busmouse(msedev); } -#endif + +module_init(atari_mouse_init); +module_exit(atari_mouse_cleanup); + diff --git a/drivers/char/atixlmouse.c b/drivers/char/atixlmouse.c index 1ab9a211f..38de427e6 100644 --- a/drivers/char/atixlmouse.c +++ b/drivers/char/atixlmouse.c @@ -23,6 +23,7 @@ #include <linux/random.h> #include <linux/poll.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -66,7 +67,7 @@ static int msedev; -void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) { char dx, dy, buttons; @@ -102,10 +103,13 @@ static struct busmouse atixlmouse = { ATIXL_BUSMOUSE, "atixl", open_mouse, release_mouse, 0 }; -int __init atixl_busmouse_init(void) +static int __init atixl_busmouse_init(void) { unsigned char a,b,c; + if (check_region(ATIXL_MSE_DATA_PORT, 3)) + return -EIO; + a = inb( ATIXL_MSE_SIGNATURE_PORT ); /* Get signature */ b = inb( ATIXL_MSE_SIGNATURE_PORT ); c = inb( ATIXL_MSE_SIGNATURE_PORT ); @@ -117,6 +121,8 @@ int __init atixl_busmouse_init(void) outb(0x07, ATIXL_MSE_CONTROL_PORT); /* Select Internal Register 7 */ outb(0x0a, ATIXL_MSE_DATA_PORT); /* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */ + request_region(ATIXL_MSE_DATA_PORT, 3, "atixl"); + msedev = register_busmouse(&atixlmouse); if (msedev < 0) printk("Bus mouse initialisation error.\n"); @@ -125,15 +131,12 @@ int __init atixl_busmouse_init(void) return msedev < 0 ? msedev : 0; } -#ifdef MODULE - -int init_module(void) -{ - return atixl_busmouse_init(); -} - -void cleanup_module(void) +static void __exit atixl_cleanup (void) { + release_region(ATIXL_MSE_DATA_PORT, 3); unregister_busmouse(msedev); } -#endif + +module_init(atixl_busmouse_init); +module_exit(atixl_cleanup); + diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c index c592258bd..89e35ff1f 100644 --- a/drivers/char/busmouse.c +++ b/drivers/char/busmouse.c @@ -48,12 +48,6 @@ */ /*#define BROKEN_MOUSE*/ -extern int adb_mouse_init(void); -extern int logi_busmouse_init(void); -extern int ms_bus_mouse_init(void); -extern int atixl_busmouse_init(void); -extern int amiga_mouse_init(void); -extern int atari_mouse_init(void); extern int sun_mouse_init(void); extern void mouse_rpc_init (void); @@ -435,27 +429,9 @@ unregister_busmouse(int mousedev) int __init bus_mouse_init(void) { -#ifdef CONFIG_LOGIBUSMOUSE - logi_busmouse_init(); -#endif -#ifdef CONFIG_MS_BUSMOUSE - ms_bus_mouse_init(); -#endif -#ifdef CONFIG_ATIXL_BUSMOUSE - atixl_busmouse_init(); -#endif -#ifdef CONFIG_AMIGAMOUSE - amiga_mouse_init(); -#endif -#ifdef CONFIG_ATARIMOUSE - atari_mouse_init(); -#endif #ifdef CONFIG_SUN_MOUSE sun_mouse_init(); #endif -#ifdef CONFIG_ADBMOUSE - adb_mouse_init(); -#endif #ifdef CONFIG_RPCMOUSE mouse_rpc_init(); #endif diff --git a/drivers/char/c-qcam.c b/drivers/char/c-qcam.c index 90eb5405d..209298c6c 100644 --- a/drivers/char/c-qcam.c +++ b/drivers/char/c-qcam.c @@ -753,33 +753,21 @@ static struct parport_driver cqcam_driver = { NULL }; -static void cqcam_init(void) +static int __init cqcam_init (void) { printk(BANNER "\n"); - parport_register_driver(&cqcam_driver); + return parport_register_driver(&cqcam_driver); } -#ifdef MODULE - MODULE_AUTHOR("Philip Blundell <philb@gnu.org>"); MODULE_DESCRIPTION(BANNER); -int init_module(void) -{ - cqcam_init(); - return 0; -} - -void cleanup_module(void) +static void __exit cqcam_cleanup (void) { unsigned int i; for (i = 0; i < num_cams; i++) close_cqcam(qcams[i]); } -#else -int __init init_colour_qcams(struct video_init *unused) -{ - cqcam_init(); - return 0; -} -#endif + +module_init(cqcam_init); +module_exit(cqcam_cleanup); diff --git a/drivers/char/console.c b/drivers/char/console.c index 49512fe42..2a58a72ec 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -95,6 +95,7 @@ #include <linux/apm_bios.h> #endif #include <linux/bootmem.h> +#include <linux/acpi.h> #include <asm/io.h> #include <asm/system.h> @@ -201,6 +202,11 @@ static int scrollback_delta = 0; #define DO_UPDATE IS_VISIBLE #endif +static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state); +static struct acpi_dev_info acpi_con_info + = {ACPI_SYS_DEV, ACPI_VGA_HID, acpi_con_transition}; +static struct acpi_dev *acpi_con = NULL; + static inline unsigned short *screenpos(int currcons, int offset, int viewed) { unsigned short *p; @@ -654,6 +660,9 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ screenbuf = (unsigned short *) q; kmalloced = 1; vc_init(currcons, video_num_lines, video_num_columns, 1); + + if (!acpi_con) + acpi_con = acpi_register(&acpi_con_info, 0); } return 0; } @@ -1991,6 +2000,8 @@ void vt_console_print(struct console *co, const char * b, unsigned count) if (!printable || test_and_set_bit(0, &printing)) return; + acpi_access(acpi_con); + if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; @@ -2148,6 +2159,7 @@ static int con_write(struct tty_struct * tty, int from_user, { int retval; + acpi_access(acpi_con); retval = do_con_write(tty, from_user, buf, count); con_flush_chars(tty); @@ -2156,6 +2168,7 @@ static int con_write(struct tty_struct * tty, int from_user, static void con_put_char(struct tty_struct *tty, unsigned char ch) { + acpi_access(acpi_con); do_con_write(tty, 0, &ch, 1); } @@ -2221,6 +2234,7 @@ static void con_flush_chars(struct tty_struct *tty) { struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + acpi_access(acpi_con); set_cursor(vt->vc_num); } @@ -2806,6 +2820,21 @@ void vcs_scr_writew(int currcons, u16 val, u16 *org) } } +static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state) +{ + switch (state) + { + case ACPI_D0: + unblank_screen(); + break; + case ACPI_D1: + case ACPI_D2: + case ACPI_D3: + do_blank_screen(0); + break; + } + return 0; +} /* * Visible symbols for modules diff --git a/drivers/char/cs8420.h b/drivers/char/cs8420.h new file mode 100644 index 000000000..2b22f3a38 --- /dev/null +++ b/drivers/char/cs8420.h @@ -0,0 +1,50 @@ +/* cs8420.h - cs8420 initializations + Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +#ifndef __CS8420_H__ +#define __CS8420_H__ + +/* Initialization Sequence */ + +static __u8 init8420[] = { + 1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46, + 5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13, +}; + +#define INIT8420LEN (sizeof(init8420)/2) + +static __u8 mode8420pro[] = { /* professional output mode */ + 32, 0xa1, 33, 0x00, 34, 0x00, 35, 0x00, + 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, + 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, + 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, + 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, + 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, +}; +#define MODE8420LEN (sizeof(mode8420pro)/2) + +static __u8 mode8420con[] = { /* consumer output mode */ + 32, 0x20, 33, 0x00, 34, 0x00, 35, 0x48, + 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, + 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, + 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, + 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, + 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, +}; + +#endif diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index f795f96bb..655f11aff 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -699,6 +699,9 @@ cy_get_user(unsigned long *addr) (ZFIRM_ID==cy_readl(&((struct FIRM_ID *) \ ((card).base_addr+ID_ADDRESS))->signature))) +#ifndef SERIAL_XMIT_SIZE +#define SERIAL_XMIT_SIZE (MIN(PAGE_SIZE, 4096)) +#endif #define WAKEUP_CHARS (SERIAL_XMIT_SIZE-256) #define STD_COM_FLAGS (0) diff --git a/drivers/char/dn_keyb.c b/drivers/char/dn_keyb.c index 38010e29b..f663790db 100644 --- a/drivers/char/dn_keyb.c +++ b/drivers/char/dn_keyb.c @@ -1,4 +1,3 @@ -#include <linux/types.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/errno.h> @@ -18,8 +17,9 @@ #include <asm/apollohw.h> #include <asm/uaccess.h> +#include "busmouse.h" -extern void handle_scancode(unsigned char); +/* extern void handle_scancode(unsigned char,int ); */ #define DNKEY_CAPS 0x7e #define BREAK_FLAG 0x80 @@ -37,18 +37,12 @@ extern void handle_scancode(unsigned char); #define APOLLO_KBD_MODE_MOUSE 0x02 #define APOLLO_KBD_MODE_CHANGE 0xff -#define MSE_UPDATE_ON() mouse_update_allowed=1 -#define MSE_UPDATE_OFF() mouse_update_allowed=0 - static u_char keyb_cmds[APOLLO_KEYB_CMD_ENTRIES]; static short keyb_cmd_read=0, keyb_cmd_write=0; static int keyb_cmd_transmit=0; +static int msedev; static unsigned int kbd_mode=APOLLO_KBD_MODE_KEYB; -static short mouse_dx,mouse_dy,mouse_buttons; -static int mouse_ready=0,mouse_update_allowed=0,mouse_active=0; -static DECLARE_WAIT_QUEUE_HEAD(mouse_wait); -static struct fasync_struct *mouse_fasyncptr=NULL; #if 0 static void debug_keyb_timer_handler(unsigned long ignored); @@ -302,103 +296,6 @@ static void debug_keyb_timer_handler(unsigned long ignored) { } #endif -static unsigned int mouse_poll(struct file *file, poll_table * wait) -{ - poll_wait(&mouse_wait, wait); - if (mouse_ready) - return POLLIN | POLLRDNORM; - return 0; -} - -static ssize_t write_mouse(struct file * file, const char * buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static ssize_t read_mouse(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - int dx,dy,r; - unsigned char buttons; - - if (count < 3) - return -EINVAL; - if ((r = verify_area(VERIFY_WRITE, buffer, count))) - return r; - if (!mouse_ready) - return -EAGAIN; - - MSE_UPDATE_OFF(); - dx=mouse_dx; - dy=mouse_dy; - if (dx < -127) - dx = -127; - else - if (dx > 127) - dx = 127; - if (dy < -127) - dy = -127; - else - if (dy > 127) - dy = 127; - buttons=(mouse_buttons & 1 ? 4 : 0) | - (mouse_buttons & 2 ? 1 : 0) | - (mouse_buttons & 4 ? 2 : 0); - - mouse_dx-=dx; - mouse_dy-=dy; - MSE_UPDATE_ON(); - - if (put_user(buttons | 0x80, buffer++) || - put_user((char)dx, buffer++) || - put_user((char)dy, buffer++)) - return -EINVAL; - - if (count > 3) - if (clear_user(buffer, count - 3)) - return -EFAULT; - return count; -} - -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - - retval = fasync_helper(fd, filp, on, &mouse_fasyncptr); - if (retval < 0) - return retval; - return 0; -} - - -static int release_mouse(struct inode * inode, struct file * file) -{ - fasync_mouse(-1, file, 0); - if (--mouse_active) - return 0; - MSE_UPDATE_OFF(); - MOD_DEC_USE_COUNT; - return 0; -} - -static int open_mouse(struct inode * inode, struct file * file) -{ - if (mouse_active++) - return 0; - /* - * use VBL to poll mouse deltas - */ - - mouse_dx = 0; - mouse_dy = 0; - mouse_buttons = 0; - mouse_active = 1; - MOD_INC_USE_COUNT; - MSE_UPDATE_ON(); - return 0; -} - static void dn_keyb_process_key_event(unsigned char scancode) { static unsigned char lastscancode; @@ -411,7 +308,7 @@ static void dn_keyb_process_key_event(unsigned char scancode) { if(prev_scancode==APOLLO_KBD_MODE_CHANGE) { kbd_mode=scancode; -/* printk("modechange: %d\n",scancode);*/ +/* printk("modechange: %d\n",scancode); */ } else if((scancode & (~BREAK_FLAG)) == DNKEY_CAPS) { /* printk("handle_scancode: %02x\n",DNKEY_CAPS); */ @@ -440,7 +337,8 @@ static void dn_keyb_process_mouse_event(unsigned char mouse_data) { static short mouse_byte_count=0; static u_char mouse_packet[3]; - + short mouse_buttons; + mouse_packet[mouse_byte_count++]=mouse_data; if(mouse_byte_count==3) { @@ -552,23 +450,20 @@ void write_keyb_cmd(u_short length, u_char *cmd) { } -struct file_operations apollo_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; +static int release_mouse(struct inode * inode, struct file * file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static int open_mouse(struct inode * inode, struct file * file) +{ + MOD_INC_USE_COUNT; + return 0; +} -static struct miscdevice apollo_mouse = { - APOLLO_MOUSE_MINOR, "apollomouse", &apollo_mouse_fops +static struct busmouse apollo_mouse = { + APOLLO_MOUSE_MINOR, "apollomouse", open_mouse, release_mouse,7 }; int __init dn_keyb_init(void){ @@ -583,12 +478,12 @@ int __init dn_keyb_init(void){ memcpy(key_maps[8], dnalt_map, sizeof(plain_map)); memcpy(key_maps[12], dnctrl_alt_map, sizeof(plain_map)); - mouse_dx=0; - mouse_dy=0; - mouse_buttons=0; - mouse_wait=NULL; - misc_register(&apollo_mouse); + msedev=register_busmouse(&apollo_mouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to install Apollo mouse driver.\n"); + else + printk(KERN_INFO "Apollo mouse installed.\n"); /* program UpDownMode */ diff --git a/drivers/char/drm/proc.c b/drivers/char/drm/proc.c index 666b6e5ac..5bc52ba0d 100644 --- a/drivers/char/drm/proc.c +++ b/drivers/char/drm/proc.c @@ -382,7 +382,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, vma->vm_flags & VM_MAYSHARE ? 's' : 'p', vma->vm_flags & VM_LOCKED ? 'l' : '-', vma->vm_flags & VM_IO ? 'i' : '-', - vma->vm_offset ); + vma->vm_pgoff << PAGE_SHIFT ); #if defined(__i386__) pgprot = pgprot_val(vma->vm_page_prot); DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", diff --git a/drivers/char/drm/sigio.c b/drivers/char/drm/sigio.c index bb75087df..30df60f66 100644 --- a/drivers/char/drm/sigio.c +++ b/drivers/char/drm/sigio.c @@ -35,7 +35,6 @@ # include "xf86.h" # include "xf86drm.h" # include "xf86_OSlib.h" -# include "xf86drm.h" #else # include <unistd.h> # include <signal.h> diff --git a/drivers/char/drm/vm.c b/drivers/char/drm/vm.c index 55bfc4c45..d29594d1f 100644 --- a/drivers/char/drm/vm.c +++ b/drivers/char/drm/vm.c @@ -96,7 +96,7 @@ unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma, if (address > vma->vm_end) return 0; /* Disallow mremap */ if (!dma->pagelist) return 0; /* Nothing allocated */ - offset = address - vma->vm_start; /* vm_offset should be 0 */ + offset = address - vma->vm_start; /* vm_pgoff should be 0 */ page = offset >> PAGE_SHIFT; physical = dma->pagelist[page] + (offset & (~PAGE_MASK)); atomic_inc(&mem_map[MAP_NR(physical)].count); /* Dec. by kernel */ @@ -168,8 +168,8 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) drm_device_dma_t *dma = dev->dma; unsigned long length = vma->vm_end - vma->vm_start; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, vma->vm_offset); + DRM_DEBUG("start = 0x%lx, end = 0x%lx, pgoff = 0x%lx\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff); /* Length must match exact page count */ if ((length >> PAGE_SHIFT) != dma->page_count) return -EINVAL; @@ -192,13 +192,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_map_t *map = NULL; + unsigned long off; int i; DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, vma->vm_offset); + vma->vm_start, vma->vm_end, vma->vm_pgoff); - if (!vma->vm_offset) return drm_mmap_dma(filp, vma); + if (!vma->vm_pgoff) return drm_mmap_dma(filp, vma); + if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) /* overflow? */ + return -EINVAL; + off = vma->vm_pgoff << PAGE_SHIFT; /* A sequential search of a linked list is fine here because: 1) there will only be about 5-10 entries in the list and, 2) a @@ -208,7 +212,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) bit longer. */ for (i = 0; i < dev->map_count; i++) { map = dev->maplist[i]; - if (map->offset == vma->vm_offset) break; + if (map->offset == off) break; } if (i >= dev->map_count) return -EINVAL; @@ -222,7 +226,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) switch (map->type) { case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: - if (vma->vm_offset >= __pa(high_memory)) { + if (off >= __pa(high_memory)) { #if defined(__i386__) if (boot_cpu_data.x86 > 3) { pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; @@ -232,7 +236,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; /* not in core dump */ } if (remap_page_range(vma->vm_start, - vma->vm_offset, + off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 30a76a04e..bce9c6e02 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -73,13 +73,13 @@ m = min(count, maxio); \ for (i = 0; i < m; i++) { \ for (t = 0; t < timeout && !ENABLE; t++) \ - wait_some(2); \ + wait_some(HZ/50); \ if(!ENABLE) \ return -EIO; \ f; \ } \ count -= m; \ - if (m == maxio) wait_some(2); \ + if (m == maxio) wait_some(HZ/50); \ } \ } @@ -87,7 +87,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \ - wait_some(1); \ + wait_some(HZ/100); \ if(!DSP56K_TRANSMIT) { \ return -EIO; \ } \ @@ -97,7 +97,7 @@ { \ int t; \ for(t = 0; t < n && !DSP56K_RECEIVE; t++) \ - wait_some(1); \ + wait_some(HZ/100); \ if(!DSP56K_RECEIVE) { \ return -EIO; \ } \ diff --git a/drivers/char/ftape/Config.in b/drivers/char/ftape/Config.in index 59004dcf2..817bf5cd2 100644 --- a/drivers/char/ftape/Config.in +++ b/drivers/char/ftape/Config.in @@ -5,7 +5,7 @@ dep_tristate ' Zftape, the VFS interface' CONFIG_ZFTAPE $CONFIG_FTAPE if [ "$CONFIG_ZFTAPE" != "n" ]; then int ' Default block size' CONFIG_ZFT_DFLT_BLK_SZ 10240 comment ' The compressor will be built as a module only!' - define_bool CONFIG_ZFT_COMPRESSOR m + define_tristate CONFIG_ZFT_COMPRESSOR m fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then int ' Number of ftape buffers (EXPERIMENTAL)' CONFIG_FT_NR_BUFFERS 3 diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c index 05f1f6146..6ec456f00 100644 --- a/drivers/char/ftape/lowlevel/ftape-ctl.c +++ b/drivers/char/ftape/lowlevel/ftape-ctl.c @@ -704,8 +704,8 @@ int ftape_mmap(struct vm_area_struct *vma) if ((vma_get_flags(vma) & (VM_READ|VM_WRITE)) == 0) { TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access"); } - if (vma_get_offset (vma) != 0) { - TRACE_ABORT(-EINVAL, ft_t_err, "offset must be 0"); + if (vma_get_pgoff(vma) != 0) { + TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0"); } if ((vma_get_end (vma) - vma_get_start (vma)) % FT_BUFF_SIZE != 0) { TRACE_ABORT(-EINVAL, ft_t_err, diff --git a/drivers/char/ftape/lowlevel/ftape-proc.c b/drivers/char/ftape/lowlevel/ftape-proc.c index edae52c38..cfea418c5 100644 --- a/drivers/char/ftape/lowlevel/ftape-proc.c +++ b/drivers/char/ftape/lowlevel/ftape-proc.c @@ -22,245 +22,25 @@ * * This file contains the procfs interface for the * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. + + * Old code removed, switched to dynamic proc entry. */ #include <linux/config.h> #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) -/* adding proc entries from inside a module is REALLY complicated - * for pre-2.1.28 kernels. I don't want to care about it. - */ - #include <linux/proc_fs.h> #include <linux/ftape.h> -#if LINUX_VERSION_CODE <= KERNEL_VER(1,2,13) /* bail out */ -#error \ -Please disable CONFIG_FT_PROC_FS in "MCONFIG" or upgrade to a newer kernel! -#endif -#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16) #include <linux/init.h> -#else -#define __initdata -#define __initfunc(__arg) __arg -#endif #include <linux/qic117.h> - #include "../lowlevel/ftape-io.h" #include "../lowlevel/ftape-ctl.h" #include "../lowlevel/ftape-proc.h" #include "../lowlevel/ftape-tracing.h" -static int ftape_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -#if LINUX_VERSION_CODE < KERNEL_VER(2,1,28) - -#include <asm/segment.h> /* for memcpy_tofs() */ - -#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0) -static long ftape_proc_read(struct inode* inode, struct file* file, - char* buf, unsigned long count); -#else -static int ftape_proc_read(struct inode* inode, struct file* file, - char* buf, int count); -#endif - -#define FT_PROC_REGISTER(parent, child) proc_register_dynamic(parent, child) - -/* - * Structures for interfacing with the /proc filesystem. - * Router creates its own directory /proc/net/router with the folowing - * entries: - * config device configuration - * status global device statistics - * <device> entry for each WAN device - */ - -/* - * Generic /proc/net/ftape/<file> file and inode operations - */ - - -static struct file_operations ftape_proc_fops = -{ - NULL, /* lseek */ - ftape_proc_read, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* select */ - NULL, /* ioctl */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL, /* can't fsync */ -}; - -static struct inode_operations ftape_proc_inode_operations = -{ - &ftape_proc_fops, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL, /* revalidate */ -}; - -/* - * Proc filesystem directory entries. - */ - -static int ftape_get_info(char *page, char **start, off_t off, - int count, int dummy) -{ - int dummy_eof; - - return ftape_read_proc(page, start, off, count, &dummy_eof, NULL); -} - -static struct proc_dir_entry proc_ftape = { - 0, /* low_ino */ - sizeof("ftape")-1, /* namelen */ - "ftape", /* name */ - S_IFREG | S_IRUGO, /* mode */ - 1, /* nlink */ - 0, /* uid */ - 0, /* gid */ - 0, /* size */ - &ftape_proc_inode_operations, /* ops */ - ftape_get_info, /* get_info */ - NULL, /* fill_inode */ - NULL, /* next */ - NULL, /* parent */ - NULL, /* subdir */ - NULL /* data */ -}; - -/* Read ftape proc directory entry. - */ - -#define PROC_BLOCK_SIZE PAGE_SIZE - -#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0) -static long ftape_proc_read(struct inode * inode, struct file * file, - char * buf, unsigned long nbytes) -#else -static int ftape_proc_read(struct inode * inode, struct file * file, - char * buf, int nbytes) -#endif -{ - char *page; - int retval=0; - int eof=0; - int n, count; - char *start; - struct proc_dir_entry * dp; - - if (nbytes < 0) - return -EINVAL; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if (!(page = (char*) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - - while ((nbytes > 0) && !eof) - { - count = PROC_BLOCK_SIZE <= nbytes ? PROC_BLOCK_SIZE : nbytes; - - start = NULL; - if (dp->get_info) { - /* - * Handle backwards compatibility with the old net - * routines. - * - * XXX What gives with the file->f_flags & O_ACCMODE - * test? Seems stupid to me.... - */ - n = dp->get_info(page, &start, file->f_pos, count, - (file->f_flags & O_ACCMODE) == O_RDWR); - if (n < count) - eof = 1; - } else - break; - - if (!start) { - /* - * For proc files that are less than 4k - */ - start = page + file->f_pos; - n -= file->f_pos; - if (n <= 0) - break; - if (n > count) - n = count; - } - if (n == 0) - break; /* End of file */ - if (n < 0) { - if (retval == 0) - retval = n; - break; - } -#if LINUX_VERSION_CODE > KERNEL_VER(2,1,3) - copy_to_user(buf, start, n); -#else - memcpy_tofs(buf, start, n); -#endif - file->f_pos += n; /* Move down the file */ - nbytes -= n; - buf += n; - retval += n; - } - free_page((unsigned long) page); - return retval; -} - -#else /* LINUX_VERSION_CODE < KERNEL_VER(2,1,28) */ - -#define FT_PROC_REGISTER(parent, child) proc_register(parent, child) - -/* - * Proc filesystem directory entries. - */ - -static struct proc_dir_entry proc_ftape = { - 0, /* low_ino */ - sizeof("ftape")-1, /* namelen */ - "ftape", /* name */ - S_IFREG | S_IRUGO, /* mode */ - 1, /* nlink */ - 0, /* uid */ - 0, /* gid */ - 0, /* size */ - NULL, /* ops */ - NULL, /* get_info */ - NULL, /* fill_inode */ - NULL, /* next */ - NULL, /* parent */ - NULL, /* subdir */ - NULL, /* data */ - ftape_read_proc, /* read_proc */ - NULL /* write_proc */ -}; - -#endif - static size_t get_driver_info(char *buf) { const char *debug_level[] = { "bugs" , @@ -423,13 +203,14 @@ int ftape_read_proc(char *page, char **start, off_t off, int __init ftape_proc_init(void) { - return FT_PROC_REGISTER(&proc_root, &proc_ftape); + return create_proc_read_entry("ftape", 0, &proc_root, + ftape_read_proc, NULL) != NULL; } #ifdef MODULE void ftape_proc_destroy(void) { - proc_unregister(&proc_root, proc_ftape.low_ino); + remove_proc_entry("ftape", &proc_root); } #endif diff --git a/drivers/char/h8.c b/drivers/char/h8.c index d146a808f..0a6a63fff 100644 --- a/drivers/char/h8.c +++ b/drivers/char/h8.c @@ -3,6 +3,9 @@ * * The H8 is used to deal with the power and thermal environment * of a system. + * + * Fixes: + * June 1999, AV added releasing /proc/driver/h8 */ #include <linux/config.h> @@ -18,10 +21,8 @@ #include <linux/fcntl.h> #include <linux/malloc.h> #include <linux/linkage.h> -#ifdef CONFIG_PROC_FS #include <linux/stat.h> #include <linux/proc_fs.h> -#endif #include <linux/miscdevice.h> #include <linux/lists.h> #include <linux/ioport.h> @@ -58,6 +59,8 @@ static void h8_intr(int irq, void *dev_id, struct pt_regs *regs); #ifdef CONFIG_PROC_FS static int h8_get_info(char *, char **, off_t, int, int); +#else +static int h8_get_info(char *, char **, off_t, int, int) {} #endif /* @@ -125,12 +128,6 @@ static struct miscdevice h8_device = { &h8_fops }; -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry h8_proc_entry = { - 0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info -}; -#endif - union intr_buf intrbuf; int intr_buf_ptr; union intr_buf xx; @@ -321,9 +318,7 @@ int init_module(void) misc_register(&h8_device); request_region(h8_base, 8, "h8"); -#ifdef CONFIG_PROC_FS - proc_register(&proc_root, &h8_proc_entry); -#endif + create_proc_info_entry("driver/h8", 0, NULL, h8_get_info); QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *); QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *); @@ -339,6 +334,7 @@ int init_module(void) void cleanup_module(void) { + remove_proc_entry("driver/h8", NULL); misc_deregister(&h8_device); release_region(h8_base, 8); free_irq(h8_irq, NULL); @@ -355,9 +351,7 @@ int h8_init(void) } printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq); -#ifdef CONFIG_PROC_FS - proc_register(&proc_root, &h8_proc_entry); -#endif + create_proc_info_entry("driver/h8", 0, NULL, h8_get_info); misc_register(&h8_device); request_region(h8_base, 8, "h8"); diff --git a/drivers/char/ibmmpeg2.h b/drivers/char/ibmmpeg2.h new file mode 100644 index 000000000..68e10387c --- /dev/null +++ b/drivers/char/ibmmpeg2.h @@ -0,0 +1,94 @@ +/* ibmmpeg2.h - IBM MPEGCD21 definitions */ + +#ifndef __IBM_MPEG2__ +#define __IBM_MPEG2__ + +/* Define all MPEG Decoder registers */ +/* Chip Control and Status */ +#define IBM_MP2_CHIP_CONTROL 0x200*2 +#define IBM_MP2_CHIP_MODE 0x201*2 +/* Timer Control and Status */ +#define IBM_MP2_SYNC_STC2 0x202*2 +#define IBM_MP2_SYNC_STC1 0x203*2 +#define IBM_MP2_SYNC_STC0 0x204*2 +#define IBM_MP2_SYNC_PTS2 0x205*2 +#define IBM_MP2_SYNC_PTS1 0x206*2 +#define IBM_MP2_SYNC_PTS0 0x207*2 +/* Video FIFO Control */ +#define IBM_MP2_FIFO 0x208*2 +#define IBM_MP2_FIFOW 0x100*2 +#define IBM_MP2_FIFO_STAT 0x209*2 +#define IBM_MP2_RB_THRESHOLD 0x22b*2 +/* Command buffer */ +#define IBM_MP2_COMMAND 0x20a*2 +#define IBM_MP2_CMD_DATA 0x20b*2 +#define IBM_MP2_CMD_STAT 0x20c*2 +#define IBM_MP2_CMD_ADDR 0x20d*2 +/* Internal Processor Control and Status */ +#define IBM_MP2_PROC_IADDR 0x20e*2 +#define IBM_MP2_PROC_IDATA 0x20f*2 +#define IBM_MP2_WR_PROT 0x235*2 +/* DRAM Access */ +#define IBM_MP2_DRAM_ADDR 0x210*2 +#define IBM_MP2_DRAM_DATA 0x212*2 +#define IBM_MP2_DRAM_CMD_STAT 0x213*2 +#define IBM_MP2_BLOCK_SIZE 0x23b*2 +#define IBM_MP2_SRC_ADDR 0x23c*2 +/* Onscreen Display */ +#define IBM_MP2_OSD_ADDR 0x214*2 +#define IBM_MP2_OSD_DATA 0x215*2 +#define IBM_MP2_OSD_MODE 0x217*2 +#define IBM_MP2_OSD_LINK_ADDR 0x229*2 +#define IBM_MP2_OSD_SIZE 0x22a*2 +/* Interrupt Control */ +#define IBM_MP2_HOST_INT 0x218*2 +#define IBM_MP2_MASK0 0x219*2 +#define IBM_MP2_HOST_INT1 0x23e*2 +#define IBM_MP2_MASK1 0x23f*2 +/* Audio Control */ +#define IBM_MP2_AUD_IADDR 0x21a*2 +#define IBM_MP2_AUD_IDATA 0x21b*2 +#define IBM_MP2_AUD_FIFO 0x21c*2 +#define IBM_MP2_AUD_FIFOW 0x101*2 +#define IBM_MP2_AUD_CTL 0x21d*2 +#define IBM_MP2_BEEP_CTL 0x21e*2 +#define IBM_MP2_FRNT_ATTEN 0x22d*2 +/* Display Control */ +#define IBM_MP2_DISP_MODE 0x220*2 +#define IBM_MP2_DISP_DLY 0x221*2 +#define IBM_MP2_VBI_CTL 0x222*2 +#define IBM_MP2_DISP_LBOR 0x223*2 +#define IBM_MP2_DISP_TBOR 0x224*2 +/* Polarity Control */ +#define IBM_MP2_INFC_CTL 0x22c*2 + +/* control commands */ +#define IBM_MP2_PLAY 0 +#define IBM_MP2_PAUSE 1 +#define IBM_MP2_SINGLE_FRAME 2 +#define IBM_MP2_FAST_FORWARD 3 +#define IBM_MP2_SLOW_MOTION 4 +#define IBM_MP2_IMED_NORM_PLAY 5 +#define IBM_MP2_RESET_WINDOW 6 +#define IBM_MP2_FREEZE_FRAME 7 +#define IBM_MP2_RESET_VID_RATE 8 +#define IBM_MP2_CONFIG_DECODER 9 +#define IBM_MP2_CHANNEL_SWITCH 10 +#define IBM_MP2_RESET_AUD_RATE 11 +#define IBM_MP2_PRE_OP_CHN_SW 12 +#define IBM_MP2_SET_STILL_MODE 14 + +/* Define Xilinx FPGA Internal Registers */ + +/* general control register 0 */ +#define XILINX_CTL0 0x600 +/* genlock delay resister 1 */ +#define XILINX_GLDELAY 0x602 +/* send 16 bits to CS3310 port */ +#define XILINX_CS3310 0x604 +/* send 16 bits to CS3310 and complete */ +#define XILINX_CS3310_CMPLT 0x60c +/* pulse width modulator control */ +#define XILINX_PWM 0x606 + +#endif diff --git a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h index 7236744b0..4fc99c55c 100644 --- a/drivers/char/ip2/ip2.h +++ b/drivers/char/ip2/ip2.h @@ -70,8 +70,7 @@ * console warning. * When the driver is loaded as a module these setting can be overridden on the - * modprobe command line or on an option line in /etc/conf.modules - * or /etc/modules.conf depending on your distrubution. + * modprobe command line or on an option line in /etc/modules.conf. * If the driver is built-in the configuration must be * set here for ISA cards and address set to 1 and 2 for PCI and EISA. * @@ -92,8 +91,8 @@ /* this structure is zeroed out because the suggested method is to configure * the driver as a module, set up the parameters with an options line in - * /etc/modules.conf or /etc/conf.modules and load with modprobe, kerneld or - * kmod, the kernel module loader + * /etc/modules.conf and load with modprobe, kerneld or kmod, the kernel + * module loader */ static ip2config_t ip2config = { diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c index 8f0ef75ae..b31f10ac9 100644 --- a/drivers/char/ip2main.c +++ b/drivers/char/ip2main.c @@ -74,16 +74,6 @@ int ip2_read_procmem(char *, char **, off_t, int, int ); int ip2_read_proc(char *, char **, off_t, int, int *, void * ); -struct proc_dir_entry ip2_proc_entry = { - 0, - 6,"ip2mem", - S_IFREG | S_IRUGO, - 1, 0, 0, - 0, - NULL, - ip2_read_procmem -}; - /********************/ /* Type Definitions */ /********************/ @@ -429,9 +419,7 @@ cleanup_module(void) if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); } - if ( ( err = proc_unregister( &proc_root, ip2_proc_entry.low_ino ) ) ) { - printk(KERN_ERR "IP2: failed to unregister read_procmem (%d)\n", err); - } + remove_proc_entry("ip2mem", &proc_root); // free memory for (i = 0; i < IP2_MAX_BOARDS; i++) { @@ -673,8 +661,8 @@ old_ip2_init(void) printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); } else /* Register the read_procmem thing */ - if ( ( err = proc_register( &proc_root, &ip2_proc_entry ) ) ) { - printk(KERN_ERR "IP2: failed to register read_procmem (%d)\n", err ); + if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) { + printk(KERN_ERR "IP2: failed to register read_procmem\n"); } else { #ifdef IP2DEBUG_TRACE diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 041858997..6d2b5ed83 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -25,7 +25,7 @@ * You can find the original tools for this direct from Multitech * ftp://ftp.multitech.com/ISI-Cards/ * - * Having installed the cards the module options (/etc/conf.modules) + * Having installed the cards the module options (/etc/modules.conf) * * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4 * diff --git a/drivers/char/joystick/joy-amiga.c b/drivers/char/joystick/joy-amiga.c index 520f262a4..918025040 100644 --- a/drivers/char/joystick/joy-amiga.c +++ b/drivers/char/joystick/joy-amiga.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -39,7 +39,7 @@ static struct js_port* js_am_port __initdata = NULL; -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_PARM(js_am, "1-2i"); static int js_am[]={0,0}; diff --git a/drivers/char/joystick/joy-analog.c b/drivers/char/joystick/joy-analog.c index fdf04b212..7c1c9719d 100644 --- a/drivers/char/joystick/joy-analog.c +++ b/drivers/char/joystick/joy-analog.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -43,7 +43,7 @@ static int js_an_port_list[] __initdata = {0x201, 0}; static struct js_port* js_an_port __initdata = NULL; -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_PARM(js_an, "2-24i"); static int js_an[]={-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0}; diff --git a/drivers/char/joystick/joy-analog.h b/drivers/char/joystick/joy-analog.h index 06c0079a4..84479fcd1 100644 --- a/drivers/char/joystick/joy-analog.h +++ b/drivers/char/joystick/joy-analog.h @@ -26,7 +26,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -238,7 +238,7 @@ static int __init js_an_probe_devs(struct js_an_info *info, int exist, int mask0 break; default: printk(KERN_WARNING "joy-analog: Unknown joystick device detected " - "(data=%#x), contact <vojtech@ucw.cz>\n", exist); + "(data=%#x), contact <vojtech@suse.cz>\n", exist); return -1; } } diff --git a/drivers/char/joystick/joy-assasin.c b/drivers/char/joystick/joy-assasin.c index 64d16d7b0..731c6e56a 100644 --- a/drivers/char/joystick/joy-assasin.c +++ b/drivers/char/joystick/joy-assasin.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -49,7 +49,7 @@ #define JS_AS_MODE_OEM 3 /* Panther OEM version */ #define JS_AS_MODE_PXL 4 /* Panther XL */ -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_PARM(js_as, "2-24i"); static int js_as[]={-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0}; @@ -319,7 +319,7 @@ static struct js_port __init *js_as_probe(int io, int mask0, int mask1, struct j info = port->info; } else { printk(KERN_WARNING "joy-assasin: unknown joystick device detected " - "(io=%#x, id=%d), contact <vojtech@ucw.cz>\n", io, data[0]); + "(io=%#x, id=%d), contact <vojtech@suse.cz>\n", io, data[0]); return port; } diff --git a/drivers/char/joystick/joy-gravis.c b/drivers/char/joystick/joy-gravis.c index 9185d3113..7416527e4 100644 --- a/drivers/char/joystick/joy-gravis.c +++ b/drivers/char/joystick/joy-gravis.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ diff --git a/drivers/char/joystick/joy-lightning.c b/drivers/char/joystick/joy-lightning.c index fc36c3d50..3b337fd9f 100644 --- a/drivers/char/joystick/joy-lightning.c +++ b/drivers/char/joystick/joy-lightning.c @@ -26,7 +26,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -52,7 +52,7 @@ static struct js_port* __initdata js_l4_port = NULL; -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_PARM(js_l4, "2-24i"); static int js_l4[]={-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0}; diff --git a/drivers/char/joystick/joy-logitech.c b/drivers/char/joystick/joy-logitech.c index 2dcafbfeb..064ecade4 100644 --- a/drivers/char/joystick/joy-logitech.c +++ b/drivers/char/joystick/joy-logitech.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -318,7 +318,7 @@ static struct js_port __init *js_lt_probe(int io, struct js_port *port) return port; default: printk(KERN_WARNING "joy-logitech: unknown joystick device detected " - "(io=%#x, count=%d, data=0x%08x%08x), contact <vojtech@ucw.cz>\n", + "(io=%#x, count=%d, data=0x%08x%08x), contact <vojtech@suse.cz>\n", io, i, (int)(data >> 32), (int)(data & 0xffffffff)); return port; } diff --git a/drivers/char/joystick/joy-sidewinder.c b/drivers/char/joystick/joy-sidewinder.c index 3fb0d8cef..d097471bc 100644 --- a/drivers/char/joystick/joy-sidewinder.c +++ b/drivers/char/joystick/joy-sidewinder.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -422,7 +422,7 @@ static struct js_port __init *js_sw_probe(int io, struct js_port *port) return port; default: printk(KERN_WARNING "joy-sidewinder: unknown joystick device detected " - "(io=%#x, count=%d, data=0x%08x%08x), contact <vojtech@ucw.cz>\n", + "(io=%#x, count=%d, data=0x%08x%08x), contact <vojtech@suse.cz>\n", io, i, (int)(data >> 32), (int)(data & 0xffffffff)); return port; } diff --git a/drivers/char/joystick/joy-thrustmaster.c b/drivers/char/joystick/joy-thrustmaster.c index 3ea71416d..1e79b3281 100644 --- a/drivers/char/joystick/joy-thrustmaster.c +++ b/drivers/char/joystick/joy-thrustmaster.c @@ -25,7 +25,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -278,7 +278,7 @@ static struct js_port __init *js_tm_probe(int io, struct js_port *port) if (info.mode >= JS_TM_MODE_MAX || !names[info.mode]) { printk(KERN_WARNING "joy-thrustmaster: unknown device detected " - "(io=%#x, id=%d), contact <vojtech@ucw.cz>\n", + "(io=%#x, id=%d), contact <vojtech@suse.cz>\n", io, info.mode); return port; } diff --git a/drivers/char/joystick/joy-turbografx.c b/drivers/char/joystick/joy-turbografx.c index fdf1aa433..6b30efe85 100644 --- a/drivers/char/joystick/joy-turbografx.c +++ b/drivers/char/joystick/joy-turbografx.c @@ -26,7 +26,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -41,7 +41,7 @@ #include <linux/delay.h> -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_PARM(js_tg, "2-8i"); MODULE_PARM(js_tg_2, "2-8i"); MODULE_PARM(js_tg_3, "2-8i"); diff --git a/drivers/char/joystick/joystick.c b/drivers/char/joystick/joystick.c index 941f1795d..6c2abda1f 100644 --- a/drivers/char/joystick/joystick.c +++ b/drivers/char/joystick/joystick.c @@ -26,7 +26,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: + * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ @@ -90,7 +90,7 @@ js_delta_func js_delta_a; * Module info. */ -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_SUPPORTED_DEVICE("js"); /* diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 5989fbff5..ea97ee151 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -32,7 +32,6 @@ #include <linux/string.h> #include <linux/random.h> #include <linux/init.h> -#include <linux/module.h> #include <asm/keyboard.h> #include <asm/bitops.h> @@ -42,6 +41,7 @@ #include <linux/vt_kern.h> #include <linux/kbd_ll.h> #include <linux/sysrq.h> +#include <linux/acpi.h> #define SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -159,6 +159,9 @@ static int sysrq_pressed; int sysrq_enabled = 1; #endif +static struct acpi_dev_info acpi_kbd_info = {ACPI_SYS_DEV, ACPI_KBC_HID, NULL}; +static struct acpi_dev *acpi_kbd = NULL; + /* * Many other routines do put_queue, but I think either * they produce ASCII, or they produce some user-assigned @@ -201,6 +204,8 @@ void handle_scancode(unsigned char scancode, int down) char up_flag = down ? 0 : 0200; char raw_mode; + acpi_access(acpi_kbd); + do_poke_blanked_console = 1; mark_bh(CONSOLE_BH); add_keyboard_randomness(scancode | up_flag); @@ -939,5 +944,8 @@ int __init kbd_init(void) kbd_init_hw(); init_bh(KEYBOARD_BH, kbd_bh); mark_bh(KEYBOARD_BH); + + acpi_kbd = acpi_register(&acpi_kbd_info, 0); + return 0; } diff --git a/drivers/char/logibusmouse.c b/drivers/char/logibusmouse.c index d8c7d37dd..f9eae25eb 100644 --- a/drivers/char/logibusmouse.c +++ b/drivers/char/logibusmouse.c @@ -40,6 +40,7 @@ #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/init.h> #include <linux/logibusmouse.h> #include <linux/signal.h> #include <linux/errno.h> @@ -49,7 +50,6 @@ #include <linux/random.h> #include <linux/delay.h> #include <linux/ioport.h> -#include <linux/init.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -61,16 +61,26 @@ static int msedev; static int mouse_irq = MOUSE_IRQ; -#ifdef MODULE MODULE_PARM(mouse_irq, "i"); -#endif -void __init bmouse_setup(char *str, int *ints) +#ifndef MODULE + +static int __init bmouse_setup(char *str) { + int ints[4]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) mouse_irq=ints[1]; + + return 1; } +__setup("logi_busmouse=", bmouse_setup); + +#endif /* !MODULE */ + static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) { char dx, dy; @@ -118,7 +128,7 @@ static struct busmouse busmouse = { LOGITECH_BUSMOUSE, "busmouse", open_mouse, close_mouse, 7 }; -int __init logi_busmouse_init(void) +static int __init logi_busmouse_init(void) { if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) return -EIO; @@ -142,16 +152,11 @@ int __init logi_busmouse_init(void) return msedev < 0 ? msedev : 0; } -#ifdef MODULE - -int init_module(void) -{ - return logi_busmouse_init(); -} - -void cleanup_module(void) +static void __exit logi_busmouse_cleanup (void) { unregister_busmouse(msedev); release_region(LOGIBM_BASE, LOGIBM_EXTENT); } -#endif + +module_init(logi_busmouse_init); +module_exit(logi_busmouse_cleanup); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index a334205cb..873f0a955 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -56,6 +56,9 @@ extern void adbdev_init(void); #ifdef CONFIG_USB extern void usb_init(void); #endif +#ifdef CONFIG_PPDEV +extern int pp_init(void); +#endif static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, const char * buf, size_t count, loff_t *ppos) @@ -190,10 +193,7 @@ static inline int noncached_address(unsigned long addr) static int mmap_mem(struct file * file, struct vm_area_struct * vma) { - unsigned long offset = vma->vm_offset; - - if (offset & ~PAGE_MASK) - return -ENXIO; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; /* * Accessing memory above the top the kernel knows about or @@ -679,5 +679,8 @@ int __init chr_dev_init(void) #ifdef CONFIG_VIDEO_DEV videodev_init(); #endif +#ifdef CONFIG_PPDEV + pp_init(); +#endif return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index c30f10594..05abbe3b0 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -75,7 +75,6 @@ extern int rtc_init(void); extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */ extern int ds1286_init(void); extern int dsp56k_init(void); -extern int nvram_init(void); extern int radio_init(void); extern int pc110pad_init(void); extern int pmu_device_init(void); @@ -179,13 +178,9 @@ int misc_deregister(struct miscdevice * misc) EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister); -static struct proc_dir_entry *proc_misc; - int __init misc_init(void) { - proc_misc = create_proc_entry("misc", 0, 0); - if (proc_misc) - proc_misc->read_proc = misc_read_proc; + create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL); #ifdef CONFIG_BUSMOUSE bus_mouse_init(); #endif @@ -237,9 +232,6 @@ int __init misc_init(void) #ifdef CONFIG_ATARI_DSP56K dsp56k_init(); #endif -#ifdef CONFIG_NVRAM - nvram_init(); -#endif #ifdef CONFIG_MISC_RADIO radio_init(); #endif diff --git a/drivers/char/msbusmouse.c b/drivers/char/msbusmouse.c index 753c9d460..c3148a9cc 100644 --- a/drivers/char/msbusmouse.c +++ b/drivers/char/msbusmouse.c @@ -56,16 +56,26 @@ static int msedev; static int mouse_irq = MOUSE_IRQ; -#ifdef MODULE MODULE_PARM(mouse_irq, "i"); -#endif -void __init msmouse_setup(char *str, int *ints) +#ifndef MODULE + +static int __init msmouse_setup(char *str) { + int ints[4]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) mouse_irq=ints[1]; + + return 1; } +__setup("msmouse=",msmouse_setup); + +#endif /* !MODULE */ + static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) { char dx, dy; @@ -117,7 +127,7 @@ static struct busmouse msbusmouse = { MICROSOFT_BUSMOUSE, "msbusmouse", open_mouse, release_mouse, 0 }; -int __init ms_bus_mouse_init(void) +static int __init ms_bus_mouse_init(void) { int present = 0; int mse_byte, i; @@ -151,7 +161,7 @@ int __init ms_bus_mouse_init(void) return msedev < 0 ? msedev : 0; } -void ms_bus_mouse_exit(void) +static void __exit ms_bus_mouse_exit(void) { unregister_busmouse(msedev); release_region(MS_MSE_CONTROL_PORT, 0x04); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 0717fa418..b4f50243e 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -105,7 +105,6 @@ #include <linux/malloc.h> #include <linux/tty.h> #include <linux/errno.h> -#include <linux/sched.h> /* to get the struct task_struct */ #include <linux/string.h> /* used in new tty drivers */ #include <linux/signal.h> /* used in new tty drivers */ #include <asm/system.h> diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index dde61fe77..60ee17688 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -95,9 +95,7 @@ #include <linux/mc146818rtc.h> #include <linux/nvram.h> #include <linux/init.h> -#ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> -#endif #include <asm/io.h> #include <asm/uaccess.h> @@ -351,9 +349,10 @@ static int nvram_release( struct inode *inode, struct file *file ) } -#ifdef CONFIG_PROC_FS - -struct proc_dir_entry *proc_nvram; +#ifndef CONFIG_PROC_FS +static int nvram_read_proc( char *buffer, char **start, off_t offset, + int size, int *eof, void *data) { return 0; } +#else static int nvram_read_proc( char *buffer, char **start, off_t offset, int size, int *eof, void *data ) @@ -391,7 +390,7 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset, } \ } while(0) -#endif +#endif /* CONFIG_PROC_FS */ static struct file_operations nvram_fops = { nvram_llseek, @@ -413,7 +412,7 @@ static struct miscdevice nvram_dev = { }; -int __init nvram_init(void) +static int __init nvram_init(void) { /* First test whether the driver should init at all */ if (!CHECK_DRIVER_INIT()) @@ -421,29 +420,18 @@ int __init nvram_init(void) printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION ); misc_register( &nvram_dev ); -#ifdef CONFIG_PROC_FS - if ((proc_nvram = create_proc_entry( "nvram", 0, 0 ))) - proc_nvram->read_proc = nvram_read_proc; -#endif - + create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL); return( 0 ); } -#ifdef MODULE -int init_module (void) -{ - return( nvram_init() ); -} - -void cleanup_module (void) +static void __exit nvram_cleanup_module (void) { -#ifdef CONFIG_PROC_FS - if (proc_nvram) - remove_proc_entry( "nvram", 0 ); -#endif + remove_proc_entry( "driver/nvram", 0 ); misc_deregister( &nvram_dev ); } -#endif + +module_init(nvram_init); +module_exit(nvram_cleanup_module); /* diff --git a/drivers/char/pcmcia/.cvsignore b/drivers/char/pcmcia/.cvsignore new file mode 100644 index 000000000..857dd22e9 --- /dev/null +++ b/drivers/char/pcmcia/.cvsignore @@ -0,0 +1,2 @@ +.depend +.*.flags diff --git a/drivers/char/pcmcia/Config.in b/drivers/char/pcmcia/Config.in new file mode 100644 index 000000000..88545b788 --- /dev/null +++ b/drivers/char/pcmcia/Config.in @@ -0,0 +1,31 @@ +# +# PCMCIA character device configuration +# + +mainmenu_option next_comment +comment 'PCMCIA character device support' + +if [ "$CONFIG_SERIAL" = "y" ]; then + dep_tristate ' PCMCIA serial device support' \ + CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA + if [ "$CONFIG_CARDBUS" = "y" ]; then + dep_tristate ' CardBus serial device support' \ + CONFIG_PCMCIA_SERIAL_CB $CONFIG_PCMCIA + fi +fi + +if [ "$CONFIG_SERIAL" = "m" ]; then + dep_tristate ' PCMCIA serial device support' \ + CONFIG_PCMCIA_SERIAL_CS m + if [ "$CONFIG_CARDBUS" = "y" ]; then + dep_tristate ' CardBus serial device support' \ + CONFIG_PCMCIA_SERIAL_CB m + fi +fi + +if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" -o \ + "$CONFIG_PCMCIA_SERIAL_CB" = "y" ]; then + define_bool CONFIG_PCMCIA_CHRDEV y +fi + +endmenu diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile new file mode 100644 index 000000000..198500763 --- /dev/null +++ b/drivers/char/pcmcia/Makefile @@ -0,0 +1,27 @@ +# +# drivers/char/pcmcia/Makefile +# +# Makefile for the Linux PCMCIA char device drivers. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +O_TARGET := pcmcia_char.o +MOD_LIST_NAME := PCMCIA_CHAR_MODULES + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_PCMCIA_SERIAL_CS) += serial_cs.o +obj-$(CONFIG_PCMCIA_SERIAL_CB) += serial_cb.o + +O_OBJS := $(obj-y) +OX_OBJS := +M_OBJS := $(obj-m) +MX_OBJS := + +include $(TOPDIR)/Rules.make diff --git a/drivers/char/pcmcia/serial_cb.c b/drivers/char/pcmcia/serial_cb.c new file mode 100644 index 000000000..8a2dede85 --- /dev/null +++ b/drivers/char/pcmcia/serial_cb.c @@ -0,0 +1,150 @@ +/*====================================================================== + + A driver for CardBus serial devices + + serial_cb.c 1.14 1999/11/11 02:18:08 + + Copyright 1998, 1999 by Donald Becker and David Hinds + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + All other rights reserved. + + This driver is an activator for CardBus serial cards, as + found on multifunction (e.g. Ethernet and Modem) CardBus cards. + + Donald Becker may be reached as becker@CESDIS.edu, or C/O + USRA Center of Excellence in Space Data and Information Sciences + Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 + David Hinds may be reached at dhinds@pcmcia.sourceforge.org + +======================================================================*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/malloc.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/major.h> +#include <linux/pci.h> +#include <asm/io.h> + +#include <pcmcia/driver_ops.h> + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"serial_cb.c 1.14 1999/11/11 02:18:08 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================== + + Card-specific configuration hacks + +======================================================================*/ + +static void device_setup(u_char bus, u_char devfn, u_int ioaddr) +{ + u_short a, b; + + pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &a); + pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_ID, &b); + if ((a == 0x13a2) && (b == 0x8007)) { + /* Ositech Jack of Spades */ + DEBUG(0, " 83c175 NVCTL_m = 0x%4.4x.\n", inl(ioaddr+0x80)); + outl(0x4C00, ioaddr + 0x80); + outl(0x4C80, ioaddr + 0x80); + } + DEBUG(0, " modem registers are %2.2x %2.2x %2.2x " + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x.\n", + inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2), + inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5), + inb(ioaddr + 6), inb(ioaddr + 7), inb(ioaddr + 8)); +} + +/*====================================================================== + + serial_attach() creates a serial device "instance" and registers + it with the kernel serial driver, and serial_detach() unregisters + an instance. + +======================================================================*/ + +static dev_node_t *serial_attach(dev_locator_t *loc) +{ + u_int io; + u_char bus, devfn, irq; + int line; + struct serial_struct serial; + + if (loc->bus != LOC_PCI) return NULL; + bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + printk(KERN_INFO "serial_attach(bus %d, fn %d)\n", bus, devfn); + pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); + pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); + if (io & PCI_BASE_ADDRESS_SPACE_IO) { + io &= PCI_BASE_ADDRESS_IO_MASK; + } else { + printk(KERN_NOTICE "serial_cb: PCI base address 0 is not IO\n"); + return NULL; + } + device_setup(bus, devfn, io); + memset(&serial, 0, sizeof(serial)); + serial.port = io; serial.irq = irq; + serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; + + /* Some devices seem to need extra time */ + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); + + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cb: register_serial() at 0x%04x, " + "irq %d failed\n", serial.port, serial.irq); + return NULL; + } else { + dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); + sprintf(node->dev_name, "ttyS%d", line); + node->major = TTY_MAJOR; node->minor = 0x40 + line; + node->next = NULL; + MOD_INC_USE_COUNT; + return node; + } +} + +static void serial_detach(dev_node_t *node) +{ + DEBUG(0, "serial_detach(tty%02d)\n", node->minor - 0x40); + unregister_serial(node->minor - 0x40); + kfree(node); + MOD_DEC_USE_COUNT; +} + +/*====================================================================*/ + +struct driver_operations serial_ops = { + "serial_cb", serial_attach, NULL, NULL, serial_detach +}; + +static int __init init_serial_cb(void) +{ + DEBUG(0, "%s\n", version); + register_driver(&serial_ops); + return 0; +} + +static void __exit exit_serial_cb(void) +{ + DEBUG(0, "serial_cb: unloading\n"); + unregister_driver(&serial_ops); +} + +module_init(init_serial_cb); +module_exit(exit_serial_cb); diff --git a/drivers/char/pcmcia/serial_cs.c b/drivers/char/pcmcia/serial_cs.c new file mode 100644 index 000000000..38345b1b5 --- /dev/null +++ b/drivers/char/pcmcia/serial_cs.c @@ -0,0 +1,667 @@ +/*====================================================================== + + A driver for PCMCIA serial devices + + serial_cs.c 1.114 1999/11/11 00:54:46 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/ptrace.h> +#include <linux/malloc.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/major.h> +#include <asm/io.h> +#include <asm/system.h> + +#include <pcmcia/version.h> +#include <pcmcia/cs_types.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ciscode.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"serial_cs.c 1.114 1999/11/11 00:54:46 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +/* Enable the speaker? */ +static int do_sound = 1; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(do_sound, "i"); + +/*====================================================================*/ + +/* Table of multi-port card ID's */ + +typedef struct { + u_short manfid; + u_short prodid; + int multi; /* 1 = multifunction, > 1 = # ports */ +} multi_id_t; + +static multi_id_t multi_id[] = { + { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, + { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, + { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, + { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } +}; +#define MULTI_COUNT (sizeof(multi_id)/sizeof(multi_id_t)) + +typedef struct serial_info_t { + int ndev; + int multi; + int slave; + int manfid; + dev_node_t node[4]; + int line[4]; +} serial_info_t; + +static void serial_config(dev_link_t *link); +static void serial_release(u_long arg); +static int serial_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "serial_cs"; + +static dev_link_t *serial_attach(void); +static void serial_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + serial_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *serial_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "serial_attach()\n"); + + /* Create new serial device */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + memset(link, 0, sizeof(struct dev_link_t)); + link->release.function = &serial_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + if (do_sound) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + link->conf.IntType = INT_MEMORY_AND_IO; + link->priv = kmalloc(sizeof(struct serial_info_t), GFP_KERNEL); + memset(link->priv, 0, sizeof(struct serial_info_t)); + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &serial_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + serial_detach(link); + return NULL; + } + + return link; +} /* serial_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void serial_detach(dev_link_t *link) +{ + dev_link_t **linkp; + long flags; + int ret; + + DEBUG(0, "serial_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + save_flags(flags); + cli(); + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + + if (link->state & DEV_CONFIG) + serial_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree_s(link->priv, sizeof(serial_info_t)); + kfree_s(link, sizeof(struct dev_link_t)); + +} /* serial_detach */ + +/*====================================================================*/ + +static int setup_serial(serial_info_t *info, ioaddr_t port, int irq) +{ + struct serial_struct serial; + int line; + + memset(&serial, 0, sizeof(serial)); + serial.port = port; + serial.irq = irq; + serial.flags = ASYNC_SKIP_TEST; + serial.flags |= (info->multi || info->slave) ? ASYNC_SHARE_IRQ : 0; + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04x, " + "irq %d failed\n", serial.port, serial.irq); + return -1; + } + + info->line[info->ndev] = line; + sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); + info->node[info->ndev].major = TTY_MAJOR; + info->node[info->ndev].minor = 0x40+line; + if (info->ndev > 0) + info->node[info->ndev-1].next = &info->node[info->ndev]; + info->ndev++; + + return 0; +} + +/*====================================================================*/ + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i; + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) return CS_NO_MORE_ITEMS; + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) return i; + return CardServices(ParseTuple, handle, tuple, parse); +} + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +/*====================================================================*/ + +static int simple_config(dev_link_t *link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j; + + /* If the card is already configured, look up the port and irq */ + i = CardServices(GetConfigurationInfo, handle, &config); + if ((i == CS_SUCCESS) && + (config.Attributes & CONF_VALID_CLIENT)) { + ioaddr_t port = 0; + if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { + port = config.BasePort2; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (config.NumPorts1 == 0x40)) { + port = config.BasePort1 + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(info, port, config.AssignedIRQ); + } + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) goto next_entry; + if (cf->vpp1.present & (1<<CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM]/10000; + if ((cf->io.nwin > 0) && ((cf->io.win[0].base & 0xf) == 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) goto found_port; + } + next_entry: + i = next_tuple(handle, &tuple, &parse); + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && + ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + i = CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + +found_port: + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + if (info->multi && (info->manfid == MANFID_3COM)) + link->conf.ConfigIndex &= ~(0x08); + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); +} + +static int multi_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, base2 = 0; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* First, look for a generic full-sized window */ + link->io.NumPorts1 = info->multi * 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + /* The quad port cards have bad CIS's, so just look for a + window larger than 8 ports and assume it will be right */ + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && + (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort1 + 8; + if (i == CS_SUCCESS) break; + } + i = next_tuple(handle, &tuple, &parse); + } + + /* If that didn't work, look for two windows */ + if (i != CS_SUCCESS) { + link->io.NumPorts1 = link->io.NumPorts2 = 8; + info->multi = 2; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.BasePort2 = cf->io.win[1].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort2; + if (i == CS_SUCCESS) break; + } + i = next_tuple(handle, &tuple, &parse); + } + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + /* Socket Dual IO: this enables irq's for second port */ + if (info->multi && (info->manfid == MANFID_SOCKET)) { + link->conf.Present |= PRESENT_EXT_STATUS; + link->conf.ExtStatus = ESR_REQ_ATTN_ENA; + } + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + for (i = 0; i < info->multi-1; i++) + setup_serial(info, base2+(8*i), link->irq.AssignedIRQ); + + return 0; +} + +/*====================================================================== + + serial_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + serial device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +void serial_config(dev_link_t *link) +{ + client_handle_t handle; + serial_info_t *info; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, last_ret, last_fn; + + sti(); + handle = link->handle; + info = link->priv; + + DEBUG(0, "serial_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Is this a compliant multifunction card? */ + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); + + /* Is this a multiport card? */ + tuple.DesiredTuple = CISTPL_MANFID; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + info->manfid = le16_to_cpu(buf[0]); + for (i = 0; i < MULTI_COUNT; i++) + if ((info->manfid == multi_id[i].manfid) && + (le16_to_cpu(buf[1]) == multi_id[i].prodid)) + break; + if (i < MULTI_COUNT) + info->multi = multi_id[i].multi; + } + + /* Another check for dual-serial cards: look for either serial or + multifunction cards that ask for appropriate IO port ranges */ + tuple.DesiredTuple = CISTPL_FUNCID; + if ((info->multi == 0) && + ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || + (parse.funcid.func == CISTPL_FUNCID_MULTI) || + (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((first_tuple(handle, &tuple, &parse) == CS_SUCCESS) && + (((cf->io.nwin == 1) && (cf->io.win[0].len == 16)) || + ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)))) + info->multi = 2; + } + + if (info->multi > 1) + multi_config(link); + else + simple_config(link); + + if (info->ndev == 0) + goto failed; + + if (info->manfid == MANFID_IBM) { + conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + reg.Action = CS_WRITE; + reg.Value = reg.Value | 1; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + } + + link->dev = &info->node[0]; + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + serial_release((u_long)link); + +} /* serial_config */ + +/*====================================================================== + + After a card is removed, serial_release() will unregister the net + device, and release the PCMCIA configuration. + +======================================================================*/ + +void serial_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + serial_info_t *info = link->priv; + int i; + + sti(); + + DEBUG(0, "serial_release(0x%p)\n", link); + + for (i = 0; i < info->ndev; i++) { + unregister_serial(info->line[i]); + } + link->dev = NULL; + + if (!info->slave) { + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + } + + link->state &= ~DEV_CONFIG; + +} /* serial_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the serial drivers from + talking to the ports. + +======================================================================*/ + +static int serial_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + serial_info_t *info = link->priv; + + DEBUG(1, "serial_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + link->release.expires = jiffies + HZ/20; + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + serial_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if ((link->state & DEV_CONFIG) && !info->slave) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link) && !info->slave) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} /* serial_event */ + +/*====================================================================*/ + +static int __init init_serial_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "serial_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &serial_attach, &serial_detach); + return 0; +} + +static void __exit exit_serial_cs(void) +{ + DEBUG(0, "serial_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + serial_detach(dev_list); +} + +module_init(init_serial_cs); +module_exit(exit_serial_cs); diff --git a/drivers/char/pms.c b/drivers/char/pms.c index c96570b73..1e50880a0 100644 --- a/drivers/char/pms.c +++ b/drivers/char/pms.c @@ -624,7 +624,7 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count) { int y; int dw = 2*dev->width; - char *src = (char *)bus_to_virt(mem_base); + u32 src = mem_base; char tmp[dw+32]; /* using a temp buffer is faster than direct */ int cnt = 0; @@ -639,8 +639,14 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count) for (y = 0; y < dev->height; y++ ) { - *src = 0; /* synchronisiert neue Zeile */ - memcpy(tmp, src, dw+32); /* discard 16 word */ + isa_writeb(0, src); /* synchronisiert neue Zeile */ + + /* + * This is in truth a fifo, be very careful as if you + * forgot this odd things will occur 8) + */ + + isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word */ cnt -= dev->height; while (cnt <= 0) { diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index d73f128d8..5afcec0c9 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -505,13 +505,14 @@ static int pp_open (struct inode * inode, struct file * file) if (minor >= PARPORT_MAX) return -ENXIO; - pp = kmalloc (GFP_KERNEL, sizeof (struct pp_struct)); + pp = kmalloc (sizeof (struct pp_struct), GFP_KERNEL); if (!pp) return -ENOMEM; pp->state.mode = IEEE1284_MODE_COMPAT; pp->state.phase = init_phase (pp->state.mode); pp->flags = 0; + pp->irqresponse = 0; atomic_set (&pp->irqc, 0); init_waitqueue_head (&pp->irq_wait); @@ -538,8 +539,9 @@ static int pp_release (struct inode * inode, struct file * file) } if (pp->pdev) { + const char *name = pp->pdev->name; parport_unregister_device (pp->pdev); - kfree (pp->pdev->name); + kfree (name); pp->pdev = NULL; printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n", minor); diff --git a/drivers/char/radio-cadet.c b/drivers/char/radio-cadet.c index 98b66f0c2..a979e7424 100644 --- a/drivers/char/radio-cadet.c +++ b/drivers/char/radio-cadet.c @@ -39,7 +39,6 @@ struct timer_list tunertimer,rdstimer,readtimer; static __u8 rdsin=0,rdsout=0,rdsstat=0; static unsigned char rdsbuf[RDS_BUFFER]; static int cadet_lock=0; -static int cadet_probe(void); /* * Signal Strength Threshold Values @@ -543,22 +542,6 @@ static struct video_device cadet_radio= NULL }; -int __init cadet_init(struct video_init *v) -{ -#ifndef MODULE - if(cadet_probe()<0) { - return EINVAL; - } -#endif - if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1) - return -EINVAL; - - request_region(io,2,"cadet"); - printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); - return 0; -} - - #ifndef MODULE static int cadet_probe(void) { @@ -578,9 +561,27 @@ static int cadet_probe(void) } #endif +int __init cadet_init(void) +{ +#ifndef MODULE + io = cadet_probe (); +#endif + + if(io < 0) { +#ifdef MODULE + printk(KERN_ERR "You must set an I/O address with io=0x???\n"); +#endif + return EINVAL; + } + if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1) + return -EINVAL; + + request_region(io,2,"cadet"); + printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); + return 0; +} -#ifdef MODULE MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); @@ -589,21 +590,12 @@ MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0 EXPORT_NO_SYMBOLS; -int init_module(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - return cadet_init(NULL); -} - -void cleanup_module(void) +static void __exit cadet_cleanup_module(void) { video_unregister_device(&cadet_radio); release_region(io,2); } -#endif +module_init(cadet_init); +module_exit(cadet_cleanup_module); diff --git a/drivers/char/radio-rtrack2.c b/drivers/char/radio-rtrack2.c index 8876d789d..c060ded4a 100644 --- a/drivers/char/radio-rtrack2.c +++ b/drivers/char/radio-rtrack2.c @@ -228,8 +228,13 @@ static struct video_device rtrack2_radio= NULL }; -int __init rtrack2_init(struct video_init *v) +static int __init rtrack2_init(void) { + if(io==-1) + { + printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); + return -EINVAL; + } if (check_region(io, 4)) { printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); @@ -252,8 +257,6 @@ int __init rtrack2_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("Ben Pfaff"); MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); MODULE_PARM(io, "i"); @@ -261,23 +264,14 @@ MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); EXPORT_NO_SYMBOLS; -int init_module(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); - return -EINVAL; - } - return rtrack2_init(NULL); -} - -void cleanup_module(void) +static void __exit rtrack2_cleanup_module(void) { video_unregister_device(&rtrack2_radio); release_region(io,4); } -#endif +module_init(rtrack2_init); +module_exit(rtrack2_cleanup_module); /* Local variables: diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c index ef73f2d77..55328a96f 100644 --- a/drivers/char/radio-sf16fmi.c +++ b/drivers/char/radio-sf16fmi.c @@ -289,8 +289,13 @@ static struct video_device fmi_radio= NULL }; -int __init fmi_init(struct video_init *v) +static int __init fmi_init(void) { + if(io==-1) + { + printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + return -EINVAL; + } if (check_region(io, 2)) { printk(KERN_ERR "fmi: port 0x%x already in use\n", io); @@ -316,8 +321,6 @@ int __init fmi_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); MODULE_DESCRIPTION("A driver for the SF16MI radio."); MODULE_PARM(io, "i"); @@ -325,20 +328,12 @@ MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); EXPORT_NO_SYMBOLS; -int init_module(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - return fmi_init(NULL); -} - -void cleanup_module(void) +static void __exit fmi_cleanup_module(void) { video_unregister_device(&fmi_radio); release_region(io,2); } -#endif +module_init(fmi_init); +module_exit(fmi_cleanup_module); + diff --git a/drivers/char/radio-terratec.c b/drivers/char/radio-terratec.c index 9fb119c30..1dda1618e 100644 --- a/drivers/char/radio-terratec.c +++ b/drivers/char/radio-terratec.c @@ -307,8 +307,13 @@ static struct video_device terratec_radio= NULL }; -int __init terratec_init(struct video_init *v) +static int __init terratec_init(void) { + if(io==-1) + { + printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + return -EINVAL; + } if (check_region(io, 2)) { printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); @@ -334,8 +339,6 @@ int __init terratec_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("R.OFFERMANNS & others"); MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card."); MODULE_PARM(io, "i"); @@ -343,21 +346,13 @@ MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x5 EXPORT_NO_SYMBOLS; -int init_module(void) -{ - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - return terratec_init(NULL); -} - -void cleanup_module(void) +static void __exit terratec_cleanup_module(void) { video_unregister_device(&terratec_radio); release_region(io,2); printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); } -#endif +module_init(terratec_init); +module_exit(terratec_cleanup_module); + diff --git a/drivers/char/radio-trust.c b/drivers/char/radio-trust.c index 15dee607a..4e86bda90 100644 --- a/drivers/char/radio-trust.c +++ b/drivers/char/radio-trust.c @@ -333,8 +333,6 @@ static int __init trust_init(void) return 0; } -#ifdef MODULE - MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); MODULE_PARM(io, "i"); @@ -342,8 +340,6 @@ MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); EXPORT_NO_SYMBOLS; -#endif /* MODULE */ - static void __exit cleanup_trust_module(void) { video_unregister_device(&trust_radio); diff --git a/drivers/char/radio-typhoon.c b/drivers/char/radio-typhoon.c index 698f113e8..7f546a12d 100644 --- a/drivers/char/radio-typhoon.c +++ b/drivers/char/radio-typhoon.c @@ -72,15 +72,8 @@ static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg); static int typhoon_open(struct video_device *dev, int flags); static void typhoon_close(struct video_device *dev); #ifdef CONFIG_RADIO_TYPHOON_PROC_FS -static int typhoon_read_proc(char *buf, char **start, off_t offset, int len, - int unused); -#endif -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -int typhoon_init(struct video_init *v); -#else -int typhoon_init(struct video_init *v) __init; +static int typhoon_get_info(char *buf, char **start, off_t offset, int len, + int unused); #endif static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) @@ -306,8 +299,8 @@ static struct video_device typhoon_radio = #ifdef CONFIG_RADIO_TYPHOON_PROC_FS -static int typhoon_read_proc(char *buf, char **start, off_t offset, int len, - int unused) +static int typhoon_get_info(char *buf, char **start, off_t offset, int len, + int unused) { #ifdef MODULE #define MODULEPROCSTRING "Driver loaded as a module" @@ -337,53 +330,8 @@ static int typhoon_read_proc(char *buf, char **start, off_t offset, int len, return len; } -static struct proc_dir_entry typhoon_proc_entry = { - 0, /* low_ino: inode is dynamic */ - 13, "radio-typhoon", /* length of name and name */ - S_IFREG | S_IRUGO, /* mode */ - 1, 0, 0, /* nlinks, owner, group */ - 0, /* size -- not used */ - NULL, /* operations -- use default */ - &typhoon_read_proc, /* function used to read data */ - /* nothing more */ -}; - #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ -int typhoon_init(struct video_init *v) -{ - printk(KERN_INFO BANNER); - if (check_region(typhoon_unit.iobase, 8)) { - printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", - typhoon_unit.iobase); - return -EBUSY; - } - - typhoon_radio.priv = &typhoon_unit; - if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1) - return -EINVAL; - - request_region(typhoon_unit.iobase, 8, "typhoon"); - printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); - printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", - typhoon_unit.mutefreq); - typhoon_unit.mutefreq <<= 4; - - /* mute card - prevents noisy bootups */ - typhoon_mute(&typhoon_unit); - -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - - if (proc_register(&proc_root, &typhoon_proc_entry)) - printk(KERN_ERR "radio-typhoon: registering /proc/radio-typhoon failed\n"); - -#endif - - return 0; -} - -#ifdef MODULE - MODULE_AUTHOR("Dr. Henrik Seidel"); MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio)."); MODULE_PARM(io, "i"); @@ -394,10 +342,14 @@ MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); EXPORT_NO_SYMBOLS; static int io = -1; + +#ifdef MODULE static unsigned long mutefreq = 0; +#endif -int init_module(void) +static int __init typhoon_init(void) { +#ifdef MODULE if (io == -1) { printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n"); return -EINVAL; @@ -410,24 +362,49 @@ int init_module(void) return -EINVAL; } typhoon_unit.mutefreq = mutefreq; +#endif /* MODULE */ - return typhoon_init(NULL); -} + printk(KERN_INFO BANNER); + io = typhoon_unit.iobase; + if (check_region(io, 8)) { + printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", + typhoon_unit.iobase); + return -EBUSY; + } -void cleanup_module(void) -{ + typhoon_radio.priv = &typhoon_unit; + if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1) + return -EINVAL; + + request_region(typhoon_unit.iobase, 8, "typhoon"); + printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); + printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", + typhoon_unit.mutefreq); + typhoon_unit.mutefreq <<= 4; + + /* mute card - prevents noisy bootups */ + typhoon_mute(&typhoon_unit); #ifdef CONFIG_RADIO_TYPHOON_PROC_FS + if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL, + typhoon_get_info)) + printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); +#endif + + return 0; +} - if (proc_unregister(&proc_root, typhoon_proc_entry.low_ino)) - printk(KERN_ERR "radio-typhoon: unregistering /proc/radio-typhoon failed\n"); +static void __exit typhoon_cleanup_module(void) +{ +#ifdef CONFIG_RADIO_TYPHOON_PROC_FS + remove_proc_entry("driver/radio-typhoon", NULL); #endif video_unregister_device(&typhoon_radio); release_region(io, 8); } -#endif - +module_init(typhoon_init); +module_exit(typhoon_cleanup_module); diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c index a11de7ba8..dd688935a 100644 --- a/drivers/char/radio-zoltrix.c +++ b/drivers/char/radio-zoltrix.c @@ -354,8 +354,12 @@ static struct video_device zoltrix_radio = NULL }; -int __init zoltrix_init(struct video_init *v) +static int __init zoltrix_init(void) { + if (io == -1) { + printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + return -EINVAL; + } if (check_region(io, 2)) { printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); return -EBUSY; @@ -390,8 +394,6 @@ int __init zoltrix_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("C.van Schaik"); MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); MODULE_PARM(io, "i"); @@ -399,19 +401,12 @@ MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); EXPORT_NO_SYMBOLS; -int init_module(void) -{ - if (io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); - return -EINVAL; - } - return zoltrix_init(NULL); -} - -void cleanup_module(void) +static void __exit zoltrix_cleanup_module(void) { video_unregister_device(&zoltrix_radio); release_region(io, 2); } -#endif +module_init(zoltrix_init); +module_exit(zoltrix_cleanup_module); + diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index d53aa4e52..34e1dd51c 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -75,6 +75,8 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#define RS_EVENT_WRITE_WAKEUP 0 + DECLARE_TASK_QUEUE(tq_riscom); #define RISCOM_TYPE_NORMAL 1 diff --git a/drivers/char/saa5249.c b/drivers/char/saa5249.c index 5ab107a0f..aab98908a 100644 --- a/drivers/char/saa5249.c +++ b/drivers/char/saa5249.c @@ -41,21 +41,22 @@ */ #include <linux/module.h> - #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/ioport.h> -#include <linux/malloc.h> -#include <asm/io.h> -#include <asm/uaccess.h> +#include <linux/slab.h> +#include <linux/init.h> #include <stdarg.h> #include <linux/i2c.h> #include <linux/videotext.h> #include <linux/videodev.h> +#include <asm/io.h> +#include <asm/uaccess.h> + #define VTX_VER_MAJ 1 #define VTX_VER_MIN 7 @@ -661,54 +662,32 @@ static long saa5249_write(struct video_device *v, const char *buf, unsigned long return -EINVAL; } -static long saa5249_read(struct video_device *v, char *buf, unsigned long l, int nb) -{ - return -EINVAL; -} - -int init_saa_5249(struct video_init *v) +static int __init init_saa_5249 (void) { printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n", VTX_VER_MAJ, VTX_VER_MIN); - i2c_register_driver(&i2c_driver_videotext); + return i2c_register_driver(&i2c_driver_videotext); +} - return 0; +static void __exit cleanup_saa_5249 (void) +{ + i2c_unregister_driver(&i2c_driver_videotext); } -static struct video_device saa_template= +module_init(init_saa_5249); +module_exit(cleanup_saa_5249); + +static struct video_device saa_template = { IF_NAME, VID_TYPE_TELETEXT, /*| VID_TYPE_TUNER ?? */ VID_HARDWARE_SAA5249, saa5249_open, saa5249_release, - saa5249_read, + NULL, /* read */ saa5249_write, - NULL, /* poll */ + NULL, /* poll */ saa5249_ioctl, - NULL, - NULL, - NULL, - 0, - 0 + /* the rest are null */ }; -#ifdef MODULE - -/* - * Routines for loadable modules - */ - -int init_module(void) -{ - init_saa_5249(NULL); - return 0; -} - - -void cleanup_module(void) -{ - i2c_unregister_driver(&i2c_driver_videotext); -} - -#endif diff --git a/drivers/char/saa7121.h b/drivers/char/saa7121.h new file mode 100644 index 000000000..74e37d405 --- /dev/null +++ b/drivers/char/saa7121.h @@ -0,0 +1,132 @@ +/* saa7121.h - saa7121 initializations + Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +#ifndef __SAA7121_H__ +#define __SAA7121_H__ + +#define NTSC_BURST_START 0x19 /* 28 */ +#define NTSC_BURST_END 0x1d /* 29 */ +#define NTSC_CHROMA_PHASE 0x67 /* 5a */ +#define NTSC_GAINU 0x76 /* 5b */ +#define NTSC_GAINV 0xa5 /* 5c */ +#define NTSC_BLACK_LEVEL 0x2a /* 5d */ +#define NTSC_BLANKING_LEVEL 0x2e /* 5e */ +#define NTSC_VBI_BLANKING 0x2e /* 5f */ +#define NTSC_DAC_CONTROL 0x11 /* 61 */ +#define NTSC_BURST_AMP 0x3f /* 62 */ +#define NTSC_SUBC3 0x1f /* 63 */ +#define NTSC_SUBC2 0x7c /* 64 */ +#define NTSC_SUBC1 0xf0 /* 65 */ +#define NTSC_SUBC0 0x21 /* 66 */ +#define NTSC_HTRIG 0x72 /* 6c */ +#define NTSC_VTRIG 0x00 /* 6c */ +#define NTSC_MULTI 0x30 /* 6e */ +#define NTSC_CCTTX 0x11 /* 6f */ +#define NTSC_FIRST_ACTIVE 0x12 /* 7a */ +#define NTSC_LAST_ACTIVE 0x02 /* 7b */ +#define NTSC_MSB_VERTICAL 0x40 /* 7c */ + +#define PAL_BURST_START 0x21 /* 28 */ +#define PAL_BURST_END 0x1d /* 29 */ +#define PAL_CHROMA_PHASE 0x3f /* 5a */ +#define PAL_GAINU 0x7d /* 5b */ +#define PAL_GAINV 0xaf /* 5c */ +#define PAL_BLACK_LEVEL 0x23 /* 5d */ +#define PAL_BLANKING_LEVEL 0x35 /* 5e */ +#define PAL_VBI_BLANKING 0x35 /* 5f */ +#define PAL_DAC_CONTROL 0x02 /* 61 */ +#define PAL_BURST_AMP 0x2f /* 62 */ +#define PAL_SUBC3 0xcb /* 63 */ +#define PAL_SUBC2 0x8a /* 64 */ +#define PAL_SUBC1 0x09 /* 65 */ +#define PAL_SUBC0 0x2a /* 66 */ +#define PAL_HTRIG 0x86 /* 6c */ +#define PAL_VTRIG 0x04 /* 6d */ +#define PAL_MULTI 0x20 /* 6e */ +#define PAL_CCTTX 0x15 /* 6f */ +#define PAL_FIRST_ACTIVE 0x16 /* 7a */ +#define PAL_LAST_ACTIVE 0x36 /* 7b */ +#define PAL_MSB_VERTICAL 0x40 /* 7c */ + +/* Initialization Sequence */ + +static __u8 init7121ntsc[] = { + 0x26, 0x0, 0x27, 0x0, + 0x28, NTSC_BURST_START, 0x29, NTSC_BURST_END, + 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, + 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, + 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, + 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, + 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, + 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, + 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, + 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, + 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, + 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, + 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, + 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, + 0x5a, NTSC_CHROMA_PHASE, 0x5b, NTSC_GAINU, + 0x5c, NTSC_GAINV, 0x5d, NTSC_BLACK_LEVEL, + 0x5e, NTSC_BLANKING_LEVEL, 0x5f, NTSC_VBI_BLANKING, + 0x60, 0x0, 0x61, NTSC_DAC_CONTROL, + 0x62, NTSC_BURST_AMP, 0x63, NTSC_SUBC3, + 0x64, NTSC_SUBC2, 0x65, NTSC_SUBC1, + 0x66, NTSC_SUBC0, 0x67, 0x80, 0x68, 0x80, + 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, + 0x6c, NTSC_HTRIG, 0x6d, NTSC_VTRIG, + 0x6e, NTSC_MULTI, 0x6f, NTSC_CCTTX, + 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, + 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, + 0x78, 0x0, 0x79, 0x0, 0x7a, NTSC_FIRST_ACTIVE, + 0x7b, NTSC_LAST_ACTIVE, 0x7c, NTSC_MSB_VERTICAL, + 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 +}; +#define INIT7121LEN (sizeof(init7121ntsc)/2) + +static __u8 init7121pal[] = { + 0x26, 0x0, 0x27, 0x0, + 0x28, PAL_BURST_START, 0x29, PAL_BURST_END, + 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, + 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, + 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, + 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, + 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, + 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, + 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, + 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, + 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, + 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, + 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, + 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, + 0x5a, PAL_CHROMA_PHASE, 0x5b, PAL_GAINU, + 0x5c, PAL_GAINV, 0x5d, PAL_BLACK_LEVEL, + 0x5e, PAL_BLANKING_LEVEL, 0x5f, PAL_VBI_BLANKING, + 0x60, 0x0, 0x61, PAL_DAC_CONTROL, + 0x62, PAL_BURST_AMP, 0x63, PAL_SUBC3, + 0x64, PAL_SUBC2, 0x65, PAL_SUBC1, + 0x66, PAL_SUBC0, 0x67, 0x80, 0x68, 0x80, + 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, + 0x6c, PAL_HTRIG, 0x6d, PAL_VTRIG, + 0x6e, PAL_MULTI, 0x6f, PAL_CCTTX, + 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, + 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, + 0x78, 0x0, 0x79, 0x0, 0x7a, PAL_FIRST_ACTIVE, + 0x7b, PAL_LAST_ACTIVE, 0x7c, PAL_MSB_VERTICAL, + 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 +}; +#endif diff --git a/drivers/char/saa7146.h b/drivers/char/saa7146.h new file mode 100644 index 000000000..481308e6c --- /dev/null +++ b/drivers/char/saa7146.h @@ -0,0 +1,117 @@ +/* + saa7146.h - definitions philips saa7146 based cards + Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SAA7146__ +#define __SAA7146__ + +#define SAA7146_VERSION_CODE 0x000101 + +#include <linux/types.h> +#include <linux/wait.h> + +#include <linux/i2c.h> +#include <linux/videodev.h> + +#ifndef O_NONCAP +#define O_NONCAP O_TRUNC +#endif + +#define MAX_GBUFFERS 2 +#define FBUF_SIZE 0x190000 + +#ifdef __KERNEL__ + +struct saa7146_window +{ + int x, y; + ushort width, height; + ushort bpp, bpl; + ushort swidth, sheight; + short cropx, cropy; + ushort cropwidth, cropheight; + unsigned long vidadr; + int color_fmt; + ushort depth; +}; + +/* Per-open data for handling multiple opens on one device */ +struct device_open +{ + int isopen; + int noncapturing; + struct saa7146 *dev; +}; +#define MAX_OPENS 3 + +struct saa7146 +{ + struct video_device video_dev; + struct video_picture picture; + struct video_audio audio_dev; + struct video_info vidinfo; + int user; + int cap; + int capuser; + int irqstate; /* irq routine is state driven */ + int writemode; + int playmode; + unsigned int nr; + unsigned long irq; /* IRQ used by SAA7146 card */ + unsigned short id; + struct i2c_bus i2c; + struct pci_dev *dev; + unsigned char revision; + unsigned char boardcfg[64]; /* 64 bytes of config from eeprom */ + unsigned long saa7146_adr; /* bus address of IO mem from PCI BIOS */ + struct saa7146_window win; + unsigned char *saa7146_mem; /* pointer to mapped IO memory */ + struct device_open open_data[MAX_OPENS]; +#define MAX_MARKS 16 + /* for a/v sync */ + int endmark[MAX_MARKS], endmarkhead, endmarktail; + u32 *dmaRPS1, *pageRPS1, *dmaRPS2, *pageRPS2, *dmavid1, *dmavid2, + *dmavid3, *dmaa1in, *dmaa1out, *dmaa2in, *dmaa2out, + *pagedebi, *pagevid1, *pagevid2, *pagevid3, *pagea1in, + *pagea1out, *pagea2in, *pagea2out; + wait_queue_head_t i2cq, debiq, audq, vidq; + u8 *vidbuf, *audbuf, *osdbuf, *dmadebi; + int audhead, vidhead, osdhead, audtail, vidtail, osdtail; + spinlock_t lock; /* the device lock */ +}; +#endif + +#ifdef _ALPHA_SAA7146 +#define saawrite(dat,adr) writel((dat),(char *) (saa->saa7146_adr+(adr))) +#define saaread(adr) readl(saa->saa7146_adr+(adr)) +#else +#define saawrite(dat,adr) writel((dat), (char *) (saa->saa7146_mem+(adr))) +#define saaread(adr) readl(saa->saa7146_mem+(adr)) +#endif + +#define saaand(dat,adr) saawrite((dat) & saaread(adr), adr) +#define saaor(dat,adr) saawrite((dat) | saaread(adr), adr) +#define saaaor(dat,mask,adr) saawrite((dat) | ((mask) & saaread(adr)), adr) + +/* bitmask of attached hardware found */ +#define SAA7146_UNKNOWN 0x00000000 +#define SAA7146_SAA7111 0x00000001 +#define SAA7146_SAA7121 0x00000002 +#define SAA7146_IBMMPEG 0x00000004 + +#endif diff --git a/drivers/char/saa7146reg.h b/drivers/char/saa7146reg.h new file mode 100644 index 000000000..6cc910f50 --- /dev/null +++ b/drivers/char/saa7146reg.h @@ -0,0 +1,283 @@ +/* + saa7146.h - definitions philips saa7146 based cards + Copyright (C) 1999 Nathan Laredo (laredo@gnu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SAA7146_REG__ +#define __SAA7146_REG__ +#define SAA7146_BASE_ODD1 0x00 +#define SAA7146_BASE_EVEN1 0x04 +#define SAA7146_PROT_ADDR1 0x08 +#define SAA7146_PITCH1 0x0c +#define SAA7146_PAGE1 0x10 +#define SAA7146_NUM_LINE_BYTE1 0x14 +#define SAA7146_BASE_ODD2 0x18 +#define SAA7146_BASE_EVEN2 0x1c +#define SAA7146_PROT_ADDR2 0x20 +#define SAA7146_PITCH2 0x24 +#define SAA7146_PAGE2 0x28 +#define SAA7146_NUM_LINE_BYTE2 0x2c +#define SAA7146_BASE_ODD3 0x30 +#define SAA7146_BASE_EVEN3 0x34 +#define SAA7146_PROT_ADDR3 0x38 +#define SAA7146_PITCH3 0x3c +#define SAA7146_PAGE3 0x40 +#define SAA7146_NUM_LINE_BYTE3 0x44 +#define SAA7146_PCI_BT_V1 0x48 +#define SAA7146_PCI_BT_V2 0x49 +#define SAA7146_PCI_BT_V3 0x4a +#define SAA7146_PCI_BT_DEBI 0x4b +#define SAA7146_PCI_BT_A 0x4c +#define SAA7146_DD1_INIT 0x50 +#define SAA7146_DD1_STREAM_B 0x54 +#define SAA7146_DD1_STREAM_A 0x56 +#define SAA7146_BRS_CTRL 0x58 +#define SAA7146_HPS_CTRL 0x5c +#define SAA7146_HPS_V_SCALE 0x60 +#define SAA7146_HPS_V_GAIN 0x64 +#define SAA7146_HPS_H_PRESCALE 0x68 +#define SAA7146_HPS_H_SCALE 0x6c +#define SAA7146_BCS_CTRL 0x70 +#define SAA7146_CHROMA_KEY_RANGE 0x74 +#define SAA7146_CLIP_FORMAT_CTRL 0x78 +#define SAA7146_DEBI_CONFIG 0x7c +#define SAA7146_DEBI_COMMAND 0x80 +#define SAA7146_DEBI_PAGE 0x84 +#define SAA7146_DEBI_AD 0x88 +#define SAA7146_I2C_TRANSFER 0x8c +#define SAA7146_I2C_STATUS 0x90 +#define SAA7146_BASE_A1_IN 0x94 +#define SAA7146_PROT_A1_IN 0x98 +#define SAA7146_PAGE_A1_IN 0x9C +#define SAA7146_BASE_A1_OUT 0xa0 +#define SAA7146_PROT_A1_OUT 0xa4 +#define SAA7146_PAGE_A1_OUT 0xa8 +#define SAA7146_BASE_A2_IN 0xac +#define SAA7146_PROT_A2_IN 0xb0 +#define SAA7146_PAGE_A2_IN 0xb4 +#define SAA7146_BASE_A2_OUT 0xb8 +#define SAA7146_PROT_A2_OUT 0xbc +#define SAA7146_PAGE_A2_OUT 0xc0 +#define SAA7146_RPS_PAGE0 0xc4 +#define SAA7146_RPS_PAGE1 0xc8 +#define SAA7146_RPS_THRESH0 0xcc +#define SAA7146_RPS_THRESH1 0xd0 +#define SAA7146_RPS_TOV0 0xd4 +#define SAA7146_RPS_TOV1 0xd8 +#define SAA7146_IER 0xdc +#define SAA7146_GPIO_CTRL 0xe0 +#define SAA7146_EC1SSR 0xe4 +#define SAA7146_EC2SSR 0xe8 +#define SAA7146_ECT1R 0xec +#define SAA7146_ECT2R 0xf0 +#define SAA7146_ACON1 0xf4 +#define SAA7146_ACON2 0xf8 +#define SAA7146_MC1 0xfc +#define SAA7146_MC2 0x100 +#define SAA7146_RPS_ADDR0 0x104 +#define SAA7146_RPS_ADDR1 0x108 +#define SAA7146_ISR 0x10c +#define SAA7146_PSR 0x110 +#define SAA7146_SSR 0x114 +#define SAA7146_EC1R 0x118 +#define SAA7146_EC2R 0x11c +#define SAA7146_VDP1 0x120 +#define SAA7146_VDP2 0x124 +#define SAA7146_VDP3 0x128 +#define SAA7146_ADP1 0x12c +#define SAA7146_ADP2 0x130 +#define SAA7146_ADP3 0x134 +#define SAA7146_ADP4 0x138 +#define SAA7146_DDP 0x13c +#define SAA7146_LEVEL_REP 0x140 +#define SAA7146_FB_BUFFER1 0x144 +#define SAA7146_FB_BUFFER2 0x148 +#define SAA7146_A_TIME_SLOT1 0x180 +#define SAA7146_A_TIME_SLOT2 0x1C0 + +/* bitfield defines */ +#define MASK_31 0x80000000 +#define MASK_30 0x40000000 +#define MASK_29 0x20000000 +#define MASK_28 0x10000000 +#define MASK_27 0x08000000 +#define MASK_26 0x04000000 +#define MASK_25 0x02000000 +#define MASK_24 0x01000000 +#define MASK_23 0x00800000 +#define MASK_22 0x00400000 +#define MASK_21 0x00200000 +#define MASK_20 0x00100000 +#define MASK_19 0x00080000 +#define MASK_18 0x00040000 +#define MASK_17 0x00020000 +#define MASK_16 0x00010000 +#define MASK_15 0x00008000 +#define MASK_14 0x00004000 +#define MASK_13 0x00002000 +#define MASK_12 0x00001000 +#define MASK_11 0x00000800 +#define MASK_10 0x00000400 +#define MASK_09 0x00000200 +#define MASK_08 0x00000100 +#define MASK_07 0x00000080 +#define MASK_06 0x00000040 +#define MASK_05 0x00000020 +#define MASK_04 0x00000010 +#define MASK_03 0x00000008 +#define MASK_02 0x00000004 +#define MASK_01 0x00000002 +#define MASK_00 0x00000001 +#define MASK_B0 0x000000ff +#define MASK_B1 0x0000ff00 +#define MASK_B2 0x00ff0000 +#define MASK_B3 0xff000000 +#define MASK_W0 0x0000ffff +#define MASK_W1 0xffff0000 +#define MASK_PA 0xfffffffc +#define MASK_PR 0xfffffffe +#define MASK_ER 0xffffffff +#define MASK_NONE 0x00000000 + +#define SAA7146_PAGE_MAP_EN MASK_11 +/* main control register 1 */ +#define SAA7146_MC1_MRST_N MASK_15 +#define SAA7146_MC1_ERPS1 MASK_13 +#define SAA7146_MC1_ERPS0 MASK_12 +#define SAA7146_MC1_EDP MASK_11 +#define SAA7146_MC1_EVP MASK_10 +#define SAA7146_MC1_EAP MASK_09 +#define SAA7146_MC1_EI2C MASK_08 +#define SAA7146_MC1_TR_E_DEBI MASK_07 +#define SAA7146_MC1_TR_E_1 MASK_06 +#define SAA7146_MC1_TR_E_2 MASK_05 +#define SAA7146_MC1_TR_E_3 MASK_04 +#define SAA7146_MC1_TR_E_A2_OUT MASK_03 +#define SAA7146_MC1_TR_E_A2_IN MASK_02 +#define SAA7146_MC1_TR_E_A1_OUT MASK_01 +#define SAA7146_MC1_TR_E_A1_IN MASK_00 +/* main control register 2 */ +#define SAA7146_MC2_RPS_SIG4 MASK_15 +#define SAA7146_MC2_RPS_SIG3 MASK_14 +#define SAA7146_MC2_RPS_SIG2 MASK_13 +#define SAA7146_MC2_RPS_SIG1 MASK_12 +#define SAA7146_MC2_RPS_SIG0 MASK_11 +#define SAA7146_MC2_UPLD_D1_B MASK_10 +#define SAA7146_MC2_UPLD_D1_A MASK_09 +#define SAA7146_MC2_UPLD_BRS MASK_08 +#define SAA7146_MC2_UPLD_HPS_H MASK_06 +#define SAA7146_MC2_UPLD_HPS_V MASK_05 +#define SAA7146_MC2_UPLD_DMA3 MASK_04 +#define SAA7146_MC2_UPLD_DMA2 MASK_03 +#define SAA7146_MC2_UPLD_DMA1 MASK_02 +#define SAA7146_MC2_UPLD_DEBI MASK_01 +#define SAA7146_MC2_UPLD_I2C MASK_00 +/* Primary Status Register and Interrupt Enable/Status Registers */ +#define SAA7146_PSR_PPEF MASK_31 +#define SAA7146_PSR_PABO MASK_30 +#define SAA7146_PSR_PPED MASK_29 +#define SAA7146_PSR_RPS_I1 MASK_28 +#define SAA7146_PSR_RPS_I0 MASK_27 +#define SAA7146_PSR_RPS_LATE1 MASK_26 +#define SAA7146_PSR_RPS_LATE0 MASK_25 +#define SAA7146_PSR_RPS_E1 MASK_24 +#define SAA7146_PSR_RPS_E0 MASK_23 +#define SAA7146_PSR_RPS_TO1 MASK_22 +#define SAA7146_PSR_RPS_TO0 MASK_21 +#define SAA7146_PSR_UPLD MASK_20 +#define SAA7146_PSR_DEBI_S MASK_19 +#define SAA7146_PSR_DEBI_E MASK_18 +#define SAA7146_PSR_I2C_S MASK_17 +#define SAA7146_PSR_I2C_E MASK_16 +#define SAA7146_PSR_A2_IN MASK_15 +#define SAA7146_PSR_A2_OUT MASK_14 +#define SAA7146_PSR_A1_IN MASK_13 +#define SAA7146_PSR_A1_OUT MASK_12 +#define SAA7146_PSR_AFOU MASK_11 +#define SAA7146_PSR_V_PE MASK_10 +#define SAA7146_PSR_VFOU MASK_09 +#define SAA7146_PSR_FIDA MASK_08 +#define SAA7146_PSR_FIDB MASK_07 +#define SAA7146_PSR_PIN3 MASK_06 +#define SAA7146_PSR_PIN2 MASK_05 +#define SAA7146_PSR_PIN1 MASK_04 +#define SAA7146_PSR_PIN0 MASK_03 +#define SAA7146_PSR_ECS MASK_02 +#define SAA7146_PSR_EC3S MASK_01 +#define SAA7146_PSR_EC0S MASK_00 +/* Secondary Status Register */ +#define SAA7146_SSR_PRQ MASK_31 +#define SAA7146_SSR_PMA MASK_30 +#define SAA7146_SSR_RPS_RE1 MASK_29 +#define SAA7146_SSR_RPS_PE1 MASK_28 +#define SAA7146_SSR_RPS_A1 MASK_27 +#define SAA7146_SSR_RPS_RE0 MASK_26 +#define SAA7146_SSR_RPS_PE0 MASK_25 +#define SAA7146_SSR_RPS_A0 MASK_24 +#define SAA7146_SSR_DEBI_TO MASK_23 +#define SAA7146_SSR_DEBI_EF MASK_22 +#define SAA7146_SSR_I2C_EA MASK_21 +#define SAA7146_SSR_I2C_EW MASK_20 +#define SAA7146_SSR_I2C_ER MASK_19 +#define SAA7146_SSR_I2C_EL MASK_18 +#define SAA7146_SSR_I2C_EF MASK_17 +#define SAA7146_SSR_V3P MASK_16 +#define SAA7146_SSR_V2P MASK_15 +#define SAA7146_SSR_V1P MASK_14 +#define SAA7146_SSR_VF3 MASK_13 +#define SAA7146_SSR_VF2 MASK_12 +#define SAA7146_SSR_VF1 MASK_11 +#define SAA7146_SSR_AF2_IN MASK_10 +#define SAA7146_SSR_AF2_OUT MASK_09 +#define SAA7146_SSR_AF1_IN MASK_08 +#define SAA7146_SSR_AF1_OUT MASK_07 +#define SAA7146_SSR_VGT MASK_05 +#define SAA7146_SSR_LNQG MASK_04 +#define SAA7146_SSR_EC5S MASK_03 +#define SAA7146_SSR_EC4S MASK_02 +#define SAA7146_SSR_EC2S MASK_01 +#define SAA7146_SSR_EC1S MASK_00 +/* I2C status register */ +#define SAA7146_I2C_ABORT MASK_07 +#define SAA7146_I2C_SPERR MASK_06 +#define SAA7146_I2C_APERR MASK_05 +#define SAA7146_I2C_DTERR MASK_04 +#define SAA7146_I2C_DRERR MASK_03 +#define SAA7146_I2C_AL MASK_02 +#define SAA7146_I2C_ERR MASK_01 +#define SAA7146_I2C_BUSY MASK_00 +/* output formats */ +#define SAA7146_YUV422 0 +#define SAA7146_RGB16 0 +#define SAA7146_YUV444 1 +#define SAA7146_RGB24 1 +#define SAA7146_ARGB32 2 +#define SAA7146_YUV411 3 +#define SAA7146_ARGB15 3 +#define SAA7146_YUV2 4 +#define SAA7146_RGAB15 4 +#define SAA7146_Y8 6 +#define SAA7146_YUV8 7 +#define SAA7146_RGB8 7 +#define SAA7146_YUV444p 8 +#define SAA7146_YUV422p 9 +#define SAA7146_YUV420p 10 +#define SAA7146_YUV1620 11 +#define SAA7146_Y1 13 +#define SAA7146_Y2 14 +#define SAA7146_YUV1 15 +#endif diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 45193f9ce..1ececdf7b 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -154,12 +154,12 @@ #endif #endif /* NEW_MODULES */ #include <linux/module.h> - +#include <linux/types.h> #ifdef LOCAL_HEADERS #include "serial_local.h" #else -#include <linux/serialP.h> #include <linux/serial.h> +#include <linux/serialP.h> #include <linux/serial_reg.h> #include <asm/serial.h> static char *serial_version = "4.30"; @@ -3507,11 +3507,13 @@ static void autoconfig(struct serial_state * state) } if (state->type == PORT_16550A) { /* Check for Oxford Semiconductor 16C950 */ + unsigned char scratch4; + scratch = serial_icr_read(info, UART_ID1); - scratch2 = serial_icr_read(info, UART_ID2); + scratch4 = serial_icr_read(info, UART_ID2); scratch3 = serial_icr_read(info, UART_ID3); - if (scratch == 0x16 && scratch2 == 0xC9 && + if (scratch == 0x16 && scratch4 == 0xC9 && (scratch3 == 0x50 || scratch3 == 0x52 || scratch3 == 0x54)) { state->type = PORT_16C950; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 22014dacf..d04f90964 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -171,7 +171,8 @@ DECLARE_TASK_QUEUE(tq_specialix); - +#undef RS_EVENT_WRITE_WAKEUP +#define RS_EVENT_WRITE_WAKEUP 0 #define SPECIALIX_TYPE_NORMAL 1 #define SPECIALIX_TYPE_CALLOUT 2 diff --git a/drivers/char/stradis.c b/drivers/char/stradis.c new file mode 100644 index 000000000..6edbf218c --- /dev/null +++ b/drivers/char/stradis.c @@ -0,0 +1,2286 @@ +/* + * stradis.c - stradis 4:2:2 mpeg decoder driver + * + * Stradis 4:2:2 MPEG-2 Decoder Driver + * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/version.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/malloc.h> +#include <linux/mm.h> +#include <linux/poll.h> +#include <linux/pci.h> +#include <linux/signal.h> +#include <asm/io.h> +#include <linux/ioport.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <linux/sched.h> +#include <asm/segment.h> +#include <asm/types.h> +#include <linux/types.h> +#include <linux/wrapper.h> +#include <linux/interrupt.h> +#include <asm/uaccess.h> +#include <linux/vmalloc.h> +#include <linux/videodev.h> +#include <linux/i2c.h> + +#include "saa7146.h" +#include "saa7146reg.h" +#include "ibmmpeg2.h" +#include "saa7121.h" +#include "cs8420.h" + +#define DEBUG(x) /* debug driver */ +#undef IDEBUG(x) /* debug irq handler */ +#undef MDEBUG(x) /* debug memory management */ + +#define SAA7146_MAX 6 + +static struct saa7146 saa7146s[SAA7146_MAX]; + +static int saa_num = 0; /* number of SAA7146s in use */ + +#define nDebNormal 0x00480000 +#define nDebNoInc 0x00480000 +#define nDebVideo 0xd0480000 +#define nDebAudio 0xd0400000 +#define nDebDMA 0x02c80000 + +#define oDebNormal 0x13c80000 +#define oDebNoInc 0x13c80000 +#define oDebVideo 0xd1080000 +#define oDebAudio 0xd1080000 +#define oDebDMA 0x03080000 + +#define NewCard (saa->boardcfg[3]) +#define ChipControl (saa->boardcfg[1]) +#define NTSCFirstActive (saa->boardcfg[4]) +#define PALFirstActive (saa->boardcfg[5]) +#define NTSCLastActive (saa->boardcfg[54]) +#define PALLastActive (saa->boardcfg[55]) +#define Have2MB (saa->boardcfg[18] & 0x40) +#define HaveCS8420 (saa->boardcfg[18] & 0x04) +#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20) +#define HaveCS3310 (saa->boardcfg[18] & 0x01) +#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31]) +#define HaveCS4341 (saa->boardcfg[40] == 2) +#define SDIType (saa->boardcfg[27]) +#define CurrentMode (saa->boardcfg[2]) + +#define debNormal (NewCard ? nDebNormal : oDebNormal) +#define debNoInc (NewCard ? nDebNoInc : oDebNoInc) +#define debVideo (NewCard ? nDebVideo : oDebVideo) +#define debAudio (NewCard ? nDebAudio : oDebAudio) +#define debDMA (NewCard ? nDebDMA : oDebDMA) + +#ifdef DEBUG +int stradis_driver(void) /* for the benefit of ksymoops */ +{ + return 1; +} +#endif + +#ifdef USE_RESCUE_EEPROM_SDM275 +static unsigned char rescue_eeprom[64] = { +0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +#endif + +/* ----------------------------------------------------------------------- */ +/* Hardware I2C functions */ +static void I2CWipe(struct saa7146 *saa) +{ + int i; + /* set i2c to ~=100kHz, abort transfer, clear busy */ + saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + saawrite(0x600, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + saawrite(0x600, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); +} +/* read I2C */ +static int I2CRead(struct i2c_bus *bus, unsigned char addr, + unsigned char subaddr, int dosub) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + + + if (saaread(SAA7146_I2C_STATUS) & 0x3c) + I2CWipe(saa); + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (i == 1000) + I2CWipe(saa); + if (dosub) + saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) | + ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER); + else + saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | + 0xf1, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + /* wait for valid data */ + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) + return -1; + if (i == 1000) + printk("i2c setup read timeout\n"); + saawrite(0x41, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + /* wait for valid data */ + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) + schedule(); + if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) + return -1; + if (i == 1000) + printk("i2c read timeout\n"); + return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff); +} +static int I2CReadOld(struct i2c_bus *bus, unsigned char addr) +{ + return I2CRead(bus, addr, 0, 0); +} + +/* set both to write both bytes, reset it to write only b1 */ + +static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, + unsigned char b2, int both) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + u32 data; + + if (saaread(SAA7146_I2C_STATUS) & 0x3c) + I2CWipe(saa); + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (i == 1000) + I2CWipe(saa); + data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); + if (both) + data |= ((b2 & 0xff) << 8) | 0xe5; + else + data |= 0xd1; + saawrite(data, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, + SAA7146_MC2); + return 0; +} + +static void attach_inform(struct i2c_bus *bus, int id) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + + DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id)); + if (id == 0xa0) { /* we have rev2 or later board, fill in info */ + for (i = 0; i < 64; i++) + saa->boardcfg[i] = I2CRead(bus, 0xa0, i, 1); +#ifdef USE_RESCUE_EEPROM_SDM275 + if (saa->boardcfg[0] != 0) { + printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr); + for (i = 0; i < 64; i++) + saa->boardcfg[i] = rescue_eeprom[i]; + } +#endif + printk("stradis%d: config =", saa->nr); + for (i = 0; i < 51; i++) { + printk(" %02x",saa->boardcfg[i]); + } + printk("\n"); + } +} + +static void detach_inform(struct i2c_bus *bus, int id) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + i = saa->nr; +} + +static void I2CBusScan(struct i2c_bus *bus) +{ + int i; + for (i = 0; i < 0xff; i += 2) + if ((I2CRead(bus, i, 0, 0)) >= 0) + attach_inform(bus, i); +} + +static struct i2c_bus saa7146_i2c_bus_template = +{ + "saa7146", + I2C_BUSID_BT848, + NULL, + SPIN_LOCK_UNLOCKED, + attach_inform, + detach_inform, + NULL, + NULL, + I2CReadOld, + I2CWrite, +}; + +static int debiwait_maxwait = 0; + +static int wait_for_debi_done(struct saa7146 *saa) +{ + int i; + + /* wait for registers to be programmed */ + for (i = 0; i < 100000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) + saaread(SAA7146_MC2); + /* wait for transfer to complete */ + for (i = 0; i < 500000 && + (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++) + saaread(SAA7146_MC2); + if (i > debiwait_maxwait) + printk("wait-for-debi-done maxwait: %d\n", + debiwait_maxwait = i); + + if (i == 500000) + return -1; + return 0; +} + +static int debiwrite(struct saa7146 *saa, u32 config, int addr, + u32 val, int count) +{ + u32 cmd; + if (count <= 0 || count > 32764) + return -1; + if (wait_for_debi_done(saa) < 0) + return -1; + saawrite(config, SAA7146_DEBI_CONFIG); + if (count <= 4) /* immediate transfer */ + saawrite(val, SAA7146_DEBI_AD); + else /* block transfer */ + saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); + saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); + saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, + SAA7146_MC2); + return 0; +} + +static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count) +{ + u32 result = 0; + + if (count > 32764 || count <= 0) + return 0; + if (wait_for_debi_done(saa) < 0) + return 0; + saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); + saawrite((count << 17) | 0x10000 | (addr & 0xffff), + SAA7146_DEBI_COMMAND); + saawrite(config, SAA7146_DEBI_CONFIG); + saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, + SAA7146_MC2); + if (count > 4) /* not an immediate transfer */ + return count; + wait_for_debi_done(saa); + result = saaread(SAA7146_DEBI_AD); + if (count == 1) + result &= 0xff; + if (count == 2) + result &= 0xffff; + if (count == 3) + result &= 0xffffff; + return result; +} + +/* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */ +/* data copied into saa->dmadebi buffer, caller must re-enable interrupts */ +static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes) +{ + int i, j; + u32 *buf; + buf = (u32 *) saa->dmadebi; + if (bytes > 0x7000) + bytes = 0x7000; + saawrite(0, SAA7146_IER); /* disable interrupts */ + for (i=0; i < 10000 && + (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) + & 0x8000); i++) + saaread(SAA7146_MC2); + if (i == 10000) + printk(KERN_ERR "stradis%d: dram_busy never cleared\n", + saa->nr); + debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) | + (address>>16), 4); + debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2); + for (j = 0; j < bytes/4; j++) { + for (i = 0; i < 10000 && + (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) + & 0x4000)); i++) + saaread(SAA7146_MC2); + if (i == 10000) + printk(KERN_ERR "stradis%d: dram_ready never set\n", + saa->nr); + buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4); + } +} + +static void do_irq_send_data(struct saa7146 *saa) +{ + int split, audbytes, vidbytes; + + saawrite(SAA7146_PSR_PIN1, SAA7146_IER); + /* if special feature mode in effect, disable audio sending */ + if (saa->playmode != VID_PLAY_NORMAL) + saa->audtail = saa->audhead = 0; + if (saa->audhead <= saa->audtail) + audbytes = saa->audtail - saa->audhead; + else + audbytes = 65536 - (saa->audhead - saa->audtail); + if (saa->vidhead <= saa->vidtail) + vidbytes = saa->vidtail - saa->vidhead; + else + vidbytes = 524288 - (saa->vidhead - saa->vidtail); + if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { + saawrite(0, SAA7146_IER); + return; + } + /* if at least 1 block audio waiting and audio fifo isn't full */ + if (audbytes >= 2048 && (debiread(saa, debNormal, + IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) { + if (saa->audhead > saa->audtail) + split = 65536 - saa->audhead; + else + split = 0; + audbytes = 2048; + if (split > 0 && split < 2048) { + memcpy(saa->dmadebi, saa->audbuf + saa->audhead, + split); + saa->audhead = 0; + audbytes -= split; + } else + split = 0; + memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, + audbytes); + saa->audhead += audbytes; + saa->audhead &= 0xffff; + debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO : + IBM_MP2_AUD_FIFOW), 0, 2048); + wake_up_interruptible(&saa->audq); + /* if at least 1 block video waiting and video fifo isn't full */ + } else if (vidbytes >= 30720 && (debiread(saa, debNormal, + IBM_MP2_FIFO, 2)) < 16384) { + if (saa->vidhead > saa->vidtail) + split = 524288 - saa->vidhead; + else + split = 0; + vidbytes = 30720; + if (split > 0 && split < 30720) { + memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, + split); + saa->vidhead = 0; + vidbytes -= split; + } else + split = 0; + memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead, + vidbytes); + saa->vidhead += vidbytes; + saa->vidhead &= 0x7ffff; + debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO : + IBM_MP2_FIFOW), 0, 30720); + wake_up_interruptible(&saa->vidq); + } + saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); +} + +static void send_osd_data(struct saa7146 *saa) +{ + int size = saa->osdtail - saa->osdhead; + if (size > 30720) + size = 30720; + /* ensure some multiple of 8 bytes is transferred */ + size = 8 * ((size + 8)>>3); + if (size) { + debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, + (saa->osdhead>>3), 2); + memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size); + saa->osdhead += size; + /* block transfer of next 8 bytes to ~32k bytes */ + debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size); + } + if (saa->osdhead >= saa->osdtail) { + saa->osdhead = saa->osdtail = 0; + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + } +} + +static void saa7146_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct saa7146 *saa = (struct saa7146 *) dev_id; + u32 stat, astat; + int count; + + count = 0; + while (1) { + /* get/clear interrupt status bits */ + stat = saaread(SAA7146_ISR); + astat = stat & saaread(SAA7146_IER); + if (!astat) + return; + saawrite(astat, SAA7146_ISR); + if (astat & SAA7146_PSR_DEBI_S) { + do_irq_send_data(saa); + } + if (astat & SAA7146_PSR_PIN1) { + int istat; + /* the following read will trigger DEBI_S */ + istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + if (istat & 1) { + saawrite(0, SAA7146_IER); + send_osd_data(saa); + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + } + if (istat & 0x20) { /* Video Start */ + saa->vidinfo.frame_count++; + } + if (istat & 0x400) { /* Picture Start */ + /* update temporal reference */ + } + if (istat & 0x200) { /* Picture Resolution Change */ + /* read new resolution */ + } + if (istat & 0x100) { /* New User Data found */ + /* read new user data */ + } + if (istat & 0x1000) { /* new GOP/SMPTE */ + /* read new SMPTE */ + } + if (istat & 0x8000) { /* Sequence Start Code */ + /* reset frame counter, load sizes */ + saa->vidinfo.frame_count = 0; + saa->vidinfo.h_size = 704; + saa->vidinfo.v_size = 480; +#if 0 + if (saa->endmarkhead != saa->endmarktail) { + saa->audhead = + saa->endmark[saa->endmarkhead]; + saa->endmarkhead++; + if (saa->endmarkhead >= MAX_MARKS) + saa->endmarkhead = 0; + } +#endif + } + if (istat & 0x4000) { /* Sequence Error Code */ + if (saa->endmarkhead != saa->endmarktail) { + saa->audhead = + saa->endmark[saa->endmarkhead]; + saa->endmarkhead++; + if (saa->endmarkhead >= MAX_MARKS) + saa->endmarkhead = 0; + } + } + } +#ifdef IDEBUG + if (astat & SAA7146_PSR_PPEF) { + IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr)); + } + if (astat & SAA7146_PSR_PABO) { + IDEBUG(printk("stradis%d irq: PABO\n", saa->nr)); + } + if (astat & SAA7146_PSR_PPED) { + IDEBUG(printk("stradis%d irq: PPED\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_I1) { + IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_I0) { + IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_LATE1) { + IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_LATE0) { + IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_E1) { + IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_E0) { + IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_TO1) { + IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_TO0) { + IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr)); + } + if (astat & SAA7146_PSR_UPLD) { + IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr)); + } + if (astat & SAA7146_PSR_DEBI_E) { + IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr)); + } + if (astat & SAA7146_PSR_I2C_S) { + IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr)); + } + if (astat & SAA7146_PSR_I2C_E) { + IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr)); + } + if (astat & SAA7146_PSR_A2_IN) { + IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr)); + } + if (astat & SAA7146_PSR_A2_OUT) { + IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr)); + } + if (astat & SAA7146_PSR_A1_IN) { + IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr)); + } + if (astat & SAA7146_PSR_A1_OUT) { + IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr)); + } + if (astat & SAA7146_PSR_AFOU) { + IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr)); + } + if (astat & SAA7146_PSR_V_PE) { + IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr)); + } + if (astat & SAA7146_PSR_VFOU) { + IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr)); + } + if (astat & SAA7146_PSR_FIDA) { + IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr)); + } + if (astat & SAA7146_PSR_FIDB) { + IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN3) { + IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN2) { + IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN0) { + IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr)); + } + if (astat & SAA7146_PSR_ECS) { + IDEBUG(printk("stradis%d irq: ECS\n", saa->nr)); + } + if (astat & SAA7146_PSR_EC3S) { + IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr)); + } + if (astat & SAA7146_PSR_EC0S) { + IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr)); + } +#endif + count++; + if (count > 15) + printk(KERN_WARNING "stradis%d: irq loop %d\n", + saa->nr, count); + if (count > 20) { + saawrite(0, SAA7146_IER); + printk(KERN_ERR + "stradis%d: IRQ loop cleared\n", saa->nr); + } + } +} + +static int ibm_send_command(struct saa7146 *saa, + int command, int data, int chain) +{ + int i; + + if (chain) + debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2); + else + debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2); + for (i = 0; i < 100 && + (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++) + schedule(); + if (i == 100) + return -1; + return 0; +} + +static void cs4341_setlevel(struct saa7146 *saa, int left, int right) +{ + I2CWrite(&(saa->i2c), 0x22, 0x03, + left > 94 ? 94 : left, 2); + I2CWrite(&(saa->i2c), 0x22, 0x04, + right > 94 ? 94 : right, 2); +} + +static void initialize_cs4341(struct saa7146 *saa) +{ + int i; + for (i = 0; i < 200; i++) { + /* auto mute off, power on, no de-emphasis */ + /* I2S data up to 24-bit 64xFs internal SCLK */ + I2CWrite(&(saa->i2c), 0x22, 0x01, 0x11, 2); + /* ATAPI mixer setings */ + I2CWrite(&(saa->i2c), 0x22, 0x02, 0x49, 2); + /* attenuation left 3db */ + I2CWrite(&(saa->i2c), 0x22, 0x03, 0x00, 2); + /* attenuation right 3db */ + I2CWrite(&(saa->i2c), 0x22, 0x04, 0x00, 2); + I2CWrite(&(saa->i2c), 0x22, 0x01, 0x10, 2); + if (I2CRead(&(saa->i2c), 0x22, 0x02, 1) == 0x49) + break; + schedule(); + } + printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i); + return; +} + +static void initialize_cs8420(struct saa7146 *saa, int pro) +{ + int i; + u8 *sequence; + if (pro) + sequence = mode8420pro; + else + sequence = mode8420con; + for (i = 0; i < INIT8420LEN; i++) + I2CWrite(&(saa->i2c), 0x20, init8420[i * 2], + init8420[i * 2 + 1], 2); + for (i = 0; i < MODE8420LEN; i++) + I2CWrite(&(saa->i2c), 0x20, sequence[i * 2], + sequence[i * 2 + 1], 2); + printk("stradis%d: CS8420 initialized\n", saa->nr); +} + +static void initialize_saa7121(struct saa7146 *saa, int dopal) +{ + int i, mod; + u8 *sequence; + if (dopal) + sequence = init7121pal; + else + sequence = init7121ntsc; + mod = saaread(SAA7146_PSR) & 0x08; + /* initialize PAL/NTSC video encoder */ + for (i = 0; i < INIT7121LEN; i++) { + if (NewCard) { /* handle new card encoder differences */ + if (sequence[i*2] == 0x3a) + I2CWrite(&(saa->i2c), 0x88, 0x3a, 0x13, 2); + else if (sequence[i*2] == 0x6b) + I2CWrite(&(saa->i2c), 0x88, 0x6b, 0x20, 2); + else if (sequence[i*2] == 0x6c) + I2CWrite(&(saa->i2c), 0x88, 0x6c, + dopal ? 0x09 : 0xf5, 2); + else if (sequence[i*2] == 0x6d) + I2CWrite(&(saa->i2c), 0x88, 0x6d, + dopal ? 0x20 : 0x00, 2); + else if (sequence[i*2] == 0x7a) + I2CWrite(&(saa->i2c), 0x88, 0x7a, + dopal ? (PALFirstActive - 1) : + (NTSCFirstActive - 4), 2); + else if (sequence[i*2] == 0x7b) + I2CWrite(&(saa->i2c), 0x88, 0x7b, + dopal ? PALLastActive : + NTSCLastActive, 2); + else I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], + sequence[i * 2 + 1], 2); + } else { + if (sequence[i*2] == 0x6b && mod) + I2CWrite(&(saa->i2c), 0x88, 0x6b, + (sequence[i * 2 + 1] ^ 0x09), 2); + else if (sequence[i*2] == 0x7a) + I2CWrite(&(saa->i2c), 0x88, 0x7a, + dopal ? (PALFirstActive - 1) : + (NTSCFirstActive - 4), 2); + else if (sequence[i*2] == 0x7b) + I2CWrite(&(saa->i2c), 0x88, 0x7b, + dopal ? PALLastActive : + NTSCLastActive, 2); + else + I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], + sequence[i * 2 + 1], 2); + } + } +} + +static void set_genlock_offset(struct saa7146 *saa, int noffset) +{ + int nCode; + int PixelsPerLine = 858; + if (CurrentMode == VIDEO_MODE_PAL) + PixelsPerLine = 864; + if (noffset > 500) + noffset = 500; + else if (noffset < -500) + noffset = -500; + nCode = noffset + 0x100; + if (nCode == 1) + nCode = 0x401; + else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode; + debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2); +} + +static void set_out_format(struct saa7146 *saa, int mode) +{ + initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1)); + saa->boardcfg[2] = mode; + /* do not adjust analog video parameters here, use saa7121 init */ + /* you will affect the SDI output on the new card */ + if (mode == VIDEO_MODE_PAL) { /* PAL */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2); + mdelay(50); + saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1); + if (NewCard) { + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + 0xe100, 2); + mdelay(50); + } + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + NewCard ? 0xe500: 0x6500, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, + (1 << 8) | + (NewCard ? PALFirstActive : PALFirstActive-6), 2); + } else { /* NTSC */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2); + mdelay(50); + saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1); + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + NewCard ? 0xe100: 0x6100, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, + (1 << 8) | + (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2); + } +} + + +/* Intialize bitmangler to map from a byte value to the mangled word that + * must be output to program the Xilinx part through the DEBI port. + * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0 + * transfer FPGA code, init IBM chip, transfer IBM microcode + * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0 + */ +static u16 bitmangler[256]; + +static int initialize_fpga(struct video_code *bitdata) +{ + int i, num, startindex, failure = 0, loadtwo, loadfile = 0; + u16 *dmabuf; + u8 *newdma; + struct saa7146 *saa; + + /* verify fpga code */ + for (startindex = 0; startindex < bitdata->datasize; startindex++) + if (bitdata->data[startindex] == 255) + break; + if (startindex == bitdata->datasize) { + printk(KERN_INFO "stradis: bad fpga code\n"); + return -1; + } + /* initialize all detected cards */ + for (num = 0; num < saa_num; num++) { + saa = &saa7146s[num]; + if (saa->boardcfg[0] > 20) + continue; /* card was programmed */ + loadtwo = (saa->boardcfg[18] & 0x10); + if (!NewCard) /* we have an old board */ + for (i = 0; i < 256; i++) + bitmangler[i] = ((i & 0x01) << 15) | + ((i & 0x02) << 6) | ((i & 0x04) << 4) | + ((i & 0x08) << 9) | ((i & 0x10) << 7) | + ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | + ((i & 0x80) >> 7); + else /* else we have a new board */ + for (i = 0; i < 256; i++) + bitmangler[i] = ((i & 0x01) << 7) | + ((i & 0x02) << 5) | ((i & 0x04) << 3) | + ((i & 0x08) << 1) | ((i & 0x10) >> 1) | + ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | + ((i & 0x80) >> 7); + + dmabuf = (u16 *) saa->dmadebi; + newdma = (u8 *) saa->dmadebi; + if (NewCard) { /* SDM2xxx */ + if (!strncmp(bitdata->loadwhat, "decoder2", 8)) + continue; /* fpga not for this card */ + if (!strncmp(&saa->boardcfg[42], + bitdata->loadwhat, 8)) { + loadfile = 1; + } else if (loadtwo && !strncmp(&saa->boardcfg[19], + bitdata->loadwhat, 8)) { + loadfile = 2; + } else if (!saa->boardcfg[42] && /* special */ + !strncmp("decxl", bitdata->loadwhat, 8)) { + loadfile = 1; + } else + continue; /* fpga not for this card */ + if (loadfile != 1 && loadfile != 2) { + continue; /* skip to next card */ + } + if (saa->boardcfg[0] && loadfile == 1 ) + continue; /* skip to next card */ + if (saa->boardcfg[0] != 1 && loadfile == 2) + continue; /* skip to next card */ + saa->boardcfg[0]++; /* mark fpga handled */ + printk("stradis%d: loading %s\n", saa->nr, + bitdata->loadwhat); + if (loadtwo && loadfile == 2) + goto send_fpga_stuff; + /* turn on the Audio interface to set PROG low */ + saawrite(0x00400040, SAA7146_GPIO_CTRL); + saaread(SAA7146_PSR); /* ensure posted write */ + /* wait for everyone to reset */ + mdelay(10); + saawrite(0x00400000, SAA7146_GPIO_CTRL); + } else { /* original card */ + if (strncmp(bitdata->loadwhat, "decoder2", 8)) + continue; /* fpga not for this card */ + /* Pull the Xilinx PROG signal WS3 low */ + saawrite(0x02000200, SAA7146_MC1); + /* Turn on the Audio interface so can set PROG low */ + saawrite(0x000000c0, SAA7146_ACON1); + /* Pull the Xilinx INIT signal (GPIO2) low */ + saawrite(0x00400000, SAA7146_GPIO_CTRL); + /* Make sure everybody resets */ + saaread(SAA7146_PSR); /* ensure posted write */ + mdelay(10); + /* Release the Xilinx PROG signal */ + saawrite(0x00000000, SAA7146_ACON1); + /* Turn off the Audio interface */ + saawrite(0x02000000, SAA7146_MC1); + } + /* Release Xilinx INIT signal (WS2) */ + saawrite(0x00000000, SAA7146_GPIO_CTRL); + /* Wait for the INIT to go High */ + for (i = 0; i < 10000 && + !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) + schedule(); + if (i == 1000) { + printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr); + return -1; + } +send_fpga_stuff: + if (NewCard) { + for (i = startindex; i < bitdata->datasize; i++) + newdma[i - startindex] = + bitmangler[bitdata->data[i]]; + debiwrite(saa, 0x01420000, 0, 0, + ((bitdata->datasize - startindex) + 5)); + if (loadtwo) { + if (loadfile == 1) { + printk("stradis%d: " + "awaiting 2nd FPGA bitfile\n", + saa->nr); + continue; /* skip to next card */ + } + + } + } else { + for (i = startindex; i < bitdata->datasize; i++) + dmabuf[i - startindex] = + bitmangler[bitdata->data[i]]; + debiwrite(saa, 0x014a0000, 0, 0, + ((bitdata->datasize - startindex) + 5) * 2); + } + for (i = 0; i < 1000 && + !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) + schedule(); + if (i == 1000) { + printk(KERN_INFO "stradis%d: FPGA load failed\n", + saa->nr); + failure++; + continue; + } + if (!NewCard) { + /* Pull the Xilinx INIT signal (GPIO2) low */ + saawrite(0x00400000, SAA7146_GPIO_CTRL); + saaread(SAA7146_PSR); /* ensure posted write */ + mdelay(2); + saawrite(0x00000000, SAA7146_GPIO_CTRL); + mdelay(2); + } + printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr); + saa->boardcfg[0] = 26; /* mark fpga programmed */ + /* set VXCO to its lowest frequency */ + debiwrite(saa, debNormal, XILINX_PWM, 0, 2); + if (NewCard) { + /* mute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, + 0, 2); + /* set VXCO to PWM mode, release reset, blank on */ + debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2); + mdelay(10); + /* unmute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CTL0, + 0x2020, 2); + } + /* set source Black */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); + saa->boardcfg[4] = 22; /* set NTSC First Active Line */ + saa->boardcfg[5] = 23; /* set PAL First Active Line */ + saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */ + saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */ + set_out_format(saa, VIDEO_MODE_NTSC); + mdelay(50); + /* begin IBM chip init */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); + saaread(SAA7146_PSR); /* wait for reset */ + mdelay(5); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); + debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); + if (NewCard) { + mdelay(5); + /* set i2s rate converter to 48KHz */ + debiwrite(saa, debNormal, 0x80c0, 6, 2); + /* we must init CS8420 first since rev b pulls i2s */ + /* master clock low and CS4341 needs i2s master to */ + /* run the i2c port. */ + if (HaveCS8420) { + /* 0=consumer, 1=pro */ + initialize_cs8420(saa, 0); + } + mdelay(5); + if (HaveCS4341) + initialize_cs4341(saa); + } + debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); + debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); + if (NewCard) + set_genlock_offset(saa, 0); + debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); +#if 0 + /* enable genlock */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2); +#else + /* disable genlock */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2); +#endif + } + return failure; +} + +static int do_ibm_reset(struct saa7146 *saa) +{ + /* failure if decoder not previously programmed */ + if (saa->boardcfg[0] < 37) + return -EIO; + /* mute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2); + /* disable interrupts */ + saawrite(0, SAA7146_IER); + saa->audhead = saa->audtail = 0; + saa->vidhead = saa->vidtail = 0; + /* tristate debi bus, disable debi transfers */ + saawrite(0x00880000, SAA7146_MC1); + /* ensure posted write */ + saaread(SAA7146_MC1); + mdelay(50); + /* re-enable debi transfers */ + saawrite(0x00880088, SAA7146_MC1); + /* set source Black */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); + /* begin IBM chip init */ + set_out_format(saa, CurrentMode); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); + saaread(SAA7146_PSR); /* wait for reset */ + mdelay(5); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); + debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); + if (NewCard) { + mdelay(5); + /* set i2s rate converter to 48KHz */ + debiwrite(saa, debNormal, 0x80c0, 6, 2); + /* we must init CS8420 first since rev b pulls i2s */ + /* master clock low and CS4341 needs i2s master to */ + /* run the i2c port. */ + if (HaveCS8420) { + /* 0=consumer, 1=pro */ + initialize_cs8420(saa, 1); + } + mdelay(5); + if (HaveCS4341) + initialize_cs4341(saa); + } + debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); + debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); + if (NewCard) + set_genlock_offset(saa, 0); + debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); + if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, + (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) { + printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr); + } + if (HaveCS3310) { + int i = CS3310MaxLvl; + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2); + } + /* start video decoder */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); + /* 256k vid, 3520 bytes aud */ + debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); + ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); + /* enable buffer threshold irq */ + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + /* clear pending interrupts */ + debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); + return 0; +} + +/* load the decoder microcode */ +static int initialize_ibmmpeg2(struct video_code *microcode) +{ + int i, num; + struct saa7146 *saa; + + for (num = 0; num < saa_num; num++) { + saa = &saa7146s[num]; + /* check that FPGA is loaded */ + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2); + if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) != + 0xa55a) { + printk(KERN_INFO "stradis%d: %04x != 0xa55a\n", + saa->nr, i); +#if 0 + return -1; +#endif + } + if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) { + if (saa->boardcfg[0] > 27) + continue; /* skip to next card */ + /* load video control store */ + saa->boardcfg[1] = 0x13; /* no-sync default */ + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); + debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); + for (i = 0; i < microcode->datasize / 2; i++) + debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA, + (microcode->data[i * 2] << 8) | + microcode->data[i * 2 + 1], 2); + debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + saa->boardcfg[0] = 28; + } + if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) { + if (saa->boardcfg[0] > 35) + continue; /* skip to next card */ + /* load audio control store */ + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); + for (i = 0; i < microcode->datasize; i++) + debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA, + microcode->data[i], 1); + debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); + if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, + 0xe000, 1)) { + printk(KERN_ERR + "stradis%d: IBM config failed\n", + saa->nr); + return -1; + } + /* set PWM to center value */ + if (NewCard) { + debiwrite(saa, debNormal, XILINX_PWM, + saa->boardcfg[14] + + (saa->boardcfg[13]<<8), 2); + } else + debiwrite(saa, debNormal, XILINX_PWM, + 0x46, 2); + if (HaveCS3310) { + i = CS3310MaxLvl; + debiwrite(saa, debNormal, + XILINX_CS3310_CMPLT, ((i<<8)|i), 2); + } + printk(KERN_INFO + "stradis%d: IBM MPEGCD%d Initialized\n", + saa->nr, 18 + (debiread(saa, debNormal, + IBM_MP2_CHIP_CONTROL, 2) >> 12)); + /* start video decoder */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, + 0x4037, 2); /* 256k vid, 3520 bytes aud */ + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); + ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); + /* enable buffer threshold irq */ + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + /* enable gpio irq */ + saawrite(0x00002000, SAA7146_GPIO_CTRL); + /* enable decoder output to HPS */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); + saa->boardcfg[0] = 37; + } + } + return 0; +} + +static u32 palette2fmt[] = +{ /* some of these YUV translations are wrong */ + 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000, + 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000, + 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000 +}; +static int bpp2fmt[4] = +{ + VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24, + VIDEO_PALETTE_RGB32 +}; + +/* I wish I could find a formula to calculate these... */ +static u32 h_prescale[64] = +{ + 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808, + 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460, + 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f, + 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000, + 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000, + 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000, + 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000, + 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000, + 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000, + 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000, + 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000, +}; +static u32 v_gain[64] = +{ + 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff, + 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, + 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, +}; + + +static void saa7146_set_winsize(struct saa7146 *saa) +{ + u32 format; + int offset, yacl, ysci; + saa->win.color_fmt = format = + (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] : + palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]]; + offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl; + saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1); + saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1); + saawrite(saa->win.bpl * 2, SAA7146_PITCH1); + saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight, + SAA7146_PROT_ADDR1); + saawrite(0, SAA7146_PAGE1); + saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); + offset = (704 / (saa->win.width - 1)) & 0x3f; + saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE); + offset = (720896 / saa->win.width) / (offset + 1); + saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE); + if (CurrentMode == VIDEO_MODE_NTSC) { + yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0; + ysci = 1024 - (saa->win.height * 1024 / 480); + } else { + yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0; + ysci = 1024 - (saa->win.height * 1024 / 576); + } + saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE); + saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN); + saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V | + SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 | + SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), + SAA7146_MC2); +} + +/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area + * bitmap is fixed width, 128 bytes (1024 pixels represented) + * arranged most-sigificant-bit-left in 32-bit words + * based on saa7146 clipping hardware, it swaps bytes if LE + * much of this makes up for egcs brain damage -- so if you + * are wondering "why did he do this?" it is because the C + * was adjusted to generate the optimal asm output without + * writing non-portable __asm__ directives. + */ + +static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h) +{ + register int startword, endword; + register u32 bitsleft, bitsright; + u32 *temp; + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if (w <= 0 || h <= 0 || x > 1023 || y > 639) + return; /* throw away bad clips */ + if (x + w > 1024) + w = 1024 - x; + if (y + h > 640) + h = 640 - y; + startword = (x >> 5); + endword = ((x + w) >> 5); + bitsleft = (0xffffffff >> (x & 31)); + bitsright = (0xffffffff << (~((x + w) - (endword<<5)))); + temp = &clipmap[(y<<5) + startword]; + w = endword - startword; + if (!w) { + bitsleft |= bitsright; + for (y = 0; y < h; y++) { + *temp |= bitsleft; + temp += 32; + } + } else { + for (y = 0; y < h; y++) { + *temp++ |= bitsleft; + for (x = 1; x < w; x++) + *temp++ = 0xffffffff; + *temp |= bitsright; + temp += (32 - w); + } + } +} + +static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) +{ + int i, width, height; + u32 *clipmap; + + clipmap = saa->dmavid2; + if((width=saa->win.width)>1023) + width = 1023; /* sanity check */ + if((height=saa->win.height)>640) + height = 639; /* sanity check */ + if (ncr > 0) { /* rectangles pased */ + /* convert rectangular clips to a bitmap */ + memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ + for (i = 0; i < ncr; i++) + clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, + cr[i].width, cr[i].height); + } + /* clip against viewing window AND screen + so we do not have to rely on the user program + */ + clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ? + (saa->win.swidth-saa->win.x) : width, 0, 1024, 768); + clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ? + (saa->win.sheight-saa->win.y) : height,1024,768); + if (saa->win.x<0) + clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768); + if (saa->win.y<0) + clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y)); +} + +static int saa_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability b; + strcpy(b.name, saa->video_dev.name); + b.type = VID_TYPE_CAPTURE | + VID_TYPE_OVERLAY | + VID_TYPE_CLIPPING | + VID_TYPE_FRAMERAM | + VID_TYPE_SCALES; + b.channels = 1; + b.audios = 1; + b.maxwidth = 768; + b.maxheight = 576; + b.minwidth = 32; + b.minheight = 32; + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture p = saa->picture; + if (saa->win.depth == 8) + p.palette = VIDEO_PALETTE_HI240; + if (saa->win.depth == 15) + p.palette = VIDEO_PALETTE_RGB555; + if (saa->win.depth == 16) + p.palette = VIDEO_PALETTE_RGB565; + if (saa->win.depth == 24) + p.palette = VIDEO_PALETTE_RGB24; + if (saa->win.depth == 32) + p.palette = VIDEO_PALETTE_RGB32; + if (copy_to_user(arg, &p, sizeof(p))) + return -EFAULT; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture p; + u32 format; + if (copy_from_user(&p, arg, sizeof(p))) + return -EFAULT; + if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { + format = palette2fmt[p.palette]; + saa->win.color_fmt = format; + saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); + } + saawrite(((p.brightness & 0xff00) << 16) | + ((p.contrast & 0xfe00) << 7) | + ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL); + saa->picture = p; + /* upload changed registers */ + saawrite(((SAA7146_MC2_UPLD_HPS_H | + SAA7146_MC2_UPLD_HPS_V) << 16) | + SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V, + SAA7146_MC2); + return 0; + } + case VIDIOCSWIN: + { + struct video_window vw; + struct video_clip *vcp = NULL; + + if (copy_from_user(&vw, arg, sizeof(vw))) + return -EFAULT; + + if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */ + saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); + return -EINVAL; + } + if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */ + int i = vw.x; + vw.x = (vw.x + 3) & ~3; + i = vw.x - i; + vw.width -= i; + } + saa->win.x = vw.x; + saa->win.y = vw.y; + saa->win.width = vw.width; + if (saa->win.width > 768) + saa->win.width = 768; + saa->win.height = vw.height; + if (CurrentMode == VIDEO_MODE_NTSC) { + if (saa->win.height > 480) + saa->win.height = 480; + } else { + if (saa->win.height > 576) + saa->win.height = 576; + } + + /* stop capture */ + saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); + saa7146_set_winsize(saa); + + /* + * Do any clips. + */ + if (vw.clipcount < 0) { + if (copy_from_user(saa->dmavid2, vw.clips, + VIDEO_CLIPMAP_SIZE)) + return -EFAULT; + } else if (vw.clipcount > 0) { + if ((vcp = vmalloc(sizeof(struct video_clip) * + (vw.clipcount))) == NULL) + return -ENOMEM; + if (copy_from_user(vcp, vw.clips, + sizeof(struct video_clip) * + vw.clipcount)) { + vfree(vcp); + return -EFAULT; + } + } else /* nothing clipped */ + memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE); + make_clip_tab(saa, vcp, vw.clipcount); + if (vw.clipcount > 0) + vfree(vcp); + + /* start capture & clip dma if we have an address */ + if ((saa->cap & 3) && saa->win.vidadr != 0) + saawrite(((SAA7146_MC1_TR_E_1 | + SAA7146_MC1_TR_E_2) << 16) | 0xffff, + SAA7146_MC1); + return 0; + } + case VIDIOCGWIN: + { + struct video_window vw; + vw.x = saa->win.x; + vw.y = saa->win.y; + vw.width = saa->win.width; + vw.height = saa->win.height; + vw.chromakey = 0; + vw.flags = 0; + if (copy_to_user(arg, &vw, sizeof(vw))) + return -EFAULT; + return 0; + } + case VIDIOCCAPTURE: + { + int v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if (v == 0) { + saa->cap &= ~1; + saawrite((SAA7146_MC1_TR_E_1 << 16), + SAA7146_MC1); + } else { + if (saa->win.vidadr == 0 || saa->win.width == 0 + || saa->win.height == 0) + return -EINVAL; + saa->cap |= 1; + saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, + SAA7146_MC1); + } + return 0; + } + case VIDIOCGFBUF: + { + struct video_buffer v; + v.base = (void *) saa->win.vidadr; + v.height = saa->win.sheight; + v.width = saa->win.swidth; + v.depth = saa->win.depth; + v.bytesperline = saa->win.bpl; + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + + } + case VIDIOCSFBUF: + { + struct video_buffer v; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if (v.depth != 8 && v.depth != 15 && v.depth != 16 && + v.depth != 24 && v.depth != 32 && v.width > 16 && + v.height > 16 && v.bytesperline > 16) + return -EINVAL; + if (v.base) + saa->win.vidadr = (unsigned long) v.base; + saa->win.sheight = v.height; + saa->win.swidth = v.width; + saa->win.bpp = ((v.depth + 7) & 0x38) / 8; + saa->win.depth = v.depth; + saa->win.bpl = v.bytesperline; + + DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", + v.base, v.width, v.height, saa->win.bpp, saa->win.bpl)); + saa7146_set_winsize(saa); + return 0; + } + case VIDIOCKEY: + { + /* Will be handled higher up .. */ + return 0; + } + + case VIDIOCGAUDIO: + { + struct video_audio v; + v = saa->audio_dev; + v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); + v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; + strcpy(v.name, "MPEG"); + v.mode = VIDEO_SOUND_STEREO; + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio v; + int i; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + i = (~(v.volume>>8))&0xff; + if (!HaveCS4341) { + if (v.flags & VIDEO_AUDIO_MUTE) { + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + 0xffff, 2); + } + if (!(v.flags & VIDEO_AUDIO_MUTE)) + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + 0x0000, 2); + if (v.flags & VIDEO_AUDIO_VOLUME) + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + (i<<8)|i, 2); + } else { + if (v.flags & VIDEO_AUDIO_MUTE) + cs4341_setlevel(saa, 0xff, 0xff); + if (!(v.flags & VIDEO_AUDIO_MUTE)) + cs4341_setlevel(saa, 0, 0); + if (v.flags & VIDEO_AUDIO_VOLUME) + cs4341_setlevel(saa, i, i); + } + saa->audio_dev = v; + return 0; + } + + case VIDIOCGUNIT: + { + struct video_unit vu; + vu.video = saa->video_dev.minor; + vu.vbi = VIDEO_NO_UNIT; + vu.radio = VIDEO_NO_UNIT; + vu.audio = VIDEO_NO_UNIT; + vu.teletext = VIDEO_NO_UNIT; + if (copy_to_user((void *) arg, (void *) &vu, sizeof(vu))) + return -EFAULT; + return 0; + } + case VIDIOCSPLAYMODE: + { + struct video_play_mode pmode; + if (copy_from_user((void *) &pmode, arg, + sizeof(struct video_play_mode))) + return -EFAULT; + switch (pmode.mode) { + case VID_PLAY_VID_OUT_MODE: + if (pmode.p1 != VIDEO_MODE_NTSC && + pmode.p1 != VIDEO_MODE_PAL) + return -EINVAL; + set_out_format(saa, pmode.p1); + return 0; + case VID_PLAY_GENLOCK: + debiwrite(saa, debNormal, + XILINX_CTL0, + (pmode.p1 ? 0x8000 : 0x8080), + 2); + if (NewCard) + set_genlock_offset(saa, + pmode.p2); + return 0; + case VID_PLAY_NORMAL: + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_PLAY, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_PAUSE: + /* IBM removed the PAUSE command */ + /* they say use SINGLE_FRAME now */ + case VID_PLAY_SINGLE_FRAME: + ibm_send_command(saa, + IBM_MP2_SINGLE_FRAME, + 0, 0); + if (saa->playmode == pmode.mode) { + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + } + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_FAST_FORWARD: + ibm_send_command(saa, + IBM_MP2_FAST_FORWARD, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_SLOW_MOTION: + ibm_send_command(saa, + IBM_MP2_SLOW_MOTION, + pmode.p1, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_IMMEDIATE_NORMAL: + /* ensure transfers resume */ + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_IMED_NORM_PLAY, 0, 0); + saa->playmode = VID_PLAY_NORMAL; + return 0; + case VID_PLAY_SWITCH_CHANNELS: + saa->audhead = saa->audtail = 0; + saa->vidhead = saa->vidtail = 0; + ibm_send_command(saa, + IBM_MP2_FREEZE_FRAME, 0, 1); + ibm_send_command(saa, + IBM_MP2_RESET_AUD_RATE, 0, 1); + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, 0, 2); + ibm_send_command(saa, + IBM_MP2_CHANNEL_SWITCH, 0, 1); + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_PLAY, 0, 0); + saa->playmode = VID_PLAY_NORMAL; + return 0; + case VID_PLAY_FREEZE_FRAME: + ibm_send_command(saa, + IBM_MP2_FREEZE_FRAME, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_STILL_MODE: + ibm_send_command(saa, + IBM_MP2_SET_STILL_MODE, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_MASTER_MODE: + if (pmode.p1 == VID_PLAY_MASTER_NONE) + saa->boardcfg[1] = 0x13; + else if (pmode.p1 == + VID_PLAY_MASTER_VIDEO) + saa->boardcfg[1] = 0x23; + else if (pmode.p1 == + VID_PLAY_MASTER_AUDIO) + saa->boardcfg[1] = 0x43; + else + return -EINVAL; + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + return 0; + case VID_PLAY_ACTIVE_SCANLINES: + if (CurrentMode == VIDEO_MODE_PAL) { + if (pmode.p1 < 1 || + pmode.p2 > 625) + return -EINVAL; + saa->boardcfg[5] = pmode.p1; + saa->boardcfg[55] = (pmode.p1 + + (pmode.p2/2) - 1) & + 0xff; + } else { + if (pmode.p1 < 4 || + pmode.p2 > 525) + return -EINVAL; + saa->boardcfg[4] = pmode.p1; + saa->boardcfg[54] = (pmode.p1 + + (pmode.p2/2) - 4) & + 0xff; + } + set_out_format(saa, CurrentMode); + case VID_PLAY_RESET: + return do_ibm_reset(saa); + case VID_PLAY_END_MARK: + if (saa->endmarktail < + saa->endmarkhead) { + if (saa->endmarkhead - + saa->endmarktail < 2) + return -ENOSPC; + } else if (saa->endmarkhead <= + saa->endmarktail) { + if (saa->endmarktail - + saa->endmarkhead > + (MAX_MARKS - 2)) + return -ENOSPC; + } else + return -ENOSPC; + saa->endmark[saa->endmarktail] = + saa->audtail; + saa->endmarktail++; + if (saa->endmarktail >= MAX_MARKS) + saa->endmarktail = 0; + } + return -EINVAL; + } + case VIDIOCSWRITEMODE: + { + int mode; + if (copy_from_user((void *) &mode, arg, sizeof(int))) + return -EFAULT; + if (mode == VID_WRITE_MPEG_AUD || + mode == VID_WRITE_MPEG_VID || + mode == VID_WRITE_CC || + mode == VID_WRITE_TTX || + mode == VID_WRITE_OSD) { + saa->writemode = mode; + return 0; + } + return -EINVAL; + } + case VIDIOCSMICROCODE: + { + struct video_code ucode; + __u8 *udata; + int i; + if (copy_from_user((void *) &ucode, arg, + sizeof(ucode))) + return -EFAULT; + if (ucode.datasize > 65536 || ucode.datasize < 1024 || + strncmp(ucode.loadwhat, "dec", 3)) + return -EINVAL; + if ((udata = vmalloc(ucode.datasize)) == NULL) + return -ENOMEM; + if (copy_from_user((void *) udata, ucode.data, + ucode.datasize)) { + vfree(udata); + return -EFAULT; + } + ucode.data = udata; + if (!strncmp(ucode.loadwhat, "decoder.aud", 11) + || !strncmp(ucode.loadwhat, "decoder.vid", 11)) + i = initialize_ibmmpeg2(&ucode); + else + i = initialize_fpga(&ucode); + vfree(udata); + if (i) + return -EINVAL; + return 0; + + } + case VIDIOCGCHAN: /* this makes xawtv happy */ + { + struct video_channel v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + v.flags = VIDEO_VC_AUDIO; + v.tuners = 0; + v.type = VID_TYPE_MPEG_DECODER; + v.norm = CurrentMode; + strcpy(v.name, "MPEG2"); + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSCHAN: /* this makes xawtv happy */ + { + struct video_channel v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + /* do nothing */ + return 0; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int saa_init_done(struct video_device *dev) +{ + return 0; +} + +static int saa_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); + return -EINVAL; +} + +static long saa_read(struct video_device *dev, char *buf, + unsigned long count, int nonblock) +{ + return -EINVAL; +} + +static long saa_write(struct video_device *dev, const char *buf, + unsigned long count, int nonblock) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + unsigned long todo = count; + int blocksize, split; + unsigned long flags; + + while (todo > 0) { + if (saa->writemode == VID_WRITE_MPEG_AUD) { + spin_lock_irqsave(&saa->lock, flags); + if (saa->audhead <= saa->audtail) + blocksize = 65536-(saa->audtail - saa->audhead); + else + blocksize = saa->audhead - saa->audtail; + spin_unlock_irqrestore(&saa->lock, flags); + if (blocksize < 16384) { + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + /* wait for buffer space to open */ + interruptible_sleep_on(&saa->audq); + } + spin_lock_irqsave(&saa->lock, flags); + if (saa->audhead <= saa->audtail) { + blocksize = 65536-(saa->audtail - saa->audhead); + split = 65536 - saa->audtail; + } else { + blocksize = saa->audhead - saa->audtail; + split = 65536; + } + spin_unlock_irqrestore(&saa->lock, flags); + blocksize--; + if (blocksize > todo) + blocksize = todo; + /* double check that we really have space */ + if (!blocksize) + return -ENOSPC; + if (split < blocksize) { + if (copy_from_user(saa->audbuf + + saa->audtail, buf, split)) + return -EFAULT; + buf += split; + todo -= split; + blocksize -= split; + saa->audtail = 0; + } + if (copy_from_user(saa->audbuf + saa->audtail, buf, + blocksize)) + return -EFAULT; + saa->audtail += blocksize; + todo -= blocksize; + buf += blocksize; + saa->audtail &= 0xffff; + } else if (saa->writemode == VID_WRITE_MPEG_VID) { + spin_lock_irqsave(&saa->lock, flags); + if (saa->vidhead <= saa->vidtail) + blocksize=524288-(saa->vidtail - saa->vidhead); + else + blocksize = saa->vidhead - saa->vidtail; + spin_unlock_irqrestore(&saa->lock, flags); + if (blocksize < 65536) { + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + /* wait for buffer space to open */ + interruptible_sleep_on(&saa->vidq); + } + spin_lock_irqsave(&saa->lock, flags); + if (saa->vidhead <= saa->vidtail) { + blocksize=524288-(saa->vidtail - saa->vidhead); + split = 524288 - saa->vidtail; + } else { + blocksize = saa->vidhead - saa->vidtail; + split = 524288; + } + spin_unlock_irqrestore(&saa->lock, flags); + blocksize--; + if (blocksize > todo) + blocksize = todo; + /* double check that we really have space */ + if (!blocksize) + return -ENOSPC; + if (split < blocksize) { + if (copy_from_user(saa->vidbuf + + saa->vidtail, buf, split)) + return -EFAULT; + buf += split; + todo -= split; + blocksize -= split; + saa->vidtail = 0; + } + if (copy_from_user(saa->vidbuf + saa->vidtail, buf, + blocksize)) + return -EFAULT; + saa->vidtail += blocksize; + todo -= blocksize; + buf += blocksize; + saa->vidtail &= 0x7ffff; + } else if (saa->writemode == VID_WRITE_OSD) { + if (count > 131072) + return -ENOSPC; + if (copy_from_user(saa->osdbuf, buf, count)) + return -EFAULT; + buf += count; + saa->osdhead = 0; + saa->osdtail = count; + debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + debiread(saa, debNormal, + IBM_MP2_DISP_MODE, 2) | 1, 2); + /* trigger osd data transfer */ + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + } + } + return count; +} + +static int saa_open(struct video_device *dev, int flags) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + + saa->video_dev.busy = 0; + saa->user++; + if (saa->user > 1) + return 0; /* device open already, don't reset */ + saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ + return 0; +} + +static void saa_close(struct video_device *dev) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + saa->user--; + saa->video_dev.busy = 0; + if (saa->user > 0) /* still someone using device */ + return; + saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ +} + +/* template for video_device-structure */ +static struct video_device saa_template = +{ + "SAA7146A", + VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, + VID_HARDWARE_SAA7146, + saa_open, + saa_close, + saa_read, + saa_write, + NULL, /* poll */ + saa_ioctl, + saa_mmap, + saa_init_done, + NULL, + 0, + 0 +}; + +static int configure_saa7146(struct pci_dev *dev, int num) +{ + int result; + struct saa7146 *saa; + + saa = &saa7146s[num]; + + saa->endmarkhead = saa->endmarktail = 0; + saa->win.x = saa->win.y = 0; + saa->win.width = saa->win.cropwidth = 720; + saa->win.height = saa->win.cropheight = 480; + saa->win.cropx = saa->win.cropy = 0; + saa->win.bpp = 2; + saa->win.depth = 16; + saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; + saa->win.bpl = 1024 * saa->win.bpp; + saa->win.swidth = 1024; + saa->win.sheight = 768; + saa->picture.brightness = 32768; + saa->picture.contrast = 38768; + saa->picture.colour = 32768; + saa->cap = 0; + saa->dev = dev; + saa->nr = num; + saa->playmode = VID_PLAY_NORMAL; + memset(saa->boardcfg, 0, 64); /* clear board config area */ + saa->saa7146_mem = NULL; + saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = + saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = + saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = + saa->pagea1out = saa->pagea2in = saa->pagea2out = + saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = + saa->pageRPS2 = NULL; + saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; + saa->audhead = saa->vidtail = 0; + + init_waitqueue_head(&saa->i2cq); + init_waitqueue_head(&saa->audq); + init_waitqueue_head(&saa->debiq); + init_waitqueue_head(&saa->vidq); + spin_lock_init(&saa->lock); + + saa->id = dev->device; + saa->irq = dev->irq; + saa->video_dev.minor = -1; + saa->saa7146_adr = dev->resource[0].start; + pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision); + saa->saa7146_mem = ioremap(((saa->saa7146_adr) & + PCI_BASE_ADDRESS_MEM_MASK), 0x200); + memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus)); + memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); + sprintf(saa->i2c.name, "stradis%d", num); + saa->i2c.data = saa; + saawrite(0, SAA7146_IER); /* turn off all interrupts */ + result = request_irq(saa->irq, saa7146_irq, + SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa); + if (result == -EINVAL) + printk(KERN_ERR "stradis%d: Bad irq number or handler\n", + num); + if (result == -EBUSY) + printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP" + " config in BIOS\n", num, saa->irq); + if (result < 0) + return result; + pci_set_master(dev); + if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0) + return -1; +#if 0 + /* i2c generic interface is currently BROKEN */ + i2c_register_bus(&saa->i2c); +#endif + return 0; +} + +static int init_saa7146(int i) +{ + struct saa7146 *saa = &saa7146s[i]; + + saa->user = 0; + /* reset the saa7146 */ + saawrite(0xffff0000, SAA7146_MC1); + mdelay(5); + /* enable debi and i2c transfers and pins */ + saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | + SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); + /* ensure proper state of chip */ + saawrite(0x00000000, SAA7146_PAGE1); + saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); + saawrite(0x00000000, SAA7146_PAGE2); + saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); + saawrite(0x00000000, SAA7146_DD1_INIT); + saawrite(0x00000000, SAA7146_DD1_STREAM_B); + saawrite(0x00000000, SAA7146_DD1_STREAM_A); + saawrite(0x00000000, SAA7146_BRS_CTRL); + saawrite(0x80400040, SAA7146_BCS_CTRL); + saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL); + saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL); + saawrite(0x00000000, SAA7146_ACON1); + saawrite(0x00000000, SAA7146_ACON2); + saawrite(0x00000600, SAA7146_I2C_STATUS); + saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A | + SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H | + SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 | + SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff, + SAA7146_MC2); + /* setup arbitration control registers */ + saawrite(0x1412121a, SAA7146_PCI_BT_V1); + + /* allocate 32k dma buffer + 4k for page table */ + if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) { + printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i); + return -1; + } +#if 0 + saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ + saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); + for (i = 0; i < 12; i++) /* setup mmu page table */ + saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096)); +#endif + saa->audhead = saa->vidhead = saa->osdhead = 0; + saa->audtail = saa->vidtail = saa->osdtail = 0; + if (saa->vidbuf == NULL) + if ((saa->vidbuf = vmalloc(524288)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + return -ENOMEM; + } + if (saa->audbuf == NULL) + if ((saa->audbuf = vmalloc(65536)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + vfree(saa->vidbuf); + saa->vidbuf = NULL; + return -ENOMEM; + } + if (saa->osdbuf == NULL) + if ((saa->osdbuf = vmalloc(131072)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + vfree(saa->vidbuf); + vfree(saa->audbuf); + saa->vidbuf = saa->audbuf = NULL; + return -ENOMEM; + } + /* allocate 81920 byte buffer for clipping */ + if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { + printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr); + vfree(saa->vidbuf); + vfree(saa->audbuf); + vfree(saa->osdbuf); + saa->vidbuf = saa->audbuf = saa->osdbuf = NULL; + saa->dmavid2 = NULL; + return -1; + } + memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */ + /* setup clipping registers */ + saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); + saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); + saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE, + SAA7146_PROT_ADDR2); + saawrite(256, SAA7146_PITCH2); + saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ + saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, + SAA7146_MC2); + I2CBusScan(&(saa->i2c)); + return 0; +} + +static void release_saa(void) +{ + u8 command; + int i; + struct saa7146 *saa; + + for (i = 0; i < saa_num; i++) { + saa = &saa7146s[i]; + + /* turn off all capturing, DMA and IRQs */ + saawrite(0xffff0000, SAA7146_MC1); /* reset chip */ + saawrite(0, SAA7146_MC2); + saawrite(0, SAA7146_IER); + saawrite(0xffffffffUL, SAA7146_ISR); +#if 0 + /* unregister i2c_bus */ + i2c_unregister_bus((&saa->i2c)); +#endif + + /* disable PCI bus-mastering */ + pci_read_config_byte(saa->dev, PCI_COMMAND, &command); + /* Should this be &=~ ?? */ + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte(saa->dev, PCI_COMMAND, command); + /* unmap and free memory */ + saa->audhead = saa->audtail = saa->osdhead = 0; + saa->vidhead = saa->vidtail = saa->osdtail = 0; + if (saa->vidbuf) + vfree(saa->vidbuf); + if (saa->audbuf) + vfree(saa->audbuf); + if (saa->osdbuf) + vfree(saa->osdbuf); + if (saa->dmavid2) + kfree((void *) saa->dmavid2); + saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; + saa->dmavid2 = NULL; + if (saa->dmadebi) + kfree((void *) saa->dmadebi); + if (saa->dmavid1) + kfree((void *) saa->dmavid1); + if (saa->dmavid2) + kfree((void *) saa->dmavid2); + if (saa->dmavid3) + kfree((void *) saa->dmavid3); + if (saa->dmaa1in) + kfree((void *) saa->dmaa1in); + if (saa->dmaa1out) + kfree((void *) saa->dmaa1out); + if (saa->dmaa2in) + kfree((void *) saa->dmaa2in); + if (saa->dmaa2out) + kfree((void *) saa->dmaa2out); + if (saa->dmaRPS1) + kfree((void *) saa->dmaRPS1); + if (saa->dmaRPS2) + kfree((void *) saa->dmaRPS2); + free_irq(saa->irq, saa); + if (saa->saa7146_mem) + iounmap(saa->saa7146_mem); + if (saa->video_dev.minor != -1) + video_unregister_device(&saa->video_dev); + } +} + +#ifdef MODULE +int init_module(void) +{ +#else +int init_stradis_cards(struct video_init *unused) +{ +#endif + struct pci_dev *dev = pci_devices; + int result = 0, i; + u32 newcard; + + saa_num = 0; + + while (dev) { + if (dev->vendor == PCI_VENDOR_ID_PHILIPS) + if (dev->device == PCI_DEVICE_ID_PHILIPS_SAA7146) { + pci_read_config_dword(dev, + PCI_SUBSYSTEM_VENDOR_ID, &newcard); + if (!newcard) + printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num); + else + printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); + result = configure_saa7146(dev, saa_num++); + } + if (result) + return result; + dev = dev->next; + } + if (saa_num) + printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num); + else + return -EINVAL; + for (i = 0; i < saa_num; i++) + if (init_saa7146(i) < 0) { + release_saa(); + return -EIO; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + release_saa(); + printk(KERN_INFO "stradis: module cleanup complete\n"); +} + +#endif diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 7e5ff9465..6ff328783 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -340,6 +340,8 @@ static inline void *ioremap(unsigned long base, long length) #endif +#undef RS_EVENT_WRITE_WAKEUP +#define RS_EVENT_WRITE_WAKEUP 0 #include "generic_serial.h" diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 85e436565..6fece9470 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -24,15 +24,14 @@ #include <asm/ptrace.h> -#ifdef CONFIG_APM -#include <linux/apm_bios.h> -#endif - extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); extern int console_loglevel; extern struct vfsmount *vfsmntlist; +/* Machine specific power off function */ +void (*sysrq_power_off)(void) = NULL; + /* Send a signal to all user processes */ static void send_sig_all(int sig, int even_init) @@ -82,12 +81,12 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, printk("Resetting\n"); machine_restart(NULL); break; -#ifdef CONFIG_APM case 'o': /* O -- power off */ - printk("Power off\n"); - apm_power_off(); + if (sysrq_power_off) { + printk("Power off\n"); + sysrq_power_off(); + } break; -#endif case 's': /* S -- emergency sync */ printk("Emergency Sync\n"); emergency_sync_scheduled = EMERG_SYNC; @@ -137,11 +136,10 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, if (tty) printk("saK "); #endif - printk("Boot " -#ifdef CONFIG_APM - "Off " -#endif - "Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n"); + printk("Boot "); + if (sysrq_power_off) + printk("Off "); + printk("Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n"); /* Don't use 'A' as it's handled specially on the Sparc */ } diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c index 108ea55a7..bb8dd3a7b 100644 --- a/drivers/char/tuner.c +++ b/drivers/char/tuner.c @@ -40,6 +40,8 @@ struct tuner int type; /* chip type */ int freq; /* keep track of the current settings */ int radio; + + int mode; /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */ }; /* ---------------------------------------------------------------------- */ @@ -58,6 +60,11 @@ struct tunertype unsigned char config; unsigned char I2C; unsigned short IFPCoff; + + unsigned char mode; /* mode change value (tested PHILIPS_SECAM only) */ + /* 0x01 -> ??? no change ??? */ + /* 0x02 -> PAL BDGHI / SECAM L */ + /* 0x04 -> ??? PAL others / SECAM others ??? */ }; /* @@ -73,7 +80,7 @@ static struct tunertype tuners[] = { {"Philips NTSC", Philips, NTSC, 16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,0xc0,732}, {"Philips SECAM", Philips, SECAM, - 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,0xc0,623}, + 16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,0xc0,623,0x02}, {"NoTuner", NoTuner, NOTUNER, 0 ,0 ,0x00,0x00,0x00,0x00,0x00,000}, {"Philips PAL", Philips, PAL, @@ -100,6 +107,7 @@ static int tuner_getstatus (struct tuner *t) #define TUNER_POR 0x80 #define TUNER_FL 0x40 +#define TUNER_MODE 0x38 #define TUNER_AFC 0x07 static int tuner_islocked (struct tuner *t) @@ -112,7 +120,6 @@ static int tuner_afcstatus (struct tuner *t) return (tuner_getstatus (t) & TUNER_AFC) - 2; } - static void set_tv_freq(struct tuner *t, int freq) { u8 config; @@ -133,15 +140,43 @@ static void set_tv_freq(struct tuner *t, int freq) else config = tun->UHF; + if (t->type == TUNER_PHILIPS_SECAM && t->mode) + config |= tun->mode; + else + config &= ~tun->mode; + div=freq + tun->IFPCoff; div&=0x7fff; LOCK_I2C_BUS(t->bus); - if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) { - printk("tuner: i2c i/o error #1\n"); + if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) { + /* + * Philips FI1216MK2 remark from specification : + * for channel selection involving band switching, and to ensure + * smooth tuning to the desired channel without causing + * unnecessary charge pump action, it is recommended to consider + * the difference between wanted channel frequency and the + * current channel frequency. Unnecessary charge pump action + * will result in very low tuning voltage which may drive the + * oscillator to extreme conditions. + */ + /* + * Progfou: specification says to send config data before + * frequency in case (wanted frequency < current frequency). + */ + if (i2c_write(t->bus, t->addr, tun->config, config, 1)) { + printk("tuner: i2c i/o error #1\n"); + } else { + if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) + printk("tuner: i2c i/o error #2\n"); + } } else { - if (i2c_write(t->bus, t->addr, tun->config, config, 1)) - printk("tuner: i2c i/o error #2\n"); + if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) { + printk("tuner: i2c i/o error #1\n"); + } else { + if (i2c_write(t->bus, t->addr, tun->config, config, 1)) + printk("tuner: i2c i/o error #2\n"); + } } UNLOCK_I2C_BUS(t->bus); } @@ -258,6 +293,16 @@ static int tuner_command(struct i2c_device *device, t->freq = *iarg; break; + case TUNER_SET_MODE: + if (t->type != TUNER_PHILIPS_SECAM) { + dprintk("tuner: trying to change mode for other than TUNER_PHILIPS_SECAM\n"); + } else { + dprintk("tuner: mode set to %d\n", *iarg); + t->mode = *iarg; + set_tv_freq(t,t->freq); + } + break; + default: return -EINVAL; } diff --git a/drivers/char/tuner.h b/drivers/char/tuner.h index afb0f10fb..f5c8edc2d 100644 --- a/drivers/char/tuner.h +++ b/drivers/char/tuner.h @@ -47,5 +47,6 @@ #define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ #define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ #define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */ +#define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */ #endif diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index eb76d446d..05f2eeeea 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -45,33 +45,12 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; extern int init_bttv_cards(struct video_init *); extern int i2c_tuner_init(struct video_init *); #endif -#ifdef CONFIG_VIDEO_SAA5249 -extern int init_saa_5249(struct video_init *); -#endif -#ifdef CONFIG_VIDEO_CQCAM -extern int init_colour_qcams(struct video_init *); -#endif #ifdef CONFIG_VIDEO_BWQCAM extern int init_bw_qcams(struct video_init *); #endif #ifdef CONFIG_VIDEO_PLANB extern int init_planbs(struct video_init *); #endif -#ifdef CONFIG_RADIO_RTRACK2 -extern int rtrack2_init(struct video_init *); -#endif -#ifdef CONFIG_RADIO_SF16FMI -extern int fmi_init(struct video_init *); -#endif -#ifdef CONFIG_RADIO_TYPHOON -extern int typhoon_init(struct video_init *); -#endif -#ifdef CONFIG_RADIO_CADET -extern int cadet_init(struct video_init *); -#endif -#ifdef CONFIG_RADIO_TERRATEC -extern int terratec_init(struct video_init *); -#endif #ifdef CONFIG_VIDEO_ZORAN extern int init_zoran_cards(struct video_init *); #endif @@ -81,11 +60,8 @@ static struct video_init video_init_list[]={ {"i2c-tuner", i2c_tuner_init}, {"bttv", init_bttv_cards}, #endif -#ifdef CONFIG_VIDEO_SAA5249 - {"saa5249", init_saa_5249}, -#endif -#ifdef CONFIG_VIDEO_CQCAM - {"c-qcam", init_colour_qcams}, +#ifdef CONFIG_VIDEO_STRADIS + {"stradis", init_stradis_cards}, #endif #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, @@ -93,21 +69,6 @@ static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_PLANB {"planb", init_planbs}, #endif -#ifdef CONFIG_RADIO_RTRACK2 - {"RTrack2", rtrack2_init}, -#endif -#ifdef CONFIG_RADIO_SF16FMI - {"SF16FMI", fmi_init}, -#endif -#ifdef CONFIG_RADIO_CADET - {"Cadet", cadet_init}, -#endif -#ifdef CONFIG_RADIO_TYPHOON - {"radio-typhoon", typhoon_init}, -#endif -#ifdef CONFIG_RADIO_TERRATEC - {"radio-terratec", terratec_init}, -#endif #ifdef CONFIG_VIDEO_ZORAN {"zoran", init_zoran_cards}, #endif |