Path: blob/master/drivers/media/video/au0828/au0828-core.c
17880 views
/*1* Driver for the Auvitek USB bridge2*3* Copyright (c) 2008 Steven Toth <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13*14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.19*/2021#include <linux/module.h>22#include <linux/slab.h>23#include <linux/videodev2.h>24#include <media/v4l2-common.h>25#include <linux/mutex.h>2627#include "au0828.h"2829/*30* 1 = General debug messages31* 2 = USB handling32* 4 = I2C related33* 8 = Bridge related34*/35int au0828_debug;36module_param_named(debug, au0828_debug, int, 0644);37MODULE_PARM_DESC(debug, "enable debug messages");3839static unsigned int disable_usb_speed_check;40module_param(disable_usb_speed_check, int, 0444);41MODULE_PARM_DESC(disable_usb_speed_check,42"override min bandwidth requirement of 480M bps");4344#define _AU0828_BULKPIPE 0x0345#define _BULKPIPESIZE 0xffff4647static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,48u16 index, unsigned char *cp, u16 size);49static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,50u16 index, unsigned char *cp, u16 size);5152/* USB Direction */53#define CMD_REQUEST_IN 0x0054#define CMD_REQUEST_OUT 0x015556u32 au0828_readreg(struct au0828_dev *dev, u16 reg)57{58recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);59dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]);60return dev->ctrlmsg[0];61}6263u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)64{65dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);66return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,67dev->ctrlmsg, 0);68}6970static void cmd_msg_dump(struct au0828_dev *dev)71{72int i;7374for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)75dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "76"%02x %02x %02x %02x %02x %02x %02x %02x\n",77__func__,78dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],79dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],80dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],81dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],82dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],83dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],84dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],85dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);86}8788static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,89u16 index, unsigned char *cp, u16 size)90{91int status = -ENODEV;92mutex_lock(&dev->mutex);93if (dev->usbdev) {9495/* cp must be memory that has been allocated by kmalloc */96status = usb_control_msg(dev->usbdev,97usb_sndctrlpipe(dev->usbdev, 0),98request,99USB_DIR_OUT | USB_TYPE_VENDOR |100USB_RECIP_DEVICE,101value, index,102cp, size, 1000);103104status = min(status, 0);105106if (status < 0) {107printk(KERN_ERR "%s() Failed sending control message, error %d.\n",108__func__, status);109}110111}112mutex_unlock(&dev->mutex);113return status;114}115116static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,117u16 index, unsigned char *cp, u16 size)118{119int status = -ENODEV;120mutex_lock(&dev->mutex);121if (dev->usbdev) {122123memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));124125/* cp must be memory that has been allocated by kmalloc */126status = usb_control_msg(dev->usbdev,127usb_rcvctrlpipe(dev->usbdev, 0),128request,129USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,130value, index,131cp, size, 1000);132133status = min(status, 0);134135if (status < 0) {136printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",137__func__, status);138} else139cmd_msg_dump(dev);140}141mutex_unlock(&dev->mutex);142return status;143}144145static void au0828_usb_disconnect(struct usb_interface *interface)146{147struct au0828_dev *dev = usb_get_intfdata(interface);148149dprintk(1, "%s()\n", __func__);150151/* Digital TV */152au0828_dvb_unregister(dev);153154if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)155au0828_analog_unregister(dev);156157/* I2C */158au0828_i2c_unregister(dev);159160v4l2_device_unregister(&dev->v4l2_dev);161162usb_set_intfdata(interface, NULL);163164mutex_lock(&dev->mutex);165dev->usbdev = NULL;166mutex_unlock(&dev->mutex);167168kfree(dev);169170}171172static int au0828_usb_probe(struct usb_interface *interface,173const struct usb_device_id *id)174{175int ifnum, retval;176struct au0828_dev *dev;177struct usb_device *usbdev = interface_to_usbdev(interface);178179ifnum = interface->altsetting->desc.bInterfaceNumber;180181if (ifnum != 0)182return -ENODEV;183184dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,185le16_to_cpu(usbdev->descriptor.idVendor),186le16_to_cpu(usbdev->descriptor.idProduct),187ifnum);188189/*190* Make sure we have 480 Mbps of bandwidth, otherwise things like191* video stream wouldn't likely work, since 12 Mbps is generally192* not enough even for most Digital TV streams.193*/194if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {195printk(KERN_ERR "au0828: Device initialization failed.\n");196printk(KERN_ERR "au0828: Device must be connected to a "197"high-speed USB 2.0 port.\n");198return -ENODEV;199}200201dev = kzalloc(sizeof(*dev), GFP_KERNEL);202if (dev == NULL) {203printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);204return -ENOMEM;205}206207mutex_init(&dev->mutex);208mutex_init(&dev->dvb.lock);209dev->usbdev = usbdev;210dev->boardnr = id->driver_info;211212/* Create the v4l2_device */213retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);214if (retval) {215printk(KERN_ERR "%s() v4l2_device_register failed\n",216__func__);217kfree(dev);218return -EIO;219}220221/* Power Up the bridge */222au0828_write(dev, REG_600, 1 << 4);223224/* Bring up the GPIO's and supporting devices */225au0828_gpio_setup(dev);226227/* I2C */228au0828_i2c_register(dev);229230/* Setup */231au0828_card_setup(dev);232233/* Analog TV */234if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)235au0828_analog_register(dev, interface);236237/* Digital TV */238au0828_dvb_register(dev);239240/* Store the pointer to the au0828_dev so it can be accessed in241au0828_usb_disconnect */242usb_set_intfdata(interface, dev);243244printk(KERN_INFO "Registered device AU0828 [%s]\n",245dev->board.name == NULL ? "Unset" : dev->board.name);246247return 0;248}249250static struct usb_driver au0828_usb_driver = {251.name = DRIVER_NAME,252.probe = au0828_usb_probe,253.disconnect = au0828_usb_disconnect,254.id_table = au0828_usb_id_table,255};256257static int __init au0828_init(void)258{259int ret;260261if (au0828_debug & 1)262printk(KERN_INFO "%s() Debugging is enabled\n", __func__);263264if (au0828_debug & 2)265printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);266267if (au0828_debug & 4)268printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);269270if (au0828_debug & 8)271printk(KERN_INFO "%s() Bridge Debugging is enabled\n",272__func__);273274printk(KERN_INFO "au0828 driver loaded\n");275276ret = usb_register(&au0828_usb_driver);277if (ret)278printk(KERN_ERR "usb_register failed, error = %d\n", ret);279280return ret;281}282283static void __exit au0828_exit(void)284{285usb_deregister(&au0828_usb_driver);286}287288module_init(au0828_init);289module_exit(au0828_exit);290291MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");292MODULE_AUTHOR("Steven Toth <[email protected]>");293MODULE_LICENSE("GPL");294295296