10c0d06caSMauro Carvalho Chehab /* 20c0d06caSMauro Carvalho Chehab * Driver for the Auvitek USB bridge 30c0d06caSMauro Carvalho Chehab * 40c0d06caSMauro Carvalho Chehab * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> 50c0d06caSMauro Carvalho Chehab * 60c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 70c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 80c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 90c0d06caSMauro Carvalho Chehab * (at your option) any later version. 100c0d06caSMauro Carvalho Chehab * 110c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 120c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 130c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140c0d06caSMauro Carvalho Chehab * 150c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 160c0d06caSMauro Carvalho Chehab * 170c0d06caSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 180c0d06caSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 190c0d06caSMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 200c0d06caSMauro Carvalho Chehab */ 210c0d06caSMauro Carvalho Chehab 2283afb32aSMauro Carvalho Chehab #include "au0828.h" 2383afb32aSMauro Carvalho Chehab 240c0d06caSMauro Carvalho Chehab #include <linux/module.h> 250c0d06caSMauro Carvalho Chehab #include <linux/slab.h> 260c0d06caSMauro Carvalho Chehab #include <linux/videodev2.h> 270c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h> 280c0d06caSMauro Carvalho Chehab #include <linux/mutex.h> 290c0d06caSMauro Carvalho Chehab 300c0d06caSMauro Carvalho Chehab /* 310c0d06caSMauro Carvalho Chehab * 1 = General debug messages 320c0d06caSMauro Carvalho Chehab * 2 = USB handling 330c0d06caSMauro Carvalho Chehab * 4 = I2C related 340c0d06caSMauro Carvalho Chehab * 8 = Bridge related 352fcfd317SMauro Carvalho Chehab * 16 = IR related 360c0d06caSMauro Carvalho Chehab */ 370c0d06caSMauro Carvalho Chehab int au0828_debug; 380c0d06caSMauro Carvalho Chehab module_param_named(debug, au0828_debug, int, 0644); 392fcfd317SMauro Carvalho Chehab MODULE_PARM_DESC(debug, 402fcfd317SMauro Carvalho Chehab "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR"); 410c0d06caSMauro Carvalho Chehab 420c0d06caSMauro Carvalho Chehab static unsigned int disable_usb_speed_check; 430c0d06caSMauro Carvalho Chehab module_param(disable_usb_speed_check, int, 0444); 440c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(disable_usb_speed_check, 450c0d06caSMauro Carvalho Chehab "override min bandwidth requirement of 480M bps"); 460c0d06caSMauro Carvalho Chehab 470c0d06caSMauro Carvalho Chehab #define _AU0828_BULKPIPE 0x03 480c0d06caSMauro Carvalho Chehab #define _BULKPIPESIZE 0xffff 490c0d06caSMauro Carvalho Chehab 500c0d06caSMauro Carvalho Chehab static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, 510c0d06caSMauro Carvalho Chehab u16 index); 520c0d06caSMauro Carvalho Chehab static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, 530c0d06caSMauro Carvalho Chehab u16 index, unsigned char *cp, u16 size); 540c0d06caSMauro Carvalho Chehab 550c0d06caSMauro Carvalho Chehab /* USB Direction */ 560c0d06caSMauro Carvalho Chehab #define CMD_REQUEST_IN 0x00 570c0d06caSMauro Carvalho Chehab #define CMD_REQUEST_OUT 0x01 580c0d06caSMauro Carvalho Chehab 590c0d06caSMauro Carvalho Chehab u32 au0828_readreg(struct au0828_dev *dev, u16 reg) 600c0d06caSMauro Carvalho Chehab { 610c0d06caSMauro Carvalho Chehab u8 result = 0; 620c0d06caSMauro Carvalho Chehab 630c0d06caSMauro Carvalho Chehab recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1); 640c0d06caSMauro Carvalho Chehab dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result); 650c0d06caSMauro Carvalho Chehab 660c0d06caSMauro Carvalho Chehab return result; 670c0d06caSMauro Carvalho Chehab } 680c0d06caSMauro Carvalho Chehab 690c0d06caSMauro Carvalho Chehab u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) 700c0d06caSMauro Carvalho Chehab { 710c0d06caSMauro Carvalho Chehab dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); 720c0d06caSMauro Carvalho Chehab return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); 730c0d06caSMauro Carvalho Chehab } 740c0d06caSMauro Carvalho Chehab 750c0d06caSMauro Carvalho Chehab static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, 760c0d06caSMauro Carvalho Chehab u16 index) 770c0d06caSMauro Carvalho Chehab { 780c0d06caSMauro Carvalho Chehab int status = -ENODEV; 790c0d06caSMauro Carvalho Chehab 800c0d06caSMauro Carvalho Chehab if (dev->usbdev) { 810c0d06caSMauro Carvalho Chehab 820c0d06caSMauro Carvalho Chehab /* cp must be memory that has been allocated by kmalloc */ 830c0d06caSMauro Carvalho Chehab status = usb_control_msg(dev->usbdev, 840c0d06caSMauro Carvalho Chehab usb_sndctrlpipe(dev->usbdev, 0), 850c0d06caSMauro Carvalho Chehab request, 860c0d06caSMauro Carvalho Chehab USB_DIR_OUT | USB_TYPE_VENDOR | 870c0d06caSMauro Carvalho Chehab USB_RECIP_DEVICE, 880c0d06caSMauro Carvalho Chehab value, index, NULL, 0, 1000); 890c0d06caSMauro Carvalho Chehab 900c0d06caSMauro Carvalho Chehab status = min(status, 0); 910c0d06caSMauro Carvalho Chehab 920c0d06caSMauro Carvalho Chehab if (status < 0) { 9383afb32aSMauro Carvalho Chehab pr_err("%s() Failed sending control message, error %d.\n", 940c0d06caSMauro Carvalho Chehab __func__, status); 950c0d06caSMauro Carvalho Chehab } 960c0d06caSMauro Carvalho Chehab 970c0d06caSMauro Carvalho Chehab } 980c0d06caSMauro Carvalho Chehab 990c0d06caSMauro Carvalho Chehab return status; 1000c0d06caSMauro Carvalho Chehab } 1010c0d06caSMauro Carvalho Chehab 1020c0d06caSMauro Carvalho Chehab static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, 1030c0d06caSMauro Carvalho Chehab u16 index, unsigned char *cp, u16 size) 1040c0d06caSMauro Carvalho Chehab { 1050c0d06caSMauro Carvalho Chehab int status = -ENODEV; 1060c0d06caSMauro Carvalho Chehab mutex_lock(&dev->mutex); 1070c0d06caSMauro Carvalho Chehab if (dev->usbdev) { 1080c0d06caSMauro Carvalho Chehab status = usb_control_msg(dev->usbdev, 1090c0d06caSMauro Carvalho Chehab usb_rcvctrlpipe(dev->usbdev, 0), 1100c0d06caSMauro Carvalho Chehab request, 1110c0d06caSMauro Carvalho Chehab USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1120c0d06caSMauro Carvalho Chehab value, index, 1130c0d06caSMauro Carvalho Chehab dev->ctrlmsg, size, 1000); 1140c0d06caSMauro Carvalho Chehab 1150c0d06caSMauro Carvalho Chehab status = min(status, 0); 1160c0d06caSMauro Carvalho Chehab 1170c0d06caSMauro Carvalho Chehab if (status < 0) { 11883afb32aSMauro Carvalho Chehab pr_err("%s() Failed receiving control message, error %d.\n", 1190c0d06caSMauro Carvalho Chehab __func__, status); 1200c0d06caSMauro Carvalho Chehab } 1210c0d06caSMauro Carvalho Chehab 1220c0d06caSMauro Carvalho Chehab /* the host controller requires heap allocated memory, which 1230c0d06caSMauro Carvalho Chehab is why we didn't just pass "cp" into usb_control_msg */ 1240c0d06caSMauro Carvalho Chehab memcpy(cp, dev->ctrlmsg, size); 1250c0d06caSMauro Carvalho Chehab } 1260c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->mutex); 1270c0d06caSMauro Carvalho Chehab return status; 1280c0d06caSMauro Carvalho Chehab } 1290c0d06caSMauro Carvalho Chehab 130823beb7eSHans Verkuil static void au0828_usb_release(struct au0828_dev *dev) 131823beb7eSHans Verkuil { 132823beb7eSHans Verkuil /* I2C */ 133823beb7eSHans Verkuil au0828_i2c_unregister(dev); 134823beb7eSHans Verkuil 135823beb7eSHans Verkuil kfree(dev); 136823beb7eSHans Verkuil } 137823beb7eSHans Verkuil 138823beb7eSHans Verkuil #ifdef CONFIG_VIDEO_AU0828_V4L2 139823beb7eSHans Verkuil static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev) 140823beb7eSHans Verkuil { 141823beb7eSHans Verkuil struct au0828_dev *dev = 142823beb7eSHans Verkuil container_of(v4l2_dev, struct au0828_dev, v4l2_dev); 143823beb7eSHans Verkuil 144823beb7eSHans Verkuil v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl); 145823beb7eSHans Verkuil v4l2_device_unregister(&dev->v4l2_dev); 146823beb7eSHans Verkuil au0828_usb_release(dev); 147823beb7eSHans Verkuil } 148823beb7eSHans Verkuil #endif 149823beb7eSHans Verkuil 1500c0d06caSMauro Carvalho Chehab static void au0828_usb_disconnect(struct usb_interface *interface) 1510c0d06caSMauro Carvalho Chehab { 1520c0d06caSMauro Carvalho Chehab struct au0828_dev *dev = usb_get_intfdata(interface); 1530c0d06caSMauro Carvalho Chehab 1540c0d06caSMauro Carvalho Chehab dprintk(1, "%s()\n", __func__); 1550c0d06caSMauro Carvalho Chehab 156eb336eabSShuah Khan /* there is a small window after disconnect, before 157eb336eabSShuah Khan dev->usbdev is NULL, for poll (e.g: IR) try to access 158eb336eabSShuah Khan the device and fill the dmesg with error messages. 159eb336eabSShuah Khan Set the status so poll routines can check and avoid 160eb336eabSShuah Khan access after disconnect. 161eb336eabSShuah Khan */ 162eb336eabSShuah Khan dev->dev_state = DEV_DISCONNECTED; 163eb336eabSShuah Khan 1642fcfd317SMauro Carvalho Chehab au0828_rc_unregister(dev); 1650c0d06caSMauro Carvalho Chehab /* Digital TV */ 1660c0d06caSMauro Carvalho Chehab au0828_dvb_unregister(dev); 1670c0d06caSMauro Carvalho Chehab 1680c0d06caSMauro Carvalho Chehab usb_set_intfdata(interface, NULL); 1690c0d06caSMauro Carvalho Chehab mutex_lock(&dev->mutex); 1700c0d06caSMauro Carvalho Chehab dev->usbdev = NULL; 1710c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->mutex); 172823beb7eSHans Verkuil #ifdef CONFIG_VIDEO_AU0828_V4L2 173823beb7eSHans Verkuil if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { 174823beb7eSHans Verkuil au0828_analog_unregister(dev); 175823beb7eSHans Verkuil v4l2_device_disconnect(&dev->v4l2_dev); 176823beb7eSHans Verkuil v4l2_device_put(&dev->v4l2_dev); 177823beb7eSHans Verkuil return; 178823beb7eSHans Verkuil } 179823beb7eSHans Verkuil #endif 180823beb7eSHans Verkuil au0828_usb_release(dev); 1810c0d06caSMauro Carvalho Chehab } 1820c0d06caSMauro Carvalho Chehab 1830c0d06caSMauro Carvalho Chehab static int au0828_usb_probe(struct usb_interface *interface, 1840c0d06caSMauro Carvalho Chehab const struct usb_device_id *id) 1850c0d06caSMauro Carvalho Chehab { 1868a4e7866SMichael Krufky int ifnum; 187f251b3e7STim Mester int retval = 0; 188f251b3e7STim Mester 1890c0d06caSMauro Carvalho Chehab struct au0828_dev *dev; 1900c0d06caSMauro Carvalho Chehab struct usb_device *usbdev = interface_to_usbdev(interface); 1910c0d06caSMauro Carvalho Chehab 1920c0d06caSMauro Carvalho Chehab ifnum = interface->altsetting->desc.bInterfaceNumber; 1930c0d06caSMauro Carvalho Chehab 1940c0d06caSMauro Carvalho Chehab if (ifnum != 0) 1950c0d06caSMauro Carvalho Chehab return -ENODEV; 1960c0d06caSMauro Carvalho Chehab 1970c0d06caSMauro Carvalho Chehab dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, 1980c0d06caSMauro Carvalho Chehab le16_to_cpu(usbdev->descriptor.idVendor), 1990c0d06caSMauro Carvalho Chehab le16_to_cpu(usbdev->descriptor.idProduct), 2000c0d06caSMauro Carvalho Chehab ifnum); 2010c0d06caSMauro Carvalho Chehab 2020c0d06caSMauro Carvalho Chehab /* 2030c0d06caSMauro Carvalho Chehab * Make sure we have 480 Mbps of bandwidth, otherwise things like 2040c0d06caSMauro Carvalho Chehab * video stream wouldn't likely work, since 12 Mbps is generally 2050c0d06caSMauro Carvalho Chehab * not enough even for most Digital TV streams. 2060c0d06caSMauro Carvalho Chehab */ 2070c0d06caSMauro Carvalho Chehab if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { 20883afb32aSMauro Carvalho Chehab pr_err("au0828: Device initialization failed.\n"); 20983afb32aSMauro Carvalho Chehab pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n"); 2100c0d06caSMauro Carvalho Chehab return -ENODEV; 2110c0d06caSMauro Carvalho Chehab } 2120c0d06caSMauro Carvalho Chehab 2130c0d06caSMauro Carvalho Chehab dev = kzalloc(sizeof(*dev), GFP_KERNEL); 2140c0d06caSMauro Carvalho Chehab if (dev == NULL) { 21583afb32aSMauro Carvalho Chehab pr_err("%s() Unable to allocate memory\n", __func__); 2160c0d06caSMauro Carvalho Chehab return -ENOMEM; 2170c0d06caSMauro Carvalho Chehab } 2180c0d06caSMauro Carvalho Chehab 2190c0d06caSMauro Carvalho Chehab mutex_init(&dev->lock); 2200c0d06caSMauro Carvalho Chehab mutex_lock(&dev->lock); 2210c0d06caSMauro Carvalho Chehab mutex_init(&dev->mutex); 2220c0d06caSMauro Carvalho Chehab mutex_init(&dev->dvb.lock); 2230c0d06caSMauro Carvalho Chehab dev->usbdev = usbdev; 2240c0d06caSMauro Carvalho Chehab dev->boardnr = id->driver_info; 225e42c8c6eSRafael Lourenço de Lima Chehab dev->board = au0828_boards[dev->boardnr]; 226e42c8c6eSRafael Lourenço de Lima Chehab 2270c0d06caSMauro Carvalho Chehab 2288a4e7866SMichael Krufky #ifdef CONFIG_VIDEO_AU0828_V4L2 229823beb7eSHans Verkuil dev->v4l2_dev.release = au0828_usb_v4l2_release; 230823beb7eSHans Verkuil 2310c0d06caSMauro Carvalho Chehab /* Create the v4l2_device */ 2320c0d06caSMauro Carvalho Chehab retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); 2330c0d06caSMauro Carvalho Chehab if (retval) { 234e8c26f45SHans Verkuil pr_err("%s() v4l2_device_register failed\n", 2350c0d06caSMauro Carvalho Chehab __func__); 2360c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 2370c0d06caSMauro Carvalho Chehab kfree(dev); 238e8c26f45SHans Verkuil return retval; 2390c0d06caSMauro Carvalho Chehab } 240e8c26f45SHans Verkuil /* This control handler will inherit the controls from au8522 */ 241e8c26f45SHans Verkuil retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4); 242e8c26f45SHans Verkuil if (retval) { 243e8c26f45SHans Verkuil pr_err("%s() v4l2_ctrl_handler_init failed\n", 244e8c26f45SHans Verkuil __func__); 245e8c26f45SHans Verkuil mutex_unlock(&dev->lock); 246e8c26f45SHans Verkuil kfree(dev); 247e8c26f45SHans Verkuil return retval; 248e8c26f45SHans Verkuil } 249e8c26f45SHans Verkuil dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl; 2508a4e7866SMichael Krufky #endif 2510c0d06caSMauro Carvalho Chehab 2520c0d06caSMauro Carvalho Chehab /* Power Up the bridge */ 2530c0d06caSMauro Carvalho Chehab au0828_write(dev, REG_600, 1 << 4); 2540c0d06caSMauro Carvalho Chehab 2550c0d06caSMauro Carvalho Chehab /* Bring up the GPIO's and supporting devices */ 2560c0d06caSMauro Carvalho Chehab au0828_gpio_setup(dev); 2570c0d06caSMauro Carvalho Chehab 2580c0d06caSMauro Carvalho Chehab /* I2C */ 2590c0d06caSMauro Carvalho Chehab au0828_i2c_register(dev); 2600c0d06caSMauro Carvalho Chehab 2610c0d06caSMauro Carvalho Chehab /* Setup */ 2620c0d06caSMauro Carvalho Chehab au0828_card_setup(dev); 2630c0d06caSMauro Carvalho Chehab 2648a4e7866SMichael Krufky #ifdef CONFIG_VIDEO_AU0828_V4L2 2650c0d06caSMauro Carvalho Chehab /* Analog TV */ 2660c0d06caSMauro Carvalho Chehab if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) 2670c0d06caSMauro Carvalho Chehab au0828_analog_register(dev, interface); 2688a4e7866SMichael Krufky #endif 2690c0d06caSMauro Carvalho Chehab 2700c0d06caSMauro Carvalho Chehab /* Digital TV */ 271f251b3e7STim Mester retval = au0828_dvb_register(dev); 272f251b3e7STim Mester if (retval) 273f251b3e7STim Mester pr_err("%s() au0282_dev_register failed\n", 274f251b3e7STim Mester __func__); 275f251b3e7STim Mester 2762fcfd317SMauro Carvalho Chehab /* Remote controller */ 2772fcfd317SMauro Carvalho Chehab au0828_rc_register(dev); 2780c0d06caSMauro Carvalho Chehab 2792fcfd317SMauro Carvalho Chehab /* 2802fcfd317SMauro Carvalho Chehab * Store the pointer to the au0828_dev so it can be accessed in 2812fcfd317SMauro Carvalho Chehab * au0828_usb_disconnect 2822fcfd317SMauro Carvalho Chehab */ 2830c0d06caSMauro Carvalho Chehab usb_set_intfdata(interface, dev); 2840c0d06caSMauro Carvalho Chehab 28583afb32aSMauro Carvalho Chehab pr_info("Registered device AU0828 [%s]\n", 2860c0d06caSMauro Carvalho Chehab dev->board.name == NULL ? "Unset" : dev->board.name); 2870c0d06caSMauro Carvalho Chehab 2880c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->lock); 2890c0d06caSMauro Carvalho Chehab 290f251b3e7STim Mester return retval; 2910c0d06caSMauro Carvalho Chehab } 2920c0d06caSMauro Carvalho Chehab 293aaeac199SMauro Carvalho Chehab static int au0828_suspend(struct usb_interface *interface, 294aaeac199SMauro Carvalho Chehab pm_message_t message) 295aaeac199SMauro Carvalho Chehab { 296aaeac199SMauro Carvalho Chehab struct au0828_dev *dev = usb_get_intfdata(interface); 297aaeac199SMauro Carvalho Chehab 298aaeac199SMauro Carvalho Chehab if (!dev) 299aaeac199SMauro Carvalho Chehab return 0; 300aaeac199SMauro Carvalho Chehab 30181187240SMauro Carvalho Chehab pr_info("Suspend\n"); 30281187240SMauro Carvalho Chehab 303aaeac199SMauro Carvalho Chehab au0828_rc_suspend(dev); 3041a1ba95eSMauro Carvalho Chehab au0828_v4l2_suspend(dev); 305b799de75SMauro Carvalho Chehab au0828_dvb_suspend(dev); 306aaeac199SMauro Carvalho Chehab 307aaeac199SMauro Carvalho Chehab /* FIXME: should suspend also ATV/DTV */ 308aaeac199SMauro Carvalho Chehab 309aaeac199SMauro Carvalho Chehab return 0; 310aaeac199SMauro Carvalho Chehab } 311aaeac199SMauro Carvalho Chehab 312aaeac199SMauro Carvalho Chehab static int au0828_resume(struct usb_interface *interface) 313aaeac199SMauro Carvalho Chehab { 314aaeac199SMauro Carvalho Chehab struct au0828_dev *dev = usb_get_intfdata(interface); 315aaeac199SMauro Carvalho Chehab if (!dev) 316aaeac199SMauro Carvalho Chehab return 0; 317aaeac199SMauro Carvalho Chehab 31881187240SMauro Carvalho Chehab pr_info("Resume\n"); 31981187240SMauro Carvalho Chehab 320fa500461SMauro Carvalho Chehab /* Power Up the bridge */ 321fa500461SMauro Carvalho Chehab au0828_write(dev, REG_600, 1 << 4); 322fa500461SMauro Carvalho Chehab 323fa500461SMauro Carvalho Chehab /* Bring up the GPIO's and supporting devices */ 324fa500461SMauro Carvalho Chehab au0828_gpio_setup(dev); 325fa500461SMauro Carvalho Chehab 326aaeac199SMauro Carvalho Chehab au0828_rc_resume(dev); 3271a1ba95eSMauro Carvalho Chehab au0828_v4l2_resume(dev); 328b799de75SMauro Carvalho Chehab au0828_dvb_resume(dev); 329aaeac199SMauro Carvalho Chehab 330aaeac199SMauro Carvalho Chehab /* FIXME: should resume also ATV/DTV */ 331aaeac199SMauro Carvalho Chehab 332aaeac199SMauro Carvalho Chehab return 0; 333aaeac199SMauro Carvalho Chehab } 334aaeac199SMauro Carvalho Chehab 3350c0d06caSMauro Carvalho Chehab static struct usb_driver au0828_usb_driver = { 33683afb32aSMauro Carvalho Chehab .name = KBUILD_MODNAME, 3370c0d06caSMauro Carvalho Chehab .probe = au0828_usb_probe, 3380c0d06caSMauro Carvalho Chehab .disconnect = au0828_usb_disconnect, 3390c0d06caSMauro Carvalho Chehab .id_table = au0828_usb_id_table, 340aaeac199SMauro Carvalho Chehab .suspend = au0828_suspend, 341aaeac199SMauro Carvalho Chehab .resume = au0828_resume, 342aaeac199SMauro Carvalho Chehab .reset_resume = au0828_resume, 3430c0d06caSMauro Carvalho Chehab }; 3440c0d06caSMauro Carvalho Chehab 3450c0d06caSMauro Carvalho Chehab static int __init au0828_init(void) 3460c0d06caSMauro Carvalho Chehab { 3470c0d06caSMauro Carvalho Chehab int ret; 3480c0d06caSMauro Carvalho Chehab 3490c0d06caSMauro Carvalho Chehab if (au0828_debug & 1) 35083afb32aSMauro Carvalho Chehab pr_info("%s() Debugging is enabled\n", __func__); 3510c0d06caSMauro Carvalho Chehab 3520c0d06caSMauro Carvalho Chehab if (au0828_debug & 2) 35383afb32aSMauro Carvalho Chehab pr_info("%s() USB Debugging is enabled\n", __func__); 3540c0d06caSMauro Carvalho Chehab 3550c0d06caSMauro Carvalho Chehab if (au0828_debug & 4) 35683afb32aSMauro Carvalho Chehab pr_info("%s() I2C Debugging is enabled\n", __func__); 3570c0d06caSMauro Carvalho Chehab 3580c0d06caSMauro Carvalho Chehab if (au0828_debug & 8) 35983afb32aSMauro Carvalho Chehab pr_info("%s() Bridge Debugging is enabled\n", 3600c0d06caSMauro Carvalho Chehab __func__); 3610c0d06caSMauro Carvalho Chehab 3622fcfd317SMauro Carvalho Chehab if (au0828_debug & 16) 36383afb32aSMauro Carvalho Chehab pr_info("%s() IR Debugging is enabled\n", 3642fcfd317SMauro Carvalho Chehab __func__); 3652fcfd317SMauro Carvalho Chehab 36683afb32aSMauro Carvalho Chehab pr_info("au0828 driver loaded\n"); 3670c0d06caSMauro Carvalho Chehab 3680c0d06caSMauro Carvalho Chehab ret = usb_register(&au0828_usb_driver); 3690c0d06caSMauro Carvalho Chehab if (ret) 37083afb32aSMauro Carvalho Chehab pr_err("usb_register failed, error = %d\n", ret); 3710c0d06caSMauro Carvalho Chehab 3720c0d06caSMauro Carvalho Chehab return ret; 3730c0d06caSMauro Carvalho Chehab } 3740c0d06caSMauro Carvalho Chehab 3750c0d06caSMauro Carvalho Chehab static void __exit au0828_exit(void) 3760c0d06caSMauro Carvalho Chehab { 3770c0d06caSMauro Carvalho Chehab usb_deregister(&au0828_usb_driver); 3780c0d06caSMauro Carvalho Chehab } 3790c0d06caSMauro Carvalho Chehab 3800c0d06caSMauro Carvalho Chehab module_init(au0828_init); 3810c0d06caSMauro Carvalho Chehab module_exit(au0828_exit); 3820c0d06caSMauro Carvalho Chehab 3830c0d06caSMauro Carvalho Chehab MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); 3840c0d06caSMauro Carvalho Chehab MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); 3850c0d06caSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 3862fcfd317SMauro Carvalho Chehab MODULE_VERSION("0.0.3"); 387