diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 00:13:22 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 16:25:07 -0300 |
commit | 0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch) | |
tree | e759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/video/au0828 | |
parent | 84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff) | |
download | linux-0c0d06cac63ee327ceaab4b5ffe2206574ab86bd.tar.bz2 |
[media] rename most media/video usb drivers to media/usb
Rename all USB drivers with their own directory under
drivers/media/video into drivers/media/usb and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/au0828')
-rw-r--r-- | drivers/media/video/au0828/Kconfig | 18 | ||||
-rw-r--r-- | drivers/media/video/au0828/Makefile | 9 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-cards.c | 339 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-cards.h | 27 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-core.c | 282 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-dvb.c | 500 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-i2c.c | 401 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-reg.h | 66 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-vbi.c | 138 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828-video.c | 2034 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828.h | 304 |
11 files changed, 0 insertions, 4118 deletions
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig deleted file mode 100644 index 23f7fd22f0eb..000000000000 --- a/drivers/media/video/au0828/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ - -config VIDEO_AU0828 - tristate "Auvitek AU0828 support" - depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 - depends on DVB_CAPTURE_DRIVERS - select I2C_ALGOBIT - select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC - select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE - select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - ---help--- - This is a video4linux driver for Auvitek's USB device. - - To compile this driver as a module, choose M here: the - module will be called au0828 diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile deleted file mode 100644 index 98cc20cc0ffb..000000000000 --- a/drivers/media/video/au0828/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o - -obj-$(CONFIG_VIDEO_AU0828) += au0828.o - -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends - -ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c deleted file mode 100644 index 448361c6a13e..000000000000 --- a/drivers/media/video/au0828/au0828-cards.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "au0828.h" -#include "au0828-cards.h" -#include "au8522.h" -#include "media/tuner.h" -#include "media/v4l2-common.h" - -void hvr950q_cs5340_audio(void *priv, int enable) -{ - /* Because the HVR-950q shares an i2s bus between the cs5340 and the - au8522, we need to hold cs5340 in reset when using the au8522 */ - struct au0828_dev *dev = priv; - if (enable == 1) - au0828_set(dev, REG_000, 0x10); - else - au0828_clear(dev, REG_000, 0x10); -} - -struct au0828_board au0828_boards[] = { - [AU0828_BOARD_UNKNOWN] = { - .name = "Unknown board", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - }, - [AU0828_BOARD_HAUPPAUGE_HVR850] = { - .name = "Hauppauge HVR850", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, - .input = { - { - .type = AU0828_VMUX_TELEVISION, - .vmux = AU8522_COMPOSITE_CH4_SIF, - .amux = AU8522_AUDIO_SIF, - }, - { - .type = AU0828_VMUX_COMPOSITE, - .vmux = AU8522_COMPOSITE_CH1, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - { - .type = AU0828_VMUX_SVIDEO, - .vmux = AU8522_SVIDEO_CH13, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - }, - }, - [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { - .name = "Hauppauge HVR950Q", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - /* The au0828 hardware i2c implementation does not properly - support the xc5000's i2c clock stretching. So we need to - lower the clock frequency enough where the 15us clock - stretch fits inside of a normal clock cycle, or else the - au0828 fails to set the STOP bit. A 30 KHz clock puts the - clock pulse width at 18us */ - .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, - .input = { - { - .type = AU0828_VMUX_TELEVISION, - .vmux = AU8522_COMPOSITE_CH4_SIF, - .amux = AU8522_AUDIO_SIF, - }, - { - .type = AU0828_VMUX_COMPOSITE, - .vmux = AU8522_COMPOSITE_CH1, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - { - .type = AU0828_VMUX_SVIDEO, - .vmux = AU8522_SVIDEO_CH13, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - }, - }, - [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { - .name = "Hauppauge HVR950Q rev xxF8", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, - [AU0828_BOARD_DVICO_FUSIONHDTV7] = { - .name = "DViCO FusionHDTV USB", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, - [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { - .name = "Hauppauge Woodbury", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, -}; - -/* Tuner callback function for au0828 boards. Currently only needed - * for HVR1500Q, which has an xc5000 tuner. - */ -int au0828_tuner_callback(void *priv, int component, int command, int arg) -{ - struct au0828_dev *dev = priv; - - dprintk(1, "%s()\n", __func__); - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_DVICO_FUSIONHDTV7: - if (command == 0) { - /* Tuner Reset Command from xc5000 */ - /* Drive the tuner into reset and out */ - au0828_clear(dev, REG_001, 2); - mdelay(10); - au0828_set(dev, REG_001, 2); - mdelay(10); - return 0; - } else { - printk(KERN_ERR - "%s(): Unknown command.\n", __func__); - return -EINVAL; - } - break; - } - - return 0; /* Should never be here */ -} - -static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) -{ - struct tveeprom tv; - - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); - dev->board.tuner_type = tv.tuner_type; - - /* Make sure we support the board model */ - switch (tv.model) { - case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ - case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ - case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ - case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ - break; - default: - printk(KERN_WARNING "%s: warning: " - "unknown hauppauge model #%d\n", __func__, tv.model); - break; - } - - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", - __func__, tv.model); -} - -void au0828_card_setup(struct au0828_dev *dev) -{ - static u8 eeprom[256]; - struct tuner_setup tun_setup; - struct v4l2_subdev *sd; - unsigned int mode_mask = T_ANALOG_TV; - - dprintk(1, "%s()\n", __func__); - - memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board)); - - if (dev->i2c_rc == 0) { - dev->i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); - } - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - if (dev->i2c_rc == 0) - hauppauge_eeprom(dev, eeprom+0xa0); - break; - } - - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - /* Load the analog demodulator driver (note this would need to - be abstracted out if we ever need to support a different - demod) */ - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "au8522", 0x8e >> 1, NULL); - if (sd == NULL) - printk(KERN_ERR "analog subdev registration failed\n"); - } - - /* Setup tuners */ - if (dev->board.tuner_type != TUNER_ABSENT) { - /* Load the tuner module, which does the attach */ - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->board.tuner_addr, NULL); - if (sd == NULL) - printk(KERN_ERR "tuner subdev registration fail\n"); - - tun_setup.mode_mask = mode_mask; - tun_setup.type = dev->board.tuner_type; - tun_setup.addr = dev->board.tuner_addr; - tun_setup.tuner_callback = au0828_tuner_callback; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, - &tun_setup); - } -} - -/* - * The bridge has between 8 and 12 gpios. - * Regs 1 and 0 deal with output enables. - * Regs 3 and 2 deal with direction. - */ -void au0828_gpio_setup(struct au0828_dev *dev) -{ - dprintk(1, "%s()\n", __func__); - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - /* GPIO's - * 4 - CS5340 - * 5 - AU8522 Demodulator - * 6 - eeprom W/P - * 7 - power supply - * 9 - XC5000 Tuner - */ - - /* Into reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); - au0828_write(dev, REG_001, 0x0); - au0828_write(dev, REG_000, 0x0); - msleep(100); - - /* Out of reset (leave the cs5340 in reset until needed) */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); - au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20); - - msleep(250); - break; - case AU0828_BOARD_DVICO_FUSIONHDTV7: - /* GPIO's - * 6 - ? - * 8 - AU8522 Demodulator - * 9 - XC5000 Tuner - */ - - /* Into reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0xa0); - au0828_write(dev, REG_001, 0x0); - au0828_write(dev, REG_000, 0x0); - msleep(100); - - /* Out of reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0xa0); - au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_000, 0xa0); - msleep(250); - break; - } -} - -/* table of devices that work with this driver */ -struct usb_device_id au0828_usb_id_table[] = { - { USB_DEVICE(0x2040, 0x7200), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7240), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, - { USB_DEVICE(0x0fe9, 0xd620), - .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, - { USB_DEVICE(0x2040, 0x7210), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7217), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721b), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721e), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721f), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7280), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x0fd9, 0x0008), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7201), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x2040, 0x7211), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x2040, 0x7281), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x05e1, 0x0480), - .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, - { USB_DEVICE(0x2040, 0x8200), - .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, - { USB_DEVICE(0x2040, 0x7260), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7213), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { }, -}; - -MODULE_DEVICE_TABLE(usb, au0828_usb_id_table); diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h deleted file mode 100644 index 48a1882c2b6b..000000000000 --- a/drivers/media/video/au0828/au0828-cards.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define AU0828_BOARD_UNKNOWN 0 -#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1 -#define AU0828_BOARD_HAUPPAUGE_HVR850 2 -#define AU0828_BOARD_DVICO_FUSIONHDTV7 3 -#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL 4 -#define AU0828_BOARD_HAUPPAUGE_WOODBURY 5 diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c deleted file mode 100644 index 745a80a798c8..000000000000 --- a/drivers/media/video/au0828/au0828-core.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <linux/mutex.h> - -#include "au0828.h" - -/* - * 1 = General debug messages - * 2 = USB handling - * 4 = I2C related - * 8 = Bridge related - */ -int au0828_debug; -module_param_named(debug, au0828_debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); - -static unsigned int disable_usb_speed_check; -module_param(disable_usb_speed_check, int, 0444); -MODULE_PARM_DESC(disable_usb_speed_check, - "override min bandwidth requirement of 480M bps"); - -#define _AU0828_BULKPIPE 0x03 -#define _BULKPIPESIZE 0xffff - -static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index); -static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size); - -/* USB Direction */ -#define CMD_REQUEST_IN 0x00 -#define CMD_REQUEST_OUT 0x01 - -u32 au0828_readreg(struct au0828_dev *dev, u16 reg) -{ - u8 result = 0; - - recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1); - dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result); - - return result; -} - -u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) -{ - dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); - return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); -} - -static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index) -{ - int status = -ENODEV; - - if (dev->usbdev) { - - /* cp must be memory that has been allocated by kmalloc */ - status = usb_control_msg(dev->usbdev, - usb_sndctrlpipe(dev->usbdev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, - value, index, NULL, 0, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_ERR "%s() Failed sending control message, error %d.\n", - __func__, status); - } - - } - - return status; -} - -static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size) -{ - int status = -ENODEV; - mutex_lock(&dev->mutex); - if (dev->usbdev) { - status = usb_control_msg(dev->usbdev, - usb_rcvctrlpipe(dev->usbdev, 0), - request, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - dev->ctrlmsg, size, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", - __func__, status); - } - - /* the host controller requires heap allocated memory, which - is why we didn't just pass "cp" into usb_control_msg */ - memcpy(cp, dev->ctrlmsg, size); - } - mutex_unlock(&dev->mutex); - return status; -} - -static void au0828_usb_disconnect(struct usb_interface *interface) -{ - struct au0828_dev *dev = usb_get_intfdata(interface); - - dprintk(1, "%s()\n", __func__); - - /* Digital TV */ - au0828_dvb_unregister(dev); - - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_unregister(dev); - - /* I2C */ - au0828_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - usb_set_intfdata(interface, NULL); - - mutex_lock(&dev->mutex); - dev->usbdev = NULL; - mutex_unlock(&dev->mutex); - - kfree(dev); - -} - -static int au0828_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int ifnum, retval; - struct au0828_dev *dev; - struct usb_device *usbdev = interface_to_usbdev(interface); - - ifnum = interface->altsetting->desc.bInterfaceNumber; - - if (ifnum != 0) - return -ENODEV; - - dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - ifnum); - - /* - * Make sure we have 480 Mbps of bandwidth, otherwise things like - * video stream wouldn't likely work, since 12 Mbps is generally - * not enough even for most Digital TV streams. - */ - if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { - printk(KERN_ERR "au0828: Device initialization failed.\n"); - printk(KERN_ERR "au0828: Device must be connected to a " - "high-speed USB 2.0 port.\n"); - return -ENODEV; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "%s() Unable to allocate memory\n", __func__); - return -ENOMEM; - } - - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - mutex_init(&dev->mutex); - mutex_init(&dev->dvb.lock); - dev->usbdev = usbdev; - dev->boardnr = id->driver_info; - - /* Create the v4l2_device */ - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); - if (retval) { - printk(KERN_ERR "%s() v4l2_device_register failed\n", - __func__); - mutex_unlock(&dev->lock); - kfree(dev); - return -EIO; - } - - /* Power Up the bridge */ - au0828_write(dev, REG_600, 1 << 4); - - /* Bring up the GPIO's and supporting devices */ - au0828_gpio_setup(dev); - - /* I2C */ - au0828_i2c_register(dev); - - /* Setup */ - au0828_card_setup(dev); - - /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_register(dev, interface); - - /* Digital TV */ - au0828_dvb_register(dev); - - /* Store the pointer to the au0828_dev so it can be accessed in - au0828_usb_disconnect */ - usb_set_intfdata(interface, dev); - - printk(KERN_INFO "Registered device AU0828 [%s]\n", - dev->board.name == NULL ? "Unset" : dev->board.name); - - mutex_unlock(&dev->lock); - - return 0; -} - -static struct usb_driver au0828_usb_driver = { - .name = DRIVER_NAME, - .probe = au0828_usb_probe, - .disconnect = au0828_usb_disconnect, - .id_table = au0828_usb_id_table, -}; - -static int __init au0828_init(void) -{ - int ret; - - if (au0828_debug & 1) - printk(KERN_INFO "%s() Debugging is enabled\n", __func__); - - if (au0828_debug & 2) - printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__); - - if (au0828_debug & 4) - printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__); - - if (au0828_debug & 8) - printk(KERN_INFO "%s() Bridge Debugging is enabled\n", - __func__); - - printk(KERN_INFO "au0828 driver loaded\n"); - - ret = usb_register(&au0828_usb_driver); - if (ret) - printk(KERN_ERR "usb_register failed, error = %d\n", ret); - - return ret; -} - -static void __exit au0828_exit(void) -{ - usb_deregister(&au0828_usb_driver); -} - -module_init(au0828_init); -module_exit(au0828_exit); - -MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); -MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.2"); diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c deleted file mode 100644 index b328f6550d0b..000000000000 --- a/drivers/media/video/au0828/au0828-dvb.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/suspend.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#include "au0828.h" -#include "au8522.h" -#include "xc5000.h" -#include "mxl5007t.h" -#include "tda18271.h" - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define _AU0828_BULKPIPE 0x83 -#define _BULKPIPESIZE 0xe522 - -static u8 hauppauge_hvr950q_led_states[] = { - 0x00, /* off */ - 0x02, /* yellow */ - 0x04, /* green */ -}; - -static struct au8522_led_config hauppauge_hvr950q_led_cfg = { - .gpio_output = 0x00e0, - .gpio_output_enable = 0x6006, - .gpio_output_disable = 0x0660, - - .gpio_leds = 0x00e2, - .led_states = hauppauge_hvr950q_led_states, - .num_led_states = sizeof(hauppauge_hvr950q_led_states), - - .vsb8_strong = 20 /* dB */ * 10, - .qam64_strong = 25 /* dB */ * 10, - .qam256_strong = 32 /* dB */ * 10, -}; - -static struct au8522_config hauppauge_hvr950q_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_6MHZ, - .vsb_if = AU8522_IF_6MHZ, - .led_cfg = &hauppauge_hvr950q_led_cfg, -}; - -static struct au8522_config fusionhdtv7usb_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_6MHZ, - .vsb_if = AU8522_IF_6MHZ, -}; - -static struct au8522_config hauppauge_woodbury_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_4MHZ, - .vsb_if = AU8522_IF_3_25MHZ, -}; - -static struct xc5000_config hauppauge_xc5000a_config = { - .i2c_address = 0x61, - .if_khz = 6000, - .chip_id = XC5000A, -}; - -static struct xc5000_config hauppauge_xc5000c_config = { - .i2c_address = 0x61, - .if_khz = 6000, - .chip_id = XC5000C, -}; - -static struct mxl5007t_config mxl5007t_hvr950q_config = { - .xtal_freq_hz = MxL_XTAL_24_MHZ, - .if_freq_hz = MxL_IF_6_MHZ, -}; - -static struct tda18271_config hauppauge_woodbury_tunerconfig = { - .gate = TDA18271_GATE_DIGITAL, -}; - -static void au0828_restart_dvb_streaming(struct work_struct *work); - -/*-------------------------------------------------------------------*/ -static void urb_completion(struct urb *purb) -{ - struct au0828_dev *dev = purb->context; - int ptype = usb_pipetype(purb->pipe); - unsigned char *ptr; - - dprintk(2, "%s()\n", __func__); - - if (!dev) - return; - - if (dev->urb_streaming == 0) - return; - - if (ptype != PIPE_BULK) { - printk(KERN_ERR "%s() Unsupported URB type %d\n", - __func__, ptype); - return; - } - - /* See if the stream is corrupted (to work around a hardware - bug where the stream gets misaligned */ - ptr = purb->transfer_buffer; - if (purb->actual_length > 0 && ptr[0] != 0x47) { - dprintk(1, "Need to restart streaming %02x len=%d!\n", - ptr[0], purb->actual_length); - schedule_work(&dev->restart_streaming); - return; - } - - /* Feed the transport payload into the kernel demux */ - dvb_dmx_swfilter_packets(&dev->dvb.demux, - purb->transfer_buffer, purb->actual_length / 188); - - /* Clean the buffer before we requeue */ - memset(purb->transfer_buffer, 0, URB_BUFSIZE); - - /* Requeue URB */ - usb_submit_urb(purb, GFP_ATOMIC); -} - -static int stop_urb_transfer(struct au0828_dev *dev) -{ - int i; - - dprintk(2, "%s()\n", __func__); - - dev->urb_streaming = 0; - for (i = 0; i < URB_COUNT; i++) { - usb_kill_urb(dev->urbs[i]); - kfree(dev->urbs[i]->transfer_buffer); - usb_free_urb(dev->urbs[i]); - } - - return 0; -} - -static int start_urb_transfer(struct au0828_dev *dev) -{ - struct urb *purb; - int i, ret = -ENOMEM; - - dprintk(2, "%s()\n", __func__); - - if (dev->urb_streaming) { - dprintk(2, "%s: bulk xfer already running!\n", __func__); - return 0; - } - - for (i = 0; i < URB_COUNT; i++) { - - dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urbs[i]) - goto err; - - purb = dev->urbs[i]; - - purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL); - if (!purb->transfer_buffer) { - usb_free_urb(purb); - dev->urbs[i] = NULL; - goto err; - } - - purb->status = -EINPROGRESS; - usb_fill_bulk_urb(purb, - dev->usbdev, - usb_rcvbulkpipe(dev->usbdev, - _AU0828_BULKPIPE), - purb->transfer_buffer, - URB_BUFSIZE, - urb_completion, - dev); - - } - - for (i = 0; i < URB_COUNT; i++) { - ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC); - if (ret != 0) { - stop_urb_transfer(dev); - printk(KERN_ERR "%s: failed urb submission, " - "err = %d\n", __func__, ret); - return ret; - } - } - - dev->urb_streaming = 1; - ret = 0; - -err: - return ret; -} - -static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct au0828_dev *dev = (struct au0828_dev *) demux->priv; - struct au0828_dvb *dvb = &dev->dvb; - int ret = 0; - - dprintk(1, "%s()\n", __func__); - - if (!demux->dmx.frontend) - return -EINVAL; - - if (dvb) { - mutex_lock(&dvb->lock); - if (dvb->feeding++ == 0) { - /* Start transport */ - au0828_write(dev, 0x608, 0x90); - au0828_write(dev, 0x609, 0x72); - au0828_write(dev, 0x60a, 0x71); - au0828_write(dev, 0x60b, 0x01); - ret = start_urb_transfer(dev); - } - mutex_unlock(&dvb->lock); - } - - return ret; -} - -static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct au0828_dev *dev = (struct au0828_dev *) demux->priv; - struct au0828_dvb *dvb = &dev->dvb; - int ret = 0; - - dprintk(1, "%s()\n", __func__); - - if (dvb) { - mutex_lock(&dvb->lock); - if (--dvb->feeding == 0) { - /* Stop transport */ - ret = stop_urb_transfer(dev); - au0828_write(dev, 0x60b, 0x00); - } - mutex_unlock(&dvb->lock); - } - - return ret; -} - -static void au0828_restart_dvb_streaming(struct work_struct *work) -{ - struct au0828_dev *dev = container_of(work, struct au0828_dev, - restart_streaming); - struct au0828_dvb *dvb = &dev->dvb; - int ret; - - if (dev->urb_streaming == 0) - return; - - dprintk(1, "Restarting streaming...!\n"); - - mutex_lock(&dvb->lock); - - /* Stop transport */ - ret = stop_urb_transfer(dev); - au0828_write(dev, 0x608, 0x00); - au0828_write(dev, 0x609, 0x00); - au0828_write(dev, 0x60a, 0x00); - au0828_write(dev, 0x60b, 0x00); - - /* Start transport */ - au0828_write(dev, 0x608, 0x90); - au0828_write(dev, 0x609, 0x72); - au0828_write(dev, 0x60a, 0x71); - au0828_write(dev, 0x60b, 0x01); - ret = start_urb_transfer(dev); - - mutex_unlock(&dvb->lock); -} - -static int dvb_register(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - int result; - - dprintk(1, "%s()\n", __func__); - - INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming); - - /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, - &dev->usbdev->dev, adapter_nr); - if (result < 0) { - printk(KERN_ERR "%s: dvb_register_adapter failed " - "(errno = %d)\n", DRIVER_NAME, result); - goto fail_adapter; - } - dvb->adapter.priv = dev; - - /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (result < 0) { - printk(KERN_ERR "%s: dvb_register_frontend failed " - "(errno = %d)\n", DRIVER_NAME, result); - goto fail_frontend; - } - - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dev; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; - dvb->demux.start_feed = au0828_dvb_start_feed; - dvb->demux.stop_feed = au0828_dvb_stop_feed; - result = dvb_dmx_init(&dvb->demux); - if (result < 0) { - printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_dmx; - } - - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (result < 0) { - printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_dmxdev; - } - - dvb->fe_hw.source = DMX_FRONTEND_0; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result); - goto fail_fe_hw; - } - - dvb->fe_mem.source = DMX_MEMORY_FE; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); - if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result); - goto fail_fe_mem; - } - - result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_fe_conn; - } - - /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - return 0; - -fail_fe_conn: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: - dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: - dvb_dmx_release(&dvb->demux); -fail_dmx: - dvb_unregister_frontend(dvb->frontend); -fail_frontend: - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: - return result; -} - -void au0828_dvb_unregister(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - - dprintk(1, "%s()\n", __func__); - - if (dvb->frontend == NULL) - return; - - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -} - -/* All the DVB attach calls go here, this function get's modified - * for each new card. No other function in this file needs - * to change. - */ -int au0828_dvb_register(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - int ret; - - dprintk(1, "%s()\n", __func__); - - /* init frontend */ - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_hvr950q_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - switch (dev->board.tuner_type) { - default: - case TUNER_XC5000: - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000a_config); - break; - case TUNER_XC5000C: - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000c_config); - break; - } - break; - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_hvr950q_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - dvb_attach(mxl5007t_attach, dvb->frontend, - &dev->i2c_adap, 0x60, - &mxl5007t_hvr950q_config); - break; - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_woodbury_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - dvb_attach(tda18271_attach, dvb->frontend, - 0x60, &dev->i2c_adap, - &hauppauge_woodbury_tunerconfig); - break; - case AU0828_BOARD_DVICO_FUSIONHDTV7: - dvb->frontend = dvb_attach(au8522_attach, - &fusionhdtv7usb_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) { - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000a_config); - } - break; - default: - printk(KERN_WARNING "The frontend of your DVB/ATSC card " - "isn't supported yet\n"); - break; - } - if (NULL == dvb->frontend) { - printk(KERN_ERR "%s() Frontend initialization failed\n", - __func__); - return -1; - } - /* define general-purpose callback pointer */ - dvb->frontend->callback = au0828_tuner_callback; - - /* register everything */ - ret = dvb_register(dev); - if (ret < 0) { - if (dvb->frontend->ops.release) - dvb->frontend->ops.release(dvb->frontend); - return ret; - } - - return 0; -} diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c deleted file mode 100644 index 4ded17fe1957..000000000000 --- a/drivers/media/video/au0828/au0828-i2c.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Driver for the Auvitek AU0828 USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/io.h> - -#include "au0828.h" -#include "media/tuner.h" -#include <media/v4l2-common.h> - -static int i2c_scan; -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); - -#define I2C_WAIT_DELAY 25 -#define I2C_WAIT_RETRY 1000 - -static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1; -} - -static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1; -} - -static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_slave_did_read_ack(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_READ_DONE ? 0 : 1; -} - -static int i2c_wait_read_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_is_read_busy(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0; -} - -static int i2c_wait_write_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (i2c_is_write_done(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_BUSY ? 1 : 0; -} - -static int i2c_wait_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_is_busy(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -/* FIXME: Implement join handling correctly */ -static int i2c_sendbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int joined_rlen) -{ - int i, strobe = 0; - struct au0828_dev *dev = i2c_adap->algo_data; - - dprintk(4, "%s()\n", __func__); - - au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - - /* Set the I2C clock */ - if (((dev->board.tuner_type == TUNER_XC5000) || - (dev->board.tuner_type == TUNER_XC5000C)) && - (dev->board.tuner_addr == msg->addr) && - (msg->len == 64)) { - /* Hack to speed up firmware load. The xc5000 lets us do up - to 400 KHz when in firmware download mode */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_250KHZ); - } else { - /* Use the i2c clock speed in the board configuration */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - dev->board.i2c_clk_divider); - } - - /* Hardware needs 8 bit addresses */ - au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); - - dprintk(4, "SEND: %02x\n", msg->addr); - - /* Deal with i2c_scan */ - if (msg->len == 0) { - /* The analog tuner detection code makes use of the SMBUS_QUICK - message (which involves a zero length i2c write). To avoid - checking the status register when we didn't strobe out any - actual bytes to the bus, just do a read check. This is - consistent with how I saw i2c device checking done in the - USB trace of the Windows driver */ - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - if (i2c_wait_read_ack(i2c_adap)) - return -EIO; - - return 0; - } - - for (i = 0; i < msg->len;) { - - dprintk(4, " %02x\n", msg->buf[i]); - - au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]); - - strobe++; - i++; - - if ((strobe >= 4) || (i >= msg->len)) { - - /* Strobe the byte into the bus */ - if (i < msg->len) - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_WRITE | - AU0828_I2C_TRIGGER_HOLD); - else - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_WRITE); - - /* Reset strobe trigger */ - strobe = 0; - - if (!i2c_wait_write_done(i2c_adap)) - return -EIO; - - } - - } - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - dprintk(4, "\n"); - - return msg->len; -} - -/* FIXME: Implement join handling correctly */ -static int i2c_readbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int joined) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - int i; - - dprintk(4, "%s()\n", __func__); - - au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - - /* Set the I2C clock */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - dev->board.i2c_clk_divider); - - /* Hardware needs 8 bit addresses */ - au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); - - dprintk(4, " RECV:\n"); - - /* Deal with i2c_scan */ - if (msg->len == 0) { - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (i2c_wait_read_ack(i2c_adap)) - return -EIO; - return 0; - } - - for (i = 0; i < msg->len;) { - - i++; - - if (i < msg->len) - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ | - AU0828_I2C_TRIGGER_HOLD); - else - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (!i2c_wait_read_done(i2c_adap)) - return -EIO; - - msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) & - 0xff; - - dprintk(4, " %02x\n", msg->buf[i-1]); - } - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - dprintk(4, "\n"); - - return msg->len; -} - -static int i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - int i, retval = 0; - - dprintk(4, "%s(num = %d)\n", __func__, num); - - for (i = 0; i < num; i++) { - dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n", - __func__, num, msgs[i].addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) { - /* read */ - retval = i2c_readbytes(i2c_adap, &msgs[i], 0); - } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) { - /* write then read from same address */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], - msgs[i + 1].len); - if (retval < 0) - goto err; - i++; - retval = i2c_readbytes(i2c_adap, &msgs[i], 1); - } else { - /* write */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); - } - if (retval < 0) - goto err; - } - return num; - -err: - return retval; -} - -static u32 au0828_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; -} - -static struct i2c_algorithm au0828_i2c_algo_template = { - .master_xfer = i2c_xfer, - .functionality = au0828_functionality, -}; - -/* ----------------------------------------------------------------------- */ - -static struct i2c_adapter au0828_i2c_adap_template = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .algo = &au0828_i2c_algo_template, -}; - -static struct i2c_client au0828_i2c_client_template = { - .name = "au0828 internal", -}; - -static char *i2c_devs[128] = { - [0x8e >> 1] = "au8522", - [0xa0 >> 1] = "eeprom", - [0xc2 >> 1] = "tuner/xc5000", -}; - -static void do_i2c_scan(char *name, struct i2c_client *c) -{ - unsigned char buf; - int i, rc; - - for (i = 0; i < 128; i++) { - c->addr = i; - rc = i2c_master_recv(c, &buf, 0); - if (rc < 0) - continue; - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n", - name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } -} - -/* init + register i2c adapter */ -int au0828_i2c_register(struct au0828_dev *dev) -{ - dprintk(1, "%s()\n", __func__); - - memcpy(&dev->i2c_adap, &au0828_i2c_adap_template, - sizeof(dev->i2c_adap)); - memcpy(&dev->i2c_algo, &au0828_i2c_algo_template, - sizeof(dev->i2c_algo)); - memcpy(&dev->i2c_client, &au0828_i2c_client_template, - sizeof(dev->i2c_client)); - - dev->i2c_adap.dev.parent = &dev->usbdev->dev; - - strlcpy(dev->i2c_adap.name, DRIVER_NAME, - sizeof(dev->i2c_adap.name)); - - dev->i2c_adap.algo = &dev->i2c_algo; - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - i2c_add_adapter(&dev->i2c_adap); - - dev->i2c_client.adapter = &dev->i2c_adap; - - if (0 == dev->i2c_rc) { - printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME); - if (i2c_scan) - do_i2c_scan(DRIVER_NAME, &dev->i2c_client); - } else - printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME); - - return dev->i2c_rc; -} - -int au0828_i2c_unregister(struct au0828_dev *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} - diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h deleted file mode 100644 index 2140f4cfb645..000000000000 --- a/drivers/media/video/au0828/au0828-reg.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* We'll start to rename these registers once we have a better - * understanding of their meaning. - */ -#define REG_000 0x000 -#define REG_001 0x001 -#define REG_002 0x002 -#define REG_003 0x003 - -#define AU0828_SENSORCTRL_100 0x100 -#define AU0828_SENSORCTRL_VBI_103 0x103 - -/* I2C registers */ -#define AU0828_I2C_TRIGGER_200 0x200 -#define AU0828_I2C_STATUS_201 0x201 -#define AU0828_I2C_CLK_DIVIDER_202 0x202 -#define AU0828_I2C_DEST_ADDR_203 0x203 -#define AU0828_I2C_WRITE_FIFO_205 0x205 -#define AU0828_I2C_READ_FIFO_209 0x209 -#define AU0828_I2C_MULTIBYTE_MODE_2FF 0x2ff - -/* Audio registers */ -#define AU0828_AUDIOCTRL_50C 0x50C - -#define REG_600 0x600 - -/*********************************************************************/ -/* Here are constants for values associated with the above registers */ - -/* I2C Trigger (Reg 0x200) */ -#define AU0828_I2C_TRIGGER_WRITE 0x01 -#define AU0828_I2C_TRIGGER_READ 0x20 -#define AU0828_I2C_TRIGGER_HOLD 0x40 - -/* I2C Status (Reg 0x201) */ -#define AU0828_I2C_STATUS_READ_DONE 0x01 -#define AU0828_I2C_STATUS_NO_READ_ACK 0x02 -#define AU0828_I2C_STATUS_WRITE_DONE 0x04 -#define AU0828_I2C_STATUS_NO_WRITE_ACK 0x08 -#define AU0828_I2C_STATUS_BUSY 0x10 - -/* I2C Clock Divider (Reg 0x202) */ -#define AU0828_I2C_CLK_250KHZ 0x07 -#define AU0828_I2C_CLK_100KHZ 0x14 -#define AU0828_I2C_CLK_30KHZ 0x40 -#define AU0828_I2C_CLK_20KHZ 0x60 diff --git a/drivers/media/video/au0828/au0828-vbi.c b/drivers/media/video/au0828/au0828-vbi.c deleted file mode 100644 index 63f593070ee8..000000000000 --- a/drivers/media/video/au0828/au0828-vbi.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - au0828-vbi.c - VBI driver for au0828 - - Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> - - This work was sponsored by GetWellNetwork Inc. - - 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include "au0828.h" - -static unsigned int vbibufs = 5; -module_param(vbibufs, int, 0644); -MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); - -/* ------------------------------------------------------------------ */ - -static void -free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vbi_buf == buf) - dev->isoc_ctl.vbi_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; - - *size = dev->vbi_width * dev->vbi_height * 2; - - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - return 0; -} - -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - int rc = 0; - - buf->vb.size = dev->vbi_width * dev->vbi_height * 2; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->vbi_width; - buf->vb.height = dev->vbi_height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(q, buf); - return rc; -} - -static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_dmaqueue *vbiq = &dev->vbiq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vbiq->active); -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - free_buffer(q, buf); -} - -struct videobuf_queue_ops au0828_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, -}; diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c deleted file mode 100644 index fa0fa9ae91c7..000000000000 --- a/drivers/media/video/au0828/au0828-video.c +++ /dev/null @@ -1,2034 +0,0 @@ -/* - * Auvitek AU0828 USB Bridge (Analog video support) - * - * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org> - * Copyright (C) 2005-2008 Auvitek International, Ltd. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/* Developer Notes: - * - * VBI support is not yet working - * The hardware scaler supported is unimplemented - * AC97 audio support is unimplemented (only i2s audio mode) - * - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/suspend.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/tuner.h> -#include "au0828.h" -#include "au0828-reg.h" - -static DEFINE_MUTEX(au0828_sysfs_lock); - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ - -static unsigned int isoc_debug; -module_param(isoc_debug, int, 0644); -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); - -#define au0828_isocdbg(fmt, arg...) \ -do {\ - if (isoc_debug) { \ - printk(KERN_INFO "au0828 %s :"fmt, \ - __func__ , ##arg); \ - } \ - } while (0) - -static inline void print_err_status(struct au0828_dev *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - au0828_isocdbg("URB status %d [%s].\n", status, errmsg); - } else { - au0828_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static int check_dev(struct au0828_dev *dev) -{ - if (dev->dev_state & DEV_DISCONNECTED) { - printk(KERN_INFO "v4l2 ioctl: device not present\n"); - return -ENODEV; - } - - if (dev->dev_state & DEV_MISCONFIGURED) { - printk(KERN_INFO "v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); - return -EIO; - } - return 0; -} - -/* - * IRQ callback, called by URB callback - */ -static void au0828_irq_callback(struct urb *urb) -{ - struct au0828_dmaqueue *dma_q = urb->context; - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); - unsigned long flags = 0; - int i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - au0828_isocdbg("au0828_irq_callback called: status kill\n"); - return; - default: /* unknown error */ - au0828_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock_irqsave(&dev->slock, flags); - dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock_irqrestore(&dev->slock, flags); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - au0828_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -void au0828_uninit_isoc(struct au0828_dev *dev) -{ - struct urb *urb; - int i; - - au0828_isocdbg("au0828: called au0828_uninit_isoc\n"); - - dev->isoc_ctl.nfields = -1; - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (dev->isoc_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->usbdev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs = 0; -} - -/* - * Allocate URBs and start IRQ - */ -int au0828_init_isoc(struct au0828_dev *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb)) -{ - struct au0828_dmaqueue *dma_q = &dev->vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - int rc; - - au0828_isocdbg("au0828: called au0828_prepare_isoc\n"); - - /* De-allocates all pending stuff */ - au0828_uninit_isoc(dev); - - dev->isoc_ctl.isoc_copy = isoc_copy; - dev->isoc_ctl.num_bufs = num_bufs; - - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - au0828_isocdbg("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - au0828_isocdbg("cannot allocate memory for usb transfer\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - dev->isoc_ctl.max_pkt_size = max_pkt_size; - dev->isoc_ctl.buf = NULL; - - sb_size = max_packets * dev->isoc_ctl.max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i); - au0828_uninit_isoc(dev); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!dev->isoc_ctl.transfer_buffer[i]) { - printk("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - au0828_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - pipe = usb_rcvisocpipe(dev->usbdev, - dev->isoc_in_endpointaddr), - - usb_fill_int_urb(urb, dev->usbdev, pipe, - dev->isoc_ctl.transfer_buffer[i], sb_size, - au0828_irq_callback, dma_q, 1); - - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->isoc_ctl.max_pkt_size; - k += dev->isoc_ctl.max_pkt_size; - } - } - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); - if (rc) { - au0828_isocdbg("submit of urb %i failed (error=%i)\n", - i, rc); - au0828_uninit_isoc(dev); - return rc; - } - } - - return 0; -} - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf) -{ - /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -static inline void vbi_buffer_filled(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf) -{ - /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vbi_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the buffer header type and properly handles - */ -static void au0828_copy_video(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy, remain; - int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ - - if (len == 0) - return; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - remain = len; - - /* Interlaces frame */ - if (buf->top_field) - fieldstart = outp; - else - fieldstart = outp + bytesperline; - - linesdone = dma_q->pos / bytesperline; - currlinedone = dma_q->pos % bytesperline; - offset = linesdone * bytesperline * 2 + currlinedone; - startwrite = fieldstart + offset; - lencopy = bytesperline - currlinedone; - lencopy = lencopy > remain ? remain : lencopy; - - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - remain = (char *)outp + buf->vb.size - (char *)startwrite; - lencopy = remain; - } - if (lencopy <= 0) - return; - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - - while (remain > 0) { - startwrite += lencopy + bytesperline; - startread += lencopy; - if (bytesperline > remain) - lencopy = remain; - else - lencopy = bytesperline; - - if ((char *)startwrite + lencopy > (char *)outp + - buf->vb.size) { - au0828_isocdbg("Overflow %zi bytes past buf end (2)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - - (char *)startwrite; - } - if (lencopy <= 0) - break; - - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - } - - if (offset > 1440) { - /* We have enough data to check for greenscreen */ - if (outp[0] < 0x60 && outp[1440] < 0x60) - dev->greenscreen_detected = 1; - } - - dma_q->pos += len; -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct au0828_dmaqueue *dma_q, - struct au0828_buffer **buf) -{ - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); - - if (list_empty(&dma_q->active)) { - au0828_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); - dev->isoc_ctl.buf = *buf; - - return; -} - -static void au0828_copy_vbi(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - unsigned char *startwrite, *startread; - int bytesperline; - int i, j = 0; - - if (dev == NULL) { - au0828_isocdbg("dev is null\n"); - return; - } - - if (dma_q == NULL) { - au0828_isocdbg("dma_q is null\n"); - return; - } - if (buf == NULL) - return; - if (p == NULL) { - au0828_isocdbg("p is null\n"); - return; - } - if (outp == NULL) { - au0828_isocdbg("outp is null\n"); - return; - } - - bytesperline = dev->vbi_width; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - startwrite = outp + (dma_q->pos / 2); - - /* Make sure the bottom field populates the second half of the frame */ - if (buf->top_field == 0) - startwrite += bytesperline * dev->vbi_height; - - for (i = 0; i < len; i += 2) - startwrite[j++] = startread[i+1]; - - dma_q->pos += len; -} - - -/* - * video-buf generic routine to get the next available VBI buffer - */ -static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, - struct au0828_buffer **buf) -{ - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq); - char *outp; - - if (list_empty(&dma_q->active)) { - au0828_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vbi_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0x00, (*buf)->vb.size); - - dev->isoc_ctl.vbi_buf = *buf; - - return; -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) -{ - struct au0828_buffer *buf; - struct au0828_buffer *vbi_buf; - struct au0828_dmaqueue *dma_q = urb->context; - struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq; - unsigned char *outp = NULL; - unsigned char *vbioutp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - unsigned char fbyte; - unsigned int vbi_field_size; - unsigned int remain, lencopy; - - if (!dev) - return 0; - - if ((dev->dev_state & DEV_DISCONNECTED) || - (dev->dev_state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - vbi_buf = dev->isoc_ctl.vbi_buf; - if (vbi_buf != NULL) - vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - if (urb->iso_frame_desc[i].actual_length <= 0) - continue; - - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - au0828_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - fbyte = p[0]; - len = urb->iso_frame_desc[i].actual_length - 4; - p += 4; - - if (fbyte & 0x80) { - len -= 4; - p += 4; - au0828_isocdbg("Video frame %s\n", - (fbyte & 0x40) ? "odd" : "even"); - if (fbyte & 0x40) { - /* VBI */ - if (vbi_buf != NULL) - vbi_buffer_filled(dev, - vbi_dma_q, - vbi_buf); - vbi_get_next_buf(vbi_dma_q, &vbi_buf); - if (vbi_buf == NULL) - vbioutp = NULL; - else - vbioutp = videobuf_to_vmalloc( - &vbi_buf->vb); - - /* Video */ - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - - /* As long as isoc traffic is arriving, keep - resetting the timer */ - if (dev->vid_timeout_running) - mod_timer(&dev->vid_timeout, - jiffies + (HZ / 10)); - if (dev->vbi_timeout_running) - mod_timer(&dev->vbi_timeout, - jiffies + (HZ / 10)); - } - - if (buf != NULL) { - if (fbyte & 0x40) - buf->top_field = 1; - else - buf->top_field = 0; - } - - if (vbi_buf != NULL) { - if (fbyte & 0x40) - vbi_buf->top_field = 1; - else - vbi_buf->top_field = 0; - } - - dev->vbi_read = 0; - vbi_dma_q->pos = 0; - dma_q->pos = 0; - } - - vbi_field_size = dev->vbi_width * dev->vbi_height * 2; - if (dev->vbi_read < vbi_field_size) { - remain = vbi_field_size - dev->vbi_read; - if (len < remain) - lencopy = len; - else - lencopy = remain; - - if (vbi_buf != NULL) - au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, len); - - len -= lencopy; - p += lencopy; - dev->vbi_read += lencopy; - } - - if (dev->vbi_read >= vbi_field_size && buf != NULL) - au0828_copy_video(dev, dma_q, buf, p, outp, len); - } - return rc; -} - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct au0828_fh *fh = vq->priv_data; - *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; - - if (0 == *count) - *count = AU0828_DEF_BUF; - - if (*count < AU0828_MIN_BUF) - *count = AU0828_MIN_BUF; - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.buf == buf) - dev->isoc_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - struct au0828_dev *dev = fh->dev; - int rc = 0, urb_init = 0; - - buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) { - printk(KERN_INFO "videobuf_iolock failed\n"); - goto fail; - } - } - - if (!dev->isoc_ctl.num_bufs) - urb_init = 1; - - if (urb_init) { - rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, - AU0828_MAX_ISO_BUFS, dev->max_pkt_size, - au0828_isoc_copy); - if (rc < 0) { - printk(KERN_INFO "au0828_init_isoc failed\n"); - goto fail; - } - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_dmaqueue *vidq = &dev->vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops au0828_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ - V4L2 interface - ------------------------------------------------------------------*/ - -static int au0828_i2s_init(struct au0828_dev *dev) -{ - /* Enable i2s mode */ - au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01); - return 0; -} - -/* - * Auvitek au0828 analog stream enable - * Please set interface0 to AS5 before enable the stream - */ -int au0828_analog_stream_enable(struct au0828_dev *d) -{ - dprintk(1, "au0828_analog_stream_enable called\n"); - au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); - au0828_writereg(d, 0x106, 0x00); - /* set x position */ - au0828_writereg(d, 0x110, 0x00); - au0828_writereg(d, 0x111, 0x00); - au0828_writereg(d, 0x114, 0xa0); - au0828_writereg(d, 0x115, 0x05); - /* set y position */ - au0828_writereg(d, 0x112, 0x00); - au0828_writereg(d, 0x113, 0x00); - au0828_writereg(d, 0x116, 0xf2); - au0828_writereg(d, 0x117, 0x00); - au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); - - return 0; -} - -int au0828_analog_stream_disable(struct au0828_dev *d) -{ - dprintk(1, "au0828_analog_stream_disable called\n"); - au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0); - return 0; -} - -void au0828_analog_stream_reset(struct au0828_dev *dev) -{ - dprintk(1, "au0828_analog_stream_reset called\n"); - au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0); - mdelay(30); - au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3); -} - -/* - * Some operations needs to stop current streaming - */ -static int au0828_stream_interrupt(struct au0828_dev *dev) -{ - int ret = 0; - - dev->stream_state = STREAM_INTERRUPT; - if (dev->dev_state == DEV_DISCONNECTED) - return -ENODEV; - else if (ret) { - dev->dev_state = DEV_MISCONFIGURED; - dprintk(1, "%s device is misconfigured!\n", __func__); - return ret; - } - return 0; -} - -/* - * au0828_release_resources - * unregister v4l2 devices - */ -void au0828_analog_unregister(struct au0828_dev *dev) -{ - dprintk(1, "au0828_release_resources called\n"); - mutex_lock(&au0828_sysfs_lock); - - if (dev->vdev) - video_unregister_device(dev->vdev); - if (dev->vbi_dev) - video_unregister_device(dev->vbi_dev); - - mutex_unlock(&au0828_sysfs_lock); -} - - -/* Usage lock check functions */ -static int res_get(struct au0828_fh *fh, unsigned int bit) -{ - struct au0828_dev *dev = fh->dev; - - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - if (dev->resources & bit) { - /* no, someone else uses it */ - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - dprintk(1, "res: get %d\n", bit); - - return 1; -} - -static int res_check(struct au0828_fh *fh, unsigned int bit) -{ - return fh->resources & bit; -} - -static int res_locked(struct au0828_dev *dev, unsigned int bit) -{ - return dev->resources & bit; -} - -static void res_free(struct au0828_fh *fh, unsigned int bits) -{ - struct au0828_dev *dev = fh->dev; - - BUG_ON((fh->resources & bits) != bits); - - fh->resources &= ~bits; - dev->resources &= ~bits; - dprintk(1, "res: put %d\n", bits); -} - -static int get_ressource(struct au0828_fh *fh) -{ - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return AU0828_RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return AU0828_RESOURCE_VBI; - default: - BUG(); - return 0; - } -} - -/* This function ensures that video frames continue to be delivered even if - the ITU-656 input isn't receiving any data (thereby preventing applications - such as tvtime from hanging) */ -void au0828_vid_buffer_timeout(unsigned long data) -{ - struct au0828_dev *dev = (struct au0828_dev *) data; - struct au0828_dmaqueue *dma_q = &dev->vidq; - struct au0828_buffer *buf; - unsigned char *vid_data; - unsigned long flags = 0; - - spin_lock_irqsave(&dev->slock, flags); - - buf = dev->isoc_ctl.buf; - if (buf != NULL) { - vid_data = videobuf_to_vmalloc(&buf->vb); - memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ - buffer_filled(dev, dma_q, buf); - } - get_next_buf(dma_q, &buf); - - if (dev->vid_timeout_running == 1) - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - - spin_unlock_irqrestore(&dev->slock, flags); -} - -void au0828_vbi_buffer_timeout(unsigned long data) -{ - struct au0828_dev *dev = (struct au0828_dev *) data; - struct au0828_dmaqueue *dma_q = &dev->vbiq; - struct au0828_buffer *buf; - unsigned char *vbi_data; - unsigned long flags = 0; - - spin_lock_irqsave(&dev->slock, flags); - - buf = dev->isoc_ctl.vbi_buf; - if (buf != NULL) { - vbi_data = videobuf_to_vmalloc(&buf->vb); - memset(vbi_data, 0x00, buf->vb.size); - vbi_buffer_filled(dev, dma_q, buf); - } - vbi_get_next_buf(dma_q, &buf); - - if (dev->vbi_timeout_running == 1) - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - spin_unlock_irqrestore(&dev->slock, flags); -} - - -static int au0828_v4l2_open(struct file *filp) -{ - int ret = 0; - struct video_device *vdev = video_devdata(filp); - struct au0828_dev *dev = video_drvdata(filp); - struct au0828_fh *fh; - int type; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - default: - return -EINVAL; - } - - fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); - if (NULL == fh) { - dprintk(1, "Failed allocate au0828_fh struct!\n"); - return -ENOMEM; - } - - fh->type = type; - fh->dev = dev; - filp->private_data = fh; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - /* set au0828 interface0 to AS5 here again */ - ret = usb_set_interface(dev->usbdev, 0, 5); - if (ret < 0) { - printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); - return -EBUSY; - } - dev->width = NTSC_STD_W; - dev->height = NTSC_STD_H; - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->width * dev->height; - dev->bytesperline = dev->width * 2; - - au0828_analog_stream_enable(dev); - au0828_analog_stream_reset(dev); - - /* If we were doing ac97 instead of i2s, it would go here...*/ - au0828_i2s_init(dev); - - dev->stream_state = STREAM_OFF; - dev->dev_state |= DEV_INITIALIZED; - } - - dev->users++; - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct au0828_buffer), fh, - &dev->lock); - - /* VBI Setup */ - dev->vbi_width = 720; - dev->vbi_height = 1; - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct au0828_buffer), fh, - &dev->lock); - return ret; -} - -static int au0828_v4l2_close(struct file *filp) -{ - int ret; - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - /* Cancel timeout thread in case they didn't call streamoff */ - dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); - - videobuf_stop(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - - if (res_check(fh, AU0828_RESOURCE_VBI)) { - /* Cancel timeout thread in case they didn't call streamoff */ - dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); - - videobuf_stop(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); - } - - if (dev->users == 1) { - if (dev->dev_state & DEV_DISCONNECTED) { - au0828_analog_unregister(dev); - kfree(dev); - return 0; - } - - au0828_analog_stream_disable(dev); - - au0828_uninit_isoc(dev); - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - /* When close the device, set the usb intf0 into alt0 to free - USB bandwidth */ - ret = usb_set_interface(dev->usbdev, 0, 0); - if (ret < 0) - printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); - } - - videobuf_mmap_free(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vbiq); - kfree(fh); - dev->users--; - wake_up_interruptible_nr(&dev->open, 1); - return 0; -} - -static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_locked(dev, AU0828_RESOURCE_VIDEO)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return -EBUSY; - - if (dev->vbi_timeout_running == 0) { - /* Handle case where caller tries to read without - calling streamon first */ - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - return 0; -} - -static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VIDEO)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - } else { - return POLLERR; - } -} - -static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); - - return rc; -} - -static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, - struct v4l2_format *format) -{ - int ret; - int width = format->fmt.pix.width; - int height = format->fmt.pix.height; - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - /* If they are demanding a format other than the one we support, - bail out (tvtime asks for UYVY and then retries with YUYV) */ - if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) - return -EINVAL; - - /* format->fmt.pix.width only support 720 and height 480 */ - if (width != 720) - width = 720; - if (height != 480) - height = 480; - - format->fmt.pix.width = width; - format->fmt.pix.height = height; - format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - format->fmt.pix.bytesperline = width * 2; - format->fmt.pix.sizeimage = width * height * 2; - format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - format->fmt.pix.field = V4L2_FIELD_INTERLACED; - - if (cmd == VIDIOC_TRY_FMT) - return 0; - - /* maybe set new image format, driver current only support 720*480 */ - dev->width = width; - dev->height = height; - dev->frame_size = width * height * 2; - dev->field_size = width * height; - dev->bytesperline = width * 2; - - if (dev->stream_state == STREAM_ON) { - dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); - ret = au0828_stream_interrupt(dev); - if (ret != 0) { - dprintk(1, "error interrupting video stream!\n"); - return ret; - } - } - - /* set au0828 interface0 to AS5 here again */ - ret = usb_set_interface(dev->usbdev, 0, 5); - if (ret < 0) { - printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); - return -EBUSY; - } - - au0828_analog_stream_enable(dev); - - return 0; -} - - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); - if (qc->type) - return 0; - else - return -EINVAL; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - strlcpy(cap->driver, "au0828", sizeof(cap->driver)); - strlcpy(cap->card, dev->board.name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); - - /*set the device capabilities */ - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - V4L2_CAP_TUNER; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index) - return -EINVAL; - - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(f->description, "Packed YUV2"); - - f->flags = 0; - f->pixelformat = V4L2_PIX_FMT_UYVY; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - f->fmt.pix.bytesperline = dev->bytesperline; - f->fmt.pix.sizeimage = dev->frame_size; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */ - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - return au0828_set_format(dev, VIDIOC_TRY_FMT, f); -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - printk(KERN_INFO "%s queue busy\n", __func__); - rc = -EBUSY; - goto out; - } - - rc = au0828_set_format(dev, VIDIOC_S_FMT, f); -out: - return rc; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - /* FIXME: when we support something other than NTSC, we are going to - have to make the au0828 bridge adjust the size of its capture - buffer, which is currently hardcoded at 720x480 */ - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm); - dev->std_set_in_tuner_core = 1; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - return 0; -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - unsigned int tmp; - - static const char *inames[] = { - [AU0828_VMUX_UNDEFINED] = "Undefined", - [AU0828_VMUX_COMPOSITE] = "Composite", - [AU0828_VMUX_SVIDEO] = "S-Video", - [AU0828_VMUX_CABLE] = "Cable TV", - [AU0828_VMUX_TELEVISION] = "Television", - [AU0828_VMUX_DVB] = "DVB", - [AU0828_VMUX_DEBUG] = "tv debug" - }; - - tmp = input->index; - - if (tmp >= AU0828_MAX_INPUT) - return -EINVAL; - if (AUVI_INPUT(tmp).type == 0) - return -EINVAL; - - input->index = tmp; - strcpy(input->name, inames[AUVI_INPUT(tmp).type]); - if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) - input->type |= V4L2_INPUT_TYPE_TUNER; - else - input->type |= V4L2_INPUT_TYPE_CAMERA; - - input->std = dev->vdev->tvnorms; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - *i = dev->ctrl_input; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int index) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int i; - - dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, - index); - if (index >= AU0828_MAX_INPUT) - return -EINVAL; - if (AUVI_INPUT(index).type == 0) - return -EINVAL; - dev->ctrl_input = index; - - switch (AUVI_INPUT(index).type) { - case AU0828_VMUX_SVIDEO: - dev->input_type = AU0828_VMUX_SVIDEO; - break; - case AU0828_VMUX_COMPOSITE: - dev->input_type = AU0828_VMUX_COMPOSITE; - break; - case AU0828_VMUX_TELEVISION: - dev->input_type = AU0828_VMUX_TELEVISION; - break; - default: - dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n", - AUVI_INPUT(index).type); - break; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - AUVI_INPUT(index).vmux, 0, 0); - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - int enable = 0; - if (AUVI_INPUT(i).audio_setup == NULL) - continue; - - if (i == index) - enable = 1; - else - enable = 0; - if (enable) { - (AUVI_INPUT(i).audio_setup)(dev, enable); - } else { - /* Make sure we leave it turned on if some - other input is routed to this callback */ - if ((AUVI_INPUT(i).audio_setup) != - ((AUVI_INPUT(index).audio_setup))) { - (AUVI_INPUT(i).audio_setup)(dev, enable); - } - } - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - AUVI_INPUT(index).amux, 0, 0); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - unsigned int index = a->index; - - if (a->index > 1) - return -EINVAL; - - index = dev->ctrl_ainput; - if (index == 0) - strcpy(a->name, "Television"); - else - strcpy(a->name, "Line in"); - - a->capability = V4L2_AUDCAP_STEREO; - a->index = index; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - if (a->index != dev->ctrl_ainput) - return -EINVAL; - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - return 0; - -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (t->index != 0) - return -EINVAL; - - strcpy(t->name, "Auvitek tuner"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (t->index != 0) - return -EINVAL; - - t->type = V4L2_TUNER_ANALOG_TV; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, - t->afc); - - return 0; - -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = dev->ctrl_freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (freq->tuner != 0) - return -EINVAL; - if (freq->type != V4L2_TUNER_ANALOG_TV) - return -EINVAL; - - dev->ctrl_freq = freq->frequency; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - if (dev->std_set_in_tuner_core == 0) { - /* If we've never sent the standard in tuner core, do so now. We - don't do this at device probe because we don't want to incur - the cost of a firmware load */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, - dev->vdev->tvnorms); - dev->std_set_in_tuner_core = 1; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - au0828_analog_stream_reset(dev); - - return 0; -} - - -/* RAW VBI ioctls */ - -static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - format->fmt.vbi.start[0] = 21; - format->fmt.vbi.start[1] = 284; - - return 0; -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_AU0828; - return 0; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - if (chip->ident == V4L2_IDENT_NONE) - return -EINVAL; - - return 0; -} - -static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - - cc->defrect = cc->bounds; - - cc->pixelaspect.numerator = 54; - cc->pixelaspect.denominator = 59; - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc = -EINVAL; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (unlikely(type != fh->type)) - return -EINVAL; - - dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (unlikely(!res_get(fh, get_ressource(fh)))) - return -EBUSY; - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - au0828_analog_stream_enable(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vidq); - dev->vid_timeout_running = 1; - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vbiq); - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - int i; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); - rc = au0828_stream_interrupt(dev); - if (rc != 0) - return rc; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).audio_setup == NULL) - continue; - (AUVI_INPUT(i).audio_setup)(dev, 0); - } - - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); - - if (res_check(fh, AU0828_RESOURCE_VBI)) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); - } - } - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - reg->val = au0828_read(dev, reg->reg); - return 0; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - return au0828_writereg(dev, reg->reg, reg->val); -} -#endif - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vidq, rb); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vbiq, rb); - - return rc; -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - /* Workaround for a bug in the au0828 hardware design that sometimes - results in the colorspace being inverted */ - if (dev->greenscreen_detected == 1) { - dprintk(1, "Detected green frame. Resetting stream...\n"); - au0828_analog_stream_reset(dev); - dev->greenscreen_detected = 0; - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK); - - return rc; -} - -static struct v4l2_file_operations au0828_v4l_fops = { - .owner = THIS_MODULE, - .open = au0828_v4l2_open, - .release = au0828_v4l2_close, - .read = au0828_v4l2_read, - .poll = au0828_v4l2_poll, - .mmap = au0828_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .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_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .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 - .vidioc_g_chip_ident = vidioc_g_chip_ident, -}; - -static const struct video_device au0828_video_template = { - .fops = &au0828_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, -}; - -/**************************************************************************/ - -int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface) -{ - int retval = -ENOMEM; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i, ret; - - dprintk(1, "au0828_analog_register called!\n"); - - /* set au0828 usb interface0 to as5 */ - retval = usb_set_interface(dev->usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); - if (retval != 0) { - printk(KERN_INFO "Failure setting usb interface0 to as5\n"); - return retval; - } - - /* Figure out which endpoint has the isoc interface */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC)) { - - /* we find our isoc in endpoint */ - u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * - (((tmp & 0x1800) >> 11) + 1); - dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; - } - } - if (!(dev->isoc_in_endpointaddr)) { - printk(KERN_INFO "Could not locate isoc endpoint\n"); - kfree(dev); - return -ENODEV; - } - - init_waitqueue_head(&dev->open); - spin_lock_init(&dev->slock); - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - INIT_LIST_HEAD(&dev->vbiq.active); - INIT_LIST_HEAD(&dev->vbiq.queued); - - dev->vid_timeout.function = au0828_vid_buffer_timeout; - dev->vid_timeout.data = (unsigned long) dev; - init_timer(&dev->vid_timeout); - - dev->vbi_timeout.function = au0828_vbi_buffer_timeout; - dev->vbi_timeout.data = (unsigned long) dev; - init_timer(&dev->vbi_timeout); - - dev->width = NTSC_STD_W; - dev->height = NTSC_STD_H; - dev->field_size = dev->width * dev->height; - dev->frame_size = dev->field_size << 1; - dev->bytesperline = dev->width << 1; - dev->ctrl_ainput = 0; - - /* allocate and fill v4l2 video struct */ - dev->vdev = video_device_alloc(); - if (NULL == dev->vdev) { - dprintk(1, "Can't allocate video_device.\n"); - return -ENOMEM; - } - - /* allocate the VBI struct */ - dev->vbi_dev = video_device_alloc(); - if (NULL == dev->vbi_dev) { - dprintk(1, "Can't allocate vbi_device.\n"); - ret = -ENOMEM; - goto err_vdev; - } - - /* Fill the video capture device struct */ - *dev->vdev = au0828_video_template; - dev->vdev->parent = &dev->usbdev->dev; - dev->vdev->lock = &dev->lock; - strcpy(dev->vdev->name, "au0828a video"); - - /* Setup the VBI device */ - *dev->vbi_dev = au0828_video_template; - dev->vbi_dev->parent = &dev->usbdev->dev; - dev->vbi_dev->lock = &dev->lock; - strcpy(dev->vbi_dev->name, "au0828a vbi"); - - /* Register the v4l2 device */ - video_set_drvdata(dev->vdev, dev); - retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); - if (retval != 0) { - dprintk(1, "unable to register video device (error = %d).\n", - retval); - ret = -ENODEV; - goto err_vbi_dev; - } - - /* Register the vbi device */ - video_set_drvdata(dev->vbi_dev, dev); - retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); - if (retval != 0) { - dprintk(1, "unable to register vbi device (error = %d).\n", - retval); - ret = -ENODEV; - goto err_vbi_dev; - } - - dprintk(1, "%s completed!\n", __func__); - - return 0; - -err_vbi_dev: - video_device_release(dev->vbi_dev); -err_vdev: - video_device_release(dev->vdev); - return ret; -} - diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h deleted file mode 100644 index 66a56ef7bbe4..000000000000 --- a/drivers/media/video/au0828/au0828.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Driver for the Auvitek AU0828 USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <media/tveeprom.h> - -/* Analog */ -#include <linux/videodev2.h> -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> - -/* DVB */ -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" - -#include "au0828-reg.h" -#include "au0828-cards.h" - -#define DRIVER_NAME "au0828" -#define URB_COUNT 16 -#define URB_BUFSIZE (0xe522) - -/* Analog constants */ -#define NTSC_STD_W 720 -#define NTSC_STD_H 480 - -#define AU0828_INTERLACED_DEFAULT 1 -#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) - -/* Defination for AU0828 USB transfer */ -#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -#define AU0828_ISO_PACKETS_PER_URB 128 - -#define AU0828_MIN_BUF 4 -#define AU0828_DEF_BUF 8 - -#define AU0828_MAX_INPUT 4 - -/* au0828 resource types (used for res_get/res_lock etc */ -#define AU0828_RESOURCE_VIDEO 0x01 -#define AU0828_RESOURCE_VBI 0x02 - -enum au0828_itype { - AU0828_VMUX_UNDEFINED = 0, - AU0828_VMUX_COMPOSITE, - AU0828_VMUX_SVIDEO, - AU0828_VMUX_CABLE, - AU0828_VMUX_TELEVISION, - AU0828_VMUX_DVB, - AU0828_VMUX_DEBUG -}; - -struct au0828_input { - enum au0828_itype type; - unsigned int vmux; - unsigned int amux; - void (*audio_setup) (void *priv, int enable); -}; - -struct au0828_board { - char *name; - unsigned int tuner_type; - unsigned char tuner_addr; - unsigned char i2c_clk_divider; - struct au0828_input input[AU0828_MAX_INPUT]; - -}; - -struct au0828_dvb { - struct mutex lock; - struct dvb_adapter adapter; - struct dvb_frontend *frontend; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; - int feeding; -}; - -enum au0828_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON -}; - -#define AUVI_INPUT(nr) (dev->board.input[nr]) - -/* device state */ -enum au0828_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04 -}; - -struct au0828_fh { - struct au0828_dev *dev; - unsigned int resources; - - struct videobuf_queue vb_vidq; - struct videobuf_queue vb_vbiq; - enum v4l2_buf_type type; -}; - -struct au0828_usb_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct au0828_buffer *buf; - struct au0828_buffer *vbi_buf; - - /* Stores the number of received fields */ - int nfields; - - /* isoc urb callback */ - int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb); - -}; - -/* buffer for one video frame */ -struct au0828_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct list_head frame; - int top_field; - int receiving; -}; - -struct au0828_dmaqueue { - struct list_head active; - struct list_head queued; - - wait_queue_head_t wq; - - /* Counters to control buffer fill */ - int pos; -}; - -struct au0828_dev { - struct mutex mutex; - struct usb_device *usbdev; - int boardnr; - struct au0828_board board; - u8 ctrlmsg[64]; - - /* I2C */ - struct i2c_adapter i2c_adap; - struct i2c_algorithm i2c_algo; - struct i2c_client i2c_client; - u32 i2c_rc; - - /* Digital */ - struct au0828_dvb dvb; - struct work_struct restart_streaming; - - /* Analog */ - struct v4l2_device v4l2_dev; - int users; - unsigned int resources; /* resources in use */ - struct video_device *vdev; - struct video_device *vbi_dev; - struct timer_list vid_timeout; - int vid_timeout_running; - struct timer_list vbi_timeout; - int vbi_timeout_running; - int width; - int height; - int vbi_width; - int vbi_height; - u32 vbi_read; - u32 field_size; - u32 frame_size; - u32 bytesperline; - int type; - u8 ctrl_ainput; - __u8 isoc_in_endpointaddr; - u8 isoc_init_ok; - int greenscreen_detected; - unsigned int frame_count; - int ctrl_freq; - int input_type; - int std_set_in_tuner_core; - unsigned int ctrl_input; - enum au0828_dev_state dev_state; - enum au0828_stream_state stream_state; - wait_queue_head_t open; - - struct mutex lock; - - /* Isoc control struct */ - struct au0828_dmaqueue vidq; - struct au0828_dmaqueue vbiq; - struct au0828_usb_isoc_ctl isoc_ctl; - spinlock_t slock; - - /* usb transfer */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - struct urb *urb[AU0828_MAX_ISO_BUFS]; /* urb for isoc transfers */ - char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc - transfer */ - - /* USB / URB Related */ - int urb_streaming; - struct urb *urbs[URB_COUNT]; -}; - -/* ----------------------------------------------------------- */ -#define au0828_read(dev, reg) au0828_readreg(dev, reg) -#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value) -#define au0828_andor(dev, reg, mask, value) \ - au0828_writereg(dev, reg, \ - (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask))) - -#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit)) -#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0) - -/* ----------------------------------------------------------- */ -/* au0828-core.c */ -extern u32 au0828_read(struct au0828_dev *dev, u16 reg); -extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); -extern int au0828_debug; - -/* ----------------------------------------------------------- */ -/* au0828-cards.c */ -extern struct au0828_board au0828_boards[]; -extern struct usb_device_id au0828_usb_id_table[]; -extern void au0828_gpio_setup(struct au0828_dev *dev); -extern int au0828_tuner_callback(void *priv, int component, - int command, int arg); -extern void au0828_card_setup(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-i2c.c */ -extern int au0828_i2c_register(struct au0828_dev *dev); -extern int au0828_i2c_unregister(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-video.c */ -int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface); -int au0828_analog_stream_disable(struct au0828_dev *d); -void au0828_analog_unregister(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-dvb.c */ -extern int au0828_dvb_register(struct au0828_dev *dev); -extern void au0828_dvb_unregister(struct au0828_dev *dev); - -/* au0828-vbi.c */ -extern struct videobuf_queue_ops au0828_vbi_qops; - -#define dprintk(level, fmt, arg...)\ - do { if (au0828_debug & level)\ - printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) |