diff options
Diffstat (limited to 'drivers/media/video')
104 files changed, 2825 insertions, 2552 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 4cca55170e2..9dcbffd0aa1 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -11,7 +11,7 @@ menuconfig VIDEO_CAPTURE_DRIVERS webcams, analog TV, and hybrid analog/digital TV. Some of those devices also supports FM radio. -if VIDEO_CAPTURE_DRIVERS +if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" @@ -347,7 +347,7 @@ endmenu # encoder / decoder chips config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI && VIDEO_DEV + depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI select VIDEO_BUF default n ---help--- @@ -489,6 +489,15 @@ config TUNER_3036 Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. +config TUNER_TEA5761 + bool "TEA 5761 radio tuner (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on I2C + select VIDEO_TUNER + help + Say Y here to include support for Philips TEA5761 radio tuner. + If in doubt, say N. + config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 @@ -691,7 +700,7 @@ menuconfig V4L_USB_DRIVERS depends on USB default y -if V4L_USB_DRIVERS +if V4L_USB_DRIVERS && USB source "drivers/media/video/pvrusb2/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9c2de501612..10b4d446901 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -7,6 +7,8 @@ zr36067-objs := zoran_procfs.o zoran_device.o \ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ mt20xx.o tda8290.o tea5767.o tda9887.o +tuner-$(CONFIG_TUNER_TEA5761) += tea5761.o + msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o @@ -16,7 +18,7 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) endif obj-$(CONFIG_VIDEO_BT848) += bt8xx/ -obj-$(CONFIG_VIDEO_BT848) += ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o @@ -59,7 +61,7 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_VIDEO_MEYE) += meye.o -obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ +obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_IVTV) += ivtv/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 823cd6cc471..cbab53fc624 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c @@ -38,23 +38,23 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_encoder.h> MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(x) (x)->name -#include <linux/video_encoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 05c7820fe53..0d0c554bfdf 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -34,23 +34,23 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_encoder.h> MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(s) (s)->name -#include <linux/video_encoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 59a43603b5c..12d1b9248be 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c @@ -38,23 +38,24 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_decoder.h> + MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(s) (s)->name -#include <linux/video_decoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 853b1a3d6a1..e1028a76c04 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c @@ -38,23 +38,23 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> +#include <linux/video_encoder.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(s) (s)->name -#include <linux/video_encoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 2e4cf1efdd2..b767b098d14 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c @@ -257,7 +257,7 @@ static int bt866_write(struct bt866 *encoder, printk(KERN_WARNING "%s: I/O error #%d " "(write 0x%02x/0x%02x)\n", encoder->i2c->name, err, encoder->addr, subaddr); - schedule_timeout_interruptible(HZ/10); + schedule_timeout_interruptible(msecs_to_jiffies(100)); } if (err == 3) { printk(KERN_WARNING "%s: giving up\n", diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 6b31e50fb95..387cb2122d4 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -178,8 +178,8 @@ static struct CARD { /* this seems to happen as well ... */ { 0xff1211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, - { 0x3000121a, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, - { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, + { 0x3000121a, BTTV_BOARD_VOODOOTV_200, "3Dfx VoodooTV 200" }, + { 0x263710b4, BTTV_BOARD_VOODOOTV_FM, "3Dfx VoodooTV FM" }, { 0x3060121a, BTTV_BOARD_STB2, "3Dfx VoodooTV 100/ STB OEM" }, { 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, @@ -313,6 +313,7 @@ static struct CARD { { 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, + { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, { 0, -1, NULL } }; @@ -329,7 +330,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -344,7 +345,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -359,7 +360,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -387,13 +388,13 @@ struct tvcard bttv_tvcards[] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0 }, .needs_tvaudio = 0, - .tuner_type = 4, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -408,7 +409,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 1, 0, 1 }, .gpiomute = 3, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -423,7 +424,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0x0c, 0x04, 0x08, 0x04 }, /* 0x04 for some cards ?? */ .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = avermedia_tvphone_audio, @@ -433,13 +434,13 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX-Vision MV-Delta", .video_inputs = 5, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -457,7 +458,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -488,7 +489,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 4, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -503,7 +504,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0x20001,0x10001, 0, 0 }, .gpiomute = 10, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -519,7 +520,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 13, 14, 11, 7 }, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -553,7 +554,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 4, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -568,7 +569,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0, 1, 0 }, .gpiomute = 10, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -587,7 +588,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x002000, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, }, [BTTV_BOARD_WINVIEW_601] = { .name = "Leadtek WinView 601", @@ -600,7 +601,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 }, .gpiomute = 0xcfa007, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = winview_audio, @@ -616,7 +617,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 1, 0, 0, 0 }, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -624,13 +625,13 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)", .video_inputs = 4, .audio_inputs = 1, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0x8dff00, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0 }, .no_msp34xx = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -643,7 +644,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 1 }, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -674,7 +675,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -683,7 +684,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 7, .muxsel = { 2, 3, -1 }, .digital_mode = DIGITAL_MODE_CAMERA, @@ -708,7 +709,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0xc00, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_remote = 1, @@ -740,7 +741,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -813,13 +814,13 @@ struct tvcard bttv_tvcards[] = { .name = "Imagenation PXC200", .video_inputs = 5, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, /* was: 4 */ .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0}, .gpiomux = { 0 }, .needs_tvaudio = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = PXC200_muxsel, @@ -836,7 +837,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0x0800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -860,13 +861,13 @@ struct tvcard bttv_tvcards[] = { .name = "Intel Create and Share PCI/ Smart Video Recorder III", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 2, .gpiomask = 0, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0 }, .needs_tvaudio = 0, - .tuner_type = 4, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -911,7 +912,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .pll = PLL_28, .has_radio = 1, - .tuner_type = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */ + .tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */ .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = winfast2000_audio, @@ -928,7 +929,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -945,7 +946,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_radio = 1, @@ -962,7 +963,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x29, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -978,7 +979,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x551c00, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = 1, + .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_remote = 1, @@ -995,7 +996,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 1, .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1030,7 +1031,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 13, 4, 11, 7 }, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_radio = 1, @@ -1048,7 +1049,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = 1, + .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1063,7 +1064,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 }, .gpiomute = 0xff3ffc, .no_msp34xx = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1074,14 +1075,14 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 3, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 1, 1, 0, 2 }, .gpiomute = 3, .no_msp34xx = 1, .pll = PLL_NONE, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1089,14 +1090,14 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX-Vision MV-Delta 2", .video_inputs = 5, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 3, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1112,7 +1113,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0xbcb03f, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = 21, + .tuner_type = TUNER_TEMIC_4039FR5_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1129,7 +1130,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_35, - .tuner_type = 1, + .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_radio = 1, @@ -1148,7 +1149,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 1, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1206,7 +1207,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 1, 2, 3 }, .gpiomute = 4, .pll = PLL_28, - .tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */, + .tuner_type = UNSET /* TUNER_ALPS_TMDH2_NTSC */, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1234,7 +1235,7 @@ struct tvcard bttv_tvcards[] = { 1= FM stereo Radio from Tuner */ .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1277,7 +1278,7 @@ struct tvcard bttv_tvcards[] = { 0x0080: Tuner A2 SAP (second audio program = Zweikanalton) 0x0880: Tuner A2 stereo */ .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1313,7 +1314,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0x800, 0x1000, 0x1000 }, .gpiomute = 0x1800, .pll = PLL_28, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1324,7 +1325,7 @@ struct tvcard bttv_tvcards[] = { .name = "GrandTec 'Grand Video Capture' (Bt848)", .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .gpiomask = 0, .muxsel = { 3, 1 }, @@ -1332,7 +1333,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_35, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1365,7 +1366,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 2, 0, 0, 0 }, .gpiomute = 1, .pll = PLL_28, - .tuner_type = 0, + .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1377,7 +1378,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 2, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 11, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 2, 0, 0, 1 }, @@ -1392,7 +1393,7 @@ struct tvcard bttv_tvcards[] = { .name = "AG Electronics GMV1", .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .gpiomask = 0xF, .muxsel = { 2, 2 }, @@ -1400,7 +1401,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .needs_tvaudio = 0, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1447,7 +1448,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 1, .muxsel = { 2, 3, 0, 1 }, .gpiomux = { 0, 0, 1, 0 }, @@ -1476,7 +1477,7 @@ struct tvcard bttv_tvcards[] = { .no_tda9875 = 1, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1517,13 +1518,35 @@ struct tvcard bttv_tvcards[] = { /* ---- card 0x44 ---------------------------------- */ [BTTV_BOARD_VOODOOTV_FM] = { - .name = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)", + .name = "3Dfx VoodooTV FM (Euro)", + /* try "insmod msp3400 simple=0" if you have + * sound problems with this card. */ + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = UNSET, + .gpiomask = 0x4f8a00, + /* 0x100000: 1=MSP enabled (0=disable again) + * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ + .gpiomux = {0x947fff, 0x987fff,0x947fff,0x947fff }, + .gpiomute = 0x947fff, + /* tvtuner, radio, external,internal, mute, stereo + * tuner, Composit, SVid, Composit-on-Svid-adapter */ + .muxsel = { 2, 3 ,0 ,1 }, + .tuner_type = TUNER_MT2032, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + }, + [BTTV_BOARD_VOODOOTV_200] = { + .name = "VoodooTV 200 (USA)", /* try "insmod msp3400 simple=0" if you have * sound problems with this card. */ .video_inputs = 4, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0x4f8a00, /* 0x100000: 1=MSP enabled (0=disable again) * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */ @@ -1543,8 +1566,8 @@ struct tvcard bttv_tvcards[] = { .name = "Active Imaging AIMMS", .video_inputs = 1, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -1564,7 +1587,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 13, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = 25, + .tuner_type = TUNER_LG_PAL_I_FM, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_remote = 1, @@ -1580,7 +1603,7 @@ struct tvcard bttv_tvcards[] = { .name = "Lifeview FlyVideo 98EZ (capture only) LR51", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 2, .muxsel = { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */ .pll = PLL_28, @@ -1606,7 +1629,7 @@ struct tvcard bttv_tvcards[] = { .no_msp34xx = 1, .no_tda9875 = 1, .pll = PLL_28, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */ @@ -1626,13 +1649,13 @@ struct tvcard bttv_tvcards[] = { .name = "Sensoray 311", .video_inputs = 5, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 4, .gpiomask = 0, .muxsel = { 2, 3, 1, 0, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 0, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1641,15 +1664,15 @@ struct tvcard bttv_tvcards[] = { .name = "RemoteVision MX (RV605)", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0x00, .gpiomask2 = 0x07ff, .muxsel = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03, 0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 }, .no_msp34xx = 1, .no_tda9875 = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, @@ -1693,15 +1716,15 @@ struct tvcard bttv_tvcards[] = { .name = "GrandTec Multi Capture Card (Bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1724,7 +1747,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and @@ -1744,10 +1767,10 @@ struct tvcard bttv_tvcards[] = { /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */ .name = "DSP Design TCVIDEO", .video_inputs = 4, - .svhs = -1, + .svhs = UNSET, .muxsel = { 2, 3, 1, 0 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -1762,7 +1785,7 @@ struct tvcard bttv_tvcards[] = { .muxsel = { 2, 0, 1, 1 }, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -1791,11 +1814,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */ .video_inputs = 4, /* id-inputs-clock */ .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 3, .muxsel = { 3, 2, 0, 1 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1806,11 +1829,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */ .video_inputs = 3, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 2, .muxsel = { 2, 3, 1 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1823,11 +1846,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101 (848)", /* 0x05-40C0-C1 */ .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 3, 1 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1838,11 +1861,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101/151", /* 0x1(4|5)-0004-C4 */ .video_inputs = 1, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 0 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1853,11 +1876,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 101/151 w/ svid", /* 0x(16|17|20)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1868,8 +1891,8 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 200/201/250/251", /* 0x1(8|9|E|F)-0004-C4 */ .video_inputs = 1, .audio_inputs = 1, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 0 }, .pll = PLL_28, .tuner_type = UNSET, @@ -1885,7 +1908,7 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 200/250", /* 0x1(A|B)-00C4-C1 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 0, 1 }, .pll = PLL_28, @@ -1900,7 +1923,7 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, @@ -1915,11 +1938,11 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 500", /* 500 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1930,9 +1953,9 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 540", /* 540 */ .video_inputs = 4, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -1945,7 +1968,7 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 2000", /* 2000 */ .video_inputs = 2, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 2, 3 }, .pll = PLL_28, @@ -1961,11 +1984,11 @@ struct tvcard bttv_tvcards[] = { .name = "IDS Eagle", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0, .muxsel = { 0, 1, 2, 3 }, .muxsel_hook = eagle_muxsel, @@ -1978,8 +2001,8 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 0, .svhs = 1, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .no_msp34xx = 1, @@ -2020,13 +2043,13 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 7, .muxsel = { 2, 3, 1, 1}, .gpiomux = { 0, 1, 2, 3}, .gpiomute = 4, .needs_tvaudio = 1, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -2035,7 +2058,7 @@ struct tvcard bttv_tvcards[] = { .name = "Euresys Picolo", .video_inputs = 3, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 2, .gpiomask = 0, .no_msp34xx = 1, @@ -2052,8 +2075,8 @@ struct tvcard bttv_tvcards[] = { .name = "ProVideo PV150", /* 0x4f */ .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3 }, .gpiomux = { 0 }, @@ -2080,7 +2103,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = 2, + .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .audio_hook = adtvk503_audio, @@ -2098,7 +2121,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = 5, + .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, /* Notes: @@ -2121,7 +2144,7 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0, .no_tda9875 = 1, .no_tda7432 = 1, - .tuner_type = 1, + .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_radio = 1, @@ -2138,11 +2161,11 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-200", .video_inputs = 1, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0xdf, .muxsel = { 2 }, .pll = PLL_28, @@ -2151,9 +2174,9 @@ struct tvcard bttv_tvcards[] = { .name = "Grand X-Guard / Trust 814PCI", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = 4, + .tuner = UNSET, + .svhs = UNSET, + .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .gpiomask2 = 0xff, @@ -2169,14 +2192,14 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_NEBULA_DIGITV] = { .name = "Nebula Electronics DigiTV", .video_inputs = 1, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2189,15 +2212,15 @@ struct tvcard bttv_tvcards[] = { .name = "ProVideo PV143", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0 }, .needs_tvaudio = 0, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2206,14 +2229,14 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009-X1 MiniDIN (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ + .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 0 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2221,14 +2244,14 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009-X1 Combi (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ + .tuner = UNSET, /* card has no tuner */ .svhs = 3, .gpiomask = 0x00, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2238,7 +2261,7 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009 MiniDIN (bt878)", .video_inputs = 10, .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ + .tuner = UNSET, /* card has no tuner */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2248,7 +2271,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2256,7 +2279,7 @@ struct tvcard bttv_tvcards[] = { .name = "PHYTEC VD-009 Combi (bt878)", .video_inputs = 10, .audio_inputs = 0, - .tuner = -1, /* card has no tuner */ + .tuner = UNSET, /* card has no tuner */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio @@ -2266,7 +2289,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2274,11 +2297,11 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-100", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0xdf, .muxsel = { 2, 3, 1, 0 }, .pll = PLL_28, @@ -2288,11 +2311,11 @@ struct tvcard bttv_tvcards[] = { .name = "IVC-120G", .video_inputs = 16, .audio_inputs = 0, /* card has no audio */ - .tuner = -1, /* card has no tuner */ - .tuner_type = -1, + .tuner = UNSET, /* card has no tuner */ + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, /* card has no svhs */ + .svhs = UNSET, /* card has no svhs */ .needs_tvaudio = 0, .no_msp34xx = 1, .no_tda9875 = 1, @@ -2333,7 +2356,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 3, .audio_inputs = 0, .svhs = 1, - .tuner = -1, + .tuner = UNSET, .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */ .no_msp34xx = 1, .no_tda9875 = 1, @@ -2364,9 +2387,9 @@ struct tvcard bttv_tvcards[] = { .name = "SIMUS GVC1100", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, - .tuner_type = -1, + .tuner = UNSET, + .svhs = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -2395,14 +2418,14 @@ struct tvcard bttv_tvcards[] = { .name = "LMLBT4", .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 2, 3, 1, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .needs_tvaudio = 0, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2452,8 +2475,8 @@ struct tvcard bttv_tvcards[] = { .name = "Euresys Picolo Tetra", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0, .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ .no_msp34xx = 1, @@ -2464,7 +2487,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .needs_tvaudio = 0, .muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/ - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2490,7 +2513,7 @@ struct tvcard bttv_tvcards[] = { .name = "AVerMedia AVerTV DVB-T 771", .video_inputs = 2, .svhs = 1, - .tuner = -1, + .tuner = UNSET, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -2509,14 +2532,14 @@ struct tvcard bttv_tvcards[] = { /* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */ .name = "AverMedia AverTV DVB-T 761", .video_inputs = 2, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .has_dvb = 1, @@ -2528,8 +2551,8 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX Vision Sigma-SQ", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }, @@ -2537,7 +2560,7 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2546,15 +2569,15 @@ struct tvcard bttv_tvcards[] = { .name = "MATRIX Vision Sigma-SLC", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0x0, .muxsel = { 2, 2, 2, 2 }, .muxsel_hook = sigmaSLC_muxsel, .gpiomux = { 0 }, .no_msp34xx = 1, .pll = PLL_28, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2566,7 +2589,7 @@ struct tvcard bttv_tvcards[] = { .video_inputs = 2, .audio_inputs = 1, .tuner = 0, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0xFF, .muxsel = { 2, 3, 1, 1 }, .gpiomux = { 2, 0, 0, 0 }, @@ -2584,14 +2607,14 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_DVICO_DVBT_LITE] = { /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */ .name = "DViCO FusionHDTV DVB-T Lite", - .tuner = -1, + .tuner = UNSET, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .no_video = 1, .has_dvb = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2634,14 +2657,14 @@ struct tvcard bttv_tvcards[] = { .name = "Tibet Systems 'Progress DVR' CS16", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, .pll = PLL_28, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .muxsel_hook = tibetCS16_muxsel, @@ -2661,11 +2684,11 @@ struct tvcard bttv_tvcards[] = { .name = "Kodicom 4400R (master)", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, + .svhs = UNSET, /* GPIO bits 0-9 used for analog switch: * 00 - 03: camera selector * 04 - 06: channel (controller) selector @@ -2693,11 +2716,11 @@ struct tvcard bttv_tvcards[] = { .name = "Kodicom 4400R (slave)", .video_inputs = 16, .audio_inputs = 0, - .tuner = -1, - .tuner_type = -1, + .tuner = UNSET, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .svhs = -1, + .svhs = UNSET, .gpiomask = 0x010000, .no_gpioirq = 1, .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, @@ -2717,7 +2740,7 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .svhs = 2, .muxsel = { 2, 3, 1, 0 }, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .pll = PLL_28, @@ -2824,7 +2847,7 @@ struct tvcard bttv_tvcards[] = { .name = "Osprey 440", .video_inputs = 1, .audio_inputs = 1, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 2 }, .pll = PLL_28, @@ -2848,7 +2871,7 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 1, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = 2, + .tuner_type = TUNER_PHILIPS_NTSC, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2875,14 +2898,14 @@ struct tvcard bttv_tvcards[] = { .name = "Hauppauge ImpactVCB (bt878)", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .gpiomask = 0x0f, /* old: 7 */ .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */ .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2914,10 +2937,10 @@ struct tvcard bttv_tvcards[] = { .name = "SSAI Security Video Interface", .video_inputs = 4, .audio_inputs = 0, - .tuner = -1, - .svhs = -1, + .tuner = UNSET, + .svhs = UNSET, .muxsel = { 0, 1, 2, 3 }, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, @@ -2925,13 +2948,31 @@ struct tvcard bttv_tvcards[] = { .name = "SSAI Ultrasound Video Interface", .video_inputs = 2, .audio_inputs = 0, - .tuner = -1, + .tuner = UNSET, .svhs = 1, .muxsel = { 2, 0, 1, 3 }, - .tuner_type = -1, + .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + /* ---- card 0x94---------------------------------- */ + [BTTV_BOARD_DVICO_FUSIONHDTV_2] = { + .name = "DViCO FusionHDTV 2", + .tuner = 0, + .tuner_type = TUNER_PHILIPS_ATSC, /* FCV1236D */ + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .video_inputs = 3, + .audio_inputs = 1, + .svhs = 2, + .muxsel = { 2, 3, 1 }, + .gpiomask = 0x00e00007, + .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, + .gpiomute = 0x00c00007, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3040,7 +3081,7 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) static void flyvideo_gpio(struct bttv *btv) { int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; - int tuner=-1,ttype; + int tuner=UNSET,ttype; gpio_inout(0xffffff, 0); udelay(8); /* without this we would see the 0x1800 mask */ @@ -3085,7 +3126,7 @@ static void flyvideo_gpio(struct bttv *btv) * gpio & 0x001000 output bit for audio routing */ if(is_capture_only) - tuner=4; /* No tuner present */ + tuner = TUNER_ABSENT; /* No tuner present */ printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); @@ -3093,7 +3134,7 @@ static void flyvideo_gpio(struct bttv *btv) btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", is_capture_only?"yes":"no "); - if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */ + if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */ btv->tuner_type = tuner; btv->has_radio = has_radio; @@ -3302,6 +3343,7 @@ void __devinit bttv_init_card1(struct bttv *btv) case BTTV_BOARD_HAUPPAUGE878: boot_msp34xx(btv,5); break; + case BTTV_BOARD_VOODOOTV_200: case BTTV_BOARD_VOODOOTV_FM: boot_msp34xx(btv,20); break; @@ -3328,10 +3370,9 @@ void __devinit bttv_init_card1(struct bttv *btv) /* initialization part two -- after registering i2c bus */ void __devinit bttv_init_card2(struct bttv *btv) { - int tda9887; int addr=ADDR_UNSET; - btv->tuner_type = -1; + btv->tuner_type = UNSET; if (BTTV_BOARD_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); @@ -3479,7 +3520,15 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; - printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); + + if (btv->tuner_type == TUNER_ABSENT || + bttv_tvcards[btv->c.type].tuner == UNSET) + printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr); + else if(btv->tuner_type == UNSET) + printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr); + else + printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr, + btv->tuner_type); if (btv->tuner_type != UNSET) { struct tuner_setup tun_setup; @@ -3521,6 +3570,9 @@ void __devinit bttv_init_card2(struct bttv *btv) if (!autoload) return; + if (bttv_tvcards[btv->c.type].tuner == UNSET) + return; /* no tuner or related drivers to load */ + /* try to detect audio/fader chips */ if (!bttv_tvcards[btv->c.type].no_msp34xx && bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0) @@ -3541,17 +3593,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (bttv_tvcards[btv->c.type].needs_tvaudio) request_module("tvaudio"); - /* tuner modules */ - tda9887 = 0; - if (btv->tda9887_conf) - tda9887 = 1; - if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb && - bttv_I2CRead(btv, I2C_ADDR_TDA9887, "TDA9887") >=0) - tda9887 = 1; - /* Hybrid DVB card, DOES have a tda9887 */ - if (btv->c.type == BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE) - tda9887 = 1; - if (btv->tuner_type != UNSET) + if (btv->tuner_type != UNSET && btv->tuner_type != TUNER_ABSENT) request_module("tuner"); } @@ -3865,11 +3907,15 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) if(norm==VIDEO_MODE_NTSC) { bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x957fff; dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff; bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ @@ -4163,7 +4209,7 @@ static int tea5757_read(struct bttv *btv) bus_low(btv,btv->mbox_clk); udelay(10); - timeout= jiffies + HZ; + timeout= jiffies + msecs_to_jiffies(1000); /* wait for DATA line to go low; error if it doesn't */ while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout)) diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 1c38723d316..cb555f2c40f 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -1218,7 +1218,14 @@ audio_mux(struct bttv *btv, int input, int mute) break; case TVAUDIO_INPUT_TUNER: default: - route.input = MSP_INPUT_DEFAULT; + /* This is the only card that uses TUNER2, and afaik, + is the only difference between the VOODOOTV_FM + and VOODOOTV_200 */ + if (btv->c.type == BTTV_BOARD_VOODOOTV_200) + route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \ + MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER); + else + route.input = MSP_INPUT_DEFAULT; break; } route.output = MSP_OUTPUT_DEFAULT; @@ -1253,7 +1260,7 @@ i2c_vidiocschan(struct bttv *btv) v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id; bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std); - if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) + if (btv->c.type == BTTV_BOARD_VOODOOTV_FM || btv->c.type == BTTV_BOARD_VOODOOTV_200) bttv_tda9880_setnorm(btv,btv->tvnorm); } @@ -1323,6 +1330,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) switch (btv->c.type) { case BTTV_BOARD_VOODOOTV_FM: + case BTTV_BOARD_VOODOOTV_200: bttv_tda9880_setnorm(btv,norm); break; } @@ -1331,7 +1339,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) /* Call with btv->lock down. */ static void -set_input(struct bttv *btv, unsigned int input) +set_input(struct bttv *btv, unsigned int input, unsigned int norm) { unsigned long flags; @@ -1350,7 +1358,7 @@ set_input(struct bttv *btv, unsigned int input) } audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); - set_tvnorm(btv,btv->tvnorm); + set_tvnorm(btv, norm); i2c_vidiocschan(btv); } @@ -1441,7 +1449,7 @@ static void bttv_reinit_bt848(struct bttv *btv) init_bt848(btv); btv->pll.pll_current = -1; - set_input(btv,btv->input); + set_input(btv, btv->input, btv->tvnorm); } static int get_control(struct bttv *btv, struct v4l2_control *c) @@ -2011,8 +2019,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - btv->tvnorm = v->norm; - set_input(btv,v->channel); + set_input(btv, v->channel, v->norm); mutex_unlock(&btv->lock); return 0; } @@ -2148,7 +2155,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (*i > bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; mutex_lock(&btv->lock); - set_input(btv,*i); + set_input(btv, *i, btv->tvnorm); mutex_unlock(&btv->lock); return 0; } @@ -2252,6 +2259,24 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr); return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_S_REGISTER: + { + struct v4l2_register *reg = arg; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + /* bt848 has a 12-bit register space */ + reg->reg &= 0xfff; + if (cmd == VIDIOC_DBG_G_REGISTER) + reg->val = btread(reg->reg); + else + btwrite(reg->val, reg->reg); + return 0; + } +#endif default: return -ENOIOCTLCMD; @@ -3562,6 +3587,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: case VIDIOC_LOG_STATUS: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); default: @@ -3944,6 +3971,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, case VIDIOCGAUDIO: case VIDIOCSAUDIO: case VIDIOC_LOG_STATUS: + case VIDIOC_DBG_G_REGISTER: + case VIDIOC_DBG_S_REGISTER: return bttv_common_ioctls(btv,cmd,arg); default: @@ -4780,7 +4809,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, bt848_hue(btv,32768); bt848_sat(btv,32768); audio_mute(btv, 1); - set_input(btv,0); + set_input(btv, 0, btv->tvnorm); bttv_crop_reset(&btv->crop[0], btv->tvnorm); btv->crop[1] = btv->crop[0]; /* current = default */ disclaim_vbi_lines(btv); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 6f74c8042bc..4201552bc3c 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -153,7 +153,7 @@ static void bttv_ir_start(struct bttv *btv, struct card_ir *ir) { if (ir->polling) { setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv); - ir->timer.expires = jiffies + HZ; + ir->timer.expires = jiffies + msecs_to_jiffies(1000); add_timer(&ir->timer); } else if (ir->rc5_gpio) { /* set timer_end for code completion */ @@ -313,7 +313,7 @@ int bttv_input_init(struct bttv *btv) input_dev->id.vendor = btv->c.pci->vendor; input_dev->id.product = btv->c.pci->device; } - input_dev->cdev.dev = &btv->c.pci->dev; + input_dev->dev.parent = &btv->c.pci->dev; btv->remote = ir; bttv_ir_start(btv, ir); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index f821ba69db9..dcc847dc248 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -170,6 +170,8 @@ #define BTTV_BOARD_MACHTV_MAGICTV 0x90 #define BTTV_BOARD_SSAI_SECURITY 0x91 #define BTTV_BOARD_SSAI_ULTRASOUND 0x92 +#define BTTV_BOARD_VOODOOTV_200 0x93 +#define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 8f44f02029b..5b25faca150 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -33,12 +33,12 @@ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/videodev.h> -#include <media/v4l2-common.h> #include <linux/pci.h> #include <linux/input.h> #include <linux/mutex.h> #include <asm/scatterlist.h> #include <asm/io.h> +#include <media/v4l2-common.h> #include <linux/device.h> #include <media/video-buf.h> @@ -284,8 +284,8 @@ extern int fini_bttv_i2c(struct bttv *btv); #define d2printk if (bttv_debug >= 2) printk #define BTTV_MAX_FBUF 0x208000 -#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */ -#define BTTV_FREE_IDLE (HZ) /* one second */ +#define BTTV_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ +#define BTTV_FREE_IDLE msecs_to_jiffies(1000) /* one second */ struct bttv_pll_info { diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 925ff17efbb..f76c6a6c376 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -95,7 +95,7 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam, unsigned long oldjiffies = jiffies; unsigned int i; - for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); ) + for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); ) if (qcam_ready1(qcam) == value) return 0; @@ -120,7 +120,7 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) unsigned long oldjiffies = jiffies; unsigned int i; - for (oldjiffies = jiffies; (jiffies - oldjiffies) < (HZ/25); ) + for (oldjiffies = jiffies; (jiffies - oldjiffies) < msecs_to_jiffies(40); ) if (qcam_ready2(qcam) == value) return 0; diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index fd771c7a2fe..a76bd786cf1 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -663,15 +663,13 @@ int cpia2_reset_camera(struct camera_data *cam) cpia2_send_command(cam, &cmd); } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + schedule_timeout_interruptible(msecs_to_jiffies(100)); if (cam->params.pnp_id.device_type == DEVICE_STV_672) retval = apply_vp_patch(cam); /* wait for vp to go to sleep */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + schedule_timeout_interruptible(msecs_to_jiffies(100)); /*** * If this is a 676, apply VP5 fixes before we start streaming @@ -720,8 +718,7 @@ int cpia2_reset_camera(struct camera_data *cam) set_default_user_mode(cam); /* Give VP time to wake up */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(100 * HZ / 1000); /* wait for 100 msecs */ + schedule_timeout_interruptible(msecs_to_jiffies(100)); set_all_properties(cam); @@ -2227,15 +2224,13 @@ struct camera_data *cpia2_init_camera_struct(void) { struct camera_data *cam; - cam = kmalloc(sizeof(*cam), GFP_KERNEL); + cam = kzalloc(sizeof(*cam), GFP_KERNEL); if (!cam) { ERR("couldn't kmalloc cpia2 struct\n"); return NULL; } - /* Default everything to 0 */ - memset(cam, 0, sizeof(struct camera_data)); cam->present = 1; mutex_init(&cam->busy_lock); diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 1bda7ad9de1..92778cd1d73 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -105,7 +105,7 @@ static struct control_menu_info framerate_controls[] = { CPIA2_VP_FRAMERATE_25, "25 fps" }, { CPIA2_VP_FRAMERATE_30, "30 fps" }, }; -#define NUM_FRAMERATE_CONTROLS (sizeof(framerate_controls)/sizeof(framerate_controls[0])) +#define NUM_FRAMERATE_CONTROLS (ARRAY_SIZE(framerate_controls)) static struct control_menu_info flicker_controls[] = { @@ -113,7 +113,7 @@ static struct control_menu_info flicker_controls[] = { FLICKER_50, "50 Hz" }, { FLICKER_60, "60 Hz" }, }; -#define NUM_FLICKER_CONTROLS (sizeof(flicker_controls)/sizeof(flicker_controls[0])) +#define NUM_FLICKER_CONTROLS (ARRAY_SIZE(flicker_controls)) static struct control_menu_info lights_controls[] = { @@ -122,7 +122,7 @@ static struct control_menu_info lights_controls[] = { 128, "Bottom" }, { 192, "Both" }, }; -#define NUM_LIGHTS_CONTROLS (sizeof(lights_controls)/sizeof(lights_controls[0])) +#define NUM_LIGHTS_CONTROLS (ARRAY_SIZE(lights_controls)) #define GPIO_LIGHTS_MASK 192 static struct v4l2_queryctrl controls[] = { @@ -235,7 +235,7 @@ static struct v4l2_queryctrl controls[] = { .default_value = 0, }, }; -#define NUM_CONTROLS (sizeof(controls)/sizeof(controls[0])) +#define NUM_CONTROLS (ARRAY_SIZE(controls)) /****************************************************************************** diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0f9d9696361..f750a543c96 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -47,7 +47,7 @@ config VIDEO_CX88_DVB tristate "DVB/ATSC Support for cx2388x based TV cards" depends on VIDEO_CX88 && DVB_CORE select VIDEO_BUF_DVB - select DVB_PLL + select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_OR51132 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index b0466b88f52..f2fcdb92ecc 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -56,8 +56,7 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); /* ------------------------------------------------------------------ */ -#define OLD_BLACKBIRD_FIRM_IMAGE_SIZE 262144 -#define BLACKBIRD_FIRM_IMAGE_SIZE 376836 +#define BLACKBIRD_FIRM_IMAGE_SIZE 376836 /* defines below are from ivtv-driver.h */ @@ -405,7 +404,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev) u32 value; int i; - for (i = 0; i < dev->fw_size; i++) { + for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) { memory_read(dev->core, i, &value); if (value == signature[signaturecnt]) signaturecnt++; @@ -453,15 +452,12 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) return -1; } - if ((firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) && - (firmware->size != OLD_BLACKBIRD_FIRM_IMAGE_SIZE)) { - dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d or %d)\n", - firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE, - OLD_BLACKBIRD_FIRM_IMAGE_SIZE); + if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { + dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", + firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); release_firmware(firmware); return -1; } - dev->fw_size = firmware->size; if (0 != memcmp(firmware->data, magic, 8)) { dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); @@ -1034,6 +1030,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, if (unlikely(UNSET == core->tuner_type)) return -EINVAL; + if (0 != t->index) + return -EINVAL; strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index e61102dc8ad..6a136ddbccf 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1335,6 +1335,26 @@ struct cx88_board cx88_boards[] = { /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, }, + [CX88_BOARD_ADSTECH_PTV_390] = { + .name = "ADS Tech Instant Video PCI", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_DEBUG, + .vmux = 3, + .gpio0 = 0x04ff, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x07fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x07fa, + }}, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1641,6 +1661,10 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */ .card = CX88_BOARD_KWORLD_DVBS_100, + },{ + .subvendor = 0x1421, + .subdevice = 0x0390, + .card = CX88_BOARD_ADSTECH_PTV_390, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index dbfe4dc9cf8..1773b40467d 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -35,9 +35,7 @@ #include "mt352.h" #include "mt352_priv.h" -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) -# include "cx88-vp3054-i2c.h" -#endif +#include "cx88-vp3054-i2c.h" #include "zl10353.h" #include "cx22702.h" #include "or51132.h" @@ -199,7 +197,7 @@ static struct mt352_config dvico_fusionhdtv_dual = { .demod_init = dvico_dual_demod_init, }; -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) { static u8 clock_config [] = { 0x89, 0x38, 0x38 }; @@ -223,64 +221,6 @@ static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) return 0; } -static int philips_fmd1216_pll_init(struct dvb_frontend *fe) -{ - struct cx8802_dev *dev= fe->dvb->priv; - - /* this message is to set up ATC and ALC */ - static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; - struct i2c_msg msg = - { .addr = dev->core->pll_addr, .flags = 0, - .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; - int err; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - -static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) -{ - struct cx8802_dev *dev= fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = - { .addr = dev->core->pll_addr, .flags = 0, - .buf = buf, .len = 4 }; - int err; - - /* Switch PLL to DVB mode */ - err = philips_fmd1216_pll_init(fe); - if (err) - return err; - - /* Tune PLL */ - dvb_pll_configure(dev->core->pll_desc, buf, - params->frequency, - params->u.ofdm.bandwidth); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { - - printk(KERN_WARNING "cx88-dvb: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, dev->core->pll_addr, buf[0], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - static struct mt352_config dntv_live_dvbt_pro_config = { .demod_address = 0x0f, .no_tuner = 1, @@ -370,18 +310,8 @@ static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) return 0; } -static int nxt200x_set_pll_input(u8* buf, int input) -{ - if (input) - buf[3] |= 0x08; - else - buf[3] &= ~0x08; - return 0; -} - static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, - .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; @@ -456,7 +386,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_thomson_dtt759x); + DVB_PLL_THOMSON_DTT759X); } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: @@ -469,7 +399,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, &dev->core->i2c_adap, - &dvb_pll_thomson_dtt7579); + DVB_PLL_THOMSON_DTT7579); } break; case CX88_BOARD_WINFAST_DTV2000H: @@ -482,7 +412,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, &dvb_pll_fmd1216me); + &dev->core->i2c_adap, DVB_PLL_FMD1216ME); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: @@ -491,7 +421,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - NULL, &dvb_pll_thomson_dtt7579); + NULL, DVB_PLL_THOMSON_DTT7579); break; } /* ZL10353 replaces MT352 on later cards */ @@ -500,7 +430,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - NULL, &dvb_pll_thomson_dtt7579); + NULL, DVB_PLL_THOMSON_DTT7579); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: @@ -511,7 +441,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_thomson_dtt7579); + NULL, DVB_PLL_THOMSON_DTT7579); break; } /* ZL10353 replaces MT352 on later cards */ @@ -520,7 +450,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_thomson_dtt7579); + NULL, DVB_PLL_THOMSON_DTT7579); } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: @@ -529,7 +459,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_lg_z201); + NULL, DVB_PLL_LG_Z201); } break; case CX88_BOARD_KWORLD_DVB_T: @@ -540,17 +470,16 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_unknown_1); + NULL, DVB_PLL_UNKNOWN_1); } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_fmd1216me; +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &((struct vp3054_i2c_state *)dev->card_priv)->adap); if (dev->dvb.frontend != NULL) { - dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, DVB_PLL_FMD1216ME); } #else printk("%s: built without vp3054 support\n", dev->core->name); @@ -563,7 +492,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_thomson_fe6600); + DVB_PLL_THOMSON_FE6600); } break; case CX88_BOARD_PCHDTV_HD3000: @@ -572,7 +501,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_thomson_dtt761x); + DVB_PLL_THOMSON_DTT761X); } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: @@ -594,7 +523,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_microtune_4042); + DVB_PLL_MICROTUNE_4042); } } break; @@ -614,7 +543,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_thomson_dtt761x); + DVB_PLL_THOMSON_DTT761X); } } break; @@ -634,7 +563,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_lg_tdvs_h06xf); + DVB_PLL_LG_TDVS_H06XF); } } break; @@ -654,7 +583,7 @@ static int dvb_register(struct cx8802_dev *dev) if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->core->i2c_adap, - &dvb_pll_lg_tdvs_h06xf); + DVB_PLL_LG_TDVS_H06XF); } } break; @@ -664,7 +593,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap); if (dev->dvb.frontend != NULL) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_tuv1236d); + NULL, DVB_PLL_TUV1236D); } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: @@ -705,10 +634,6 @@ static int dvb_register(struct cx8802_dev *dev) return -1; } - if (dev->core->pll_desc) { - dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; - dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; - } /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; @@ -778,11 +703,10 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) goto fail_core; -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) + /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; -#endif /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); @@ -807,9 +731,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) /* dvb */ videobuf_dvb_unregister(&dev->dvb); -#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE) vp3054_i2c_remove(dev); -#endif return 0; } diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 7919a1f9da0..78bbcfab967 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -160,7 +160,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) i2c_clients_command(&core->i2c_adap, cmd, arg); } -static struct i2c_algo_bit_data cx8800_i2c_algo_template = { +static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { .setsda = cx8800_bit_setsda, .setscl = cx8800_bit_setscl, .getsda = cx8800_bit_getsda, @@ -171,18 +171,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = { /* ----------------------------------------------------------------------- */ -static struct i2c_adapter cx8800_i2c_adap_template = { - .name = "cx2388x", - .owner = THIS_MODULE, - .id = I2C_HW_B_CX2388x, - .client_register = attach_inform, - .client_unregister = detach_inform, -}; - -static struct i2c_client cx8800_i2c_client_template = { - .name = "cx88xx internal", -}; - static char *i2c_devs[128] = { [ 0x1c >> 1 ] = "lgdt330x", [ 0x86 >> 1 ] = "tda9887/cx22702", @@ -212,14 +200,9 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) /* Prevents usage of invalid delay values */ if (i2c_udelay<5) i2c_udelay=5; - cx8800_i2c_algo_template.udelay=i2c_udelay; - memcpy(&core->i2c_adap, &cx8800_i2c_adap_template, - sizeof(core->i2c_adap)); memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); - memcpy(&core->i2c_client, &cx8800_i2c_client_template, - sizeof(core->i2c_client)); if (core->tuner_type != TUNER_ABSENT) core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; @@ -228,10 +211,16 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); + core->i2c_adap.owner = THIS_MODULE; + core->i2c_adap.id = I2C_HW_B_CX2388x; + core->i2c_adap.client_register = attach_inform; + core->i2c_adap.client_unregister = detach_inform; + core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap,core); core->i2c_adap.algo_data = &core->i2c_algo; core->i2c_client.adapter = &core->i2c_adap; + strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); cx8800_bit_setscl(core,1); cx8800_bit_setsda(core,1); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8136673fe9e..f5d4a565346 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -74,7 +74,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) /* read gpio value */ gpio = cx_read(ir->gpio_addr); - if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) { + switch (core->board) { + case CX88_BOARD_NPGTECH_REALTV_TOP10FM: /* This board apparently uses a combination of 2 GPIO to represent the keys. Additionally, the second GPIO can be used for parity. @@ -90,9 +91,14 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) auxgpio = cx_read(MO_GP1_IO); /* Take out the parity part */ gpio=(gpio & 0x7fd) + (auxgpio & 0xef); - } else + break; + case CX88_BOARD_WINFAST_DTV1000: + gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); auxgpio = gpio; - + break; + default: + auxgpio = gpio; + } if (ir->polling) { if (ir->last_gpio == auxgpio) return; @@ -148,20 +154,16 @@ static void ir_timer(unsigned long data) static void cx88_ir_work(struct work_struct *work) { struct cx88_IR *ir = container_of(work, struct cx88_IR, work); - unsigned long timeout; cx88_ir_handle_key(ir); - timeout = jiffies + (ir->polling * HZ / 1000); - mod_timer(&ir->timer, timeout); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { + setup_timer(&ir->timer, ir_timer, (unsigned long)ir); INIT_WORK(&ir->work, cx88_ir_work); - init_timer(&ir->timer); - ir->timer.function = ir_timer; - ir->timer.data = (unsigned long)ir; schedule_work(&ir->work); } if (ir->sampling) { @@ -222,7 +224,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR1300: case CX88_BOARD_HAUPPAUGE_HVR3000: ir_codes = ir_codes_hauppauge_new; ir_type = IR_TYPE_RC5; @@ -236,6 +237,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->polling = 50; /* ms */ break; case CX88_BOARD_WINFAST2000XP_EXPERT: + case CX88_BOARD_WINFAST_DTV1000: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; @@ -328,7 +330,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) input_dev->id.vendor = pci->vendor; input_dev->id.product = pci->device; } - input_dev->cdev.dev = &pci->dev; + input_dev->dev.parent = &pci->dev; /* record handles to ourself */ ir->core = core; core->ir = ir; @@ -442,7 +444,6 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR1300: case CX88_BOARD_HAUPPAUGE_HVR3000: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 543b05ebc0e..317a2a3f9cc 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -336,7 +336,7 @@ static void cx8802_timeout(unsigned long data) { struct cx8802_dev *dev = (struct cx8802_dev*)data; - dprintk(0, "%s\n",__FUNCTION__); + dprintk(1, "%s\n",__FUNCTION__); if (debug) cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 259ea08e784..1cc2d286a1c 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -906,6 +906,7 @@ int cx88_audio_thread(void *data) u32 mode = 0; dprintk("cx88: tvaudio thread started\n"); + set_freezable(); for (;;) { msleep_interruptible(1000); if (kthread_should_stop()) diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 98fa35421bd..06b233a7b20 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1881,8 +1881,14 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, mutex_unlock(&core->lock); /* start tvaudio thread */ - if (core->tuner_type != TUNER_ABSENT) + if (core->tuner_type != TUNER_ABSENT) { core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); + if (IS_ERR(core->kthread)) { + err = PTR_ERR(core->kthread); + printk(KERN_ERR "Failed to create cx88 audio thread, err=%d\n", + err); + } + } return 0; fail_unreg: diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index 82bc3a28aa2..cd0877636a3 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -94,7 +94,7 @@ static int vp3054_bit_getsda(void *data) /* ----------------------------------------------------------------------- */ -static struct i2c_algo_bit_data vp3054_i2c_algo_template = { +static const struct i2c_algo_bit_data vp3054_i2c_algo_template = { .setsda = vp3054_bit_setsda, .setscl = vp3054_bit_setscl, .getsda = vp3054_bit_getsda, @@ -105,12 +105,6 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = { /* ----------------------------------------------------------------------- */ -static struct i2c_adapter vp3054_i2c_adap_template = { - .name = "cx2388x", - .owner = THIS_MODULE, - .id = I2C_HW_B_CX2388x, -}; - int vp3054_i2c_probe(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -125,8 +119,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) return -ENOMEM; vp3054_i2c = dev->card_priv; - memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template, - sizeof(vp3054_i2c->adap)); memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); @@ -135,6 +127,8 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) vp3054_i2c->adap.dev.parent = &dev->pci->dev; strlcpy(vp3054_i2c->adap.name, core->name, sizeof(vp3054_i2c->adap.name)); + vp3054_i2c->adap.owner = THIS_MODULE; + vp3054_i2c->adap.id = I2C_HW_B_CX2388x; vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h index 637a7d23223..be99c931dc3 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h @@ -30,5 +30,12 @@ struct vp3054_i2c_state { }; /* ----------------------------------------------------------------------- */ +#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) int vp3054_i2c_probe(struct cx8802_dev *dev); void vp3054_i2c_remove(struct cx8802_dev *dev); +#else +static inline int vp3054_i2c_probe(struct cx8802_dev *dev) +{ return 0; } +static inline void vp3054_i2c_remove(struct cx8802_dev *dev) +{ } +#endif diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 738d4f20c58..809126866a3 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -209,6 +209,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_NORWOOD_MICRO 54 #define CX88_BOARD_TE_DTV_250_OEM_SWANN 55 #define CX88_BOARD_HAUPPAUGE_HVR1300 56 +#define CX88_BOARD_ADSTECH_PTV_390 57 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -258,7 +259,7 @@ struct cx88_subid { #define RESOURCE_VIDEO 2 #define RESOURCE_VBI 4 -#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ /* buffer for one video frame */ struct cx88_buffer { @@ -316,8 +317,6 @@ struct cx88_core { /* config info -- dvb */ #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) - struct dvb_pll_desc *pll_desc; - unsigned int pll_addr; int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); #endif @@ -463,13 +462,10 @@ struct cx8802_dev { u32 mailbox; int width; int height; - int fw_size; #if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) /* for dvb only */ struct videobuf_dvb dvb; - void* fe_handle; - int (*fe_release)(void *handle); void *card_priv; #endif diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index 664676f4406..dcc1a033544 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on VIDEO_V4L1 + depends on VIDEO_V4L2 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index 262f98e1240..02c741d8f85 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/stddef.h> #include <linux/string.h> +#include <linux/kref.h> #include "et61x251_sensor.h" @@ -134,7 +135,7 @@ struct et61x251_module_param { }; static DEFINE_MUTEX(et61x251_sysfs_lock); -static DECLARE_RWSEM(et61x251_disconnect); +static DECLARE_RWSEM(et61x251_dev_lock); struct et61x251_device { struct video_device* v4ldev; @@ -158,12 +159,14 @@ struct et61x251_device { struct et61x251_sysfs_attr sysfs; struct et61x251_module_param module_param; + struct kref kref; enum et61x251_dev_state state; u8 users; - struct mutex dev_mutex, fileop_mutex; + struct completion probe; + struct mutex open_mutex, fileop_mutex; spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; + wait_queue_head_t wait_open, wait_frame, wait_stream; }; /*****************************************************************************/ @@ -177,7 +180,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) void et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor) + const struct et61x251_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); } @@ -195,8 +198,8 @@ do { \ else if ((level) == 2) \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ + __FILE__, __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -205,8 +208,8 @@ do { \ if ((level) == 1 || (level) == 2) \ pr_info("et61x251: " fmt "\n", ## args); \ else if ((level) == 3) \ - pr_debug("et61x251: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -222,8 +225,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ + __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index a6525513cd1..585bd1fe076 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -45,11 +45,11 @@ #define ET61X251_MODULE_NAME "V4L2 driver for ET61X[12]51 " \ "PC Camera Controllers" -#define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ET61X251_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define ET61X251_MODULE_LICENSE "GPL" -#define ET61X251_MODULE_VERSION "1:1.04" -#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4) +#define ET61X251_MODULE_VERSION "1:1.09" +#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 9) /*****************************************************************************/ @@ -245,7 +245,8 @@ int et61x251_read_reg(struct et61x251_device* cam, u16 index) static int -et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) +et61x251_i2c_wait(struct et61x251_device* cam, + const struct et61x251_sensor* sensor) { int i, r; @@ -270,7 +271,7 @@ et61x251_i2c_wait(struct et61x251_device* cam, struct et61x251_sensor* sensor) int et61x251_i2c_try_read(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address) + const struct et61x251_sensor* sensor, u8 address) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -303,7 +304,8 @@ et61x251_i2c_try_read(struct et61x251_device* cam, int et61x251_i2c_try_write(struct et61x251_device* cam, - struct et61x251_sensor* sensor, u8 address, u8 value) + const struct et61x251_sensor* sensor, u8 address, + u8 value) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; @@ -615,7 +617,7 @@ static int et61x251_start_transfer(struct et61x251_device* cam) return 0; free_urbs: - for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) + for (i = 0; (i < ET61X251_URBS) && cam->urb[i]; i++) usb_free_urb(cam->urb[i]); free_buffers: @@ -682,7 +684,7 @@ static u8 et61x251_strtou8(const char* buff, size_t len, ssize_t* count) if (len < 4) { strncpy(str, buff, len); - str[len+1] = '\0'; + str[len] = '\0'; } else { strncpy(str, buff, 4); str[4] = '\0'; @@ -977,30 +979,30 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, static int et61x251_create_sysfs(struct et61x251_device* cam) { - struct video_device *v4ldev = cam->v4ldev; + struct class_device *classdev = &(cam->v4ldev->class_dev); int err = 0; - if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) + if ((err = class_device_create_file(classdev, &class_device_attr_reg))) goto err_out; - if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) + if ((err = class_device_create_file(classdev, &class_device_attr_val))) goto err_reg; if (cam->sensor.sysfs_ops) { - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_i2c_reg))) goto err_val; - if ((err = video_device_create_file(v4ldev, + if ((err = class_device_create_file(classdev, &class_device_attr_i2c_val))) goto err_i2c_reg; } err_i2c_reg: if (cam->sensor.sysfs_ops) - video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); + class_device_remove_file(classdev, &class_device_attr_i2c_reg); err_val: - video_device_remove_file(v4ldev, &class_device_attr_val); + class_device_remove_file(classdev, &class_device_attr_val); err_reg: - video_device_remove_file(v4ldev, &class_device_attr_reg); + class_device_remove_file(classdev, &class_device_attr_reg); err_out: return err; } @@ -1103,7 +1105,8 @@ static int et61x251_init(struct et61x251_device* cam) int err = 0; if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); + mutex_init(&cam->open_mutex); + init_waitqueue_head(&cam->wait_open); qctrl = s->qctrl; rect = &(s->cropcap.defrect); cam->compression.quality = ET61X251_COMPRESSION_QUALITY; @@ -1177,64 +1180,80 @@ static int et61x251_init(struct et61x251_device* cam) return 0; } +/*****************************************************************************/ -static void et61x251_release_resources(struct et61x251_device* cam) +static void et61x251_release_resources(struct kref *kref) { + struct et61x251_device *cam; + mutex_lock(&et61x251_sysfs_lock); + cam = container_of(kref, struct et61x251_device, kref); + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + usb_put_dev(cam->usbdev); + kfree(cam->control_buffer); + kfree(cam); mutex_unlock(&et61x251_sysfs_lock); - - kfree(cam->control_buffer); } -/*****************************************************************************/ static int et61x251_open(struct inode* inode, struct file* filp) { struct et61x251_device* cam; int err = 0; - /* - This is the only safe way to prevent race conditions with - disconnect - */ - if (!down_read_trylock(&et61x251_disconnect)) + if (!down_read_trylock(&et61x251_dev_lock)) return -ERESTARTSYS; cam = video_get_drvdata(video_devdata(filp)); - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&et61x251_disconnect); + if (wait_for_completion_interruptible(&cam->probe)) { + up_read(&et61x251_dev_lock); return -ERESTARTSYS; } + kref_get(&cam->kref); + + if (mutex_lock_interruptible(&cam->open_mutex)) { + kref_put(&cam->kref, et61x251_release_resources); + up_read(&et61x251_dev_lock); + return -ERESTARTSYS; + } + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + err = -ENODEV; + goto out; + } + if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + DBG(2, "Device /dev/video%d is already in use", + cam->v4ldev->minor); + DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { err = -EWOULDBLOCK; goto out; } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED + DBG(2, "A blocking open() has been requested. Wait for the " + "device to be released..."); + up_read(&et61x251_dev_lock); + err = wait_event_interruptible_exclusive(cam->wait_open, + (cam->state & DEV_DISCONNECTED) || !cam->users); - if (err) { - up_read(&et61x251_disconnect); - return err; - } + down_read(&et61x251_dev_lock); + if (err) + goto out; if (cam->state & DEV_DISCONNECTED) { - up_read(&et61x251_disconnect); - return -ENODEV; + err = -ENODEV; + goto out; } - mutex_lock(&cam->dev_mutex); } - if (cam->state & DEV_MISCONFIGURED) { err = et61x251_init(cam); if (err) { @@ -1259,36 +1278,32 @@ static int et61x251_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - mutex_unlock(&cam->dev_mutex); - up_read(&et61x251_disconnect); + mutex_unlock(&cam->open_mutex); + if (err) + kref_put(&cam->kref, et61x251_release_resources); + up_read(&et61x251_dev_lock); return err; } static int et61x251_release(struct inode* inode, struct file* filp) { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); + struct et61x251_device* cam; - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + down_write(&et61x251_dev_lock); - et61x251_stop_transfer(cam); + cam = video_get_drvdata(video_devdata(filp)); + et61x251_stop_transfer(cam); et61x251_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - et61x251_release_resources(cam); - usb_put_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); + wake_up_interruptible_nr(&cam->wait_open, 1); DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - mutex_unlock(&cam->dev_mutex); + kref_put(&cam->kref, et61x251_release_resources); + + up_write(&et61x251_dev_lock); return 0; } @@ -1324,7 +1339,7 @@ et61x251_read(struct file* filp, char __user * buf, DBG(3, "Close and open the device again to choose the read " "method"); mutex_unlock(&cam->fileop_mutex); - return -EINVAL; + return -EBUSY; } if (cam->io == IO_NONE) { @@ -1504,7 +1519,12 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) return -EIO; } - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { + mutex_unlock(&cam->fileop_mutex); + return -EACCES; + } + + if (cam->io != IO_MMAP || size != PAGE_ALIGN(cam->frame[0].buf.length)) { mutex_unlock(&cam->fileop_mutex); return -EINVAL; @@ -1535,7 +1555,6 @@ static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) vma->vm_ops = &et61x251_vm_ops; vma->vm_private_data = &cam->frame[i]; - et61x251_vm_open(vma); mutex_unlock(&cam->fileop_mutex); @@ -1764,7 +1783,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_CROP failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } /* Preserve R,G or B origin */ @@ -1921,6 +1940,8 @@ et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_ET61X251) ? + 0 : V4L2_COLORSPACE_SRGB; pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_ET61X251) ? 0 : (pfmt->width * pfmt->priv) / 8; pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); @@ -1996,6 +2017,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, pix->pixelformat != V4L2_PIX_FMT_SBGGR8) pix->pixelformat = pfmt->pixelformat; pix->priv = pfmt->priv; /* bpp */ + pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) ? + 0 : V4L2_COLORSPACE_SRGB; pix->colorspace = pfmt->colorspace; pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_ET61X251) ? 0 : (pix->width * pix->priv) / 8; @@ -2013,7 +2036,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_FMT failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2129,14 +2152,14 @@ et61x251_vidioc_reqbufs(struct et61x251_device* cam, void __user * arg) if (cam->io == IO_READ) { DBG(3, "Close and open the device again to choose the mmap " "I/O method"); - return -EINVAL; + return -EBUSY; } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_REQBUFS failed. " "Previous buffers are still mapped."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -2284,9 +2307,6 @@ et61x251_vidioc_streamon(struct et61x251_device* cam, void __user * arg) if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (list_empty(&cam->inqueue)) - return -EINVAL; - cam->stream = STREAM_ON; DBG(3, "Stream on"); @@ -2535,8 +2555,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - mutex_init(&cam->dev_mutex); - DBG(2, "ET61X[12]51 PC Camera Controller detected " "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); @@ -2568,7 +2586,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - mutex_lock(&cam->dev_mutex); + init_completion(&cam->probe); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -2578,7 +2596,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); goto fail; } @@ -2599,11 +2617,15 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) "device controlling. Error #%d", err); #else DBG(2, "Optional device control through 'sysfs' interface disabled"); + DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' " + "configuration option to enable it."); #endif usb_set_intfdata(intf, cam); + kref_init(&cam->kref); + usb_get_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); return 0; @@ -2620,40 +2642,31 @@ fail: static void et61x251_usb_disconnect(struct usb_interface* intf) { - struct et61x251_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; + struct et61x251_device* cam; - down_write(&et61x251_disconnect); + down_write(&et61x251_dev_lock); - mutex_lock(&cam->dev_mutex); + cam = usb_get_intfdata(intf); DBG(2, "Disconnecting %s...", cam->v4ldev->name); - wake_up_interruptible_all(&cam->open); - if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", + "memory deallocation are deferred.", cam->v4ldev->minor); cam->state |= DEV_MISCONFIGURED; et61x251_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { + } else cam->state |= DEV_DISCONNECTED; - et61x251_release_resources(cam); - } - mutex_unlock(&cam->dev_mutex); + wake_up_interruptible_all(&cam->wait_open); - if (!cam->users) - kfree(cam); + kref_put(&cam->kref, et61x251_release_resources); - up_write(&et61x251_disconnect); + up_write(&et61x251_dev_lock); } diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h index 5fadb5de68b..e1458633062 100644 --- a/drivers/media/video/et61x251/et61x251_sensor.h +++ b/drivers/media/video/et61x251/et61x251_sensor.h @@ -22,7 +22,7 @@ #define _ET61X251_SENSOR_H_ #include <linux/usb.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <linux/device.h> #include <linux/stddef.h> #include <linux/errno.h> @@ -47,7 +47,7 @@ et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); extern void et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor); + const struct et61x251_sensor* sensor); /*****************************************************************************/ @@ -56,10 +56,10 @@ extern int et61x251_read_reg(struct et61x251_device*, u16 index); extern int et61x251_i2c_write(struct et61x251_device*, u8 address, u8 value); extern int et61x251_i2c_read(struct et61x251_device*, u8 address); extern int et61x251_i2c_try_write(struct et61x251_device*, - struct et61x251_sensor*, u8 address, + const struct et61x251_sensor*, u8 address, u8 value); extern int et61x251_i2c_try_read(struct et61x251_device*, - struct et61x251_sensor*, u8 address); + const struct et61x251_sensor*, u8 address); extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5, u8 data6, u8 data7, u8 data8, u8 address); diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c index b0664340984..04b7fbb310a 100644 --- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c @@ -69,7 +69,7 @@ static int tas5130d1b_set_ctrl(struct et61x251_device* cam, } -static struct et61x251_sensor tas5130d1b = { +static const struct et61x251_sensor tas5130d1b = { .name = "TAS5130D1B", .interface = ET61X251_I2C_3WIRES, .rsta = ET61X251_I2C_RSTA_STOP, diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index ed92b6f7187..2d709e06467 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -37,6 +37,7 @@ #include <linux/errno.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/workqueue.h> #include <asm/semaphore.h> @@ -60,21 +61,22 @@ MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults /* ----------------------------------------------------------------------- */ -static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, + int size, int offset) { - unsigned char buf[3]; + unsigned char buf[6]; int start, range, toggle, dev, code; /* poll IR chip */ - if (3 != i2c_master_recv(&ir->c,buf,3)) + if (size != i2c_master_recv(&ir->c,buf,size)) return -EIO; /* split rc5 data block ... */ - start = (buf[0] >> 7) & 1; - range = (buf[0] >> 6) & 1; - toggle = (buf[0] >> 5) & 1; - dev = buf[0] & 0x1f; - code = (buf[1] >> 2) & 0x3f; + start = (buf[offset] >> 7) & 1; + range = (buf[offset] >> 6) & 1; + toggle = (buf[offset] >> 5) & 1; + dev = buf[offset] & 0x1f; + code = (buf[offset+1] >> 2) & 0x3f; /* rc5 has two start bits * the first bit must be one @@ -96,6 +98,16 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } +static inline int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + return get_key_haup_common (ir, ir_key, ir_raw, 3, 0); +} + +static inline int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + return get_key_haup_common (ir, ir_key, ir_raw, 6, 3); +} + static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -270,8 +282,9 @@ static void ir_timer(unsigned long data) static void ir_work(struct work_struct *work) { struct IR_i2c *ir = container_of(work, struct IR_i2c, work); + ir_key_poll(ir); - mod_timer(&ir->timer, jiffies+HZ/10); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); } /* ----------------------------------------------------------------------- */ @@ -354,9 +367,21 @@ static int ir_attach(struct i2c_adapter *adap, int addr, case 0x7a: case 0x47: case 0x71: - /* Handled by saa7134-input */ - name = "SAA713x remote"; - ir_type = IR_TYPE_OTHER; + if (adap->id == I2C_HW_B_CX2388x) { + /* Handled by cx88-input */ + name = "CX2388x remote"; + ir_type = IR_TYPE_RC5; + ir->get_key = get_key_haup_xvr; + if (hauppauge == 1) { + ir_codes = ir_codes_hauppauge_new; + } else { + ir_codes = ir_codes_rc5_tv; + } + } else { + /* Handled by saa7134-input */ + name = "SAA713x remote"; + ir_type = IR_TYPE_OTHER; + } break; default: /* shouldn't happen */ @@ -450,6 +475,7 @@ static int ir_probe(struct i2c_adapter *adap) static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1}; static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 }; static const int probe_em28XX[] = { 0x30, 0x47, -1 }; + static const int probe_cx88[] = { 0x18, 0x71, -1 }; const int *probe = NULL; struct i2c_client c; unsigned char buf; @@ -468,6 +494,9 @@ static int ir_probe(struct i2c_adapter *adap) case I2C_HW_B_EM28XX: probe = probe_em28XX; break; + case I2C_HW_B_CX2388x: + probe = probe_cx88; + break; } if (NULL == probe) return 0; diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index 1aaeaa02f15..e43beb2c9cb 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,7 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL + select I2C_ALGOBIT select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM @@ -16,11 +17,11 @@ config VIDEO_IVTV select VIDEO_UPD64031A select VIDEO_UPD64083 ---help--- - This is a video4linux driver for Conexant cx23416 or cx23416 based + This is a video4linux driver for Conexant cx23416 or cx23415 based PCI personal video recorder devices. This is used in devices such as the Hauppauge PVR-150/250/350/500 - cards. + cards. There is a driver homepage at <http://www.ivtvdriver.org>. To compile this driver as a module, choose M here: the module will be called ivtv. diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index efc66355339..d73d433a4ff 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -56,7 +56,6 @@ #include "ivtv-gpio.h" #include "ivtv-yuv.h" -#include <linux/vermagic.h> #include <media/tveeprom.h> #include <media/v4l2-chip-ident.h> @@ -181,7 +180,7 @@ MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC"); MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K"); MODULE_PARM_DESC(debug, "Debug level (bitmask). Default: errors only\n" - "\t\t\t(debug = 511 gives full debugging)"); + "\t\t\t(debug = 1023 gives full debugging)"); MODULE_PARM_DESC(ivtv_pci_latency, "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" "\t\t\tDefault: Yes"); @@ -276,9 +275,10 @@ int ivtv_waitq(wait_queue_head_t *waitq) } /* Generic utility functions */ -int ivtv_sleep_timeout(int timeout, int intr) +int ivtv_msleep_timeout(unsigned int msecs, int intr) { int ret; + int timeout = msecs_to_jiffies(msecs); do { set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); @@ -339,6 +339,7 @@ static void ivtv_process_eeprom(struct ivtv *itv) /* In a few cases the PCI subsystem IDs do not correctly identify the card. A better method is to check the model number from the eeprom instead. */ + case 30012 ... 30039: /* Low profile PVR250 */ case 32000 ... 32999: case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ case 48400 ... 48599: @@ -426,7 +427,7 @@ static void ivtv_process_eeprom(struct ivtv *itv) if (itv->options.newi2c == -1 && tv.has_ir != -1 && tv.has_ir != 2) { itv->options.newi2c = (tv.has_ir & 2) ? 1 : 0; if (itv->options.newi2c) { - IVTV_INFO("reopen i2c bus for IR-blaster support\n"); + IVTV_INFO("Reopen i2c bus for IR-blaster support\n"); exit_ivtv_i2c(itv); init_ivtv_i2c(itv); } @@ -622,6 +623,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ + mutex_init(&itv->serialize_lock); mutex_init(&itv->i2c_bus_lock); mutex_init(&itv->udma.lock); @@ -949,7 +951,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, /* Make sure we've got a place for this card */ if (ivtv_cards_active == IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtv: Maximum number of cards detected (%d).\n", + printk(KERN_ERR "ivtv: Maximum number of cards detected (%d)\n", ivtv_cards_active); spin_unlock(&ivtv_cards_lock); return -ENOMEM; @@ -964,9 +966,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, itv->dev = dev; itv->num = ivtv_cards_active++; snprintf(itv->name, sizeof(itv->name) - 1, "ivtv%d", itv->num); - if (itv->num) { - printk(KERN_INFO "ivtv: ====================== NEXT CARD ======================\n"); - } + IVTV_INFO("Initializing card #%d\n", itv->num); spin_unlock(&ivtv_cards_lock); @@ -1213,7 +1213,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, if (itv->has_cx23415) ivtv_set_osd_alpha(itv); - IVTV_INFO("Initialized %s, card #%d\n", itv->card_name, itv->num); + IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); return 0; @@ -1246,15 +1246,15 @@ static void ivtv_remove(struct pci_dev *pci_dev) { struct ivtv *itv = pci_get_drvdata(pci_dev); - IVTV_DEBUG_INFO("Removing Card #%d.\n", itv->num); + IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num); /* Stop all captures */ - IVTV_DEBUG_INFO(" Stopping all streams.\n"); + IVTV_DEBUG_INFO("Stopping all streams\n"); if (atomic_read(&itv->capturing) > 0) ivtv_stop_all_captures(itv); /* Stop all decoding */ - IVTV_DEBUG_INFO(" Stopping decoding.\n"); + IVTV_DEBUG_INFO("Stopping decoding\n"); if (atomic_read(&itv->decoding) > 0) { int type; @@ -1267,33 +1267,30 @@ static void ivtv_remove(struct pci_dev *pci_dev) } /* Interrupts */ - IVTV_DEBUG_INFO(" Disabling interrupts.\n"); + IVTV_DEBUG_INFO("Disabling interrupts\n"); ivtv_set_irq_mask(itv, 0xffffffff); del_timer_sync(&itv->dma_timer); /* Stop all Work Queues */ - IVTV_DEBUG_INFO(" Stop Work Queues.\n"); + IVTV_DEBUG_INFO("Stop Work Queues\n"); flush_workqueue(itv->irq_work_queues); destroy_workqueue(itv->irq_work_queues); - IVTV_DEBUG_INFO(" Stopping Firmware.\n"); + IVTV_DEBUG_INFO("Stopping Firmware\n"); ivtv_halt_firmware(itv); - IVTV_DEBUG_INFO(" Unregistering v4l devices.\n"); + IVTV_DEBUG_INFO("Unregistering v4l devices\n"); ivtv_streams_cleanup(itv); - IVTV_DEBUG_INFO(" Freeing dma resources.\n"); + IVTV_DEBUG_INFO("Freeing dma resources\n"); ivtv_udma_free(itv); exit_ivtv_i2c(itv); - IVTV_DEBUG_INFO(" Releasing irq.\n"); + IVTV_DEBUG_INFO(" Releasing irq\n"); free_irq(itv->dev->irq, (void *)itv); + ivtv_iounmap(itv); - if (itv->dev) { - ivtv_iounmap(itv); - } - - IVTV_DEBUG_INFO(" Releasing mem.\n"); + IVTV_DEBUG_INFO(" Releasing mem\n"); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); if (itv->has_cx23415) @@ -1314,28 +1311,27 @@ static struct pci_driver ivtv_pci_driver = { static int module_start(void) { - printk(KERN_INFO "ivtv: ==================== START INIT IVTV ====================\n"); - printk(KERN_INFO "ivtv: version %s (" VERMAGIC_STRING ") loading\n", IVTV_VERSION); + printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION); memset(ivtv_cards, 0, sizeof(ivtv_cards)); /* Validate parameters */ if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtv: ivtv_first_minor must be between 0 and %d. Exiting...\n", + printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n", IVTV_MAX_CARDS - 1); return -1; } - if (ivtv_debug < 0 || ivtv_debug > 511) { + if (ivtv_debug < 0 || ivtv_debug > 1023) { ivtv_debug = 0; - printk(KERN_INFO "ivtv: debug value must be >= 0 and <= 511!\n"); + printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 1023\n"); } if (pci_register_driver(&ivtv_pci_driver)) { printk(KERN_ERR "ivtv: Error detecting PCI card\n"); return -ENODEV; } - printk(KERN_INFO "ivtv: ==================== END INIT IVTV ====================\n"); + printk(KERN_INFO "ivtv: End initialization\n"); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index e6e56f175f3..91b588d261a 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -268,6 +268,8 @@ extern const u32 yuv_offset[4]; #define IVTV_DBGFLG_IRQ (1 << 6) #define IVTV_DBGFLG_DEC (1 << 7) #define IVTV_DBGFLG_YUV (1 << 8) +/* Flag to turn on high volume debugging */ +#define IVTV_DBGFLG_HIGHVOL (1 << 9) /* NOTE: extra space before comma in 'itv->num , ## args' is required for gcc-2.95, otherwise it won't compile. */ @@ -286,6 +288,21 @@ extern const u32 yuv_offset[4]; #define IVTV_DEBUG_DEC(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) #define IVTV_DEBUG_YUV(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) +#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ + do { \ + if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ + printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ + } while (0) +#define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warning", fmt , ## args) +#define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info",fmt , ## args) +#define IVTV_DEBUG_HI_API(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_API, "api", fmt , ## args) +#define IVTV_DEBUG_HI_DMA(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA, "dma", fmt , ## args) +#define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) +#define IVTV_DEBUG_HI_I2C(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) +#define IVTV_DEBUG_HI_IRQ(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) +#define IVTV_DEBUG_HI_DEC(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC, "dec", fmt , ## args) +#define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) + #define IVTV_FB_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & ivtv_debug) \ @@ -650,7 +667,6 @@ struct vbi_info { /* convenience pointer to sliced struct in vbi_in union */ struct v4l2_sliced_vbi_format *sliced_in; u32 service_set_in; - u32 service_set_out; int insert_mpeg; /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. @@ -723,6 +739,7 @@ struct ivtv { int search_pack_header; spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ + struct mutex serialize_lock; /* lock used to serialize starting streams */ /* User based DMA for OSD */ struct ivtv_user_dma udma; @@ -831,7 +848,7 @@ int ivtv_set_output_mode(struct ivtv *itv, int mode); struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv); /* Return non-zero if a signal is pending */ -int ivtv_sleep_timeout(int timeout, int intr); +int ivtv_msleep_timeout(unsigned int msecs, int intr); /* Wait on queue, returns -EINTR if interrupted */ int ivtv_waitq(wait_queue_head_t *waitq); diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 555d5e6369c..8e97a938398 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -218,7 +218,7 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, /* Process pending program info updates and pending VBI data */ ivtv_update_pgm_info(itv); - if (jiffies - itv->dualwatch_jiffies > HZ) { + if (jiffies - itv->dualwatch_jiffies > msecs_to_jiffies(1000)) { itv->dualwatch_jiffies = jiffies; ivtv_dualwatch(itv); } @@ -406,7 +406,7 @@ static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t co ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; struct ivtv *itv = s->itv; - IVTV_DEBUG_INFO("read %zd from %s, got %zd\n", count, s->name, rc); + IVTV_DEBUG_HI_INFO("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) pos += rc; return rc; @@ -497,7 +497,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_ struct ivtv_stream *s = &itv->streams[id->type]; int rc; - IVTV_DEBUG_IOCTL("read %zd bytes from %s\n", count, s->name); + IVTV_DEBUG_HI_IOCTL("read %zd bytes from %s\n", count, s->name); rc = ivtv_start_capture(id); if (rc) @@ -535,7 +535,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int rc; DEFINE_WAIT(wait); - IVTV_DEBUG_IOCTL("write %zd bytes to %s\n", count, s->name); + IVTV_DEBUG_HI_IOCTL("write %zd bytes to %s\n", count, s->name); if (s->type != IVTV_DEC_STREAM_TYPE_MPG && s->type != IVTV_DEC_STREAM_TYPE_YUV && @@ -643,7 +643,7 @@ retry: to transfer the rest. */ if (count && !(filp->f_flags & O_NONBLOCK)) goto retry; - IVTV_DEBUG_INFO("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); + IVTV_DEBUG_HI_INFO("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); return bytes_written; } @@ -832,7 +832,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) if (itv == NULL) { /* Couldn't find a device registered on that minor, shouldn't happen! */ - printk(KERN_WARNING "ivtv: no ivtv device found on minor %d\n", minor); + printk(KERN_WARNING "ivtv: No ivtv device found on minor %d\n", minor); return -ENXIO; } @@ -924,7 +924,7 @@ void ivtv_unmute(struct ivtv *itv) if (atomic_read(&itv->capturing) == 0) ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); - ivtv_sleep_timeout(HZ / 10, 0); + ivtv_msleep_timeout(100, 0); if (atomic_read(&itv->capturing)) { ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index d4c910b782a..d0feabf9308 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -36,7 +36,7 @@ #define IVTV_CMD_SPU_STOP 0x00000001 #define IVTV_CMD_SDRAM_PRECHARGE_INIT 0x0000001A #define IVTV_CMD_SDRAM_REFRESH_INIT 0x80000640 -#define IVTV_SDRAM_SLEEPTIME (60 * HZ / 100) /* 600 ms */ +#define IVTV_SDRAM_SLEEPTIME 600 #define IVTV_DECODE_INIT_MPEG_FILENAME "v4l-cx2341x-init.mpg" #define IVTV_DECODE_INIT_MPEG_SIZE (152*1024) @@ -56,14 +56,12 @@ retry: volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; const u32 *src = (const u32 *)fw->data; - /* temporarily allow 256 KB encoding firmwares as well for - compatibility with blackbird cards */ - if (fw->size != size && fw->size != 256 * 1024) { + if (fw->size != size) { /* Due to race conditions in firmware loading (esp. with udev <0.95) the wrong file was sometimes loaded. So we check filesizes to see if at least the right-sized file was loaded. If not, then we retry. */ - IVTV_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); + IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); release_firmware(fw); retries--; goto retry; @@ -75,11 +73,11 @@ retry: src++; } release_firmware(fw); - IVTV_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size); + IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); return size; } - IVTV_ERR("unable to open firmware %s (must be %ld bytes)\n", fn, size); - IVTV_ERR("did you put the firmware in the hotplug firmware directory?\n"); + IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); + IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n"); return -ENOMEM; } @@ -91,7 +89,7 @@ void ivtv_halt_firmware(struct ivtv *itv) if (itv->enc_mbox.mbox) ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0); - ivtv_sleep_timeout(HZ / 100, 0); + ivtv_msleep_timeout(10, 0); itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL; IVTV_DEBUG_INFO("Stopping VDM\n"); @@ -115,7 +113,7 @@ void ivtv_halt_firmware(struct ivtv *itv) IVTV_DEBUG_INFO("Stopping SPU\n"); write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU); - ivtv_sleep_timeout(HZ / 100, 0); + ivtv_msleep_timeout(10, 0); IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n"); write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE); @@ -131,9 +129,8 @@ void ivtv_halt_firmware(struct ivtv *itv) write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH); } - IVTV_DEBUG_INFO("Sleeping for %dms (600 recommended)\n", - (int)(IVTV_SDRAM_SLEEPTIME * 1000 / HZ)); - ivtv_sleep_timeout(IVTV_SDRAM_SLEEPTIME, 0); + IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME); + ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0); } void ivtv_firmware_versions(struct ivtv *itv) @@ -206,12 +203,12 @@ int ivtv_firmware_init(struct ivtv *itv) /* start firmware */ write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU); - ivtv_sleep_timeout(HZ / 10, 0); + ivtv_msleep_timeout(100, 0); if (itv->has_cx23415) write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU); else write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU); - ivtv_sleep_timeout(HZ / 10, 0); + ivtv_msleep_timeout(100, 0); /* find mailboxes and ping firmware */ itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE); @@ -266,7 +263,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv) IVTV_DECODE_INIT_MPEG_FILENAME); } else { ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0); - ivtv_sleep_timeout(HZ / 10, 0); + ivtv_msleep_timeout(100, 0); } ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); } diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index bc8f8ca2961..6a5a7aa6697 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c @@ -115,8 +115,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) curout = (curout & ~0xF) | 1; write_reg(curout, IVTV_REG_GPIO_OUT); /* We could use something else for smaller time */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout_interruptible(msecs_to_jiffies(1)); curout |= 2; write_reg(curout, IVTV_REG_GPIO_OUT); curdir &= ~0x80; @@ -131,20 +130,18 @@ int ivtv_reset_tuner_gpio(enum v4l2_tuner_type mode, void *priv, int ptr) if (itv->card->type != IVTV_CARD_PG600V2 || itv->options.tuner != TUNER_XCEIVE_XC3028) return -EINVAL; - IVTV_INFO("Resetting tuner.\n"); + IVTV_INFO("Resetting tuner\n"); curout = read_reg(IVTV_REG_GPIO_OUT); curdir = read_reg(IVTV_REG_GPIO_DIR); curdir |= (1 << 12); /* GPIO bit 12 */ curout &= ~(1 << 12); write_reg(curout, IVTV_REG_GPIO_OUT); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout_interruptible(msecs_to_jiffies(1)); curout |= (1 << 12); write_reg(curout, IVTV_REG_GPIO_OUT); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout_interruptible(msecs_to_jiffies(1)); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 50624c6a62a..b3557435456 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -144,7 +144,7 @@ static int attach_inform(struct i2c_client *client) } } if (i == I2C_CLIENTS_MAX) { - IVTV_ERR("insufficient room for new I2C client!\n"); + IVTV_ERR("Insufficient room for new I2C client\n"); } return 0; } @@ -236,7 +236,7 @@ static int ivtv_ack(struct ivtv *itv) int ret = 0; if (ivtv_getscl(itv) == 1) { - IVTV_DEBUG_I2C("SCL was high starting an ack\n"); + IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n"); ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) { IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n"); @@ -263,7 +263,7 @@ static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte) { int i, bit; - IVTV_DEBUG_I2C("write %x\n",byte); + IVTV_DEBUG_HI_I2C("write %x\n",byte); for (i = 0; i < 8; ++i, byte<<=1) { ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) { @@ -318,7 +318,7 @@ static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack) ivtv_scldelay(itv); ivtv_setscl(itv, 0); ivtv_scldelay(itv); - IVTV_DEBUG_I2C("read %x\n",*byte); + IVTV_DEBUG_HI_I2C("read %x\n",*byte); return 0; } @@ -330,7 +330,7 @@ static int ivtv_start(struct ivtv *itv) sda = ivtv_getsda(itv); if (sda != 1) { - IVTV_DEBUG_I2C("SDA was low at start\n"); + IVTV_DEBUG_HI_I2C("SDA was low at start\n"); ivtv_setsda(itv, 1); if (!ivtv_waitsda(itv, 1)) { IVTV_DEBUG_I2C("SDA stuck low\n"); @@ -355,7 +355,7 @@ static int ivtv_stop(struct ivtv *itv) int i; if (ivtv_getscl(itv) != 0) { - IVTV_DEBUG_I2C("SCL not low when stopping\n"); + IVTV_DEBUG_HI_I2C("SCL not low when stopping\n"); ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) { IVTV_DEBUG_I2C("SCL could not be set low\n"); @@ -569,7 +569,7 @@ int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg } } if (cmd != VIDIOC_G_CHIP_IDENT) - IVTV_ERR("i2c addr 0x%02x not found for command 0x%x!\n", addr, cmd); + IVTV_ERR("i2c addr 0x%02x not found for command 0x%x\n", addr, cmd); return -ENODEV; } @@ -640,7 +640,7 @@ int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg) addr = ivtv_i2c_hw_addr(itv, hw); if (addr < 0) { - IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x!\n", + IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x\n", hw, ivtv_i2c_hw_name(hw), cmd); return addr; } @@ -655,7 +655,7 @@ int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg) addr = ivtv_i2c_id_addr(itv, id); if (addr < 0) { if (cmd != VIDIOC_G_CHIP_IDENT) - IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x!\n", + IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x\n", id, ivtv_i2c_id_name(id), cmd); return addr; } @@ -696,7 +696,7 @@ int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg) void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg) { if (itv->i2c_adap.algo == NULL) { - IVTV_ERR("adapter is not set"); + IVTV_ERR("Adapter is not set"); return; } i2c_clients_command(&itv->i2c_adap, cmd, arg); diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 57af1762de1..4773453e8da 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1159,7 +1159,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void memset(fb, 0, sizeof(*fb)); if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) - break; + return -EINVAL; fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_GLOBAL_ALPHA; fb->fmt.pixelformat = itv->osd_pixelformat; @@ -1179,7 +1179,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void struct v4l2_framebuffer *fb = arg; if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) - break; + return -EINVAL; itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index ba98bf054f2..fcd6e7f5f12 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -48,7 +48,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv) struct list_head *p; int i = 0; - IVTV_DEBUG_DMA("ivtv_pio_work_handler\n"); + IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || s->v4l2dev == NULL || !ivtv_use_pio(s)) { itv->cur_pio_stream = -1; @@ -56,7 +56,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv) write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); return; } - IVTV_DEBUG_DMA("Process PIO %s\n", s->name); + IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name); buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list); list_for_each(p, &s->q_dma.list) { struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); @@ -187,7 +187,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA bytes_needed += UVsize; } - IVTV_DEBUG_DMA("%s %s: 0x%08x bytes at 0x%08x\n", + IVTV_DEBUG_HI_DMA("%s %s: 0x%08x bytes at 0x%08x\n", ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset); rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed); @@ -242,7 +242,7 @@ static void dma_post(struct ivtv_stream *s) u32 *u32buf; int x = 0; - IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", + IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", s->name, s->dma_offset); list_for_each(p, &s->q_dma.list) { buf = list_entry(p, struct ivtv_buffer, list); @@ -321,7 +321,7 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) unsigned long flags = 0; int idx = 0; - IVTV_DEBUG_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); + IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); list_for_each(p, &s->q_predma.list) { struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list); @@ -368,7 +368,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; int i; - IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name); + IVTV_DEBUG_HI_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name); if (s->q_predma.bytesused) ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); @@ -397,12 +397,17 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) itv->vbi.dma_offset = s_vbi->dma_offset; s_vbi->SG_length = 0; set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); - IVTV_DEBUG_DMA("include DMA for %s\n", s->name); + IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name); } /* Mark last buffer size for Interrupt flag */ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); + if (s->type == IVTV_ENC_STREAM_TYPE_VBI) + set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + else + clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); + if (ivtv_use_pio(s)) { for (i = 0; i < s->SG_length; i++) { s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src); @@ -420,7 +425,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + HZ / 10; + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); add_timer(&itv->dma_timer); } } @@ -431,13 +436,13 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) if (s->q_predma.bytesused) ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - IVTV_DEBUG_DMA("start DMA for %s\n", s->name); + IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name); /* put SG Handle into register 0x0c */ write_reg(s->SG_handle, IVTV_REG_DECDMAADDR); write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); set_bit(IVTV_F_I_DMA, &itv->i_flags); itv->cur_dma_stream = s->type; - itv->dma_timer.expires = jiffies + HZ / 10; + itv->dma_timer.expires = jiffies + msecs_to_jiffies(100); add_timer(&itv->dma_timer); } @@ -447,7 +452,7 @@ static void ivtv_irq_dma_read(struct ivtv *itv) struct ivtv_buffer *buf; int hw_stream_type; - IVTV_DEBUG_IRQ("DEC DMA READ\n"); + IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); del_timer(&itv->dma_timer); if (read_reg(IVTV_REG_DMASTATUS) & 0x14) { IVTV_DEBUG_WARN("DEC DMA ERROR %x\n", read_reg(IVTV_REG_DMASTATUS)); @@ -462,7 +467,7 @@ static void ivtv_irq_dma_read(struct ivtv *itv) s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; hw_stream_type = 0; } - IVTV_DEBUG_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); + IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); ivtv_stream_sync_for_cpu(s); @@ -495,7 +500,7 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) del_timer(&itv->dma_timer); ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); - IVTV_DEBUG_IRQ("ENC DMA COMPLETE %x %d\n", data[0], data[1]); + IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d\n", data[0], data[1]); if (test_and_clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags)) data[1] = 3; else if (data[1] > 2) @@ -532,7 +537,7 @@ static void ivtv_irq_enc_pio_complete(struct ivtv *itv) return; } s = &itv->streams[itv->cur_pio_stream]; - IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name); + IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name); s->SG_length = 0; clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); clear_bit(IVTV_F_I_PIO, &itv->i_flags); @@ -590,14 +595,13 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) /* Get DMA destination and size arguments from card */ ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data); - IVTV_DEBUG_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); + IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); if (data[0] > 2 || data[1] == 0 || data[2] == 0) { IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n", data[0], data[1], data[2]); return; } - clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); s = &itv->streams[ivtv_stream_map[data[0]]]; if (!stream_enc_dma_append(s, data)) { set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); @@ -610,7 +614,7 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv_stream *s; - IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); + IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n"); s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; /* If more than two VBI buffers are pending, then @@ -634,7 +638,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) then start a DMA request for just the VBI data. */ if (!stream_enc_dma_append(s, data) && !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { - set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); } } @@ -644,7 +647,7 @@ static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv) u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; - IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); + IVTV_DEBUG_HI_IRQ("DEC VBI REINSERT\n"); if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && !stream_enc_dma_append(s, data)) { set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags); @@ -669,7 +672,7 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) itv->dma_data_req_offset = data[1]; s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; } - IVTV_DEBUG_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused, + IVTV_DEBUG_HI_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused, itv->dma_data_req_offset, itv->dma_data_req_size); if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) { set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); @@ -791,10 +794,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) /* Exclude interrupts noted below from the output, otherwise the log is flooded with these messages */ if (combo & ~0xff6d0400) - IVTV_DEBUG_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo); + IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo); if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) { - IVTV_DEBUG_IRQ("DEC DMA COMPLETE\n"); + IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n"); } if (combo & IVTV_IRQ_DMA_READ) { diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 6ae42a3b03c..814a673712b 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c @@ -37,6 +37,7 @@ #define API_RESULT (1 << 1) /* Allow 1 second for this cmd to end */ #define API_FAST_RESULT (3 << 1) /* Allow 0.1 second for this cmd to end */ #define API_DMA (1 << 3) /* DMA mailbox, has special handling */ +#define API_HIGH_VOL (1 << 5) /* High volume command (i.e. called during encoding or decoding) */ #define API_NO_WAIT_MB (1 << 4) /* Command may not wait for a free mailbox */ #define API_NO_WAIT_RES (1 << 5) /* Command may not wait for the result */ @@ -77,11 +78,11 @@ static const struct ivtv_api_info api_info[256] = { API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE, API_CACHE), API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10, API_FAST_RESULT), API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, API_DMA), + API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, API_DMA | API_HIGH_VOL), API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT, API_RESULT), API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE, API_CACHE), API_ENTRY(CX2341X_ENC_PAUSE_ENCODER, API_RESULT), - API_ENTRY(CX2341X_ENC_REFRESH_INPUT, API_NO_WAIT_MB), + API_ENTRY(CX2341X_ENC_REFRESH_INPUT, API_NO_WAIT_MB | API_HIGH_VOL), API_ENTRY(CX2341X_ENC_SET_COPYRIGHT, API_CACHE), API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION, API_RESULT), API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES, API_CACHE), @@ -102,7 +103,7 @@ static const struct ivtv_api_info api_info[256] = { API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE, API_CACHE), API_ENTRY(CX2341X_DEC_GET_XFER_INFO, API_FAST_RESULT), API_ENTRY(CX2341X_DEC_GET_DMA_STATUS, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, API_DMA), + API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, API_DMA | API_HIGH_VOL), API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK, API_RESULT), API_ENTRY(CX2341X_DEC_HALT_FW, API_FAST_RESULT), API_ENTRY(CX2341X_DEC_SET_STANDARD, API_CACHE), @@ -175,9 +176,9 @@ static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int f /* Sleep before a retry, if not atomic */ if (!(flags & API_NO_WAIT_MB)) { - if (jiffies - then > retries * HZ / 100) + if (jiffies - then > msecs_to_jiffies(10*retries)) break; - ivtv_sleep_timeout(HZ / 100, 0); + ivtv_msleep_timeout(10, 0); } } return -ENODEV; @@ -212,7 +213,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) { struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox; volatile struct ivtv_mailbox __iomem *mbox; - int api_timeout = HZ; + int api_timeout = msecs_to_jiffies(1000); int flags, mb, i; unsigned long then; @@ -227,7 +228,12 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) return -EINVAL; } - IVTV_DEBUG_API("API Call: %s\n", api_info[cmd].name); + if (api_info[cmd].flags & API_HIGH_VOL) { + IVTV_DEBUG_HI_API("API Call: %s\n", api_info[cmd].name); + } + else { + IVTV_DEBUG_API("API Call: %s\n", api_info[cmd].name); + } /* clear possibly uninitialized part of data array */ for (i = args; i < CX2341X_MBOX_MAX_DATA; i++) @@ -237,7 +243,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) data, then just return 0 as there is no need to issue this command again. Just an optimization to prevent unnecessary use of mailboxes. */ if (itv->api_cache[cmd].last_jiffies && - jiffies - itv->api_cache[cmd].last_jiffies < HZ * 1800 && + jiffies - itv->api_cache[cmd].last_jiffies < msecs_to_jiffies(1800000) && !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) { itv->api_cache[cmd].last_jiffies = jiffies; return 0; @@ -262,7 +268,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) } if ((flags & API_FAST_RESULT) == API_FAST_RESULT) - api_timeout = HZ / 10; + api_timeout = msecs_to_jiffies(100); mb = get_mailbox(itv, mbdata, flags); if (mb < 0) { @@ -295,11 +301,12 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) if (flags & API_NO_WAIT_RES) mdelay(1); else - ivtv_sleep_timeout(HZ / 100, 0); + ivtv_msleep_timeout(10, 0); } - if (jiffies - then > HZ / 10) - IVTV_DEBUG_WARN("%s took %lu jiffies (%d per HZ)\n", - api_info[cmd].name, jiffies - then, HZ); + if (jiffies - then > msecs_to_jiffies(100)) + IVTV_DEBUG_WARN("%s took %u jiffies\n", + api_info[cmd].name, + jiffies_to_msecs(jiffies - then)); for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) data[i] = readl(&mbox->data[i]); diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 6af88ae9295..322b347b67c 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -446,6 +446,9 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) if (s->v4l2dev == NULL) return -EINVAL; + /* Big serialization lock to ensure no two streams are started + simultaneously: that can give all sorts of weird results. */ + mutex_lock(&itv->serialize_lock); IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); switch (s->type) { @@ -487,6 +490,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) 0, sizeof(itv->vbi.sliced_mpeg_size)); break; default: + mutex_unlock(&itv->serialize_lock); return -EINVAL; } s->subtype = subtype; @@ -561,13 +565,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) /* Initialize Digitizer for Capture */ ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); - ivtv_sleep_timeout(HZ / 10, 0); + ivtv_msleep_timeout(100, 0); } /* begin_capture */ if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) { IVTV_DEBUG_WARN( "Error starting capture!\n"); + mutex_unlock(&itv->serialize_lock); return -EINVAL; } @@ -583,6 +588,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) /* you're live! sit back and await interrupts :) */ atomic_inc(&itv->capturing); + mutex_unlock(&itv->serialize_lock); return 0; } @@ -762,17 +768,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); - /* only run these if we're shutting down the last cap */ - if (atomic_read(&itv->capturing) - 1 == 0) { - /* event notification (off) */ - if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { - /* type: 0 = refresh */ - /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ - ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); - ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); - } - } - then = jiffies; if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { @@ -786,8 +781,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) set_current_state(TASK_INTERRUPTIBLE); /* wait 2s for EOS interrupt */ - while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) && jiffies < then + 2 * HZ) { - schedule_timeout(HZ / 100); + while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) && + jiffies < then + msecs_to_jiffies (2000)) { + schedule_timeout(msecs_to_jiffies(10)); } /* To convert jiffies to ms, we must multiply by 1000 @@ -812,7 +808,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) then = jiffies; /* Make sure DMA is complete */ add_wait_queue(&s->waitq, &wait); - set_current_state(TASK_INTERRUPTIBLE); do { /* check if DMA is pending */ if ((s->type == IVTV_ENC_STREAM_TYPE_MPG) && /* MPG Only */ @@ -827,9 +822,8 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) } else if (read_reg(IVTV_REG_DMASTATUS) & 0x02) { break; } - - ivtv_sleep_timeout(HZ / 100, 1); - } while (then + HZ * 2 > jiffies); + } while (!ivtv_msleep_timeout(10, 1) && + then + msecs_to_jiffies(2000) > jiffies); set_current_state(TASK_RUNNING); remove_wait_queue(&s->waitq, &wait); @@ -840,17 +834,30 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) /* Clear capture and no-read bits */ clear_bit(IVTV_F_S_STREAMING, &s->s_flags); + /* ensure these global cleanup actions are done only once */ + mutex_lock(&itv->serialize_lock); + if (s->type == IVTV_ENC_STREAM_TYPE_VBI) ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); if (atomic_read(&itv->capturing) > 0) { + mutex_unlock(&itv->serialize_lock); return 0; } /* Set the following Interrupt mask bits for capture */ ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); + /* event notification (off) */ + if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { + /* type: 0 = refresh */ + /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ + ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); + ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); + } + wake_up(&s->waitq); + mutex_unlock(&itv->serialize_lock); return 0; } @@ -887,7 +894,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) break; tmp = data[3]; } - if (ivtv_sleep_timeout(HZ/10, 1)) + if (ivtv_msleep_timeout(100, 1)) break; } } diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 3ba46e07ea1..a7282a91bd9 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -219,31 +219,23 @@ ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) int found_cc = 0; int cc_pos = itv->vbi.cc_pos; - if (itv->vbi.service_set_out == 0) - return -EPERM; - while (count >= sizeof(struct v4l2_sliced_vbi_data)) { switch (p->id) { case V4L2_SLICED_CAPTION_525: - if (p->id == V4L2_SLICED_CAPTION_525 && - p->line == 21 && - (itv->vbi.service_set_out & - V4L2_SLICED_CAPTION_525) == 0) { - break; - } - found_cc = 1; - if (p->field) { - cc[2] = p->data[0]; - cc[3] = p->data[1]; - } else { - cc[0] = p->data[0]; - cc[1] = p->data[1]; + if (p->line == 21) { + found_cc = 1; + if (p->field) { + cc[2] = p->data[0]; + cc[3] = p->data[1]; + } else { + cc[0] = p->data[0]; + cc[1] = p->data[1]; + } } break; case V4L2_SLICED_VPS: - if (p->line == 16 && p->field == 0 && - (itv->vbi.service_set_out & V4L2_SLICED_VPS)) { + if (p->line == 16 && p->field == 0) { itv->vbi.vps[0] = p->data[2]; itv->vbi.vps[1] = p->data[8]; itv->vbi.vps[2] = p->data[9]; @@ -255,8 +247,7 @@ ssize_t ivtv_write_vbi(struct ivtv *itv, const char __user *ubuf, size_t count) break; case V4L2_SLICED_WSS_625: - if (p->line == 23 && p->field == 0 && - (itv->vbi.service_set_out & V4L2_SLICED_WSS_625)) { + if (p->line == 23 && p->field == 0) { /* No lock needed for WSS */ itv->vbi.wss = p->data[0] | (p->data[1] << 8); itv->vbi.wss_found = 1; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 664aba8b4d8..7533fc20331 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1809,7 +1809,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, { int ret = -EBUSY; unsigned long mchip_adr; - u8 revision; if (meye.mchip_dev != NULL) { printk(KERN_ERR "meye: only one device allowed!\n"); @@ -1885,7 +1884,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outreqirq; } - pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision); pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8); pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64); @@ -1939,7 +1937,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n", MEYE_DRIVER_VERSION); printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n", - revision, mchip_adr, meye.mchip_irq); + meye.mchip_dev->revision, mchip_adr, meye.mchip_irq); return 0; diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 3bb7d663486..11cfcf18ec3 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -157,8 +157,7 @@ static int msp_read(struct i2c_client *client, int dev, int addr) break; v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err, dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(msecs_to_jiffies(10)); + schedule_timeout_interruptible(msecs_to_jiffies(10)); } if (err == 3) { v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n"); @@ -197,8 +196,7 @@ static int msp_write(struct i2c_client *client, int dev, int addr, int val) break; v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err, dev, addr); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(msecs_to_jiffies(10)); + schedule_timeout_interruptible(msecs_to_jiffies(10)); } if (err == 3) { v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n"); @@ -814,10 +812,9 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) int msp_product, msp_prod_hi, msp_prod_lo; int msp_rom; - client = kmalloc(sizeof(*client), GFP_KERNEL); + client = kzalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) return -ENOMEM; - memset(client, 0, sizeof(*client)); client->addr = address; client->adapter = adapter; client->driver = &i2c_driver; diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index e1821eb82fb..d5ee2629121 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/freezer.h> #include <linux/videodev.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> @@ -468,6 +469,7 @@ int msp3400c_thread(void *data) v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); + set_freezable(); for (;;) { v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); msp_sleep(state, -1); @@ -646,7 +648,7 @@ int msp3410d_thread(void *data) int val, i, std, count; v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); - + set_freezable(); for (;;) { v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); msp_sleep(state,-1); @@ -940,7 +942,7 @@ int msp34xxg_thread(void *data) int val, i; v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); - + set_freezable(); for (;;) { v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); msp_sleep(state, -1); diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index c7c9f3f8715..7549114aaac 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -7,7 +7,7 @@ #include <linux/i2c.h> #include <linux/videodev.h> #include <linux/moduleparam.h> -#include <media/tuner.h> +#include "tuner-driver.h" /* ---------------------------------------------------------------------- */ @@ -37,6 +37,19 @@ static char *microtune_part[] = { [ MT2050 ] = "MT2050", }; +struct microtune_priv { + unsigned int xogc; + unsigned int radio_if2; +}; + +static void microtune_release(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + + kfree(t->priv); + t->priv = NULL; +} + // IsSpurInBand()? static int mt2032_spurcheck(struct i2c_client *c, int f1, int f2, int spectrum_from,int spectrum_to) @@ -218,6 +231,7 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, unsigned char buf[21]; int lint_try,ret,sel,lock=0; struct tuner *t = i2c_get_clientdata(c); + struct microtune_priv *priv = t->priv; tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", rfin,if1,if2,from,to); @@ -227,7 +241,7 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, i2c_master_recv(c,buf,21); buf[0]=0; - ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); + ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc); if (ret<0) return; @@ -251,10 +265,10 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, tuner_dbg("mt2032: re-init PLLs by LINT\n"); buf[0]=7; - buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs + buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs i2c_master_send(c,buf,2); mdelay(10); - buf[1]=8+t->xogc; + buf[1]=8+priv->xogc; i2c_master_send(c,buf,2); } @@ -294,17 +308,25 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - int if2 = t->radio_if2; + struct microtune_priv *priv = t->priv; + int if2 = priv->radio_if2; // per Manual for FM tuning: first if center freq. 1085 MHz mt2032_set_if_freq(c, freq * 1000 / 16, 1085*1000*1000,if2,if2,if2); } +static struct tuner_operations mt2032_tuner_ops = { + .set_tv_freq = mt2032_set_tv_freq, + .set_radio_freq = mt2032_set_radio_freq, + .release = microtune_release, +}; + // Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001 static int mt2032_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + struct microtune_priv *priv = t->priv; unsigned char buf[21]; int ret,xogc,xok=0; @@ -351,23 +373,23 @@ static int mt2032_init(struct i2c_client *c) if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); } while (xok != 1 ); - t->xogc=xogc; + priv->xogc=xogc; + + memcpy(&t->ops, &mt2032_tuner_ops, sizeof(struct tuner_operations)); - t->set_tv_freq = mt2032_set_tv_freq; - t->set_radio_freq = mt2032_set_radio_freq; return(1); } static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) { struct tuner *t = i2c_get_clientdata(c); - unsigned char buf[2]; - int ret; + unsigned char buf[2]; + int ret; - buf[0] = 6; - buf[1] = antenna ? 0x11 : 0x10; - ret=i2c_master_send(c,buf,2); - tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); + buf[0] = 6; + buf[1] = antenna ? 0x11 : 0x10; + ret=i2c_master_send(c,buf,2); + tuner_dbg("mt2050: enabled antenna connector %d\n", antenna); } static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2) @@ -456,12 +478,19 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - int if2 = t->radio_if2; + struct microtune_priv *priv = t->priv; + int if2 = priv->radio_if2; mt2050_set_if_freq(c, freq * 1000 / 16, if2); mt2050_set_antenna(c, radio_antenna); } +static struct tuner_operations mt2050_tuner_ops = { + .set_tv_freq = mt2050_set_tv_freq, + .set_radio_freq = mt2050_set_radio_freq, + .release = microtune_release, +}; + static int mt2050_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); @@ -481,28 +510,35 @@ static int mt2050_init(struct i2c_client *c) i2c_master_recv(c,buf,1); tuner_dbg("mt2050: sro is %x\n",buf[0]); - t->set_tv_freq = mt2050_set_tv_freq; - t->set_radio_freq = mt2050_set_radio_freq; + + memcpy(&t->ops, &mt2050_tuner_ops, sizeof(struct tuner_operations)); + return 0; } int microtune_init(struct i2c_client *c) { + struct microtune_priv *priv = NULL; struct tuner *t = i2c_get_clientdata(c); char *name; unsigned char buf[21]; int company_code; + priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + t->priv = priv; + + priv->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ + memset(buf,0,sizeof(buf)); - t->set_tv_freq = NULL; - t->set_radio_freq = NULL; - t->standby = NULL; + if (t->std & V4L2_STD_525_60) { tuner_dbg("pinnacle ntsc\n"); - t->radio_if2 = 41300 * 1000; + priv->radio_if2 = 41300 * 1000; } else { tuner_dbg("pinnacle pal\n"); - t->radio_if2 = 33300 * 1000; + priv->radio_if2 = 33300 * 1000; } name = "unknown"; diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 3ceb8a6249d..f8f21ddd984 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -617,7 +617,7 @@ static struct ov7670_win_size { }, }; -#define N_WIN_SIZES (sizeof(ov7670_win_sizes)/sizeof(ov7670_win_sizes[0])) +#define N_WIN_SIZES (ARRAY_SIZE(ov7670_win_sizes)) /* @@ -1183,7 +1183,7 @@ static struct ov7670_control { .query = ov7670_q_hflip, }, }; -#define N_CONTROLS (sizeof(ov7670_controls)/sizeof(ov7670_controls[0])) +#define N_CONTROLS (ARRAY_SIZE(ov7670_controls)) static struct ov7670_control *ov7670_find_control(__u32 id) { diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 1455a8f4e93..4ab1af74a97 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -353,9 +353,8 @@ static int planb_prepare_open(struct planb *pb) * PLANB_DUMMY)*sizeof(struct dbdma_cmd) +(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8 +MAX_GBUFFERS*sizeof(unsigned int); - if ((pb->priv_space = kmalloc (size, GFP_KERNEL)) == 0) + if ((pb->priv_space = kzalloc (size, GFP_KERNEL)) == 0) return -ENOMEM; - memset ((void *) pb->priv_space, 0, size); pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *) DBDMA_ALIGN (pb->priv_space); pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 085332a503d..9c0e8d18c2f 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1099,7 +1099,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) return -EBUSY; } - down(&pdev->modlock); + mutex_lock(&pdev->modlock); if (!pdev->usb_init) { PWC_DEBUG_OPEN("Doing first time initialization.\n"); pdev->usb_init = 1; @@ -1131,7 +1131,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) if (i < 0) { PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n"); pwc_free_buffers(pdev); - up(&pdev->modlock); + mutex_unlock(&pdev->modlock); return i; } @@ -1172,7 +1172,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) if (i) { PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n"); pwc_free_buffers(pdev); - up(&pdev->modlock); + mutex_unlock(&pdev->modlock); return i; } @@ -1181,7 +1181,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i); pwc_isoc_cleanup(pdev); pwc_free_buffers(pdev); - up(&pdev->modlock); + mutex_unlock(&pdev->modlock); return i; } @@ -1191,7 +1191,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) pdev->vopen++; file->private_data = vdev; - up(&pdev->modlock); + mutex_unlock(&pdev->modlock); PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); return 0; } @@ -1685,7 +1685,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->angle_range.tilt_max = 2500; } - init_MUTEX(&pdev->modlock); + mutex_init(&pdev->modlock); spin_lock_init(&pdev->ptrlock); pdev->udev = udev; diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index acbb9312960..910a04f5392 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -31,7 +31,7 @@ #include <linux/wait.h> #include <linux/smp_lock.h> #include <linux/version.h> -#include <asm/semaphore.h> +#include <linux/mutex.h> #include <asm/errno.h> #include <linux/videodev.h> #include <media/v4l2-common.h> @@ -244,7 +244,7 @@ struct pwc_device int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */ - struct semaphore modlock; /* to prevent races in video_open(), etc */ + struct mutex modlock; /* to prevent races in video_open(), etc */ spinlock_t ptrlock; /* for manipulating the buffer pointers */ /*** motorized pan/tilt feature */ diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index f2a2f34cd62..17f1e2e9a66 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -86,9 +86,9 @@ static const int disp_modes[8][3] = -#define PAGE_WAIT (300*HZ/1000) /* Time between requesting page and */ +#define PAGE_WAIT msecs_to_jiffies(300) /* Time between requesting page and */ /* checking status bits */ -#define PGBUF_EXPIRE (15*HZ) /* Time to wait before retransmitting */ +#define PGBUF_EXPIRE msecs_to_jiffies(15000) /* Time to wait before retransmitting */ /* page regardless of infobits */ typedef struct { u8 pgbuf[VTX_VIRTUALSIZE]; /* Page-buffer */ @@ -115,8 +115,8 @@ struct saa5249_device #define CCTWR 34 /* I²C write/read-address of vtx-chip */ #define CCTRD 35 #define NOACK_REPEAT 10 /* Retry access this many times on failure */ -#define CLEAR_DELAY (HZ/20) /* Time required to clear a page */ -#define READY_TIMEOUT (30*HZ/1000) /* Time to wait for ready signal of I²C-bus interface */ +#define CLEAR_DELAY msecs_to_jiffies(50) /* Time required to clear a page */ +#define READY_TIMEOUT msecs_to_jiffies(30) /* Time to wait for ready signal of I2C-bus interface */ #define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */ #define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */ diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 676b9970eb2..061134a7ba9 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -208,7 +208,7 @@ determine_norm (struct i2c_client *client) saa7110_write_block(client, initseq, sizeof(initseq)); saa7110_selmux(client, decoder->input); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/4); + schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); status = saa7110_read(client); if (status & 0x40) { @@ -249,7 +249,7 @@ determine_norm (struct i2c_client *client) //saa7110_write(client,0x2E,0x9A); prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/4); + schedule_timeout(msecs_to_jiffies(250)); finish_wait(&decoder->wq, &wait); status = saa7110_read(client); diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index c1a392e4717..7ae2d646d00 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c @@ -37,23 +37,23 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_decoder.h> MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(s) (s)->name -#include <linux/video_decoder.h> static int debug = 0; module_param(debug, int, 0644); diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 87c3144ec7f..677df51de1a 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c @@ -35,28 +35,26 @@ #include <linux/fs.h> #include <linux/kernel.h> #include <linux/major.h> - #include <linux/slab.h> - #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_decoder.h> MODULE_DESCRIPTION("Philips SAA7114H video decoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(x) (x)->name -#include <linux/video_decoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 309dca368f4..9f1417a4f7d 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -40,7 +40,7 @@ config VIDEO_SAA7134_DVB depends on VIDEO_SAA7134 && DVB_CORE select VIDEO_BUF_DVB select FW_LOADER - select DVB_PLL + select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_NXT200X if !DVB_FE_CUSTOMISE diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index ffb0f647a86..3c0fc9027ad 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -75,7 +75,8 @@ typedef struct snd_card_saa7134 { struct saa7134_dev *dev; unsigned long iobase; - int irq; + s16 irq; + u16 mute_was_on; spinlock_t lock; } snd_card_saa7134_t; @@ -589,8 +590,10 @@ static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream) snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = saa7134->dev; - dev->ctl_mute = 1; - saa7134_tvaudio_setmute(dev); + if (saa7134->mute_was_on) { + dev->ctl_mute = 1; + saa7134_tvaudio_setmute(dev); + } return 0; } @@ -637,8 +640,11 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) runtime->private_free = snd_card_saa7134_runtime_free; runtime->hw = snd_card_saa7134_capture; - dev->ctl_mute = 0; - saa7134_tvaudio_setmute(dev); + if (dev->ctl_mute != 0) { + saa7134->mute_was_on = 1; + dev->ctl_mute = 0; + saa7134_tvaudio_setmute(dev); + } if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err; diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 50f15adfa7c..8ec83bd7009 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -400,7 +400,7 @@ struct saa7134_board saa7134_boards[] = { .inputs = {{ .name = name_tv, .vmux = 1, - .amux = LINE2, + .amux = TV, .tv = 1, .gpio = 0x20000, },{ @@ -3502,6 +3502,38 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, }, }, + [SAA7134_BOARD_10MOONSTVMASTER3] = { + /* Tony Wan <aloha_cn@hotmail.com> */ + .name = "10MOONS TM300 TV Card", + .audio_clock = 0x00200000, + .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0x7000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .gpio = 0x0000, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x2000, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x2000, + }}, + .mute = { + .name = name_mute, + .amux = LINE2, + .gpio = 0x3000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4219,6 +4251,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x2003, /* OEM cardbus */ .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = PCI_VENDOR_ID_PHILIPS, + .subdevice = 0x2304, + .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -4330,6 +4368,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_A16AR: case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: + case SAA7134_BOARD_10MOONSTVMASTER3: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index e0eec80088c..1f6bd330071 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -175,18 +175,6 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, return mt352_pinnacle_init(fe); } -static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) -{ - if (buf_len < 5) - return -EINVAL; - - pllbuf[0] = 0x61; - dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, - params->frequency, - params->u.ofdm.bandwidth); - return 5; -} - static struct mt352_config pinnacle_300i = { .demod_address = 0x3c >> 1, .adc_clock = 20333, @@ -444,135 +432,6 @@ static struct tda1004x_config philips_europa_config = { /* ------------------------------------------------------------------ */ -static int philips_fmd1216_tuner_init(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - /* this message is to set up ATC and ALC */ - static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) - return -EIO; - msleep(1); - - return 0; -} - -static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - /* this message actually turns the tuner back to analog mode */ - u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 }; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - msleep(1); - fmd1216_init[2] = 0x86; - fmd1216_init[3] = 0x54; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - msleep(1); - return 0; -} - -static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - struct saa7134_dev *dev = fe->dvb->priv; - struct tda1004x_state *state = fe->demodulator_priv; - u8 addr = state->config->tuner_address; - u8 tuner_buf[4]; - struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len = - sizeof(tuner_buf) }; - int tuner_frequency = 0; - int divider = 0; - u8 band, mode, cp; - - /* determine charge pump */ - tuner_frequency = params->frequency + 36130000; - if (tuner_frequency < 87000000) - return -EINVAL; - /* low band */ - else if (tuner_frequency < 180000000) { - band = 1; - mode = 7; - cp = 0; - } else if (tuner_frequency < 195000000) { - band = 1; - mode = 6; - cp = 1; - /* mid band */ - } else if (tuner_frequency < 366000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 10; - } else { - band = 2; - } - mode = 7; - cp = 0; - } else if (tuner_frequency < 478000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 10; - } else { - band = 2; - } - mode = 6; - cp = 1; - /* high band */ - } else if (tuner_frequency < 662000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 7; - cp = 0; - } else if (tuner_frequency < 840000000) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 6; - cp = 1; - } else { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) { - band = 12; - } else { - band = 4; - } - mode = 7; - cp = 1; - - } - /* calculate divisor */ - /* ((36166000 + Finput) / 166666) rounded! */ - divider = (tuner_frequency + 83333) / 166667; - - /* setup tuner buffer */ - tuner_buf[0] = (divider >> 8) & 0x7f; - tuner_buf[1] = divider & 0xff; - tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; - tuner_buf[3] = 0x40 | band; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) { - wprintk("could not write to tuner at addr: 0x%02x\n", - addr << 1); - return -EIO; - } - return 0; -} - static struct tda1004x_config medion_cardbus = { .demod_address = 0x08, .invert = 1, @@ -958,18 +817,8 @@ static struct nxt200x_config avertvhda180 = { .demod_address = 0x0a, }; -static int nxt200x_set_pll_input(u8 *buf, int input) -{ - if (input) - buf[3] |= 0x08; - else - buf[3] &= ~0x08; - return 0; -} - static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, - .set_pll_input = nxt200x_set_pll_input, }; /* ================================================================== @@ -1005,7 +854,8 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + NULL, DVB_PLL_PHILIPS_TD1316); } break; case SAA7134_BOARD_MD7134: @@ -1013,9 +863,8 @@ static int dvb_init(struct saa7134_dev *dev) &medion_cardbus, &dev->i2c_adap); if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; + dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, + &dev->i2c_adap, DVB_PLL_FMD1216ME); } break; case SAA7134_BOARD_PHILIPS_TOUGH: @@ -1113,7 +962,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); if (dev->dvb.frontend) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_tdhu2); + NULL, DVB_PLL_TDHU2); } break; case SAA7134_BOARD_KWORLD_ATSC110: @@ -1121,7 +970,7 @@ static int dvb_init(struct saa7134_dev *dev) &dev->i2c_adap); if (dev->dvb.frontend) { dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, &dvb_pll_tuv1236d); + NULL, DVB_PLL_TUV1236D); } break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -1144,9 +993,9 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; + + dvb_attach(dvb_pll_attach, dev->dvb.frontend, medion_cardbus.tuner_address, + &dev->i2c_adap, DVB_PLL_FMD1216ME); } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200A: diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index f521603482c..fc260ec8fdc 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -96,6 +96,10 @@ static int ts_open(struct inode *inode, struct file *file) if (dev->empress_users) goto done_up; + /* Unmute audio */ + saa_writeb(SAA7134_AUDIO_MUTE_CTRL, + saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6)); + dev->empress_users++; file->private_data = dev; err = 0; @@ -121,6 +125,10 @@ static int ts_release(struct inode *inode, struct file *file) /* stop the encoder */ ts_reset_encoder(dev); + /* Mute audio */ + saa_writeb(SAA7134_AUDIO_MUTE_CTRL, + saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); + mutex_unlock(&dev->empress_tsq.lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index c0de37e3f5c..1b6dfd801cc 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -153,21 +153,18 @@ void saa7134_input_irq(struct saa7134_dev *dev) static void saa7134_input_timer(unsigned long data) { - struct saa7134_dev *dev = (struct saa7134_dev*)data; + struct saa7134_dev *dev = (struct saa7134_dev *)data; struct card_ir *ir = dev->remote; - unsigned long timeout; build_key(dev); - timeout = jiffies + (ir->polling * HZ / 1000); - mod_timer(&ir->timer, timeout); + mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) { if (ir->polling) { - init_timer(&ir->timer); - ir->timer.function = saa7134_input_timer; - ir->timer.data = (unsigned long)dev; + setup_timer(&ir->timer, saa7134_input_timer, + (unsigned long)dev); ir->timer.expires = jiffies + HZ; add_timer(&ir->timer); } else if (ir->rc5_gpio) { @@ -314,6 +311,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0x003F00; mask_keyup = 0x040000; break; + case SAA7134_BOARD_FLYDVBS_LR300: case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_FLYDVBTDUO: ir_codes = ir_codes_flydvb; @@ -333,6 +331,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x040000; polling = 50; // ms break; + case SAA7134_BOARD_10MOONSTVMASTER3: + ir_codes = ir_codes_encore_enltv; + mask_keycode = 0x5f80000; + mask_keyup = 0x8000000; + polling = 50; //ms + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", @@ -374,7 +378,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) input_dev->id.vendor = dev->pci->vendor; input_dev->id.product = dev->pci->device; } - input_dev->cdev.dev = &dev->pci->dev; + input_dev->dev.parent = &dev->pci->dev; dev->remote = ir; saa7134_ir_start(dev, ir); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 7b56041186d..18b4817b4aa 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> +#include <linux/kthread.h> #include <linux/slab.h> #include <linux/delay.h> #include <asm/div64.h> @@ -341,10 +342,8 @@ static void tvaudio_setmode(struct saa7134_dev *dev, static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&dev->thread.wq, &wait); - if (dev->thread.scan1 == dev->thread.scan2 && !dev->thread.shutdown) { + if (dev->thread.scan1 == dev->thread.scan2 && + !kthread_should_stop()) { if (timeout < 0) { set_current_state(TASK_INTERRUPTIBLE); schedule(); @@ -353,7 +352,6 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) (msecs_to_jiffies(timeout)); } } - remove_wait_queue(&dev->thread.wq, &wait); return dev->thread.scan1 != dev->thread.scan2; } @@ -505,11 +503,10 @@ static int tvaudio_thread(void *data) unsigned int i, audio, nscan; int max1,max2,carrier,rx,mode,lastmode,default_carrier; - daemonize("%s", dev->name); allow_signal(SIGTERM); for (;;) { tvaudio_sleep(dev,-1); - if (dev->thread.shutdown || signal_pending(current)) + if (kthread_should_stop() || signal_pending(current)) goto done; restart: @@ -618,7 +615,7 @@ static int tvaudio_thread(void *data) for (;;) { if (tvaudio_sleep(dev,5000)) goto restart; - if (dev->thread.shutdown || signal_pending(current)) + if (kthread_should_stop() || signal_pending(current)) break; if (UNSET == dev->thread.mode) { rx = tvaudio_getstereo(dev,&tvaudio[i]); @@ -634,7 +631,6 @@ static int tvaudio_thread(void *data) } done: - complete_and_exit(&dev->thread.exit, 0); return 0; } @@ -782,7 +778,6 @@ static int tvaudio_thread_ddep(void *data) struct saa7134_dev *dev = data; u32 value, norms, clock; - daemonize("%s", dev->name); allow_signal(SIGTERM); clock = saa7134_boards[dev->board].audio_clock; @@ -796,7 +791,7 @@ static int tvaudio_thread_ddep(void *data) for (;;) { tvaudio_sleep(dev,-1); - if (dev->thread.shutdown || signal_pending(current)) + if (kthread_should_stop() || signal_pending(current)) goto done; restart: @@ -876,7 +871,6 @@ static int tvaudio_thread_ddep(void *data) } done: - complete_and_exit(&dev->thread.exit, 0); return 0; } @@ -973,7 +967,6 @@ int saa7134_tvaudio_getstereo(struct saa7134_dev *dev) int saa7134_tvaudio_init2(struct saa7134_dev *dev) { - DECLARE_MUTEX_LOCKED(sem); int (*my_thread)(void *data) = NULL; switch (dev->pci->device) { @@ -986,15 +979,15 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) break; } - dev->thread.pid = -1; + dev->thread.thread = NULL; if (my_thread) { /* start tvaudio thread */ - init_waitqueue_head(&dev->thread.wq); - init_completion(&dev->thread.exit); - dev->thread.pid = kernel_thread(my_thread,dev,0); - if (dev->thread.pid < 0) + dev->thread.thread = kthread_run(my_thread, dev, "%s", dev->name); + if (IS_ERR(dev->thread.thread)) { printk(KERN_WARNING "%s: kernel_thread() failed\n", dev->name); + /* XXX: missing error handling here */ + } saa7134_tvaudio_do_scan(dev); } @@ -1005,11 +998,9 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) int saa7134_tvaudio_fini(struct saa7134_dev *dev) { /* shutdown tvaudio thread */ - if (dev->thread.pid >= 0) { - dev->thread.shutdown = 1; - wake_up_interruptible(&dev->thread.wq); - wait_for_completion(&dev->thread.exit); - } + if (dev->thread.thread) + kthread_stop(dev->thread.thread); + saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */ return 0; } @@ -1020,10 +1011,10 @@ int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) dprintk("sound IF not in use, skipping scan\n"); dev->automute = 0; saa7134_tvaudio_setmute(dev); - } else if (dev->thread.pid >= 0) { + } else if (dev->thread.thread) { dev->thread.mode = UNSET; dev->thread.scan2++; - wake_up_interruptible(&dev->thread.wq); + wake_up_process(dev->thread.thread); } else { dev->automute = 0; saa7134_tvaudio_setmute(dev); @@ -1040,4 +1031,3 @@ EXPORT_SYMBOL(saa7134_tvaudio_setmute); * c-basic-offset: 8 * End: */ - diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 15623b27ad2..346255468da 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -238,6 +238,7 @@ struct saa7134_format { #define SAA7134_BOARD_ECS_TVP3XP_4CB6 113 #define SAA7134_BOARD_KWORLD_DVBT_210 114 #define SAA7134_BOARD_SABRENT_TV_PCB05 115 +#define SAA7134_BOARD_10MOONSTVMASTER3 116 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -313,7 +314,7 @@ struct saa7134_board { #define INTERLACE_ON 1 #define INTERLACE_OFF 2 -#define BUFFER_TIMEOUT (HZ/2) /* 0.5 seconds */ +#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ struct saa7134_dev; struct saa7134_dma; @@ -327,10 +328,7 @@ struct saa7134_pgtable { /* tvaudio thread status */ struct saa7134_thread { - pid_t pid; - struct completion exit; - wait_queue_head_t wq; - unsigned int shutdown; + struct task_struct *thread; unsigned int scan1; unsigned int scan2; unsigned int mode; diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 339592e7722..66cc92c0ea6 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c @@ -34,23 +34,23 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/signal.h> +#include <linux/types.h> +#include <linux/i2c.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <linux/types.h> +#include <asm/uaccess.h> #include <linux/videodev.h> -#include <asm/uaccess.h> +#include <linux/video_encoder.h> MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> #define I2C_NAME(s) (s)->name -#include <linux/video_encoder.h> static int debug = 0; module_param(debug, int, 0); diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 11fcb49f5b9..2e3c3de793a 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/string.h> #include <linux/stddef.h> +#include <linux/kref.h> #include "sn9c102_config.h" #include "sn9c102_sensor.h" @@ -94,7 +95,7 @@ struct sn9c102_module_param { }; static DEFINE_MUTEX(sn9c102_sysfs_lock); -static DECLARE_RWSEM(sn9c102_disconnect); +static DECLARE_RWSEM(sn9c102_dev_lock); struct sn9c102_device { struct video_device* v4ldev; @@ -122,12 +123,14 @@ struct sn9c102_device { struct sn9c102_module_param module_param; + struct kref kref; enum sn9c102_dev_state state; u8 users; - struct mutex dev_mutex, fileop_mutex; + struct completion probe; + struct mutex open_mutex, fileop_mutex; spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; + wait_queue_head_t wait_open, wait_frame, wait_stream; }; /*****************************************************************************/ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 74a204f8ebc..36d8a455e0e 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -48,8 +48,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.44" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44) +#define SN9C102_MODULE_VERSION "1:1.47" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47) /*****************************************************************************/ @@ -64,9 +64,10 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE); static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; module_param_array(video_nr, short, NULL, 0444); MODULE_PARM_DESC(video_nr, - "\n<-1|n[,...]> Specify V4L2 minor mode number." - "\n -1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" + " <-1|n[,...]>" + "\nSpecify V4L2 minor mode number." + "\n-1 = use next available (default)" + "\n n = use minor number n (integer >= 0)" "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) " cameras this way." "\nFor example:" @@ -79,13 +80,14 @@ static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FORCE_MUNMAP}; module_param_array(force_munmap, bool, NULL, 0444); MODULE_PARM_DESC(force_munmap, - "\n<0|1[,...]> Force the application to unmap previously" + " <0|1[,...]>" + "\nForce the application to unmap previously" "\nmapped buffer memory before calling any VIDIOC_S_CROP or" "\nVIDIOC_S_FMT ioctl's. Not all the applications support" "\nthis feature. This parameter is specific for each" "\ndetected camera." - "\n 0 = do not force memory unmapping" - "\n 1 = force memory unmapping (save memory)" + "\n0 = do not force memory unmapping" + "\n1 = force memory unmapping (save memory)" "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." "\n"); @@ -93,7 +95,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = SN9C102_FRAME_TIMEOUT}; module_param_array(frame_timeout, uint, NULL, 0644); MODULE_PARM_DESC(frame_timeout, - "\n<0|n[,...]> Timeout for a video frame in seconds before" + " <0|n[,...]>" + "\nTimeout for a video frame in seconds before" "\nreturning an I/O error; 0 for infinity." "\nThis parameter is specific for each detected camera." "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." @@ -103,7 +106,8 @@ MODULE_PARM_DESC(frame_timeout, static unsigned short debug = SN9C102_DEBUG_LEVEL; module_param(debug, ushort, 0644); MODULE_PARM_DESC(debug, - "\n<n> Debugging information level, from 0 to 3:" + " <n>" + "\nDebugging information level, from 0 to 3:" "\n0 = none (use carefully)" "\n1 = critical errors" "\n2 = significant informations" @@ -1616,7 +1620,8 @@ static int sn9c102_init(struct sn9c102_device* cam) int err = 0; if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); + mutex_init(&cam->open_mutex); + init_waitqueue_head(&cam->wait_open); qctrl = s->qctrl; rect = &(s->cropcap.defrect); } else { /* use current values */ @@ -1706,21 +1711,27 @@ static int sn9c102_init(struct sn9c102_device* cam) return 0; } +/*****************************************************************************/ -static void sn9c102_release_resources(struct sn9c102_device* cam) +static void sn9c102_release_resources(struct kref *kref) { + struct sn9c102_device *cam; + mutex_lock(&sn9c102_sysfs_lock); + cam = container_of(kref, struct sn9c102_device, kref); + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + usb_put_dev(cam->usbdev); + kfree(cam->control_buffer); + kfree(cam); mutex_unlock(&sn9c102_sysfs_lock); - kfree(cam->control_buffer); } -/*****************************************************************************/ static int sn9c102_open(struct inode* inode, struct file* filp) { @@ -1728,43 +1739,78 @@ static int sn9c102_open(struct inode* inode, struct file* filp) int err = 0; /* - This is the only safe way to prevent race conditions with - disconnect + A read_trylock() in open() is the only safe way to prevent race + conditions with disconnect(), one close() and multiple (not + necessarily simultaneous) attempts to open(). For example, it + prevents from waiting for a second access, while the device + structure is being deallocated, after a possible disconnect() and + during a following close() holding the write lock: given that, after + this deallocation, no access will be possible anymore, using the + non-trylock version would have let open() gain the access to the + device structure improperly. + For this reason the lock must also not be per-device. */ - if (!down_read_trylock(&sn9c102_disconnect)) + if (!down_read_trylock(&sn9c102_dev_lock)) return -ERESTARTSYS; cam = video_get_drvdata(video_devdata(filp)); - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&sn9c102_disconnect); + if (wait_for_completion_interruptible(&cam->probe)) { + up_read(&sn9c102_dev_lock); + return -ERESTARTSYS; + } + + kref_get(&cam->kref); + + /* + Make sure to isolate all the simultaneous opens. + */ + if (mutex_lock_interruptible(&cam->open_mutex)) { + kref_put(&cam->kref, sn9c102_release_resources); + up_read(&sn9c102_dev_lock); return -ERESTARTSYS; } + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + err = -ENODEV; + goto out; + } + if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + DBG(2, "Device /dev/video%d is already in use", + cam->v4ldev->minor); DBG(3, "Simultaneous opens are not supported"); + /* + open() must follow the open flags and should block + eventually while the device is in use. + */ if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { err = -EWOULDBLOCK; goto out; } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED + DBG(2, "A blocking open() has been requested. Wait for the " + "device to be released..."); + up_read(&sn9c102_dev_lock); + /* + We will not release the "open_mutex" lock, so that only one + process can be in the wait queue below. This way the process + will be sleeping while holding the lock, without loosing its + priority after any wake_up(). + */ + err = wait_event_interruptible_exclusive(cam->wait_open, + (cam->state & DEV_DISCONNECTED) || !cam->users); - if (err) { - up_read(&sn9c102_disconnect); - return err; - } + down_read(&sn9c102_dev_lock); + if (err) + goto out; if (cam->state & DEV_DISCONNECTED) { - up_read(&sn9c102_disconnect); - return -ENODEV; + err = -ENODEV; + goto out; } - mutex_lock(&cam->dev_mutex); } - if (cam->state & DEV_MISCONFIGURED) { err = sn9c102_init(cam); if (err) { @@ -1789,36 +1835,33 @@ static int sn9c102_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - mutex_unlock(&cam->dev_mutex); - up_read(&sn9c102_disconnect); + mutex_unlock(&cam->open_mutex); + if (err) + kref_put(&cam->kref, sn9c102_release_resources); + + up_read(&sn9c102_dev_lock); return err; } static int sn9c102_release(struct inode* inode, struct file* filp) { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); + struct sn9c102_device* cam; - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + down_write(&sn9c102_dev_lock); - sn9c102_stop_transfer(cam); + cam = video_get_drvdata(video_devdata(filp)); + sn9c102_stop_transfer(cam); sn9c102_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - sn9c102_release_resources(cam); - usb_put_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); + wake_up_interruptible_nr(&cam->wait_open, 1); DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - mutex_unlock(&cam->dev_mutex); + kref_put(&cam->kref, sn9c102_release_resources); + + up_write(&sn9c102_dev_lock); return 0; } @@ -2085,7 +2128,6 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) vma->vm_ops = &sn9c102_vm_ops; vma->vm_private_data = &cam->frame[i]; - sn9c102_vm_open(vma); mutex_unlock(&cam->fileop_mutex); @@ -3215,8 +3257,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - mutex_init(&cam->dev_mutex); - r = sn9c102_read_reg(cam, 0x00); if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { DBG(1, "Sorry, this is not a SN9C1xx-based camera " @@ -3282,7 +3322,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - mutex_lock(&cam->dev_mutex); + init_completion(&cam->probe); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -3292,7 +3332,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); goto fail; } @@ -3318,8 +3358,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) #endif usb_set_intfdata(intf, cam); + kref_init(&cam->kref); + usb_get_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); return 0; @@ -3336,40 +3378,31 @@ fail: static void sn9c102_usb_disconnect(struct usb_interface* intf) { - struct sn9c102_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; + struct sn9c102_device* cam; - down_write(&sn9c102_disconnect); + down_write(&sn9c102_dev_lock); - mutex_lock(&cam->dev_mutex); + cam = usb_get_intfdata(intf); DBG(2, "Disconnecting %s...", cam->v4ldev->name); - wake_up_interruptible_all(&cam->open); - if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", + "memory deallocation are deferred.", cam->v4ldev->minor); cam->state |= DEV_MISCONFIGURED; sn9c102_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { + } else cam->state |= DEV_DISCONNECTED; - sn9c102_release_resources(cam); - } - mutex_unlock(&cam->dev_mutex); + wake_up_interruptible_all(&cam->wait_open); - if (!cam->users) - kfree(cam); + kref_put(&cam->kref, sn9c102_release_resources); - up_write(&sn9c102_disconnect); + up_write(&sn9c102_dev_lock); } diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index e6832347894..e4856fd7798 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -104,6 +104,145 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x74, 0x21); err += sn9c102_i2c_write(cam, 0x7d, 0xf7); break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x03, 0x10}, + {0x0a, 0x14}, {0xe2, 0x17}, + {0x0b, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x24, 0x21}, + {0x3b, 0x22}, {0x47, 0x23}, + {0x60, 0x24}, {0x71, 0x25}, + {0x80, 0x26}, {0x8f, 0x27}, + {0x9d, 0x28}, {0xaa, 0x29}, + {0xb8, 0x2a}, {0xc4, 0x2b}, + {0xd1, 0x2c}, {0xdd, 0x2d}, + {0xe8, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3f}, + {0xc7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xc7, 0x48}, {0x01, 0x49}, + {0xc7, 0x4a}, {0x01, 0x4b}, + {0xc7, 0x4c}, {0x01, 0x4d}, + {0x44, 0x4e}, {0x00, 0x4f}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xc7, 0x54}, {0x01, 0x55}, + {0xc7, 0x56}, {0x01, 0x57}, + {0xc7, 0x58}, {0x01, 0x59}, + {0x44, 0x5a}, {0x00, 0x5b}, + {0x44, 0x5c}, {0x00, 0x5d}, + {0x44, 0x5e}, {0x00, 0x5f}, + {0xc7, 0x60}, {0x01, 0x61}, + {0xc7, 0x62}, {0x01, 0x63}, + {0xc7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6a}, {0x00, 0x6b}, + {0xc7, 0x6c}, {0x01, 0x6d}, + {0xc7, 0x6e}, {0x01, 0x6f}, + {0xc7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xc7, 0x78}, {0x01, 0x79}, + {0xc7, 0x7a}, {0x01, 0x7b}, + {0xc7, 0x7c}, {0x01, 0x7d}, + {0x44, 0x7e}, {0x00, 0x7f}, + {0x17, 0x84}, {0x00, 0x85}, + {0x2e, 0x86}, {0x00, 0x87}, + {0x09, 0x88}, {0x00, 0x89}, + {0xe8, 0x8a}, {0x0f, 0x8b}, + {0xda, 0x8c}, {0x0f, 0x8d}, + {0x40, 0x8e}, {0x00, 0x8f}, + {0x37, 0x90}, {0x00, 0x91}, + {0xcf, 0x92}, {0x0f, 0x93}, + {0xfa, 0x94}, {0x0f, 0x95}, + {0x00, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x00, 0x9a}, {0x40, 0x9b}, + {0x20, 0x9c}, {0x00, 0x9d}, + {0x00, 0x9e}, {0x00, 0x9f}, + {0x2d, 0xc0}, {0x2d, 0xc1}, + {0x3a, 0xc2}, {0x00, 0xc3}, + {0x04, 0xc4}, {0x3f, 0xc5}, + {0x00, 0xc6}, {0x00, 0xc7}, + {0x50, 0xc8}, {0x3c, 0xc9}, + {0x28, 0xca}, {0xd8, 0xcb}, + {0x14, 0xcc}, {0xec, 0xcd}, + {0x32, 0xce}, {0xdd, 0xcf}, + {0x32, 0xd0}, {0xdd, 0xd1}, + {0x6a, 0xd2}, {0x50, 0xd3}, + {0x60, 0xd4}, {0x00, 0xd5}, + {0x00, 0xd6}); + + err += sn9c102_i2c_write(cam, 0x12, 0x80); + err += sn9c102_i2c_write(cam, 0x12, 0x48); + err += sn9c102_i2c_write(cam, 0x01, 0x80); + err += sn9c102_i2c_write(cam, 0x02, 0x80); + err += sn9c102_i2c_write(cam, 0x03, 0x80); + err += sn9c102_i2c_write(cam, 0x04, 0x10); + err += sn9c102_i2c_write(cam, 0x05, 0x20); + err += sn9c102_i2c_write(cam, 0x06, 0x80); + err += sn9c102_i2c_write(cam, 0x11, 0x00); + err += sn9c102_i2c_write(cam, 0x0c, 0x20); + err += sn9c102_i2c_write(cam, 0x0d, 0x20); + err += sn9c102_i2c_write(cam, 0x15, 0x80); + err += sn9c102_i2c_write(cam, 0x16, 0x03); + err += sn9c102_i2c_write(cam, 0x17, 0x1b); + err += sn9c102_i2c_write(cam, 0x18, 0xbd); + err += sn9c102_i2c_write(cam, 0x19, 0x05); + err += sn9c102_i2c_write(cam, 0x1a, 0xf6); + err += sn9c102_i2c_write(cam, 0x1b, 0x04); + err += sn9c102_i2c_write(cam, 0x21, 0x1b); + err += sn9c102_i2c_write(cam, 0x22, 0x00); + err += sn9c102_i2c_write(cam, 0x23, 0xde); + err += sn9c102_i2c_write(cam, 0x24, 0x10); + err += sn9c102_i2c_write(cam, 0x25, 0x8a); + err += sn9c102_i2c_write(cam, 0x26, 0xa0); + err += sn9c102_i2c_write(cam, 0x27, 0xca); + err += sn9c102_i2c_write(cam, 0x28, 0xa2); + err += sn9c102_i2c_write(cam, 0x29, 0x74); + err += sn9c102_i2c_write(cam, 0x2a, 0x88); + err += sn9c102_i2c_write(cam, 0x2b, 0x34); + err += sn9c102_i2c_write(cam, 0x2c, 0x88); + err += sn9c102_i2c_write(cam, 0x2e, 0x00); + err += sn9c102_i2c_write(cam, 0x2f, 0x00); + err += sn9c102_i2c_write(cam, 0x30, 0x00); + err += sn9c102_i2c_write(cam, 0x32, 0xc2); + err += sn9c102_i2c_write(cam, 0x33, 0x08); + err += sn9c102_i2c_write(cam, 0x4c, 0x40); + err += sn9c102_i2c_write(cam, 0x4d, 0xf3); + err += sn9c102_i2c_write(cam, 0x60, 0x05); + err += sn9c102_i2c_write(cam, 0x61, 0x40); + err += sn9c102_i2c_write(cam, 0x62, 0x12); + err += sn9c102_i2c_write(cam, 0x63, 0x57); + err += sn9c102_i2c_write(cam, 0x64, 0x73); + err += sn9c102_i2c_write(cam, 0x65, 0x00); + err += sn9c102_i2c_write(cam, 0x66, 0x55); + err += sn9c102_i2c_write(cam, 0x67, 0x01); + err += sn9c102_i2c_write(cam, 0x68, 0xac); + err += sn9c102_i2c_write(cam, 0x69, 0x38); + err += sn9c102_i2c_write(cam, 0x6f, 0x1f); + err += sn9c102_i2c_write(cam, 0x70, 0x01); + err += sn9c102_i2c_write(cam, 0x71, 0x00); + err += sn9c102_i2c_write(cam, 0x72, 0x10); + err += sn9c102_i2c_write(cam, 0x73, 0x50); + err += sn9c102_i2c_write(cam, 0x74, 0x20); + err += sn9c102_i2c_write(cam, 0x76, 0x01); + err += sn9c102_i2c_write(cam, 0x77, 0xf3); + err += sn9c102_i2c_write(cam, 0x78, 0x90); + err += sn9c102_i2c_write(cam, 0x79, 0x98); + err += sn9c102_i2c_write(cam, 0x7a, 0x98); + err += sn9c102_i2c_write(cam, 0x7b, 0x00); + err += sn9c102_i2c_write(cam, 0x7c, 0x38); + err += sn9c102_i2c_write(cam, 0x7d, 0xff); + break; default: break; } @@ -115,6 +254,7 @@ static int ov7630_init(struct sn9c102_device* cam) static int ov7630_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { + enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); int err = 0; switch (ctrl->id) { @@ -123,13 +263,20 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam, return -EIO; break; case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x07); + if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) + ctrl->value = sn9c102_pread_reg(cam, 0x05); + else + ctrl->value = sn9c102_pread_reg(cam, 0x07); break; case V4L2_CID_BLUE_BALANCE: ctrl->value = sn9c102_pread_reg(cam, 0x06); break; case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x05); + if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) + ctrl->value = sn9c102_pread_reg(cam, 0x07); + else + ctrl->value = sn9c102_pread_reg(cam, 0x05); + break; break; case V4L2_CID_GAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) @@ -177,6 +324,7 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam, static int ov7630_set_ctrl(struct sn9c102_device* cam, const struct v4l2_control* ctrl) { + enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); int err = 0; switch (ctrl->id) { @@ -184,13 +332,19 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam, err += sn9c102_i2c_write(cam, 0x10, ctrl->value); break; case V4L2_CID_RED_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x07); + if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, ctrl->value, 0x05); + else + err += sn9c102_write_reg(cam, ctrl->value, 0x07); break; case V4L2_CID_BLUE_BALANCE: err += sn9c102_write_reg(cam, ctrl->value, 0x06); break; case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x05); + if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, ctrl->value, 0x07); + else + err += sn9c102_write_reg(cam, ctrl->value, 0x05); break; case V4L2_CID_GAIN: err += sn9c102_i2c_write(cam, 0x00, ctrl->value); @@ -227,8 +381,21 @@ static int ov7630_set_crop(struct sn9c102_device* cam, { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + case BRIDGE_SN9C103: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; + break; + default: + break; + } err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); @@ -242,10 +409,28 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, { int err = 0; - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) - err += sn9c102_write_reg(cam, 0x20, 0x19); - else - err += sn9c102_write_reg(cam, 0x50, 0x19); + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C101: + case BRIDGE_SN9C102: + case BRIDGE_SN9C103: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) + err += sn9c102_write_reg(cam, 0x50, 0x19); + else + err += sn9c102_write_reg(cam, 0x20, 0x19); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { + err += sn9c102_write_reg(cam, 0xe5, 0x17); + err += sn9c102_i2c_write(cam, 0x11, 0x04); + } else { + err += sn9c102_write_reg(cam, 0xe2, 0x17); + err += sn9c102_i2c_write(cam, 0x11, 0x02); + } + break; + default: + break; + } return err; } @@ -254,7 +439,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, static const struct sn9c102_sensor ov7630 = { .name = "OV7630", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 | + BRIDGE_SN9C105 | BRIDGE_SN9C120, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, @@ -417,6 +603,12 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) err += sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}); break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, + {0x29, 0x01}, {0x74, 0x02}, + {0x0e, 0x01}, {0x44, 0x01}); + break; default: break; } diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index 4b6474048a7..8aae416ba8e 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -41,65 +41,65 @@ static int ov7660_init(struct sn9c102_device* cam) {0xbb, 0x2a}, {0xc7, 0x2b}, {0xd3, 0x2c}, {0xde, 0x2d}, {0xea, 0x2e}, {0xf4, 0x2f}, - {0xff, 0x30}, {0x00, 0x3F}, - {0xC7, 0x40}, {0x01, 0x41}, + {0xff, 0x30}, {0x00, 0x3f}, + {0xc7, 0x40}, {0x01, 0x41}, {0x44, 0x42}, {0x00, 0x43}, {0x44, 0x44}, {0x00, 0x45}, {0x44, 0x46}, {0x00, 0x47}, - {0xC7, 0x48}, {0x01, 0x49}, - {0xC7, 0x4A}, {0x01, 0x4B}, - {0xC7, 0x4C}, {0x01, 0x4D}, - {0x44, 0x4E}, {0x00, 0x4F}, + {0xc7, 0x48}, {0x01, 0x49}, + {0xc7, 0x4a}, {0x01, 0x4b}, + {0xc7, 0x4c}, {0x01, 0x4d}, + {0x44, 0x4e}, {0x00, 0x4f}, {0x44, 0x50}, {0x00, 0x51}, {0x44, 0x52}, {0x00, 0x53}, - {0xC7, 0x54}, {0x01, 0x55}, - {0xC7, 0x56}, {0x01, 0x57}, - {0xC7, 0x58}, {0x01, 0x59}, - {0x44, 0x5A}, {0x00, 0x5B}, - {0x44, 0x5C}, {0x00, 0x5D}, - {0x44, 0x5E}, {0x00, 0x5F}, - {0xC7, 0x60}, {0x01, 0x61}, - {0xC7, 0x62}, {0x01, 0x63}, - {0xC7, 0x64}, {0x01, 0x65}, + {0xc7, 0x54}, {0x01, 0x55}, + {0xc7, 0x56}, {0x01, 0x57}, + {0xc7, 0x58}, {0x01, 0x59}, + {0x44, 0x5a}, {0x00, 0x5b}, + {0x44, 0x5c}, {0x00, 0x5d}, + {0x44, 0x5e}, {0x00, 0x5f}, + {0xc7, 0x60}, {0x01, 0x61}, + {0xc7, 0x62}, {0x01, 0x63}, + {0xc7, 0x64}, {0x01, 0x65}, {0x44, 0x66}, {0x00, 0x67}, {0x44, 0x68}, {0x00, 0x69}, - {0x44, 0x6A}, {0x00, 0x6B}, - {0xC7, 0x6C}, {0x01, 0x6D}, - {0xC7, 0x6E}, {0x01, 0x6F}, - {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x6a}, {0x00, 0x6b}, + {0xc7, 0x6c}, {0x01, 0x6d}, + {0xc7, 0x6e}, {0x01, 0x6f}, + {0xc7, 0x70}, {0x01, 0x71}, {0x44, 0x72}, {0x00, 0x73}, {0x44, 0x74}, {0x00, 0x75}, {0x44, 0x76}, {0x00, 0x77}, - {0xC7, 0x78}, {0x01, 0x79}, - {0xC7, 0x7A}, {0x01, 0x7B}, - {0xC7, 0x7C}, {0x01, 0x7D}, - {0x44, 0x7E}, {0x00, 0x7F}, + {0xc7, 0x78}, {0x01, 0x79}, + {0xc7, 0x7a}, {0x01, 0x7b}, + {0xc7, 0x7c}, {0x01, 0x7d}, + {0x44, 0x7e}, {0x00, 0x7f}, {0x14, 0x84}, {0x00, 0x85}, {0x27, 0x86}, {0x00, 0x87}, {0x07, 0x88}, {0x00, 0x89}, - {0xEC, 0x8A}, {0x0f, 0x8B}, - {0xD8, 0x8C}, {0x0f, 0x8D}, - {0x3D, 0x8E}, {0x00, 0x8F}, - {0x3D, 0x90}, {0x00, 0x91}, - {0xCD, 0x92}, {0x0f, 0x93}, + {0xec, 0x8a}, {0x0f, 0x8b}, + {0xd8, 0x8c}, {0x0f, 0x8d}, + {0x3d, 0x8e}, {0x00, 0x8f}, + {0x3d, 0x90}, {0x00, 0x91}, + {0xcd, 0x92}, {0x0f, 0x93}, {0xf7, 0x94}, {0x0f, 0x95}, - {0x0C, 0x96}, {0x00, 0x97}, + {0x0c, 0x96}, {0x00, 0x97}, {0x00, 0x98}, {0x66, 0x99}, - {0x05, 0x9A}, {0x00, 0x9B}, - {0x04, 0x9C}, {0x00, 0x9D}, - {0x08, 0x9E}, {0x00, 0x9F}, - {0x2D, 0xC0}, {0x2D, 0xC1}, - {0x3A, 0xC2}, {0x05, 0xC3}, - {0x04, 0xC4}, {0x3F, 0xC5}, - {0x00, 0xC6}, {0x00, 0xC7}, - {0x50, 0xC8}, {0x3C, 0xC9}, - {0x28, 0xCA}, {0xD8, 0xCB}, - {0x14, 0xCC}, {0xEC, 0xCD}, - {0x32, 0xCE}, {0xDD, 0xCF}, - {0x32, 0xD0}, {0xDD, 0xD1}, - {0x6A, 0xD2}, {0x50, 0xD3}, - {0x00, 0xD4}, {0x00, 0xD5}, - {0x00, 0xD6}); + {0x05, 0x9a}, {0x00, 0x9b}, + {0x04, 0x9c}, {0x00, 0x9d}, + {0x08, 0x9e}, {0x00, 0x9f}, + {0x2d, 0xc0}, {0x2d, 0xc1}, + {0x3a, 0xc2}, {0x05, 0xc3}, + {0x04, 0xc4}, {0x3f, 0xc5}, + {0x00, 0xc6}, {0x00, 0xc7}, + {0x50, 0xc8}, {0x3C, 0xc9}, + {0x28, 0xca}, {0xd8, 0xcb}, + {0x14, 0xcc}, {0xec, 0xcd}, + {0x32, 0xce}, {0xdd, 0xcf}, + {0x32, 0xd0}, {0xdd, 0xd1}, + {0x6a, 0xd2}, {0x50, 0xd3}, + {0x00, 0xd4}, {0x00, 0xd5}, + {0x00, 0xd6}); err += sn9c102_i2c_write(cam, 0x12, 0x80); err += sn9c102_i2c_write(cam, 0x11, 0x09); diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 3e736be5de8..eb220461ac7 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -1321,7 +1321,7 @@ static int saa_ioctl(struct inode *inode, struct file *file, u32 format; if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; - if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { + if (p.palette < ARRAY_SIZE(palette2fmt)) { format = palette2fmt[p.palette]; saa->win.color_fmt = format; saawrite(format | 0x60, diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index bf3aa8d2d57..4dc5bc714b9 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -715,8 +715,11 @@ static int stv680_start_stream (struct usb_stv *stv680) stv680_video_irq, stv680); stv680->urb[i] = urb; err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); - if (err) - PDEBUG (0, "STV(e): urb burned down in start stream"); + if (err) { + PDEBUG (0, "STV(e): urb burned down with err " + "%d in start stream %d", err, i); + goto nomem_err; + } } /* i STV680_NUMSBUF */ stv680->framecount = 0; diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 1a1bef0e9c3..59cff5a3c59 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -21,7 +21,17 @@ #include <linux/i2c.h> #include <linux/videodev.h> #include <linux/delay.h> -#include <media/tuner.h> +#include "tuner-driver.h" + +/* ---------------------------------------------------------------------- */ + +struct tda8290_priv { + unsigned char tda8290_easy_mode; + unsigned char tda827x_lpsel; + unsigned char tda827x_addr; + unsigned char tda827x_ver; + unsigned int sgIF; +}; /* ---------------------------------------------------------------------- */ @@ -76,7 +86,8 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) u32 N; int i; struct tuner *t = i2c_get_clientdata(c); - struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0}; + struct tda8290_priv *priv = t->priv; + struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; if (t->mode == V4L2_TUNER_RADIO) freq = freq / 1000; @@ -95,7 +106,7 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) tuner_reg[1] = (unsigned char)(N>>8); tuner_reg[2] = (unsigned char) N; tuner_reg[3] = 0x40; - tuner_reg[4] = 0x52 + (t->tda827x_lpsel << 5); + tuner_reg[4] = 0x52 + (priv->tda827x_lpsel << 5); tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); @@ -146,8 +157,9 @@ static void tda827x_tune(struct i2c_client *c, u16 ifc, unsigned int freq) static void tda827x_agcf(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; unsigned char data[] = {0x80, 0x0c}; - struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, .flags = 0, .len = 2}; i2c_transfer(c->adapter, &msg, 1); } @@ -234,7 +246,8 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) u32 N; int i; struct tuner *t = i2c_get_clientdata(c); - struct i2c_msg msg = {.addr = t->tda827x_addr, .flags = 0, .buf = tuner_reg}; + struct tda8290_priv *priv = t->priv; + struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; tda827xa_lna_gain( c, 1); msleep(10); @@ -271,7 +284,7 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) tuner_reg[1] = 0xff; tuner_reg[2] = 0xe0; tuner_reg[3] = 0; - tuner_reg[4] = 0x99 + (t->tda827x_lpsel << 1); + tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); msg.len = 5; i2c_transfer(c->adapter, &msg, 1); @@ -311,15 +324,16 @@ static void tda827xa_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_transfer(c->adapter, &msg, 1); tuner_reg[0] = 0xc0; - tuner_reg[1] = 0x19 + (t->tda827x_lpsel << 1); + tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); i2c_transfer(c->adapter, &msg, 1); } static void tda827xa_agcf(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; unsigned char data[] = {0x80, 0x2c}; - struct i2c_msg msg = {.addr = t->tda827x_addr, .buf = data, + struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, .flags = 0, .len = 2}; i2c_transfer(c->adapter, &msg, 1); } @@ -347,8 +361,9 @@ static void tda8290_i2c_bridge(struct i2c_client *c, int close) static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; unsigned char soft_reset[] = { 0x00, 0x00 }; - unsigned char easy_mode[] = { 0x01, t->tda8290_easy_mode }; + unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; unsigned char agc_out_on[] = { 0x02, 0x00 }; unsigned char gainset_off[] = { 0x28, 0x14 }; @@ -375,18 +390,18 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) i2c_master_send(c, soft_reset, 2); msleep(1); - expert_mode[1] = t->tda8290_easy_mode + 0x80; + expert_mode[1] = priv->tda8290_easy_mode + 0x80; i2c_master_send(c, expert_mode, 2); i2c_master_send(c, gainset_off, 2); i2c_master_send(c, if_agc_spd, 2); - if (t->tda8290_easy_mode & 0x60) + if (priv->tda8290_easy_mode & 0x60) i2c_master_send(c, adc_head_9, 2); else i2c_master_send(c, adc_head_6, 2); i2c_master_send(c, pll_bw_nom, 2); tda8290_i2c_bridge(c, 1); - if (t->tda827x_ver != 0) + if (priv->tda827x_ver != 0) tda827xa_tune(c, ifc, freq); else tda827x_tune(c, ifc, freq); @@ -418,7 +433,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) if ((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); - if (t->tda827x_ver != 0) + if (priv->tda827x_ver != 0) tda827xa_agcf(c); else tda827x_agcf(c); @@ -437,7 +452,7 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) } /* l/ l' deadlock? */ - if(t->tda8290_easy_mode & 0x60) { + if(priv->tda8290_easy_mode & 0x60) { i2c_master_send(c, &addr_adc_sat, 1); i2c_master_recv(c, &adc_sat, 1); i2c_master_send(c, &addr_pll_stat, 1); @@ -459,41 +474,42 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq) static void set_audio(struct tuner *t) { + struct tda8290_priv *priv = t->priv; char* mode; - t->tda827x_lpsel = 0; + priv->tda827x_lpsel = 0; if (t->std & V4L2_STD_MN) { - t->sgIF = 92; - t->tda8290_easy_mode = 0x01; - t->tda827x_lpsel = 1; + priv->sgIF = 92; + priv->tda8290_easy_mode = 0x01; + priv->tda827x_lpsel = 1; mode = "MN"; } else if (t->std & V4L2_STD_B) { - t->sgIF = 108; - t->tda8290_easy_mode = 0x02; + priv->sgIF = 108; + priv->tda8290_easy_mode = 0x02; mode = "B"; } else if (t->std & V4L2_STD_GH) { - t->sgIF = 124; - t->tda8290_easy_mode = 0x04; + priv->sgIF = 124; + priv->tda8290_easy_mode = 0x04; mode = "GH"; } else if (t->std & V4L2_STD_PAL_I) { - t->sgIF = 124; - t->tda8290_easy_mode = 0x08; + priv->sgIF = 124; + priv->tda8290_easy_mode = 0x08; mode = "I"; } else if (t->std & V4L2_STD_DK) { - t->sgIF = 124; - t->tda8290_easy_mode = 0x10; + priv->sgIF = 124; + priv->tda8290_easy_mode = 0x10; mode = "DK"; } else if (t->std & V4L2_STD_SECAM_L) { - t->sgIF = 124; - t->tda8290_easy_mode = 0x20; + priv->sgIF = 124; + priv->tda8290_easy_mode = 0x20; mode = "L"; } else if (t->std & V4L2_STD_SECAM_LC) { - t->sgIF = 20; - t->tda8290_easy_mode = 0x40; + priv->sgIF = 20; + priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { - t->sgIF = 124; - t->tda8290_easy_mode = 0x10; + priv->sgIF = 124; + priv->tda8290_easy_mode = 0x10; mode = "xx"; } tuner_dbg("setting tda8290 to system %s\n", mode); @@ -502,9 +518,10 @@ static void set_audio(struct tuner *t) static void set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; set_audio(t); - tda8290_tune(c, t->sgIF, freq); + tda8290_tune(c, priv->sgIF, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -528,13 +545,14 @@ static int has_signal(struct i2c_client *c) static void standby(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; - struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; + struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; tda8290_i2c_bridge(c, 1); - if (t->tda827x_ver != 0) + if (priv->tda827x_ver != 0) cb1[1] = 0x90; i2c_transfer(c->adapter, &msg, 1); tda8290_i2c_bridge(c, 0); @@ -560,13 +578,14 @@ static void tda8290_init_if(struct i2c_client *c) static void tda8290_init_tuner(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); + struct tda8290_priv *priv = t->priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; - struct i2c_msg msg = {.addr = t->tda827x_addr, .flags=0, + struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=tda8275_init, .len = 14}; - if (t->tda827x_ver != 0) + if (priv->tda827x_ver != 0) msg.buf = tda8275a_init; tda8290_i2c_bridge(c, 1); @@ -576,14 +595,36 @@ static void tda8290_init_tuner(struct i2c_client *c) /*---------------------------------------------------------------------*/ +static void tda8290_release(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + + kfree(t->priv); + t->priv = NULL; +} + +static struct tuner_operations tda8290_tuner_ops = { + .set_tv_freq = set_tv_freq, + .set_radio_freq = set_radio_freq, + .has_signal = has_signal, + .standby = standby, + .release = tda8290_release, +}; + int tda8290_init(struct i2c_client *c) { + struct tda8290_priv *priv = NULL; struct tuner *t = i2c_get_clientdata(c); u8 data; int i, ret, tuners_found; u32 tuner_addrs; struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; + priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + t->priv = priv; + tda8290_i2c_bridge(c, 1); /* probe for tuner chip */ tuners_found = 0; @@ -618,7 +659,7 @@ int tda8290_init(struct i2c_client *c) tuner_addrs = tuner_addrs & 0xff; tuner_info ("setting tuner address to %x\n", tuner_addrs); } - t->tda827x_addr = tuner_addrs; + priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; tda8290_i2c_bridge(c, 1); @@ -627,18 +668,16 @@ int tda8290_init(struct i2c_client *c) tuner_warn ("TDA827x access failed!\n"); if ((data & 0x3c) == 0) { strlcpy(c->name, "tda8290+75", sizeof(c->name)); - t->tda827x_ver = 0; + priv->tda827x_ver = 0; } else { strlcpy(c->name, "tda8290+75a", sizeof(c->name)); - t->tda827x_ver = 2; + priv->tda827x_ver = 2; } tuner_info("type set to %s\n", c->name); - t->set_tv_freq = set_tv_freq; - t->set_radio_freq = set_radio_freq; - t->has_signal = has_signal; - t->standby = standby; - t->tda827x_lpsel = 0; + memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); + + priv->tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; tda8290_init_tuner(c); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index fde576f1101..a8f773274fe 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -11,6 +11,7 @@ #include <media/v4l2-common.h> #include <media/tuner.h> +#include "tuner-driver.h" /* Chips: @@ -29,6 +30,9 @@ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +struct tda9887_priv { + unsigned char data[4]; +}; /* ---------------------------------------------------------------------- */ @@ -508,10 +512,11 @@ static int tda9887_status(struct tuner *t) static void tda9887_configure(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); + struct tda9887_priv *priv = t->priv; int rc; - memset(t->tda9887_data,0,sizeof(t->tda9887_data)); - tda9887_set_tvnorm(t,t->tda9887_data); + memset(priv->data,0,sizeof(priv->data)); + tda9887_set_tvnorm(t,priv->data); /* A note on the port settings: These settings tend to depend on the specifics of the board. @@ -526,22 +531,22 @@ static void tda9887_configure(struct i2c_client *client) the ports should be set to active (0), but, again, that may differ depending on the precise hardware configuration. */ - t->tda9887_data[1] |= cOutputPort1Inactive; - t->tda9887_data[1] |= cOutputPort2Inactive; + priv->data[1] |= cOutputPort1Inactive; + priv->data[1] |= cOutputPort2Inactive; - tda9887_set_config(t,t->tda9887_data); - tda9887_set_insmod(t,t->tda9887_data); + tda9887_set_config(t,priv->data); + tda9887_set_insmod(t,priv->data); if (t->mode == T_STANDBY) { - t->tda9887_data[1] |= cForcedMuteAudioON; + priv->data[1] |= cForcedMuteAudioON; } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]); + priv->data[1],priv->data[2],priv->data[3]); if (tuner_debug > 1) - dump_write_message(t, t->tda9887_data); + dump_write_message(t, priv->data); - if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4))) + if (4 != (rc = i2c_master_send(&t->i2c,priv->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (tuner_debug > 2) { @@ -555,7 +560,8 @@ static void tda9887_configure(struct i2c_client *client) static void tda9887_tuner_status(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); - tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]); + struct tda9887_priv *priv = t->priv; + tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct i2c_client *client) @@ -586,20 +592,39 @@ static void tda9887_set_freq(struct i2c_client *client, unsigned int freq) tda9887_configure(client); } +static void tda9887_release(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + + kfree(t->priv); + t->priv = NULL; +} + +static struct tuner_operations tda9887_tuner_ops = { + .set_tv_freq = tda9887_set_freq, + .set_radio_freq = tda9887_set_freq, + .standby = tda9887_standby, + .tuner_status = tda9887_tuner_status, + .get_afc = tda9887_get_afc, + .release = tda9887_release, +}; + int tda9887_tuner_init(struct i2c_client *c) { + struct tda9887_priv *priv = NULL; struct tuner *t = i2c_get_clientdata(c); + priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + t->priv = priv; + strlcpy(c->name, "tda9887", sizeof(c->name)); tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, t->i2c.driver->driver.name); - t->set_tv_freq = tda9887_set_freq; - t->set_radio_freq = tda9887_set_freq; - t->standby = tda9887_standby; - t->tuner_status = tda9887_tuner_status; - t->get_afc = tda9887_get_afc; + memcpy(&t->ops, &tda9887_tuner_ops, sizeof(struct tuner_operations)); return 0; } diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c new file mode 100644 index 00000000000..ae105c2cd0a --- /dev/null +++ b/drivers/media/video/tea5761.c @@ -0,0 +1,243 @@ +/* + * For Philips TEA5761 FM Chip + * I2C address is allways 0x20 (0x10 at 7-bit mode). + * + * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This code is placed under the terms of the GNUv2 General Public License + * + */ + +#include <linux/i2c.h> +#include <linux/videodev.h> +#include <linux/delay.h> +#include <media/tuner.h> +#include "tuner-driver.h" + +#define PREFIX "TEA5761 " + +/* from tuner-core.c */ +extern int tuner_debug; + +/*****************************************************************************/ + +/*************************** + * TEA5761HN I2C registers * + ***************************/ + +/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */ + + /* first byte for reading */ +#define TEA5761_INTREG_IFFLAG 0x10 +#define TEA5761_INTREG_LEVFLAG 0x8 +#define TEA5761_INTREG_FRRFLAG 0x2 +#define TEA5761_INTREG_BLFLAG 0x1 + + /* second byte for reading / byte for writing */ +#define TEA5761_INTREG_IFMSK 0x10 +#define TEA5761_INTREG_LEVMSK 0x8 +#define TEA5761_INTREG_FRMSK 0x2 +#define TEA5761_INTREG_BLMSK 0x1 + +/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */ + + /* First byte */ +#define TEA5761_FRQSET_SEARCH_UP 0x80 /* 1=Station search from botton to up */ +#define TEA5761_FRQSET_SEARCH_MODE 0x40 /* 1=Search mode */ + + /* Bits 0-5 for divider MSB */ + + /* Second byte */ + /* Bits 0-7 for divider LSB */ + +/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */ + + /* first byte */ + +#define TEA5761_TNCTRL_PUPD_0 0x40 /* Power UP/Power Down MSB */ +#define TEA5761_TNCTRL_BLIM 0X20 /* 1= Japan Frequencies, 0= European frequencies */ +#define TEA5761_TNCTRL_SWPM 0x10 /* 1= software port is FRRFLAG */ +#define TEA5761_TNCTRL_IFCTC 0x08 /* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */ +#define TEA5761_TNCTRL_AFM 0x04 +#define TEA5761_TNCTRL_SMUTE 0x02 /* 1= Soft mute */ +#define TEA5761_TNCTRL_SNC 0x01 + + /* second byte */ + +#define TEA5761_TNCTRL_MU 0x80 /* 1=Hard mute */ +#define TEA5761_TNCTRL_SSL_1 0x40 +#define TEA5761_TNCTRL_SSL_0 0x20 +#define TEA5761_TNCTRL_HLSI 0x10 +#define TEA5761_TNCTRL_MST 0x08 /* 1 = mono */ +#define TEA5761_TNCTRL_SWP 0x04 +#define TEA5761_TNCTRL_DTC 0x02 /* 1 = deemphasis 50 us, 0 = deemphasis 75 us */ +#define TEA5761_TNCTRL_AHLSI 0x01 + +/* FRQCHECK - Read: bytes 6 and 7 */ + /* First byte */ + + /* Bits 0-5 for divider MSB */ + + /* Second byte */ + /* Bits 0-7 for divider LSB */ + +/* TUNCHECK - Read: bytes 8 and 9 */ + + /* First byte */ +#define TEA5761_TUNCHECK_IF_MASK 0x7e /* IF count */ +#define TEA5761_TUNCHECK_TUNTO 0x01 + + /* Second byte */ +#define TEA5761_TUNCHECK_LEV_MASK 0xf0 /* Level Count */ +#define TEA5761_TUNCHECK_LD 0x08 +#define TEA5761_TUNCHECK_STEREO 0x04 + +/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */ + + /* All zero = no test mode */ + +/* MANID - Read: bytes 12 and 13 */ + + /* First byte - should be 0x10 */ +#define TEA5767_MANID_VERSION_MASK 0xf0 /* Version = 1 */ +#define TEA5767_MANID_ID_MSB_MASK 0x0f /* Manufacurer ID - should be 0 */ + + /* Second byte - Should be 0x2b */ + +#define TEA5767_MANID_ID_LSB_MASK 0xfe /* Manufacturer ID - should be 0x15 */ +#define TEA5767_MANID_IDAV 0x01 /* 1 = Chip has ID, 0 = Chip has no ID */ + +/* Chip ID - Read: bytes 14 and 15 */ + + /* First byte - should be 0x57 */ + + /* Second byte - should be 0x61 */ + +/*****************************************************************************/ + +static void set_tv_freq(struct i2c_client *c, unsigned int freq) +{ + struct tuner *t = i2c_get_clientdata(c); + + tuner_warn("This tuner doesn't support TV freq.\n"); +} + +#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */ +static void tea5761_status_dump(unsigned char *buffer) +{ + unsigned int div, frq; + + div = ((buffer[2] & 0x3f) << 8) | buffer[3]; + + frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4; /* Freq in KHz */ + + printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n", + frq / 1000, frq % 1000, div); +} + +/* Freq should be specifyed at 62.5 Hz */ +static void set_radio_freq(struct i2c_client *c, unsigned int frq) +{ + struct tuner *t = i2c_get_clientdata(c); + unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; + unsigned div; + int rc; + + tuner_dbg (PREFIX "radio freq counter %d\n", frq); + + if (t->mode == T_STANDBY) { + tuner_dbg("TEA5761 set to standby mode\n"); + buffer[5] |= TEA5761_TNCTRL_MU; + } else { + buffer[4] |= TEA5761_TNCTRL_PUPD_0; + } + + + if (t->audmode == V4L2_TUNER_MODE_MONO) { + tuner_dbg("TEA5761 set to mono\n"); + buffer[5] |= TEA5761_TNCTRL_MST; +; + } else { + tuner_dbg("TEA5761 set to stereo\n"); + } + + div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15; + buffer[1] = (div >> 8) & 0x3f; + buffer[2] = div & 0xff; + + if (tuner_debug) + tea5761_status_dump(buffer); + + if (7 != (rc = i2c_master_send(c, buffer, 7))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); +} + +static int tea5761_signal(struct i2c_client *c) +{ + unsigned char buffer[16]; + int rc; + struct tuner *t = i2c_get_clientdata(c); + + memset(buffer, 0, sizeof(buffer)); + if (16 != (rc = i2c_master_recv(c, buffer, 16))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); + + return ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4)); +} + +static int tea5761_stereo(struct i2c_client *c) +{ + unsigned char buffer[16]; + int rc; + struct tuner *t = i2c_get_clientdata(c); + + memset(buffer, 0, sizeof(buffer)); + if (16 != (rc = i2c_master_recv(c, buffer, 16))) + tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc); + + rc = buffer[9] & TEA5761_TUNCHECK_STEREO; + + tuner_dbg("TEA5761 radio ST GET = %02x\n", rc); + + return (rc ? V4L2_TUNER_SUB_STEREO : 0); +} + +int tea5761_autodetection(struct i2c_client *c) +{ + unsigned char buffer[16]; + int rc; + struct tuner *t = i2c_get_clientdata(c); + + if (16 != (rc = i2c_master_recv(c, buffer, 16))) { + tuner_warn("it is not a TEA5761. Received %i chars.\n", rc); + return EINVAL; + } + + if (!((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061))) { + tuner_warn("Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",buffer[13],buffer[14],buffer[15]); + return EINVAL; + } + tuner_warn("TEA5761 detected.\n"); + return 0; +} + +static struct tuner_operations tea5761_tuner_ops = { + .set_tv_freq = set_tv_freq, + .set_radio_freq = set_radio_freq, + .has_signal = tea5761_signal, + .is_stereo = tea5761_stereo, +}; + +int tea5761_tuner_init(struct i2c_client *c) +{ + struct tuner *t = i2c_get_clientdata(c); + + if (tea5761_autodetection(c) == EINVAL) + return EINVAL; + + tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5761HN FM Radio"); + strlcpy(c->name, "tea5761", sizeof(c->name)); + + memcpy(&t->ops, &tea5761_tuner_ops, sizeof(struct tuner_operations)); + + return (0); +} diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index d1c41781ccc..4985d47a508 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -13,7 +13,7 @@ #include <linux/i2c.h> #include <linux/videodev.h> #include <linux/delay.h> -#include <media/tuner.h> +#include "tuner-driver.h" #define PREFIX "TEA5767 " @@ -343,6 +343,14 @@ int tea5767_autodetection(struct i2c_client *c) return 0; } +static struct tuner_operations tea5767_tuner_ops = { + .set_tv_freq = set_tv_freq, + .set_radio_freq = set_radio_freq, + .has_signal = tea5767_signal, + .is_stereo = tea5767_stereo, + .standby = tea5767_standby, +}; + int tea5767_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); @@ -350,11 +358,7 @@ int tea5767_tuner_init(struct i2c_client *c) tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio"); strlcpy(c->name, "tea5767", sizeof(c->name)); - t->set_tv_freq = set_tv_freq; - t->set_radio_freq = set_radio_freq; - t->has_signal = tea5767_signal; - t->is_stereo = tea5767_stereo; - t->standby = tea5767_standby; + memcpy(&t->ops, &tea5767_tuner_ops, sizeof(struct tuner_operations)); return (0); } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 505591a7abe..e646465464a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -20,11 +20,15 @@ #include <media/tuner.h> #include <media/v4l2-common.h> +#include "tuner-driver.h" #define UNSET (-1U) /* standard i2c insmod options */ static unsigned short normal_i2c[] = { +#ifdef CONFIG_TUNER_TEA5761 + 0x10, +#endif 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, @@ -77,7 +81,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->set_tv_freq) { + if (NULL == t->ops.set_tv_freq) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -92,7 +96,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - t->set_tv_freq(c, freq); + t->ops.set_tv_freq(c, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -103,7 +107,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->set_radio_freq) { + if (NULL == t->ops.set_radio_freq) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } @@ -119,7 +123,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) freq = radio_range[1] * 16000; } - t->set_radio_freq(c, freq); + t->ops.set_radio_freq(c, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -174,6 +178,14 @@ static void set_type(struct i2c_client *c, unsigned int type, return; } + /* discard private data, in case set_type() was previously called */ + if (t->ops.release) + t->ops.release(c); + else { + kfree(t->priv); + t->priv = NULL; + } + switch (t->type) { case TUNER_MT2032: microtune_init(c); @@ -189,6 +201,16 @@ static void set_type(struct i2c_client *c, unsigned int type, } t->mode_mask = T_RADIO; break; +#ifdef CONFIG_TUNER_TEA5761 + case TUNER_TEA5761: + if (tea5761_tuner_init(c) == EINVAL) { + t->type = TUNER_ABSENT; + t->mode_mask = T_UNINITIALIZED; + return; + } + t->mode_mask = T_RADIO; + break; +#endif case TUNER_PHILIPS_FMD1216ME_MK3: buffer[0] = 0x0b; buffer[1] = 0xdc; @@ -408,11 +430,11 @@ static void tuner_status(struct i2c_client *client) tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); if (t->mode != V4L2_TUNER_RADIO) return; - if (t->has_signal) { - tuner_info("Signal strength: %d\n", t->has_signal(client)); + if (t->ops.has_signal) { + tuner_info("Signal strength: %d\n", t->ops.has_signal(client)); } - if (t->is_stereo) { - tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); + if (t->ops.is_stereo) { + tuner_info("Stereo: %s\n", t->ops.is_stereo(client) ? "yes" : "no"); } } @@ -437,10 +459,9 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) memcpy(&t->i2c, &client_template, sizeof(struct i2c_client)); i2c_set_clientdata(&t->i2c, t); t->type = UNSET; - t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; - t->tuner_status = tuner_status; + t->ops.tuner_status = tuner_status; if (show_i2c) { unsigned char buffer[16]; @@ -460,6 +481,19 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* autodetection code based on the i2c addr */ if (!no_autodetect) { switch (addr) { +#ifdef CONFIG_TUNER_TEA5761 + case 0x10: + if (tea5761_autodetection(&t->i2c) != EINVAL) { + t->type = TUNER_TEA5761; + t->mode_mask = T_RADIO; + t->mode = T_STANDBY; + t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */ + default_mode_mask &= ~T_RADIO; + + goto register_client; + } + break; +#endif case 0x42: case 0x43: case 0x4a: @@ -533,6 +567,11 @@ static int tuner_detach(struct i2c_client *client) return err; } + if (t->ops.release) + t->ops.release(client); + else { + kfree(t->priv); + } kfree(t); return 0; } @@ -553,8 +592,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; - if (t->standby) - t->standby (client); + if (t->ops.standby) + t->ops.standby (client); return EINVAL; } return 0; @@ -602,8 +641,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; t->mode = T_STANDBY; - if (t->standby) - t->standby (client); + if (t->ops.standby) + t->ops.standby (client); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -662,10 +701,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; if (V4L2_TUNER_RADIO == t->mode) { - if (t->has_signal) - vt->signal = t->has_signal(client); - if (t->is_stereo) { - if (t->is_stereo(client)) + if (t->ops.has_signal) + vt->signal = t->ops.has_signal(client); + if (t->ops.is_stereo) { + if (t->ops.is_stereo(client)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -693,8 +732,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_v4l2(t) == EINVAL) return 0; - if (V4L2_TUNER_RADIO == t->mode && t->is_stereo) - va->mode = t->is_stereo(client) + if (V4L2_TUNER_RADIO == t->mode && t->ops.is_stereo) + va->mode = t->ops.is_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; return 0; } @@ -759,8 +798,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; - if (t->get_afc) - tuner->afc=t->get_afc(client); + if (t->ops.get_afc) + tuner->afc=t->ops.get_afc(client); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -770,13 +809,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } /* radio mode */ - if (t->has_signal) - tuner->signal = t->has_signal(client); + if (t->ops.has_signal) + tuner->signal = t->ops.has_signal(client); tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - if (t->is_stereo) { - tuner->rxsubchans = t->is_stereo(client) ? + if (t->ops.is_stereo) { + tuner->rxsubchans = t->ops.is_stereo(client) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } @@ -804,8 +843,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case VIDIOC_LOG_STATUS: - if (t->tuner_status) - t->tuner_status(client); + if (t->ops.tuner_status) + t->ops.tuner_status(client); break; } diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h new file mode 100644 index 00000000000..0334a912507 --- /dev/null +++ b/drivers/media/video/tuner-driver.h @@ -0,0 +1,107 @@ +/* + tuner-driver.h - interface for different tuners + + Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de) + minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 __TUNER_HW_H__ +#define __TUNER_HW_H__ + +#include <linux/videodev2.h> +#include <linux/i2c.h> + +extern unsigned const int tuner_count; + +struct tuner_operations { + void (*set_tv_freq)(struct i2c_client *c, unsigned int freq); + void (*set_radio_freq)(struct i2c_client *c, unsigned int freq); + int (*has_signal)(struct i2c_client *c); + int (*is_stereo)(struct i2c_client *c); + int (*get_afc)(struct i2c_client *c); + void (*tuner_status)(struct i2c_client *c); + void (*standby)(struct i2c_client *c); + void (*release)(struct i2c_client *c); +}; + +struct tuner { + /* device */ + struct i2c_client i2c; + + unsigned int type; /* chip type */ + + unsigned int mode; + unsigned int mode_mask; /* Combination of allowable modes */ + + unsigned int tv_freq; /* keep track of the current settings */ + unsigned int radio_freq; + u16 last_div; + unsigned int audmode; + v4l2_std_id std; + + int using_v4l2; + void *priv; + + /* used by tda9887 */ + unsigned int tda9887_config; + + unsigned int config; + int (*tuner_callback) (void *dev, int command,int arg); + + struct tuner_operations ops; +}; + +/* ------------------------------------------------------------------------ */ + +extern int default_tuner_init(struct i2c_client *c); + +extern int tda9887_tuner_init(struct i2c_client *c); + +extern int microtune_init(struct i2c_client *c); + +extern int tda8290_init(struct i2c_client *c); +extern int tda8290_probe(struct i2c_client *c); + +extern int tea5761_tuner_init(struct i2c_client *c); +extern int tea5761_autodetection(struct i2c_client *c); + +extern int tea5767_autodetection(struct i2c_client *c); +extern int tea5767_tuner_init(struct i2c_client *c); + +/* ------------------------------------------------------------------------ */ + +#define tuner_warn(fmt, arg...) do {\ + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_info(fmt, arg...) do {\ + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tuner_dbg(fmt, arg...) do {\ + extern int tuner_debug; \ + if (tuner_debug) \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + +#endif /* __TUNER_HW_H__ */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index c40b92ce1fa..2d57e8bc0db 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -8,6 +8,8 @@ #include <linux/videodev.h> #include <media/tuner.h> #include <media/v4l2-common.h> +#include <media/tuner-types.h> +#include "tuner-driver.h" static int offset = 0; module_param(offset, int, 0664); @@ -54,9 +56,9 @@ MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner"); sound 2 33.16 - - NICAM 33.05 33.05 39.80 */ -#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ -#define PHILIPS_MF_SET_PAL_L 0x03 // France -#define PHILIPS_MF_SET_PAL_L2 0x02 // L' +#define PHILIPS_MF_SET_STD_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */ +#define PHILIPS_MF_SET_STD_L 0x03 /* Used on Secam France */ +#define PHILIPS_MF_SET_STD_LC 0x02 /* Used on SECAM L' */ /* Control byte */ @@ -207,11 +209,11 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) /* 0x04 -> ??? PAL others / SECAM others ??? */ cb &= ~0x03; if (t->std & V4L2_STD_SECAM_L) //also valid for V4L2_STD_SECAM - cb |= PHILIPS_MF_SET_PAL_L; + cb |= PHILIPS_MF_SET_STD_L; else if (t->std & V4L2_STD_SECAM_LC) - cb |= PHILIPS_MF_SET_PAL_L2; + cb |= PHILIPS_MF_SET_STD_LC; else /* V4L2_STD_B|V4L2_STD_GH */ - cb |= PHILIPS_MF_SET_BG; + cb |= PHILIPS_MF_SET_STD_BG; break; case TUNER_TEMIC_4046FM5: @@ -479,6 +481,13 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); } +static struct tuner_operations simple_tuner_ops = { + .set_tv_freq = default_set_tv_freq, + .set_radio_freq = default_set_radio_freq, + .has_signal = tuner_signal, + .is_stereo = tuner_stereo, +}; + int default_tuner_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); @@ -487,11 +496,7 @@ int default_tuner_init(struct i2c_client *c) t->type, tuners[t->type].name); strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); - t->set_tv_freq = default_set_tv_freq; - t->set_radio_freq = default_set_radio_freq; - t->has_signal = tuner_signal; - t->is_stereo = tuner_stereo; - t->standby = NULL; + memcpy(&t->ops, &simple_tuner_ops, sizeof(struct tuner_operations)); return 0; } diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 74c3e6f96f1..417f642b435 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -594,19 +594,19 @@ static struct tuner_params tuner_philips_pal_mk_params[] = { }, }; -/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */ +/* ---- TUNER_PHILIPS_ATSC - Philips FCV1236D (ATSC/NTSC) ---- */ -static struct tuner_range tuner_philips_atsc_ranges[] = { +static struct tuner_range tuner_philips_fcv1236d_ranges[] = { { 16 * 157.25 /*MHz*/, 0x8e, 0xa0, }, - { 16 * 454.00 /*MHz*/, 0x8e, 0x90, }, + { 16 * 451.25 /*MHz*/, 0x8e, 0x90, }, { 16 * 999.99 , 0x8e, 0x30, }, }; -static struct tuner_params tuner_philips_atsc_params[] = { +static struct tuner_params tuner_philips_fcv1236d_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, - .ranges = tuner_philips_atsc_ranges, - .count = ARRAY_SIZE(tuner_philips_atsc_ranges), + .ranges = tuner_philips_fcv1236d_ranges, + .count = ARRAY_SIZE(tuner_philips_fcv1236d_ranges), }, }; @@ -1296,9 +1296,9 @@ struct tunertype tuners[] = { .count = ARRAY_SIZE(tuner_philips_pal_mk_params), }, [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */ - .name = "Philips 1236D ATSC/NTSC dual in", - .params = tuner_philips_atsc_params, - .count = ARRAY_SIZE(tuner_philips_atsc_params), + .name = "Philips FCV1236D ATSC/NTSC dual in", + .params = tuner_philips_fcv1236d_params, + .count = ARRAY_SIZE(tuner_philips_fcv1236d_params), }, [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", @@ -1463,6 +1463,10 @@ struct tunertype tuners[] = { .name = "Philips TDA988[5,6,7] IF PLL Demodulator", /* see tda9887.c for details */ }, + [TUNER_TEA5761] = { /* Philips RADIO */ + .name = "Philips TEA5761 FM Radio", + /* see tea5767.c for details */ + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index c9bf9dbc2ea..cffb011590e 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -271,7 +271,7 @@ static int chip_thread(void *data) struct CHIPDESC *desc = chiplist + chip->type; v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name); - + set_freezable(); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (!kthread_should_stop()) @@ -290,7 +290,7 @@ static int chip_thread(void *data) desc->checkmode(chip); /* schedule next check */ - mod_timer(&chip->wt, jiffies+2*HZ); + mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); } v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name); @@ -1770,7 +1770,7 @@ static int chip_command(struct i2c_client *client, desc->setmode(chip,VIDEO_SOUND_MONO); if (chip->prevmode != VIDEO_SOUND_MONO) chip->prevmode = -1; /* reset previous mode */ - mod_timer(&chip->wt, jiffies+2*HZ); + mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); /* the thread will call checkmode() later */ } break; diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index a1136da74ba..fdc3def437b 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -183,7 +183,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Silicon TDA8275C1 8290 FM"}, { TUNER_ABSENT, "Thompson DTT757"}, /* 80-89 */ - { TUNER_ABSENT, "Philips FQ1216LME MK3"}, + { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216LME MK3"}, { TUNER_LG_PAL_NEW_TAPC, "LG TAPC G701D"}, { TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"}, { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"}, @@ -490,7 +490,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+2] & 0x7f; - if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + if (audioic < ARRAY_SIZE(audioIC)) tvee->audio_processor = audioIC[audioic].id; else tvee->audio_processor = AUDIO_CHIP_UNKNOWN; @@ -523,7 +523,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+1] & 0x7f; - if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + if (audioic < ARRAY_SIZE(audioIC)) tvee->audio_processor = audioIC[audioic].id; else tvee->audio_processor = AUDIO_CHIP_UNKNOWN; @@ -678,7 +678,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tveeprom_info("audio processor is unknown (no idx)\n"); tvee->audio_processor=AUDIO_CHIP_UNKNOWN; } else { - if (audioic < sizeof(audioIC)/sizeof(*audioIC)) + if (audioic < ARRAY_SIZE(audioIC)) tveeprom_info("audio processor is %s (idx %d)\n", audioIC[audioic].name,audioic); else diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index d5ec05f56ad..e2f1c972754 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -1006,7 +1006,7 @@ static int tvp5150_command(struct i2c_client *c, { struct v4l2_control *ctrl = arg; u8 i, n; - n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]); + n = ARRAY_SIZE(tvp5150_qctrl); for (i = 0; i < n; i++) if (ctrl->id == tvp5150_qctrl[i].id) { if (ctrl->value < diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index abe21461909..491505d6fde 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -236,7 +236,7 @@ static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev input_dev->name = "Konicawc snapshot button"; input_dev->phys = cam->input_physname; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &dev->dev; + input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT(EV_KEY); input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index ec0ff2247f0..dd1a6d6bbc9 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -100,7 +100,7 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev) input_dev->name = "QCM button"; input_dev->phys = cam->input_physname; usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &dev->dev; + input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT(EV_KEY); input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); @@ -439,7 +439,7 @@ static int qcm_sensor_init(struct uvd *uvd) int ret; int i; - for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) { + for (i=0; i < ARRAY_SIZE(regval_table) ; i++) { CHECK_RET(ret, qcm_stv_setb(uvd->dev, regval_table[i].reg, regval_table[i].val)); diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 982b115193f..ff555129c82 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -42,7 +42,6 @@ #include <linux/usb.h> #include <linux/vmalloc.h> #include <linux/slab.h> -#include <linux/proc_fs.h> #include <linux/mutex.h> #include "usbvideo.h" @@ -417,11 +416,6 @@ struct vicam_camera { u8 open_count; u8 bulkEndpoint; int needsDummyRead; - -#if defined(CONFIG_VIDEO_PROC_FS) - struct proc_dir_entry *proc_dir; -#endif - }; static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id); @@ -1065,175 +1059,6 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -#if defined(CONFIG_VIDEO_PROC_FS) - -static struct proc_dir_entry *vicam_proc_root = NULL; - -static int vicam_read_helper(char *page, char **start, off_t off, - int count, int *eof, int value) -{ - char *out = page; - int len; - - out += sprintf(out, "%d",value); - - len = out - page; - len -= off; - if (len < count) { - *eof = 1; - if (len <= 0) - return 0; - } else - len = count; - - *start = page + off; - return len; -} - -static int vicam_read_proc_shutter(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - return vicam_read_helper(page,start,off,count,eof, - ((struct vicam_camera *)data)->shutter_speed); -} - -static int vicam_read_proc_gain(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - return vicam_read_helper(page,start,off,count,eof, - ((struct vicam_camera *)data)->gain); -} - -static int -vicam_write_proc_shutter(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - u16 stmp; - char kbuf[8]; - struct vicam_camera *cam = (struct vicam_camera *) data; - - if (count > 6) - return -EINVAL; - - if (copy_from_user(kbuf, buffer, count)) - return -EFAULT; - - stmp = (u16) simple_strtoul(kbuf, NULL, 10); - if (stmp < 4 || stmp > 32000) - return -EINVAL; - - cam->shutter_speed = stmp; - - return count; -} - -static int -vicam_write_proc_gain(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - u16 gtmp; - char kbuf[8]; - - struct vicam_camera *cam = (struct vicam_camera *) data; - - if (count > 4) - return -EINVAL; - - if (copy_from_user(kbuf, buffer, count)) - return -EFAULT; - - gtmp = (u16) simple_strtoul(kbuf, NULL, 10); - if (gtmp > 255) - return -EINVAL; - cam->gain = gtmp; - - return count; -} - -static void -vicam_create_proc_root(void) -{ - vicam_proc_root = proc_mkdir("video/vicam", NULL); - - if (vicam_proc_root) - vicam_proc_root->owner = THIS_MODULE; - else - printk(KERN_ERR - "could not create /proc entry for vicam!"); -} - -static void -vicam_destroy_proc_root(void) -{ - if (vicam_proc_root) - remove_proc_entry("video/vicam", 0); -} - -static void -vicam_create_proc_entry(struct vicam_camera *cam) -{ - char name[64]; - struct proc_dir_entry *ent; - - DBG(KERN_INFO "vicam: creating proc entry\n"); - - if (!vicam_proc_root || !cam) { - printk(KERN_INFO - "vicam: could not create proc entry, %s pointer is null.\n", - (!cam ? "camera" : "root")); - return; - } - - sprintf(name, "video%d", cam->vdev.minor); - - cam->proc_dir = proc_mkdir(name, vicam_proc_root); - - if ( !cam->proc_dir ) - return; // FIXME: We should probably return an error here - - ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); - if (ent) { - ent->data = cam; - ent->read_proc = vicam_read_proc_shutter; - ent->write_proc = vicam_write_proc_shutter; - ent->size = 64; - } - - ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); - if (ent) { - ent->data = cam; - ent->read_proc = vicam_read_proc_gain; - ent->write_proc = vicam_write_proc_gain; - ent->size = 64; - } -} - -static void -vicam_destroy_proc_entry(void *ptr) -{ - struct vicam_camera *cam = (struct vicam_camera *) ptr; - char name[16]; - - if ( !cam->proc_dir ) - return; - - sprintf(name, "video%d", cam->vdev.minor); - remove_proc_entry("shutter", cam->proc_dir); - remove_proc_entry("gain", cam->proc_dir); - remove_proc_entry(name,vicam_proc_root); - cam->proc_dir = NULL; - -} - -#else -static inline void vicam_create_proc_root(void) { } -static inline void vicam_destroy_proc_root(void) { } -static inline void vicam_create_proc_entry(struct vicam_camera *cam) { } -static inline void vicam_destroy_proc_entry(void *ptr) { } -#endif - static const struct file_operations vicam_fops = { .owner = THIS_MODULE, .open = vicam_open, @@ -1305,13 +1130,12 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) } if ((cam = - kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { + kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "could not allocate kernel memory for vicam_camera struct\n"); return -ENOMEM; } - memset(cam, 0, sizeof (struct vicam_camera)); cam->shutter_speed = 15; @@ -1330,8 +1154,6 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) return -EIO; } - vicam_create_proc_entry(cam); - printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); usb_set_intfdata (intf, cam); @@ -1363,8 +1185,6 @@ vicam_disconnect(struct usb_interface *intf) cam->udev = NULL; - vicam_destroy_proc_entry(cam); - /* the only thing left to do is synchronize with * our close/release function on who should release * the camera memory. if there are any users using the @@ -1390,7 +1210,6 @@ usb_vicam_init(void) { int retval; DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); - vicam_create_proc_root(); retval = usb_register(&vicam_driver); if (retval) printk(KERN_WARNING "usb_register failed!\n"); @@ -1404,7 +1223,6 @@ usb_vicam_exit(void) "ViCam-based WebCam driver shutdown\n"); usb_deregister(&vicam_driver); - vicam_destroy_proc_root(); } module_init(usb_vicam_init); diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 51ab265d566..380564cd331 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c @@ -79,7 +79,7 @@ struct usbvision_device_data_st usbvision_device_data[] = { .Interface = -1, .Codec = CODEC_SAA7113, .VideoChannels = 2, - .VideoNorm = V4L2_STD_PAL, + .VideoNorm = V4L2_STD_NTSC, .AudioChannels = 1, .Radio = 0, .vbi = 1, @@ -311,8 +311,8 @@ struct usbvision_device_data_st usbvision_device_data[] = { .vbi = 1, .Tuner = 1, .TunerType = TUNER_PHILIPS_SECAM, - .X_Offset = -1, - .Y_Offset = -1, + .X_Offset = 0x80, + .Y_Offset = 0x16, .ModelString = "Hauppauge WinTV USB (PAL/SECAM L)", }, [HPG_WINTV_PAL_D_K] = { @@ -586,7 +586,7 @@ struct usbvision_device_data_st usbvision_device_data[] = { .Radio = 0, .vbi = 1, .Tuner = 1, - .TunerType = TUNER_PHILIPS_PAL, + .TunerType = TUNER_LG_PAL_NEW_TAPC, .X_Offset = 0, .Y_Offset = 3, .Dvi_yuv_override = 1, diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 7df071eb0a3..5b1e346df20 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -1742,7 +1742,7 @@ static int usbvision_set_video_format(struct usb_usbvision *usbvision, int forma format = ISOC_MODE_YUV420; } value[0] = 0x0A; //TODO: See the effect of the filter - value[1] = format; + value[1] = format; // Sets the VO_MODE register which follows FILT_CONT rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | @@ -1831,10 +1831,10 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, frameRate = FRAMERATE_MAX; } - if (usbvision->tvnorm->id & V4L2_STD_625_50) { + if (usbvision->tvnormId & V4L2_STD_625_50) { frameDrop = frameRate * 32 / 25 - 1; } - else if (usbvision->tvnorm->id & V4L2_STD_525_60) { + else if (usbvision->tvnormId & V4L2_STD_525_60) { frameDrop = frameRate * 32 / 30 - 1; } @@ -2067,7 +2067,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) } - if (usbvision->tvnorm->id & V4L2_STD_PAL) { + if (usbvision->tvnormId & V4L2_STD_PAL) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2076,7 +2076,7 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[5] = 0x00; //0x0060 -> 96 Input video h offset value[6] = 0x16; value[7] = 0x00; //0x0016 -> 22 Input video v offset - } else if (usbvision->tvnorm->id & V4L2_STD_SECAM) { + } else if (usbvision->tvnormId & V4L2_STD_SECAM) { value[0] = 0xC0; value[1] = 0x02; //0x02C0 -> 704 Input video line length value[2] = 0x20; @@ -2537,7 +2537,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) { - int mode[4]; + /* inputs #0 and #3 are constant for every SAA711x. */ + /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ + int mode[4]= {SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3}; int audio[]= {1, 0, 0, 0}; struct v4l2_routing route; //channel 0 is TV with audiochannel 1 (tuner mono) @@ -2547,10 +2549,6 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); usbvision->ctl_input = channel; - route.input = SAA7115_COMPOSITE1; - route.output = 0; - call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); - call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); // set the new channel // Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video @@ -2558,28 +2556,27 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: - if (SwitchSVideoInput) { // To handle problems with S-Video Input for some devices. Use SwitchSVideoInput parameter when loading the module. - mode[2] = 1; + mode[1] = SAA7115_COMPOSITE2; + if (SwitchSVideoInput) { + /* To handle problems with S-Video Input for + * some devices. Use SwitchSVideoInput + * parameter when loading the module.*/ + mode[2] = SAA7115_COMPOSITE1; } else { - mode[2] = 7; - } - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - mode[0] = 0; mode[1] = 2; mode[3] = 3; // Special for four input devices - } - else { - mode[0] = 0; mode[1] = 2; //modes for regular saa7113 devices + mode[2] = SAA7115_SVIDEO1; } break; case CODEC_SAA7111: - mode[0] = 0; mode[1] = 1; mode[2] = 7; //modes for saa7111 - break; default: - mode[0] = 0; mode[1] = 1; mode[2] = 7; //default modes + /* modes for saa7111 */ + mode[1] = SAA7115_COMPOSITE1; + mode[2] = SAA7115_SVIDEO1; + break; } route.input = mode[channel]; + route.output = 0; call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); - usbvision->channel = channel; usbvision_set_audio(usbvision, audio[channel]); return 0; } diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index aa3258bbb4a..868b6886fe7 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -36,7 +36,8 @@ * - use submit_urb for all setup packets * - Fix memory settings for nt1004. It is 4 times as big as the * nt1003 memory. - * - Add audio on endpoint 3 for nt1004 chip. Seems impossible, needs a codec interface. Which one? + * - Add audio on endpoint 3 for nt1004 chip. + * Seems impossible, needs a codec interface. Which one? * - Clean up the driver. * - optimization for performance. * - Add Videotext capability (VBI). Working on it..... @@ -77,7 +78,8 @@ #include "usbvision.h" #include "usbvision-cards.h" -#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>, Dwaine Garden <DwaineGarden@rogers.com>" +#define DRIVER_AUTHOR "Joerg Heckenbach <joerg@heckenbach-aw.de>,\ + Dwaine Garden <DwaineGarden@rogers.com>" #define DRIVER_NAME "usbvision" #define DRIVER_ALIAS "USBVision" #define DRIVER_DESC "USBVision USB Video Device Driver for Linux" @@ -85,20 +87,25 @@ #define USBVISION_DRIVER_VERSION_MAJOR 0 #define USBVISION_DRIVER_VERSION_MINOR 9 #define USBVISION_DRIVER_VERSION_PATCHLEVEL 9 -#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,USBVISION_DRIVER_VERSION_MINOR,USBVISION_DRIVER_VERSION_PATCHLEVEL) -#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR) "." __stringify(USBVISION_DRIVER_VERSION_MINOR) "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) +#define USBVISION_DRIVER_VERSION KERNEL_VERSION(USBVISION_DRIVER_VERSION_MAJOR,\ +USBVISION_DRIVER_VERSION_MINOR,\ +USBVISION_DRIVER_VERSION_PATCHLEVEL) +#define USBVISION_VERSION_STRING __stringify(USBVISION_DRIVER_VERSION_MAJOR)\ + "." __stringify(USBVISION_DRIVER_VERSION_MINOR)\ + "." __stringify(USBVISION_DRIVER_VERSION_PATCHLEVEL) #define ENABLE_HEXDUMP 0 /* Enable if you need it */ #ifdef USBVISION_DEBUG #define PDEBUG(level, fmt, args...) \ - if (video_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) + if (video_debug & (level)) \ + info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ ,\ + ## args) #else #define PDEBUG(level, fmt, args...) do {} while(0) #endif -#define DBG_IOCTL 1<<0 #define DBG_IO 1<<1 #define DBG_PROBE 1<<2 #define DBG_MMAP 1<<3 @@ -108,7 +115,8 @@ #define goto2next(str) while(*str!=' ') str++; while(*str==' ') str++; -static int usbvision_nr = 0; // sequential number of usbvision device +/* sequential number of usbvision device */ +static int usbvision_nr = 0; static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, @@ -121,55 +129,32 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } }; -/* supported tv norms */ -static struct usbvision_tvnorm tvnorms[] = { - { - .name = "PAL", - .id = V4L2_STD_PAL, - }, { - .name = "NTSC", - .id = V4L2_STD_NTSC, - }, { - .name = "SECAM", - .id = V4L2_STD_SECAM, - }, { - .name = "PAL-M", - .id = V4L2_STD_PAL_M, - } -}; - -#define TVNORMS ARRAY_SIZE(tvnorms) - -// Function prototypes +/* Function prototypes */ static void usbvision_release(struct usb_usbvision *usbvision); -// Default initalization of device driver parameters -static int isocMode = ISOC_MODE_COMPRESS; // Set the default format for ISOC endpoint -static int video_debug = 0; // Set the default Debug Mode of the device driver -static int PowerOnAtOpen = 1; // Set the default device to power on at startup -static int video_nr = -1; // Sequential Number of Video Device -static int radio_nr = -1; // Sequential Number of Radio Device -static int vbi_nr = -1; // Sequential Number of VBI Device - -// Grab parameters for the device driver - -#if defined(module_param) // Showing parameters under SYSFS +/* Default initalization of device driver parameters */ +/* Set the default format for ISOC endpoint */ +static int isocMode = ISOC_MODE_COMPRESS; +/* Set the default Debug Mode of the device driver */ +static int video_debug = 0; +/* Set the default device to power on at startup */ +static int PowerOnAtOpen = 1; +/* Sequential Number of Video Device */ +static int video_nr = -1; +/* Sequential Number of Radio Device */ +static int radio_nr = -1; +/* Sequential Number of VBI Device */ +static int vbi_nr = -1; + +/* Grab parameters for the device driver */ + +/* Showing parameters under SYSFS */ module_param(isocMode, int, 0444); module_param(video_debug, int, 0444); module_param(PowerOnAtOpen, int, 0444); module_param(video_nr, int, 0444); module_param(radio_nr, int, 0444); module_param(vbi_nr, int, 0444); -#else // Old Style -MODULE_PARAM(isocMode, "i"); -MODULE_PARM(video_debug, "i"); // Grab the Debug Mode of the device driver -MODULE_PARM(adjustCompression, "i"); // Grab the compression to be adaptive -MODULE_PARM(PowerOnAtOpen, "i"); // Grab the device to power on at startup -MODULE_PARM(SwitchSVideoInput, "i"); // To help people with Black and White output with using s-video input. Some cables and input device are wired differently. -MODULE_PARM(video_nr, "i"); // video_nr option allows to specify a certain /dev/videoX device (like /dev/video0 or /dev/video1 ...) -MODULE_PARM(radio_nr, "i"); // radio_nr option allows to specify a certain /dev/radioX device (like /dev/radio0 or /dev/radio1 ...) -MODULE_PARM(vbi_nr, "i"); // vbi_nr option allows to specify a certain /dev/vbiX device (like /dev/vbi0 or /dev/vbi1 ...) -#endif MODULE_PARM_DESC(isocMode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); @@ -187,19 +172,21 @@ MODULE_VERSION(USBVISION_VERSION_STRING); MODULE_ALIAS(DRIVER_ALIAS); -/****************************************************************************************/ -/* SYSFS Code - Copied from the stv680.c usb module. */ -/* Device information is located at /sys/class/video4linux/video0 */ -/* Device parameters information is located at /sys/module/usbvision */ -/* Device USB Information is located at /sys/bus/usb/drivers/USBVision Video Grabber */ -/****************************************************************************************/ +/*****************************************************************************/ +/* SYSFS Code - Copied from the stv680.c usb module. */ +/* Device information is located at /sys/class/video4linux/video0 */ +/* Device parameters information is located at /sys/module/usbvision */ +/* Device USB Information is located at */ +/* /sys/bus/usb/drivers/USBVision Video Grabber */ +/*****************************************************************************/ #define YES_NO(x) ((x) ? "Yes" : "No") static inline struct usb_usbvision *cd_to_usbvision(struct class_device *cd) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); return video_get_drvdata(vdev); } @@ -211,15 +198,18 @@ static CLASS_DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t show_model(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", usbvision_device_data[usbvision->DevModel].ModelString); + return sprintf(buf, "%s\n", + usbvision_device_data[usbvision->DevModel].ModelString); } static CLASS_DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_hue(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; @@ -232,7 +222,8 @@ static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_contrast(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; @@ -245,7 +236,8 @@ static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_brightness(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; @@ -258,7 +250,8 @@ static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; @@ -271,23 +264,28 @@ static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_streaming(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->streaming==Stream_On?1:0)); + return sprintf(buf, "%s\n", + YES_NO(usbvision->streaming==Stream_On?1:0)); } static CLASS_DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); static ssize_t show_compression(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); + return sprintf(buf, "%s\n", + YES_NO(usbvision->isocMode==ISOC_MODE_COMPRESS)); } static CLASS_DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); static ssize_t show_device_bridge(struct class_device *cd, char *buf) { - struct video_device *vdev = container_of(cd, struct video_device, class_dev); + struct video_device *vdev = + container_of(cd, struct video_device, class_dev); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%d\n", usbvision->bridgeType); } @@ -376,7 +374,8 @@ static void usbvision_remove_sysfs(struct video_device *vdev) static int usbvision_v4l2_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int errCode = 0; PDEBUG(DBG_IO, "open"); @@ -390,7 +389,8 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) /* Allocate memory for the scratch ring buffer */ errCode = usbvision_scratch_alloc(usbvision); if (isocMode==ISOC_MODE_COMPRESS) { - /* Allocate intermediate decompression buffers only if needed */ + /* Allocate intermediate decompression buffers + only if needed */ errCode = usbvision_decompress_alloc(usbvision); } if (errCode) { @@ -421,11 +421,10 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) if (!errCode) { usbvision_begin_streaming(usbvision); errCode = usbvision_init_isoc(usbvision); - /* device needs to be initialized before isoc transfer */ + /* device must be initialized before isoc transfer */ usbvision_muxsel(usbvision,0); usbvision->user++; - } - else { + } else { if (PowerOnAtOpen) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); @@ -456,7 +455,8 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) static int usbvision_v4l2_close(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); PDEBUG(DBG_IO, "close"); down(&usbvision->lock); @@ -473,7 +473,8 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) usbvision->user--; if (PowerOnAtOpen) { - /* power off in a little while to avoid off/on every close/open short sequences */ + /* power off in a little while + to avoid off/on every close/open short sequences */ usbvision_set_powerOffTimer(usbvision); usbvision->initialized = 0; } @@ -498,583 +499,612 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * */ -static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int vidioc_g_register (struct file *file, void *priv, + struct v4l2_register *reg) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int errCode; - switch (cmd) { + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + /* NT100x has a 8-bit register space */ + errCode = usbvision_read_reg(usbvision, reg->reg&0xff); + if (errCode < 0) { + err("%s: VIDIOC_DBG_G_REGISTER failed: error %d", + __FUNCTION__, errCode); + return errCode; + } + return 0; +} -#ifdef CONFIG_VIDEO_ADV_DEBUG - /* ioctls to allow direct acces to the NT100x registers */ - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - int errCode; - - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - /* NT100x has a 8-bit register space */ - if (cmd == VIDIOC_DBG_G_REGISTER) - errCode = usbvision_read_reg(usbvision, reg->reg&0xff); - else - errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (errCode < 0) { - err("%s: VIDIOC_DBG_%c_REGISTER failed: error %d", __FUNCTION__, - cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', errCode); - return errCode; - } - if (cmd == VIDIOC_DBG_S_REGISTER) - reg->val = (u8)errCode; +static int vidioc_s_register (struct file *file, void *priv, + struct v4l2_register *reg) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int errCode; - PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", - cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, (unsigned int)reg->val); - return 0; - } + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + /* NT100x has a 8-bit register space */ + reg->val = (u8)usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + if (reg->val < 0) { + err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", + __FUNCTION__, errCode); + return errCode; + } + return 0; +} #endif - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IOCTL, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *vi = arg; - int chan; - - if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) - return -EINVAL; - if (usbvision->have_tuner) { - chan = vi->index; - } - else { - chan = vi->index + 1; //skip Television string - } - switch(chan) { - case 0: - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "White Video Input"); - } - else { - strcpy(vi->name, "Television"); - vi->type = V4L2_INPUT_TYPE_TUNER; - vi->audioset = 1; - vi->tuner = chan; - vi->std = V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM; - } - break; - case 1: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "Green Video Input"); - } - else { - strcpy(vi->name, "Composite Video Input"); - } - vi->std = V4L2_STD_PAL; - break; - case 2: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { - strcpy(vi->name, "Yellow Video Input"); - } - else { - strcpy(vi->name, "S-Video Input"); - } - vi->std = V4L2_STD_PAL; - break; - case 3: - vi->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(vi->name, "Red Video Input"); - vi->std = V4L2_STD_PAL; - break; - } - PDEBUG(DBG_IOCTL, "VIDIOC_ENUMINPUT name=%s:%d tuners=%d type=%d norm=%x", - vi->name, vi->index, vi->tuner,vi->type,(int)vi->std); - return 0; - } - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int i; - int ret; - - i = e->index; - if (i >= TVNORMS) - return -EINVAL; - ret = v4l2_video_std_construct(e, tvnorms[e->index].id, - tvnorms[e->index].name); - e->index = i; - if (ret < 0) - return ret; - return 0; + +static int vidioc_querycap (struct file *file, void *priv, + struct v4l2_capability *vc) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + + strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); + strlcpy(vc->card, + usbvision_device_data[usbvision->DevModel].ModelString, + sizeof(vc->card)); + strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, + sizeof(vc->bus_info)); + vc->version = USBVISION_DRIVER_VERSION; + vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING | + (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); + return 0; +} + +static int vidioc_enum_input (struct file *file, void *priv, + struct v4l2_input *vi) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int chan; + + if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) + return -EINVAL; + if (usbvision->have_tuner) { + chan = vi->index; + } else { + chan = vi->index + 1; /*skip Television string*/ + } + /* Determine the requested input characteristics + specific for each usbvision card model */ + switch(chan) { + case 0: + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "White Video Input"); + } else { + strcpy(vi->name, "Television"); + vi->type = V4L2_INPUT_TYPE_TUNER; + vi->audioset = 1; + vi->tuner = chan; + vi->std = USBVISION_NORMS; } - case VIDIOC_G_INPUT: - { - int *input = arg; - *input = usbvision->ctl_input; - return 0; + break; + case 1: + vi->type = V4L2_INPUT_TYPE_CAMERA; + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "Green Video Input"); + } else { + strcpy(vi->name, "Composite Video Input"); } - case VIDIOC_S_INPUT: - { - int *input = arg; - if ((*input >= usbvision->video_inputs) || (*input < 0) ) - return -EINVAL; - usbvision->ctl_input = *input; - - down(&usbvision->lock); - usbvision_muxsel(usbvision, usbvision->ctl_input); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, usbvision->curwidth, usbvision->curheight); - up(&usbvision->lock); - return 0; + vi->std = V4L2_STD_PAL; + break; + case 2: + vi->type = V4L2_INPUT_TYPE_CAMERA; + if (usbvision_device_data[usbvision->DevModel].VideoChannels == 4) { + strcpy(vi->name, "Yellow Video Input"); + } else { + strcpy(vi->name, "S-Video Input"); } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; + vi->std = V4L2_STD_PAL; + break; + case 3: + vi->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(vi->name, "Red Video Input"); + vi->std = V4L2_STD_PAL; + break; + } + return 0; +} - *id = usbvision->tvnorm->id; +static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - PDEBUG(DBG_IOCTL, "VIDIOC_G_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; - - for (i = 0; i < TVNORMS; i++) - if (*id == tvnorms[i].id) - break; - if (i == TVNORMS) - for (i = 0; i < TVNORMS; i++) - if (*id & tvnorms[i].id) - break; - if (i == TVNORMS) - return -EINVAL; - - down(&usbvision->lock); - usbvision->tvnorm = &tvnorms[i]; - - call_i2c_clients(usbvision, VIDIOC_S_STD, - &usbvision->tvnorm->id); + *input = usbvision->ctl_input; + return 0; +} - up(&usbvision->lock); +static int vidioc_s_input (struct file *file, void *priv, unsigned int input) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - PDEBUG(DBG_IOCTL, "VIDIOC_S_STD std_id=%s", usbvision->tvnorm->name); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *vt = arg; - - if (!usbvision->have_tuner || vt->index) // Only tuner 0 - return -EINVAL; - strcpy(vt->name, "Television"); - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_G_TUNER signal=%x, afc=%x",vt->signal,vt->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - freq->tuner = 0; // Only one tuner - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = usbvision->freq; - PDEBUG(DBG_IOCTL, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *freq = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || freq->tuner) - return -EINVAL; - - usbvision->freq = freq->frequency; - call_i2c_clients(usbvision, cmd, freq); - PDEBUG(DBG_IOCTL, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)freq->frequency); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *v = arg; - memset(v,0, sizeof(v)); - strcpy(v->name, "TV"); - PDEBUG(DBG_IOCTL, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *v = arg; - if(v->index) { - return -EINVAL; - } - PDEBUG(DBG_IOCTL, "VIDIOC_S_AUDIO"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; + if ((input >= usbvision->video_inputs) || (input < 0) ) + return -EINVAL; - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; + down(&usbvision->lock); + usbvision_muxsel(usbvision, input); + usbvision_set_input(usbvision); + usbvision_set_output(usbvision, + usbvision->curwidth, + usbvision->curheight); + up(&usbvision->lock); + return 0; +} - call_i2c_clients(usbvision, cmd, arg); +static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + usbvision->tvnormId=*id; - if (ctrl->type) - return 0; - else - return -EINVAL; + down(&usbvision->lock); + call_i2c_clients(usbvision, VIDIOC_S_STD, + &usbvision->tvnormId); + up(&usbvision->lock); + /* propagate the change to the decoder */ + usbvision_muxsel(usbvision, usbvision->ctl_input); - PDEBUG(DBG_IOCTL,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; + return 0; +} - PDEBUG(DBG_IOCTL, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - return 0; - } - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *vr = arg; - int ret; +static int vidioc_g_tuner (struct file *file, void *priv, + struct v4l2_tuner *vt) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + if (!usbvision->have_tuner || vt->index) // Only tuner 0 + return -EINVAL; + if(usbvision->radio) { + strcpy(vt->name, "Radio"); + vt->type = V4L2_TUNER_RADIO; + } else { + strcpy(vt->name, "Television"); + } + /* Let clients fill in the remainder of this struct */ + call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt); - // Check input validity : the user must do a VIDEO CAPTURE and MMAP method. - if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vr->memory != V4L2_MEMORY_MMAP)) - return -EINVAL; + return 0; +} - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } +static int vidioc_s_tuner (struct file *file, void *priv, + struct v4l2_tuner *vt) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - vr->count = usbvision_frames_alloc(usbvision,vr->count); + // Only no or one tuner for now + if (!usbvision->have_tuner || vt->index) + return -EINVAL; + /* let clients handle this */ + call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - usbvision->curFrame = NULL; + return 0; +} - PDEBUG(DBG_IOCTL, "VIDIOC_REQBUFS count=%d",vr->count); - return 0; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; +static int vidioc_g_frequency (struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - // FIXME : must control that buffers are mapped (VIDIOC_REQBUFS has been called) + freq->tuner = 0; // Only one tuner + if(usbvision->radio) { + freq->type = V4L2_TUNER_RADIO; + } else { + freq->type = V4L2_TUNER_ANALOG_TV; + } + freq->frequency = usbvision->freq; - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - if(vb->index>=usbvision->num_frames) { - return -EINVAL; - } - // Updating the corresponding frame state - vb->flags = 0; - frame = &usbvision->frame[vb->index]; - if(frame->grabstate >= FrameState_Ready) - vb->flags |= V4L2_BUF_FLAG_QUEUED; - if(frame->grabstate >= FrameState_Done) - vb->flags |= V4L2_BUF_FLAG_DONE; - if(frame->grabstate == FrameState_Unused) - vb->flags |= V4L2_BUF_FLAG_MAPPED; - vb->memory = V4L2_MEMORY_MMAP; - - vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); - - vb->memory = V4L2_MEMORY_MMAP; - vb->field = V4L2_FIELD_NONE; - vb->length = usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel; - vb->timestamp = usbvision->frame[vb->index].timestamp; - vb->sequence = usbvision->frame[vb->index].sequence; - return 0; - } - case VIDIOC_QBUF: - { - struct v4l2_buffer *vb = arg; - struct usbvision_frame *frame; - unsigned long lock_flags; - - // FIXME : works only on VIDEO_CAPTURE MODE, MMAP. - if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { - return -EINVAL; - } - if(vb->index>=usbvision->num_frames) { - return -EINVAL; - } + return 0; +} - frame = &usbvision->frame[vb->index]; +static int vidioc_s_frequency (struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - if (frame->grabstate != FrameState_Unused) { - return -EAGAIN; - } + // Only no or one tuner for now + if (!usbvision->have_tuner || freq->tuner) + return -EINVAL; - /* Mark it as ready and enqueue frame */ - frame->grabstate = FrameState_Ready; - frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + usbvision->freq = freq->frequency; + call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq); - vb->flags &= ~V4L2_BUF_FLAG_DONE; + return 0; +} - /* set v4l2_format index */ - frame->v4l2_format = usbvision->palette; +static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + memset(a,0,sizeof(*a)); + if(usbvision->radio) { + strcpy(a->name,"Radio"); + } else { + strcpy(a->name, "TV"); + } - PDEBUG(DBG_IOCTL, "VIDIOC_QBUF frame #%d",vb->index); - return 0; - } - case VIDIOC_DQBUF: - { - struct v4l2_buffer *vb = arg; - int ret; - struct usbvision_frame *f; - unsigned long lock_flags; - - if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (list_empty(&(usbvision->outqueue))) { - if (usbvision->streaming == Stream_Idle) - return -EINVAL; - ret = wait_event_interruptible - (usbvision->wait_frame, - !list_empty(&(usbvision->outqueue))); - if (ret) - return ret; - } + return 0; +} - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - f = list_entry(usbvision->outqueue.next, - struct usbvision_frame, frame); - list_del(usbvision->outqueue.next); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - f->grabstate = FrameState_Unused; - - vb->memory = V4L2_MEMORY_MMAP; - vb->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE; - vb->index = f->index; - vb->sequence = f->sequence; - vb->timestamp = f->timestamp; - vb->field = V4L2_FIELD_NONE; - vb->bytesused = f->scanlength; - - return 0; - } - case VIDIOC_STREAMON: - { - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; +static int vidioc_s_audio (struct file *file, void *fh, + struct v4l2_audio *a) +{ + if(a->index) { + return -EINVAL; + } - usbvision->streaming = Stream_On; + return 0; +} - call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); +static int vidioc_queryctrl (struct file *file, void *priv, + struct v4l2_queryctrl *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int id=ctrl->id; - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMON"); + memset(ctrl,0,sizeof(*ctrl)); + ctrl->id=id; - return 0; - } - case VIDIOC_STREAMOFF: - { - int *type = arg; - int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if(usbvision->streaming == Stream_On) { - usbvision_stream_interrupt(usbvision); - // Stop all video streamings - call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); - } - usbvision_empty_framequeues(usbvision); + call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl); - PDEBUG(DBG_IOCTL, "VIDIOC_STREAMOFF"); - return 0; - } - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *vfd = arg; + if (!ctrl->type) + return -EINVAL; - if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { - return -EINVAL; - } - vfd->flags = 0; - vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); - vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - memset(vfd->reserved, 0, sizeof(vfd->reserved)); - return 0; - } - case VIDIOC_G_FMT: - { - struct v4l2_format *vf = arg; - - switch (vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - vf->fmt.pix.width = usbvision->curwidth; - vf->fmt.pix.height = usbvision->curheight; - vf->fmt.pix.pixelformat = usbvision->palette.format; - vf->fmt.pix.bytesperline = usbvision->curwidth*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; - vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - PDEBUG(DBG_IOCTL, "VIDIOC_G_FMT invalid type %d",vf->type); - return -EINVAL; - } - return 0; - } - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - { - struct v4l2_format *vf = arg; - int formatIdx,ret; - - switch(vf->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - /* Find requested format in available ones */ - for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { - if(vf->fmt.pix.pixelformat == usbvision_v4l2_format[formatIdx].format) { - usbvision->palette = usbvision_v4l2_format[formatIdx]; - break; - } - } - /* robustness */ - if(formatIdx == USBVISION_SUPPORTED_PALETTES) { - return -EINVAL; - } - RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); - RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); - - vf->fmt.pix.bytesperline = vf->fmt.pix.width*usbvision->palette.bytes_per_pixel; - vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; - - if(cmd == VIDIOC_TRY_FMT) { - PDEBUG(DBG_IOCTL, "VIDIOC_TRY_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - - /* stop io in case it is already in progress */ - if(usbvision->streaming == Stream_On) { - if ((ret = usbvision_stream_interrupt(usbvision))) - return ret; - } - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - - usbvision->curFrame = NULL; - - // by now we are committed to the new data... - down(&usbvision->lock); - usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - up(&usbvision->lock); - - PDEBUG(DBG_IOCTL, "VIDIOC_S_FMT grabdisplay w=%d, h=%d, format=%s", - vf->fmt.pix.width, vf->fmt.pix.height,usbvision->palette.desc); - return 0; - } - default: - return -EINVAL; - } - } - default: - return -ENOIOCTLCMD; + return 0; +} + +static int vidioc_g_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); + + return 0; +} + +static int vidioc_s_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); + + return 0; +} + +static int vidioc_reqbufs (struct file *file, + void *priv, struct v4l2_requestbuffers *vr) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + + RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); + + /* Check input validity: + the user must do a VIDEO CAPTURE and MMAP method. */ + if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) || + (vr->memory != V4L2_MEMORY_MMAP)) + return -EINVAL; + + if(usbvision->streaming == Stream_On) { + if ((ret = usbvision_stream_interrupt(usbvision))) + return ret; } + + usbvision_frames_free(usbvision); + usbvision_empty_framequeues(usbvision); + vr->count = usbvision_frames_alloc(usbvision,vr->count); + + usbvision->curFrame = NULL; + return 0; } -static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_querybuf (struct file *file, + void *priv, struct v4l2_buffer *vb) { - return video_usercopy(inode, file, cmd, arg, usbvision_v4l2_do_ioctl); + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + struct usbvision_frame *frame; + + /* FIXME : must control + that buffers are mapped (VIDIOC_REQBUFS has been called) */ + if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { + return -EINVAL; + } + if(vb->index>=usbvision->num_frames) { + return -EINVAL; + } + /* Updating the corresponding frame state */ + vb->flags = 0; + frame = &usbvision->frame[vb->index]; + if(frame->grabstate >= FrameState_Ready) + vb->flags |= V4L2_BUF_FLAG_QUEUED; + if(frame->grabstate >= FrameState_Done) + vb->flags |= V4L2_BUF_FLAG_DONE; + if(frame->grabstate == FrameState_Unused) + vb->flags |= V4L2_BUF_FLAG_MAPPED; + vb->memory = V4L2_MEMORY_MMAP; + + vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); + + vb->memory = V4L2_MEMORY_MMAP; + vb->field = V4L2_FIELD_NONE; + vb->length = usbvision->curwidth* + usbvision->curheight* + usbvision->palette.bytes_per_pixel; + vb->timestamp = usbvision->frame[vb->index].timestamp; + vb->sequence = usbvision->frame[vb->index].sequence; + return 0; +} + +static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + struct usbvision_frame *frame; + unsigned long lock_flags; + + /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ + if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { + return -EINVAL; + } + if(vb->index>=usbvision->num_frames) { + return -EINVAL; + } + + frame = &usbvision->frame[vb->index]; + + if (frame->grabstate != FrameState_Unused) { + return -EAGAIN; + } + + /* Mark it as ready and enqueue frame */ + frame->grabstate = FrameState_Ready; + frame->scanstate = ScanState_Scanning; + frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + + vb->flags &= ~V4L2_BUF_FLAG_DONE; + + /* set v4l2_format index */ + frame->v4l2_format = usbvision->palette; + + spin_lock_irqsave(&usbvision->queue_lock, lock_flags); + list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue); + spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + + return 0; } +static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + struct usbvision_frame *f; + unsigned long lock_flags; + + if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (list_empty(&(usbvision->outqueue))) { + if (usbvision->streaming == Stream_Idle) + return -EINVAL; + ret = wait_event_interruptible + (usbvision->wait_frame, + !list_empty(&(usbvision->outqueue))); + if (ret) + return ret; + } + + spin_lock_irqsave(&usbvision->queue_lock, lock_flags); + f = list_entry(usbvision->outqueue.next, + struct usbvision_frame, frame); + list_del(usbvision->outqueue.next); + spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + + f->grabstate = FrameState_Unused; + + vb->memory = V4L2_MEMORY_MMAP; + vb->flags = V4L2_BUF_FLAG_MAPPED | + V4L2_BUF_FLAG_QUEUED | + V4L2_BUF_FLAG_DONE; + vb->index = f->index; + vb->sequence = f->sequence; + vb->timestamp = f->timestamp; + vb->field = V4L2_FIELD_NONE; + vb->bytesused = f->scanlength; + + return 0; +} + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; + + usbvision->streaming = Stream_On; + call_i2c_clients(usbvision,VIDIOC_STREAMON , &b); + + return 0; +} + +static int vidioc_streamoff(struct file *file, + void *priv, enum v4l2_buf_type type) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if(usbvision->streaming == Stream_On) { + usbvision_stream_interrupt(usbvision); + /* Stop all video streamings */ + call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b); + } + usbvision_empty_framequeues(usbvision); + + return 0; +} + +static int vidioc_enum_fmt_cap (struct file *file, void *priv, + struct v4l2_fmtdesc *vfd) +{ + if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { + return -EINVAL; + } + vfd->flags = 0; + vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc); + vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; + memset(vfd->reserved, 0, sizeof(vfd->reserved)); + return 0; +} + +static int vidioc_g_fmt_cap (struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + vf->fmt.pix.width = usbvision->curwidth; + vf->fmt.pix.height = usbvision->curheight; + vf->fmt.pix.pixelformat = usbvision->palette.format; + vf->fmt.pix.bytesperline = + usbvision->curwidth*usbvision->palette.bytes_per_pixel; + vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*usbvision->curheight; + vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */ + + return 0; +} + +static int vidioc_try_fmt_cap (struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int formatIdx; + + /* Find requested format in available ones */ + for(formatIdx=0;formatIdx<USBVISION_SUPPORTED_PALETTES;formatIdx++) { + if(vf->fmt.pix.pixelformat == + usbvision_v4l2_format[formatIdx].format) { + usbvision->palette = usbvision_v4l2_format[formatIdx]; + break; + } + } + /* robustness */ + if(formatIdx == USBVISION_SUPPORTED_PALETTES) { + return -EINVAL; + } + RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); + RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); + + vf->fmt.pix.bytesperline = vf->fmt.pix.width* + usbvision->palette.bytes_per_pixel; + vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height; + + return 0; +} + +static int vidioc_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *vf) +{ + struct video_device *dev = video_devdata(file); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); + int ret; + + if( 0 != (ret=vidioc_try_fmt_cap (file, priv, vf)) ) { + return ret; + } + + /* stop io in case it is already in progress */ + if(usbvision->streaming == Stream_On) { + if ((ret = usbvision_stream_interrupt(usbvision))) + return ret; + } + usbvision_frames_free(usbvision); + usbvision_empty_framequeues(usbvision); + + usbvision->curFrame = NULL; + + /* by now we are committed to the new data... */ + down(&usbvision->lock); + usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); + up(&usbvision->lock); + + return 0; +} static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int noblock = file->f_flags & O_NONBLOCK; unsigned long lock_flags; int ret,i; struct usbvision_frame *frame; - PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, (unsigned long)count, noblock); + PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __FUNCTION__, + (unsigned long)count, noblock); if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) return -EFAULT; - /* This entry point is compatible with the mmap routines so that a user can do either - VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */ + /* This entry point is compatible with the mmap routines + so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF + to get frames or call read on the device. */ if(!usbvision->num_frames) { - /* First, allocate some frames to work with if this has not been done with - VIDIOC_REQBUF */ + /* First, allocate some frames to work with + if this has not been done with VIDIOC_REQBUF */ usbvision_frames_free(usbvision); usbvision_empty_framequeues(usbvision); usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); @@ -1086,21 +1116,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); } - /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ + /* Then, enqueue as many frames as possible + (like a user of VIDIOC_QBUF would do) */ for(i=0;i<usbvision->num_frames;i++) { frame = &usbvision->frame[i]; if(frame->grabstate == FrameState_Unused) { /* Mark it as ready and enqueue frame */ frame->grabstate = FrameState_Ready; frame->scanstate = ScanState_Scanning; - frame->scanlength = 0; /* Accumulated in usbvision_parse_data() */ + /* Accumulated in usbvision_parse_data() */ + frame->scanlength = 0; /* set v4l2_format index */ frame->v4l2_format = usbvision->palette; spin_lock_irqsave(&usbvision->queue_lock, lock_flags); list_add_tail(&frame->frame, &usbvision->inqueue); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); + spin_unlock_irqrestore(&usbvision->queue_lock, + lock_flags); } } @@ -1128,8 +1161,9 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, return 0; } - PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", __FUNCTION__, - frame->index, frame->bytes_read, frame->scanlength); + PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", + __FUNCTION__, + frame->index, frame->bytes_read, frame->scanlength); /* copy bytes to user space; we allow for partials reads */ if ((count + frame->bytes_read) > (unsigned long)frame->scanlength) @@ -1140,10 +1174,11 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, } frame->bytes_read += count; - PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", __FUNCTION__, - (unsigned long)count, frame->bytes_read); + PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", + __FUNCTION__, + (unsigned long)count, frame->bytes_read); - // For now, forget the frame if it has not been read in one shot. + /* For now, forget the frame if it has not been read in one shot. */ /* if (frame->bytes_read >= frame->scanlength) {// All data has been read */ frame->bytes_read = 0; @@ -1162,7 +1197,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) u32 i; struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); PDEBUG(DBG_MMAP, "mmap"); @@ -1180,11 +1216,13 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) } for (i = 0; i < usbvision->num_frames; i++) { - if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff) + if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == + vma->vm_pgoff) break; } if (i == usbvision->num_frames) { - PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); + PDEBUG(DBG_MMAP, + "mmap: user supplied mapping address is out of range"); up(&usbvision->lock); return -EINVAL; } @@ -1218,8 +1256,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) static int usbvision_radio_open(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - struct v4l2_frequency freq; + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int errCode = 0; PDEBUG(DBG_IO, "%s:", __FUNCTION__); @@ -1249,8 +1287,6 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) // If so far no errors then we shall start the radio usbvision->radio = 1; call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type); - freq.frequency = 1517; //SWR3 @ 94.8MHz - call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, &freq); usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); usbvision->user++; } @@ -1270,7 +1306,8 @@ static int usbvision_radio_open(struct inode *inode, struct file *file) static int usbvision_radio_close(struct inode *inode, struct file *file) { struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); + struct usb_usbvision *usbvision = + (struct usb_usbvision *) video_get_drvdata(dev); int errCode = 0; PDEBUG(DBG_IO, ""); @@ -1304,149 +1341,6 @@ static int usbvision_radio_close(struct inode *inode, struct file *file) return errCode; } -static int usbvision_do_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *dev = video_devdata(file); - struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EIO; - - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *vc=arg; - - memset(vc, 0, sizeof(*vc)); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, usbvision_device_data[usbvision->DevModel].ModelString, - sizeof(vc->card)); - strlcpy(vc->bus_info, usbvision->dev->dev.bus_id, - sizeof(vc->bus_info)); - vc->version = USBVISION_DRIVER_VERSION; - vc->capabilities = (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - PDEBUG(DBG_IO, "VIDIOC_QUERYCAP"); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - int id=ctrl->id; - - memset(ctrl,0,sizeof(*ctrl)); - ctrl->id=id; - - call_i2c_clients(usbvision, cmd, arg); - PDEBUG(DBG_IO,"VIDIOC_QUERYCTRL id=%x value=%x",ctrl->id,ctrl->type); - - if (ctrl->type) - return 0; - else - return -EINVAL; - - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); - PDEBUG(DBG_IO,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - - call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); - PDEBUG(DBG_IO, "VIDIOC_S_CTRL id=%x value=%x",ctrl->id,ctrl->value); - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - - if (t->index > 0) - return -EINVAL; - - memset(t,0,sizeof(*t)); - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - /* Let clients fill in the remainder of this struct */ - call_i2c_clients(usbvision,VIDIOC_G_TUNER,t); - PDEBUG(DBG_IO, "VIDIOC_G_TUNER signal=%x, afc=%x",t->signal,t->afc); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *vt = arg; - - // Only no or one tuner for now - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt); - - PDEBUG(DBG_IO, "VIDIOC_S_TUNER"); - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *a = arg; - - memset(a,0,sizeof(*a)); - strcpy(a->name,"Radio"); - PDEBUG(DBG_IO, "VIDIOC_G_AUDIO"); - return 0; - } - case VIDIOC_S_AUDIO: - case VIDIOC_S_INPUT: - case VIDIOC_S_STD: - return 0; - - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - memset(f,0,sizeof(*f)); - - f->type = V4L2_TUNER_RADIO; - f->frequency = usbvision->freq; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_G_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - if (f->tuner != 0) - return -EINVAL; - usbvision->freq = f->frequency; - call_i2c_clients(usbvision, cmd, f); - PDEBUG(DBG_IO, "VIDIOC_S_FREQUENCY freq=0x%X", (unsigned)f->frequency); - - return 0; - } - default: - { - PDEBUG(DBG_IO, "%s: Unknown command %x", __FUNCTION__, cmd); - return -ENOIOCTLCMD; - } - } - return 0; -} - - -static int usbvision_radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, usbvision_do_radio_ioctl); -} - - /* * Here comes the stuff for vbi on usbvision based devices * @@ -1454,21 +1348,21 @@ static int usbvision_radio_ioctl(struct inode *inode, struct file *file, static int usbvision_vbi_open(struct inode *inode, struct file *file) { /* TODO */ - return -EINVAL; + return -ENODEV; } static int usbvision_vbi_close(struct inode *inode, struct file *file) { /* TODO */ - return -EINVAL; + return -ENODEV; } static int usbvision_do_vbi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { /* TODO */ - return -EINVAL; + return -ENOIOCTLCMD; } static int usbvision_vbi_ioctl(struct inode *inode, struct file *file, @@ -1489,8 +1383,11 @@ static const struct file_operations usbvision_fops = { .release = usbvision_v4l2_close, .read = usbvision_v4l2_read, .mmap = usbvision_v4l2_mmap, - .ioctl = usbvision_v4l2_ioctl, + .ioctl = video_ioctl2, .llseek = no_llseek, +/* .poll = video_poll, */ + .mmap = usbvision_v4l2_mmap, + .compat_ioctl = v4l_compat_ioctl32, }; static struct video_device usbvision_video_template = { .owner = THIS_MODULE, @@ -1500,6 +1397,39 @@ static struct video_device usbvision_video_template = { .name = "usbvision-video", .release = video_device_release, .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, + .vidioc_g_fmt_cap = vidioc_g_fmt_cap, + .vidioc_try_fmt_cap = vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = vidioc_s_fmt_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_g_audio = vidioc_s_audio, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +#ifdef CONFIG_VIDEO_V4L1_COMPAT +/* .vidiocgmbuf = vidiocgmbuf, */ +#endif + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; @@ -1508,8 +1438,9 @@ static const struct file_operations usbvision_radio_fops = { .owner = THIS_MODULE, .open = usbvision_radio_open, .release = usbvision_radio_close, - .ioctl = usbvision_radio_ioctl, + .ioctl = video_ioctl2, .llseek = no_llseek, + .compat_ioctl = v4l_compat_ioctl32, }; static struct video_device usbvision_radio_template= @@ -1518,12 +1449,27 @@ static struct video_device usbvision_radio_template= .type = VID_TYPE_TUNER, .hardware = VID_HARDWARE_USBVISION, .fops = &usbvision_radio_fops, - .release = video_device_release, .name = "usbvision-radio", + .release = video_device_release, .minor = -1, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_g_audio = vidioc_s_audio, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + + .tvnorms = USBVISION_NORMS, + .current_norm = V4L2_STD_PAL }; - // vbi template static const struct file_operations usbvision_vbi_fops = { .owner = THIS_MODULE, @@ -1531,6 +1477,7 @@ static const struct file_operations usbvision_vbi_fops = { .release = usbvision_vbi_close, .ioctl = usbvision_vbi_ioctl, .llseek = no_llseek, + .compat_ioctl = v4l_compat_ioctl32, }; static struct video_device usbvision_vbi_template= @@ -1574,11 +1521,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) { // vbi Device: if (usbvision->vbi) { - PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", + usbvision->vbi->minor & 0x1f); if (usbvision->vbi->minor != -1) { video_unregister_device(usbvision->vbi); - } - else { + } else { video_device_release(usbvision->vbi); } usbvision->vbi = NULL; @@ -1586,11 +1533,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Radio Device: if (usbvision->rdev) { - PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", + usbvision->rdev->minor & 0x1f); if (usbvision->rdev->minor != -1) { video_unregister_device(usbvision->rdev); - } - else { + } else { video_device_release(usbvision->rdev); } usbvision->rdev = NULL; @@ -1598,11 +1545,11 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Video Device: if (usbvision->vdev) { - PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->minor & 0x1f); + PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", + usbvision->vdev->minor & 0x1f); if (usbvision->vdev->minor != -1) { video_unregister_device(usbvision->vdev); - } - else { + } else { video_device_release(usbvision->vdev); } usbvision->vdev = NULL; @@ -1613,37 +1560,52 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) { // Video Device: - usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); + usbvision->vdev = usbvision_vdev_init(usbvision, + &usbvision_video_template, + "USBVision Video"); if (usbvision->vdev == NULL) { goto err_exit; } - if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { + if (video_register_device(usbvision->vdev, + VFL_TYPE_GRABBER, + video_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr,usbvision->vdev->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", + usbvision->nr,usbvision->vdev->minor & 0x1f); // Radio Device: if (usbvision_device_data[usbvision->DevModel].Radio) { // usbvision has radio - usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); + usbvision->rdev = usbvision_vdev_init(usbvision, + &usbvision_radio_template, + "USBVision Radio"); if (usbvision->rdev == NULL) { goto err_exit; } - if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { + if (video_register_device(usbvision->rdev, + VFL_TYPE_RADIO, + radio_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", + usbvision->nr, usbvision->rdev->minor & 0x1f); } // vbi Device: if (usbvision_device_data[usbvision->DevModel].vbi) { - usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); + usbvision->vbi = usbvision_vdev_init(usbvision, + &usbvision_vbi_template, + "USBVision VBI"); if (usbvision->vdev == NULL) { goto err_exit; } - if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { + if (video_register_device(usbvision->vbi, + VFL_TYPE_VBI, + vbi_nr)<0) { goto err_exit; } - printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr,usbvision->vbi->minor & 0x1f); + printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", + usbvision->nr,usbvision->vbi->minor & 0x1f); } // all done return 0; @@ -1657,7 +1619,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) /* * usbvision_alloc() * - * This code allocates the struct usb_usbvision. It is filled with default values. + * This code allocates the struct usb_usbvision. + * It is filled with default values. * * Returns NULL on error, a pointer to usb_usbvision else. * @@ -1666,7 +1629,8 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev) { struct usb_usbvision *usbvision; - if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { + if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == + NULL) { goto err_exit; } @@ -1728,11 +1692,11 @@ static void usbvision_release(struct usb_usbvision *usbvision) } -/******************************** usb interface *****************************************/ +/*********************** usb interface **********************************/ static void usbvision_configure_video(struct usb_usbvision *usbvision) { - int model,i; + int model; if (usbvision == NULL) return; @@ -1741,25 +1705,23 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) { - usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2; + usbvision->Vin_Reg2_Preset = + usbvision_device_data[usbvision->DevModel].Vin_Reg2; } else { usbvision->Vin_Reg2_Preset = 0; } - for (i = 0; i < TVNORMS; i++) - if (usbvision_device_data[model].VideoNorm == tvnorms[i].mode) - break; - if (i == TVNORMS) - i = 0; - usbvision->tvnorm = &tvnorms[i]; /* set default norm */ + usbvision->tvnormId = usbvision_device_data[model].VideoNorm; usbvision->video_inputs = usbvision_device_data[model].VideoChannels; usbvision->ctl_input = 0; /* This should be here to make i2c clients to be able to register */ - usbvision_audio_off(usbvision); //first switch off audio + /* first switch off audio */ + usbvision_audio_off(usbvision); if (!PowerOnAtOpen) { - usbvision_power_on(usbvision); //and then power up the noisy tuner + /* and then power up the noisy tuner */ + usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); } } @@ -1796,18 +1758,22 @@ static int __devinit usbvision_probe(struct usb_interface *intf, if (usbvision_device_data[model].Interface >= 0) { interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; - } - else { + } else { interface = &dev->actconfig->interface[ifnum]->altsetting[0]; } endpoint = &interface->endpoint[1].desc; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { - err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum); - err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes); + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) { + err("%s: interface %d. has non-ISO endpoint!", + __FUNCTION__, ifnum); + err("%s: Endpoint attributes %d", + __FUNCTION__, endpoint->bmAttributes); return -ENODEV; } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - err("%s: interface %d. has ISO OUT endpoint!", __FUNCTION__, ifnum); + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_OUT) { + err("%s: interface %d. has ISO OUT endpoint!", + __FUNCTION__, ifnum); return -ENODEV; } @@ -1818,11 +1784,9 @@ static int __devinit usbvision_probe(struct usb_interface *intf, if (dev->descriptor.bNumConfigurations > 1) { usbvision->bridgeType = BRIDGE_NT1004; - } - else if (model == DAZZLE_DVC_90_REV_1_SECAM) { + } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { usbvision->bridgeType = BRIDGE_NT1005; - } - else { + } else { usbvision->bridgeType = BRIDGE_NT1003; } PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); @@ -1919,11 +1883,11 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf) up(&usbvision->lock); if (usbvision->user) { - printk(KERN_INFO "%s: In use, disconnect pending\n", __FUNCTION__); + printk(KERN_INFO "%s: In use, disconnect pending\n", + __FUNCTION__); wake_up_interruptible(&usbvision->wait_frame); wake_up_interruptible(&usbvision->wait_stream); - } - else { + } else { usbvision_release(usbvision); } @@ -1950,7 +1914,6 @@ static int __init usbvision_init(void) PDEBUG(DBG_PROBE, ""); - PDEBUG(DBG_IOCTL, "IOCTL debugging is enabled [video]"); PDEBUG(DBG_IO, "IO debugging is enabled [video]"); PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index c759d00d701..c5b6c501c86 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h @@ -221,6 +221,8 @@ enum { #define I2C_USB_ADAP_MAX 16 +#define USBVISION_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_M) + /* ----------------------------------------------------------------- */ /* usbvision video structures */ /* ----------------------------------------------------------------- */ @@ -301,14 +303,6 @@ struct usbvision_frame_header { __u16 frameHeight; /* 10 - 11 after endian correction*/ }; -/* tvnorms */ -struct usbvision_tvnorm { - char *name; - v4l2_std_id id; - /* mode for saa7113h */ - int mode; -}; - struct usbvision_frame { char *data; /* Frame buffer */ struct usbvision_frame_header isocHeader; /* Header from stream */ @@ -386,7 +380,6 @@ struct usb_usbvision { int tuner_type; int tuner_addr; int bridgeType; // NT1003, NT1004, NT1005 - int channel; int radio; int video_inputs; // # of inputs unsigned long freq; @@ -441,7 +434,7 @@ struct usb_usbvision { struct v4l2_capability vcap; /* Video capabilities */ unsigned int ctl_input; /* selected input */ - struct usbvision_tvnorm *tvnorm; /* selected tv norm */ + v4l2_std_id tvnormId; /* selected tv norm */ unsigned char video_endp; /* 0x82 for USBVISION devices based */ // Decompression stuff: diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 13ee550d321..d2915d3530e 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -939,16 +939,25 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc When no more controls are available 0 is returned. */ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) { - u32 ctrl_class; + u32 ctrl_class = V4L2_CTRL_ID2CLASS(id); const u32 *pctrl; - /* if no query is desired, then just return the control ID */ - if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) - return id; if (ctrl_classes == NULL) return 0; + + /* if no query is desired, then check if the ID is part of ctrl_classes */ + if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) { + /* find class */ + while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class) + ctrl_classes++; + if (*ctrl_classes == NULL) + return 0; + pctrl = *ctrl_classes; + /* find control ID */ + while (*pctrl && *pctrl != id) pctrl++; + return *pctrl ? id : 0; + } id &= V4L2_CTRL_ID_MASK; - ctrl_class = V4L2_CTRL_ID2CLASS(id); id++; /* select next control */ /* find first class that matches (or is greater than) the class of the ID */ diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index fcc5467e763..e617925ba31 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c @@ -47,6 +47,7 @@ static int videobuf_dvb_thread(void *data) int err; dprintk("dvb thread started\n"); + set_freezable(); videobuf_read_start(&dvb->dvbq); for (;;) { diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 0c658b74f2c..a0c1647a2ba 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -2077,12 +2077,10 @@ static int vino_wait_for_frame(struct vino_channel_settings *vcs) init_waitqueue_entry(&wait, current); /* add ourselves into wait queue */ add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait); - /* and set current state */ - set_current_state(TASK_INTERRUPTIBLE); /* to ensure that schedule_timeout will return immediately - * if VINO interrupt was triggred meanwhile */ - schedule_timeout(HZ / 10); + * if VINO interrupt was triggered meanwhile */ + schedule_timeout_interruptible(msecs_to_jiffies(100)); if (signal_pending(current)) err = -EINTR; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index f7e1d191037..f6d3a9460cc 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -25,6 +25,7 @@ #include <linux/pci.h> #include <linux/random.h> #include <linux/version.h> +#include <linux/mutex.h> #include <linux/videodev2.h> #include <linux/dma-mapping.h> #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -145,9 +146,6 @@ struct vivi_buffer { struct vivi_fmt *fmt; -#ifdef CONFIG_VIVI_SCATTER - struct sg_to_addr *to_addr; -#endif }; struct vivi_dmaqueue { @@ -168,7 +166,7 @@ static LIST_HEAD(vivi_devlist); struct vivi_dev { struct list_head vivi_devlist; - struct semaphore lock; + struct mutex lock; int users; @@ -232,68 +230,13 @@ static u8 bars[8][3] = { #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 #define TSTAMP_MIN_X 64 -#ifdef CONFIG_VIVI_SCATTER -static void prep_to_addr(struct sg_to_addr to_addr[], - struct videobuf_buffer *vb) -{ - int i, pos=0; - - for (i=0;i<vb->dma.nr_pages;i++) { - to_addr[i].sg=&vb->dma.sglist[i]; - to_addr[i].pos=pos; - pos += vb->dma.sglist[i].length; - } -} - -static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) -{ - int p1=0,p2=pages-1,p3=pages/2; - - /* Sanity test */ - BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length); - - while (p1+1<p2) { - if (pos < to_addr[p3].pos) { - p2=p3; - } else { - p1=p3; - } - p3=(p1+p2)/2; - } - if (pos >= to_addr[p2].pos) - p1=p2; - - return (p1); -} -#endif -#ifdef CONFIG_VIVI_SCATTER -static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, - int hmax, int line, char *timestr) -#else static void gen_line(char *basep,int inipos,int wmax, int hmax, int line, char *timestr) -#endif { int w,i,j,pos=inipos,y; char *p,*s; u8 chr,r,g,b,color; -#ifdef CONFIG_VIVI_SCATTER - int pgpos,oldpg; - char *basep; - struct page *pg; - - unsigned long flags; - spinlock_t spinlock; - - spin_lock_init(&spinlock); - - /* Get first addr pointed to pixel position */ - oldpg=get_addr_pos(pos,pages,to_addr); - pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT); - spin_lock_irqsave(&spinlock,flags); - basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; -#endif /* We will just duplicate the second pixel at the packet */ wmax/=2; @@ -305,18 +248,7 @@ static void gen_line(char *basep,int inipos,int wmax, b=bars[w*7/wmax][2]; for (color=0;color<4;color++) { -#ifdef CONFIG_VIVI_SCATTER - pgpos=get_addr_pos(pos,pages,to_addr); - if (pgpos!=oldpg) { - pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT); - kunmap_atomic(basep, KM_BOUNCE_READ); - basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset; - oldpg=pgpos; - } - p=basep+pos-to_addr[pgpos].pos; -#else p=basep+pos; -#endif switch (color) { case 0: @@ -361,23 +293,7 @@ static void gen_line(char *basep,int inipos,int wmax, pos=inipos+j*2; for (color=0;color<4;color++) { -#ifdef CONFIG_VIVI_SCATTER - pgpos=get_addr_pos(pos,pages,to_addr); - if (pgpos!=oldpg) { - pg=pfn_to_page(sg_dma_address( - to_addr[pgpos].sg) - >> PAGE_SHIFT); - kunmap_atomic(basep, - KM_BOUNCE_READ); - basep= kmap_atomic(pg, - KM_BOUNCE_READ)+ - to_addr[pgpos].sg->offset; - oldpg=pgpos; - } - p=basep+pos-to_addr[pgpos].pos; -#else p=basep+pos; -#endif y=TO_Y(r,g,b); @@ -402,12 +318,7 @@ static void gen_line(char *basep,int inipos,int wmax, end: -#ifdef CONFIG_VIVI_SCATTER - kunmap_atomic(basep, KM_BOUNCE_READ); - spin_unlock_irqrestore(&spinlock,flags); -#else return; -#endif } static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) { @@ -415,35 +326,16 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) int hmax = buf->vb.height; int wmax = buf->vb.width; struct timeval ts; -#ifdef CONFIG_VIVI_SCATTER - struct sg_to_addr *to_addr=buf->to_addr; - struct videobuf_buffer *vb=&buf->vb; -#else char *tmpbuf; -#endif - -#ifdef CONFIG_VIVI_SCATTER - /* Test if DMA mapping is ready */ - if (!sg_dma_address(&vb->dma.sglist[0])) - return; - - prep_to_addr(to_addr,vb); - /* Check if there is enough memory */ - BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); -#else if (buf->vb.dma.varea) { tmpbuf=kmalloc (wmax*2, GFP_KERNEL); } else { tmpbuf=buf->vb.dma.vmalloc; } -#endif for (h=0;h<hmax;h++) { -#ifdef CONFIG_VIVI_SCATTER - gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr); -#else if (buf->vb.dma.varea) { gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr); /* FIXME: replacing to __copy_to_user */ @@ -452,7 +344,6 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) } else { gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr); } -#endif pos += wmax*2; } @@ -573,6 +464,7 @@ static int vivi_thread(void *data) dprintk(1,"thread started\n"); mod_timer(&dma_q->timeout, jiffies+BUFFER_TIMEOUT); + set_freezable(); for (;;) { vivi_sleep(dma_q); @@ -717,11 +609,6 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) if (in_interrupt()) BUG(); -#ifdef CONFIG_VIVI_SCATTER - /*FIXME: Maybe a spinlock is required here */ - kfree(buf->to_addr); - buf->to_addr=NULL; -#endif videobuf_waiton(&buf->vb,0,0); videobuf_dma_unmap(vq, &buf->vb.dma); @@ -767,12 +654,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, buf->vb.state = STATE_PREPARED; -#ifdef CONFIG_VIVI_SCATTER - if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { - rc=-ENOMEM; - goto fail; - } -#endif return 0; fail: @@ -837,40 +718,6 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb free_buffer(vq,buf); } -#ifdef CONFIG_VIVI_SCATTER -static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, - int direction) -{ - int i; - - dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents); - BUG_ON(direction == DMA_NONE); - - for (i = 0; i < nents; i++ ) { - BUG_ON(!sg[i].page); - - sg_dma_address(&sg[i]) = page_to_phys(sg[i].page) + sg[i].offset; - } - - return nents; -} - -static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, - int direction) -{ - dprintk(1,"%s\n",__FUNCTION__); - return 0; -} - -static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, - int direction) -{ -// dprintk(1,"%s\n",__FUNCTION__); - -// flush_write_buffers(); - return 0; -} -#endif static struct videobuf_queue_ops vivi_video_qops = { .buf_setup = buffer_setup, @@ -892,16 +739,16 @@ static struct videobuf_queue_ops vivi_video_qops = { static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) { /* is it free? */ - down(&dev->lock); + mutex_lock(&dev->lock); if (dev->resources) { /* no, someone else uses it */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ dev->resources =1; dprintk(1,"res: get\n"); - up(&dev->lock); + mutex_unlock(&dev->lock); return 1; } @@ -912,10 +759,10 @@ static int res_locked(struct vivi_dev *dev) static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) { - down(&dev->lock); + mutex_lock(&dev->lock); dev->resources = 0; dprintk(1,"res: put\n"); - up(&dev->lock); + mutex_lock(&dev->lock); } /* ------------------------------------------------------------------ @@ -1259,19 +1106,11 @@ static int vivi_open(struct inode *inode, struct file *file) sprintf(dev->timestr,"%02d:%02d:%02d:%03d", dev->h,dev->m,dev->s,(dev->us+500)/1000); -#ifdef CONFIG_VIVI_SCATTER - videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops, - NULL, NULL, - fh->type, - V4L2_FIELD_INTERLACED, - sizeof(struct vivi_buffer),fh); -#else videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, NULL, NULL, fh->type, V4L2_FIELD_INTERLACED, sizeof(struct vivi_buffer),fh); -#endif return 0; } @@ -1422,7 +1261,7 @@ static int __init vivi_init(void) init_waitqueue_head(&dev->vidq.wq); /* initialize locks */ - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); dev->vidq.timeout.function = vivi_vid_timeout; dev->vidq.timeout.data = (unsigned long)dev; diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index 8f6741a28a4..1bf4cbec6a8 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c @@ -321,12 +321,14 @@ static int wm8739_probe(struct i2c_adapter *adapter) static int wm8739_detach(struct i2c_client *client) { + struct wm8739_state *state = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); if (err) return err; + kfree(state); kfree(client); return 0; } diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 4df5d30d4d0..9f7e894ef96 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -222,12 +222,14 @@ static int wm8775_probe(struct i2c_adapter *adapter) static int wm8775_detach(struct i2c_client *client) { + struct wm8775_state *state = i2c_get_clientdata(client); int err; err = i2c_detach_client(client); if (err) { return err; } + kfree(state); kfree(client); return 0; diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index 47cd93f9c7d..edb00293cd5 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301[P] Image Processor and Control Chip support" - depends on VIDEO_V4L1 + depends on VIDEO_V4L2 ---help--- Say Y here if you want support for cameras based on the ZC0301 or ZC0301P Image Processors and Control Chips. diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h index 710f12eb912..a2de50efa31 100644 --- a/drivers/media/video/zc0301/zc0301.h +++ b/drivers/media/video/zc0301/zc0301.h @@ -36,6 +36,7 @@ #include <linux/rwsem.h> #include <linux/stddef.h> #include <linux/string.h> +#include <linux/kref.h> #include "zc0301_sensor.h" @@ -98,7 +99,7 @@ struct zc0301_module_param { u16 frame_timeout; }; -static DECLARE_RWSEM(zc0301_disconnect); +static DECLARE_RWSEM(zc0301_dev_lock); struct zc0301_device { struct video_device* v4ldev; @@ -121,12 +122,14 @@ struct zc0301_device { struct zc0301_module_param module_param; + struct kref kref; enum zc0301_dev_state state; u8 users; - struct mutex dev_mutex, fileop_mutex; + struct completion probe; + struct mutex open_mutex, fileop_mutex; spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; + wait_queue_head_t wait_open, wait_frame, wait_stream; }; /*****************************************************************************/ @@ -156,8 +159,8 @@ do { \ else if ((level) == 2) \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args); \ + dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ + __FILE__, __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define KDBG(level, fmt, args...) \ @@ -166,8 +169,8 @@ do { \ if ((level) == 1 || (level) == 2) \ pr_info("zc0301: " fmt "\n", ## args); \ else if ((level) == 3) \ - pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ - __LINE__ , ## args); \ + pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ + __FUNCTION__, __LINE__ , ## args); \ } \ } while (0) # define V4LDBG(level, name, cmd) \ @@ -183,8 +186,8 @@ do { \ #undef PDBG #define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __FUNCTION__, __LINE__ , ## args) +dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ + __LINE__ , ## args) #undef PDBGG #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index f1120551c70..703b741e46d 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -49,11 +49,11 @@ #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ "Image Processor and Control Chip" -#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" +#define ZC0301_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.07" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 7) +#define ZC0301_MODULE_VERSION "1:1.10" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 10) /*****************************************************************************/ @@ -573,7 +573,8 @@ static int zc0301_init(struct zc0301_device* cam) int err = 0; if (!(cam->state & DEV_INITIALIZED)) { - init_waitqueue_head(&cam->open); + mutex_init(&cam->open_mutex); + init_waitqueue_head(&cam->wait_open); qctrl = s->qctrl; rect = &(s->cropcap.defrect); cam->compression.quality = ZC0301_COMPRESSION_QUALITY; @@ -634,59 +635,73 @@ static int zc0301_init(struct zc0301_device* cam) return 0; } +/*****************************************************************************/ -static void zc0301_release_resources(struct zc0301_device* cam) +static void zc0301_release_resources(struct kref *kref) { + struct zc0301_device *cam = container_of(kref, struct zc0301_device, + kref); DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + usb_put_dev(cam->usbdev); kfree(cam->control_buffer); + kfree(cam); } -/*****************************************************************************/ static int zc0301_open(struct inode* inode, struct file* filp) { struct zc0301_device* cam; int err = 0; - /* - This is the only safe way to prevent race conditions with - disconnect - */ - if (!down_read_trylock(&zc0301_disconnect)) + if (!down_read_trylock(&zc0301_dev_lock)) return -ERESTARTSYS; cam = video_get_drvdata(video_devdata(filp)); - if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&zc0301_disconnect); + if (wait_for_completion_interruptible(&cam->probe)) { + up_read(&zc0301_dev_lock); return -ERESTARTSYS; } + kref_get(&cam->kref); + + if (mutex_lock_interruptible(&cam->open_mutex)) { + kref_put(&cam->kref, zc0301_release_resources); + up_read(&zc0301_dev_lock); + return -ERESTARTSYS; + } + + if (cam->state & DEV_DISCONNECTED) { + DBG(1, "Device not present"); + err = -ENODEV; + goto out; + } + if (cam->users) { DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { err = -EWOULDBLOCK; goto out; } - mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED + DBG(2, "A blocking open() has been requested. Wait for the " + "device to be released..."); + up_read(&zc0301_dev_lock); + err = wait_event_interruptible_exclusive(cam->wait_open, + (cam->state & DEV_DISCONNECTED) || !cam->users); - if (err) { - up_read(&zc0301_disconnect); - return err; - } + down_read(&zc0301_dev_lock); + if (err) + goto out; if (cam->state & DEV_DISCONNECTED) { - up_read(&zc0301_disconnect); - return -ENODEV; + err = -ENODEV; + goto out; } - mutex_lock(&cam->dev_mutex); } - if (cam->state & DEV_MISCONFIGURED) { err = zc0301_init(cam); if (err) { @@ -711,36 +726,32 @@ static int zc0301_open(struct inode* inode, struct file* filp) DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); out: - mutex_unlock(&cam->dev_mutex); - up_read(&zc0301_disconnect); + mutex_unlock(&cam->open_mutex); + if (err) + kref_put(&cam->kref, zc0301_release_resources); + up_read(&zc0301_dev_lock); return err; } static int zc0301_release(struct inode* inode, struct file* filp) { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); + struct zc0301_device* cam; - mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ + down_write(&zc0301_dev_lock); - zc0301_stop_transfer(cam); + cam = video_get_drvdata(video_devdata(filp)); + zc0301_stop_transfer(cam); zc0301_release_buffers(cam); - - if (cam->state & DEV_DISCONNECTED) { - zc0301_release_resources(cam); - usb_put_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } - cam->users--; - wake_up_interruptible_nr(&cam->open, 1); + wake_up_interruptible_nr(&cam->wait_open, 1); DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - mutex_unlock(&cam->dev_mutex); + kref_put(&cam->kref, zc0301_release_resources); + + up_write(&zc0301_dev_lock); return 0; } @@ -775,7 +786,7 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) DBG(3, "Close and open the device again to choose the read " "method"); mutex_unlock(&cam->fileop_mutex); - return -EINVAL; + return -EBUSY; } if (cam->io == IO_NONE) { @@ -953,7 +964,12 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) return -EIO; } - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { + mutex_unlock(&cam->fileop_mutex); + return -EACCES; + } + + if (cam->io != IO_MMAP || size != PAGE_ALIGN(cam->frame[0].buf.length)) { mutex_unlock(&cam->fileop_mutex); return -EINVAL; @@ -984,7 +1000,6 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) vma->vm_ops = &zc0301_vm_ops; vma->vm_private_data = &cam->frame[i]; - zc0301_vm_open(vma); mutex_unlock(&cam->fileop_mutex); @@ -1211,7 +1226,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_CROP failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } if (!s->set_crop) { @@ -1434,7 +1449,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_S_FMT failed. " "Unmap the buffers first."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -1544,14 +1559,14 @@ zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) if (cam->io == IO_READ) { DBG(3, "Close and open the device again to choose the mmap " "I/O method"); - return -EINVAL; + return -EBUSY; } for (i = 0; i < cam->nbuffers; i++) if (cam->frame[i].vma_use_count) { DBG(3, "VIDIOC_REQBUFS failed. " "Previous buffers are still mapped."); - return -EINVAL; + return -EBUSY; } if (cam->stream == STREAM_ON) @@ -1699,9 +1714,6 @@ zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) return -EINVAL; - if (list_empty(&cam->inqueue)) - return -EINVAL; - cam->stream = STREAM_ON; DBG(3, "Stream on"); @@ -1949,8 +1961,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - mutex_init(&cam->dev_mutex); - DBG(2, "ZC0301[P] Image Processor and Control Chip detected " "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); @@ -1982,7 +1992,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->release = video_device_release; video_set_drvdata(cam->v4ldev, cam); - mutex_lock(&cam->dev_mutex); + init_completion(&cam->probe); err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, video_nr[dev_nr]); @@ -1992,7 +2002,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(1, "Free /dev/videoX node not found"); video_nr[dev_nr] = -1; dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); goto fail; } @@ -2004,8 +2014,10 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; usb_set_intfdata(intf, cam); + kref_init(&cam->kref); + usb_get_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); + complete_all(&cam->probe); return 0; @@ -2022,40 +2034,31 @@ fail: static void zc0301_usb_disconnect(struct usb_interface* intf) { - struct zc0301_device* cam = usb_get_intfdata(intf); - - if (!cam) - return; + struct zc0301_device* cam; - down_write(&zc0301_disconnect); + down_write(&zc0301_dev_lock); - mutex_lock(&cam->dev_mutex); + cam = usb_get_intfdata(intf); DBG(2, "Disconnecting %s...", cam->v4ldev->name); - wake_up_interruptible_all(&cam->open); - if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " - "memory deallocation are deferred on close.", + "memory deallocation are deferred.", cam->v4ldev->minor); cam->state |= DEV_MISCONFIGURED; zc0301_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; wake_up_interruptible(&cam->wait_frame); wake_up(&cam->wait_stream); - usb_get_dev(cam->usbdev); - } else { + } else cam->state |= DEV_DISCONNECTED; - zc0301_release_resources(cam); - } - mutex_unlock(&cam->dev_mutex); + wake_up_interruptible_all(&cam->wait_open); - if (!cam->users) - kfree(cam); + kref_put(&cam->kref, zc0301_release_resources); - up_write(&zc0301_disconnect); + up_write(&zc0301_dev_lock); } diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index 3efb92a0d0d..24b0dfba357 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c @@ -327,6 +327,7 @@ static struct zc0301_sensor pas202bcb = { .height = 480, .pixelformat = V4L2_PIX_FMT_JPEG, .priv = 8, + .colorspace = V4L2_COLORSPACE_JPEG, }, }; diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c index 5784b1d1491..9519aba3612 100644 --- a/drivers/media/video/zc0301/zc0301_pb0330.c +++ b/drivers/media/video/zc0301/zc0301_pb0330.c @@ -157,6 +157,7 @@ static struct zc0301_sensor pb0330 = { .height = 480, .pixelformat = V4L2_PIX_FMT_JPEG, .priv = 8, + .colorspace = V4L2_COLORSPACE_JPEG, }, }; diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 44e82cff931..70fe6fc6cdd 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -23,7 +23,7 @@ #define _ZC0301_SENSOR_H_ #include <linux/usb.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <linux/device.h> #include <linux/stddef.h> #include <linux/errno.h> diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index cf0ed6cbb0e..17118a490f8 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -183,14 +183,7 @@ static const int zoran_num_formats = (sizeof(zoran_formats) / sizeof(struct zoran_format)); // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined -#if !defined(CONFIG_BIGPHYS_AREA) -//#undef CONFIG_BIGPHYS_AREA -#define BUZ_USE_HIMEM -#endif -#if defined(CONFIG_BIGPHYS_AREA) -# include <linux/bigphysarea.h> -#endif extern int *zr_debug; @@ -250,7 +243,6 @@ static void jpg_fbuffer_free(struct file *file); * Linux with the necessary memory left over). */ -#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA) static unsigned long get_high_mem (unsigned long size) { @@ -314,7 +306,6 @@ get_high_mem (unsigned long size) return hi_mem_ph; } -#endif static int v4l_fbuffer_alloc (struct file *file) @@ -323,9 +314,7 @@ v4l_fbuffer_alloc (struct file *file) struct zoran *zr = fh->zr; int i, off; unsigned char *mem; -#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA) unsigned long pmem = 0; -#endif /* we might have old buffers lying around... */ if (fh->v4l_buffers.ready_to_be_freed) { @@ -369,39 +358,6 @@ v4l_fbuffer_alloc (struct file *file) ZR_DEVNAME(zr), i, (unsigned long) mem, virt_to_bus(mem)); } else { -#if defined(CONFIG_BIGPHYS_AREA) - /* Use bigphysarea_alloc_pages */ - - int n = - (fh->v4l_buffers.buffer_size + PAGE_SIZE - - 1) / PAGE_SIZE; - - mem = - (unsigned char *) bigphysarea_alloc_pages(n, 0, - GFP_KERNEL); - if (mem == 0) { - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - bigphysarea_alloc_pages for V4L buf %d failed\n", - ZR_DEVNAME(zr), i); - v4l_fbuffer_free(file); - return -ENOBUFS; - } - fh->v4l_buffers.buffer[i].fbuffer = mem; - fh->v4l_buffers.buffer[i].fbuffer_phys = - virt_to_phys(mem); - fh->v4l_buffers.buffer[i].fbuffer_bus = - virt_to_bus(mem); - dprintk(4, - KERN_INFO - "%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)\n", - ZR_DEVNAME(zr), i, (unsigned) mem, - (unsigned) virt_to_bus(mem)); - - /* Zero out the allocated memory */ - memset(fh->v4l_buffers.buffer[i].fbuffer, 0, - fh->v4l_buffers.buffer_size); -#elif defined(BUZ_USE_HIMEM) /* Use high memory which has been left at boot time */ @@ -441,20 +397,6 @@ v4l_fbuffer_alloc (struct file *file) fh->v4l_buffers.buffer[i].fbuffer_bus = pmem + i * fh->v4l_buffers.buffer_size; } -#else - /* No bigphysarea present, usage of high memory disabled, - * but user wants buffers of more than MAX_KMALLOC_MEM */ - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - no bigphysarea_patch present, usage of high memory disabled,\n", - ZR_DEVNAME(zr)); - dprintk(1, - KERN_ERR - "%s: v4l_fbuffer_alloc() - sorry, could not allocate %d V4L buffers of size %d KB.\n", - ZR_DEVNAME(zr), fh->v4l_buffers.num_buffers, - fh->v4l_buffers.buffer_size >> 10); - return -ENOBUFS; -#endif } } @@ -485,11 +427,6 @@ v4l_fbuffer_free (struct file *file) ClearPageReserved(MAP_NR(mem + off)); kfree((void *) fh->v4l_buffers.buffer[i].fbuffer); } -#if defined(CONFIG_BIGPHYS_AREA) - else - bigphysarea_free_pages((void *) fh->v4l_buffers. - buffer[i].fbuffer); -#endif fh->v4l_buffers.buffer[i].fbuffer = NULL; } diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index b5d3364c94c..6f1892585cb 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -92,6 +92,7 @@ static struct usb_device_id device_table[] = { {USB_DEVICE(0x0784, 0x0040), .driver_info = METHOD1 }, {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 }, {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 }, + {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, {} /* Terminating entry */ }; @@ -792,6 +793,7 @@ static int zr364xx_probe(struct usb_interface *intf, { struct usb_device *udev = interface_to_usbdev(intf); struct zr364xx_camera *cam = NULL; + int err; DBG("probing..."); @@ -799,12 +801,11 @@ static int zr364xx_probe(struct usb_interface *intf, info("model %04x:%04x detected", udev->descriptor.idVendor, udev->descriptor.idProduct); - if ((cam = - kmalloc(sizeof(struct zr364xx_camera), GFP_KERNEL)) == NULL) { + cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); + if (cam == NULL) { info("cam: out of memory !"); - return -ENODEV; + return -ENOMEM; } - memset(cam, 0x00, sizeof(struct zr364xx_camera)); /* save the init method used by this camera */ cam->method = id->driver_info; @@ -812,7 +813,7 @@ static int zr364xx_probe(struct usb_interface *intf, if (cam->vdev == NULL) { info("cam->vdev: out of memory !"); kfree(cam); - return -ENODEV; + return -ENOMEM; } memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template)); video_set_drvdata(cam->vdev, cam); @@ -858,12 +859,13 @@ static int zr364xx_probe(struct usb_interface *intf, cam->brightness = 64; mutex_init(&cam->lock); - if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); + if (err) { info("video_register_device failed"); video_device_release(cam->vdev); kfree(cam->buffer); kfree(cam); - return -ENODEV; + return err; } usb_set_intfdata(intf, cam); @@ -905,7 +907,7 @@ static struct usb_driver zr364xx_driver = { static int __init zr364xx_init(void) { int retval; - retval = usb_register(&zr364xx_driver) < 0; + retval = usb_register(&zr364xx_driver); if (retval) info("usb_register failed!"); else |