1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20c0d06caSMauro Carvalho Chehab /*
30c0d06caSMauro Carvalho Chehab * Hauppauge HD PVR USB driver
40c0d06caSMauro Carvalho Chehab *
50c0d06caSMauro Carvalho Chehab * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
60c0d06caSMauro Carvalho Chehab * Copyright (C) 2008 Janne Grunau (j@jannau.net)
70c0d06caSMauro Carvalho Chehab * Copyright (C) 2008 John Poet
80c0d06caSMauro Carvalho Chehab */
90c0d06caSMauro Carvalho Chehab
100c0d06caSMauro Carvalho Chehab #include <linux/kernel.h>
110c0d06caSMauro Carvalho Chehab #include <linux/errno.h>
120c0d06caSMauro Carvalho Chehab #include <linux/init.h>
130c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
140c0d06caSMauro Carvalho Chehab #include <linux/module.h>
150c0d06caSMauro Carvalho Chehab #include <linux/uaccess.h>
160c0d06caSMauro Carvalho Chehab #include <linux/atomic.h>
170c0d06caSMauro Carvalho Chehab #include <linux/usb.h>
180c0d06caSMauro Carvalho Chehab #include <linux/mutex.h>
190c0d06caSMauro Carvalho Chehab #include <linux/i2c.h>
200c0d06caSMauro Carvalho Chehab
210c0d06caSMauro Carvalho Chehab #include <linux/videodev2.h>
220c0d06caSMauro Carvalho Chehab #include <media/v4l2-dev.h>
230c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
240c0d06caSMauro Carvalho Chehab
250c0d06caSMauro Carvalho Chehab #include "hdpvr.h"
260c0d06caSMauro Carvalho Chehab
270c0d06caSMauro Carvalho Chehab static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET};
280c0d06caSMauro Carvalho Chehab module_param_array(video_nr, int, NULL, 0);
290c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
300c0d06caSMauro Carvalho Chehab
310c0d06caSMauro Carvalho Chehab /* holds the number of currently registered devices */
320c0d06caSMauro Carvalho Chehab static atomic_t dev_nr = ATOMIC_INIT(-1);
330c0d06caSMauro Carvalho Chehab
340c0d06caSMauro Carvalho Chehab int hdpvr_debug;
350c0d06caSMauro Carvalho Chehab module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR);
360c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(hdpvr_debug, "enable debugging output");
370c0d06caSMauro Carvalho Chehab
380c0d06caSMauro Carvalho Chehab static uint default_video_input = HDPVR_VIDEO_INPUTS;
390c0d06caSMauro Carvalho Chehab module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
404d5ded75SMauro Carvalho Chehab MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / 1=S-Video / 2=Composite");
410c0d06caSMauro Carvalho Chehab
420c0d06caSMauro Carvalho Chehab static uint default_audio_input = HDPVR_AUDIO_INPUTS;
430c0d06caSMauro Carvalho Chehab module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
444d5ded75SMauro Carvalho Chehab MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / 1=RCA front / 2=S/PDIF");
450c0d06caSMauro Carvalho Chehab
460c0d06caSMauro Carvalho Chehab static bool boost_audio;
470c0d06caSMauro Carvalho Chehab module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
480c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(boost_audio, "boost the audio signal");
490c0d06caSMauro Carvalho Chehab
500c0d06caSMauro Carvalho Chehab
510c0d06caSMauro Carvalho Chehab /* table of devices that work with this driver */
527fb2e072SArvind Yadav static const struct usb_device_id hdpvr_table[] = {
530c0d06caSMauro Carvalho Chehab { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) },
540c0d06caSMauro Carvalho Chehab { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) },
550c0d06caSMauro Carvalho Chehab { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) },
560c0d06caSMauro Carvalho Chehab { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) },
570c0d06caSMauro Carvalho Chehab { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) },
580c0d06caSMauro Carvalho Chehab { } /* Terminating entry */
590c0d06caSMauro Carvalho Chehab };
600c0d06caSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, hdpvr_table);
610c0d06caSMauro Carvalho Chehab
620c0d06caSMauro Carvalho Chehab
hdpvr_delete(struct hdpvr_device * dev)630c0d06caSMauro Carvalho Chehab void hdpvr_delete(struct hdpvr_device *dev)
640c0d06caSMauro Carvalho Chehab {
650c0d06caSMauro Carvalho Chehab hdpvr_free_buffers(dev);
660c0d06caSMauro Carvalho Chehab usb_put_dev(dev->udev);
670c0d06caSMauro Carvalho Chehab }
680c0d06caSMauro Carvalho Chehab
challenge(u8 * bytes)690c0d06caSMauro Carvalho Chehab static void challenge(u8 *bytes)
700c0d06caSMauro Carvalho Chehab {
71c8e479c4SHans Verkuil __le64 *i64P;
72c8e479c4SHans Verkuil u64 tmp64;
730c0d06caSMauro Carvalho Chehab uint i, idx;
740c0d06caSMauro Carvalho Chehab
750c0d06caSMauro Carvalho Chehab for (idx = 0; idx < 32; ++idx) {
760c0d06caSMauro Carvalho Chehab
770c0d06caSMauro Carvalho Chehab if (idx & 0x3)
780c0d06caSMauro Carvalho Chehab bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3];
790c0d06caSMauro Carvalho Chehab
800c0d06caSMauro Carvalho Chehab switch (idx & 0x3) {
810c0d06caSMauro Carvalho Chehab case 0x3:
820c0d06caSMauro Carvalho Chehab bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5];
830c0d06caSMauro Carvalho Chehab bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9;
840c0d06caSMauro Carvalho Chehab break;
850c0d06caSMauro Carvalho Chehab case 0x1:
860c0d06caSMauro Carvalho Chehab bytes[0] *= 8;
870c0d06caSMauro Carvalho Chehab bytes[0] += 7*idx + 4;
880c0d06caSMauro Carvalho Chehab bytes[6] += bytes[3] * 3;
890c0d06caSMauro Carvalho Chehab break;
900c0d06caSMauro Carvalho Chehab case 0x0:
910c0d06caSMauro Carvalho Chehab bytes[3 - (idx >> 3)] = bytes[idx >> 2];
920c0d06caSMauro Carvalho Chehab bytes[5] += bytes[6] * 3;
930c0d06caSMauro Carvalho Chehab for (i = 0; i < 3; i++)
940c0d06caSMauro Carvalho Chehab bytes[3] *= bytes[3] + 1;
950c0d06caSMauro Carvalho Chehab break;
960c0d06caSMauro Carvalho Chehab case 0x2:
970c0d06caSMauro Carvalho Chehab for (i = 0; i < 3; i++)
980c0d06caSMauro Carvalho Chehab bytes[1] *= bytes[6] + 1;
990c0d06caSMauro Carvalho Chehab for (i = 0; i < 3; i++) {
100c8e479c4SHans Verkuil i64P = (__le64 *)bytes;
1010c0d06caSMauro Carvalho Chehab tmp64 = le64_to_cpup(i64P);
102c8e479c4SHans Verkuil tmp64 = tmp64 + (tmp64 << (bytes[7] & 0x0f));
103c8e479c4SHans Verkuil *i64P = cpu_to_le64(tmp64);
1040c0d06caSMauro Carvalho Chehab }
1050c0d06caSMauro Carvalho Chehab break;
1060c0d06caSMauro Carvalho Chehab }
1070c0d06caSMauro Carvalho Chehab }
1080c0d06caSMauro Carvalho Chehab }
1090c0d06caSMauro Carvalho Chehab
1100c0d06caSMauro Carvalho Chehab /* try to init the device like the windows driver */
device_authorization(struct hdpvr_device * dev)1110c0d06caSMauro Carvalho Chehab static int device_authorization(struct hdpvr_device *dev)
1120c0d06caSMauro Carvalho Chehab {
1130c0d06caSMauro Carvalho Chehab
1140c0d06caSMauro Carvalho Chehab int ret, retval = -ENOMEM;
1150c0d06caSMauro Carvalho Chehab char request_type = 0x38, rcv_request = 0x81;
1160c0d06caSMauro Carvalho Chehab char *response;
1170c0d06caSMauro Carvalho Chehab
1180c0d06caSMauro Carvalho Chehab mutex_lock(&dev->usbc_mutex);
1190c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev->udev,
1200c0d06caSMauro Carvalho Chehab usb_rcvctrlpipe(dev->udev, 0),
1210c0d06caSMauro Carvalho Chehab rcv_request, 0x80 | request_type,
1220c0d06caSMauro Carvalho Chehab 0x0400, 0x0003,
1230c0d06caSMauro Carvalho Chehab dev->usbc_buf, 46,
1240c0d06caSMauro Carvalho Chehab 10000);
1250c0d06caSMauro Carvalho Chehab if (ret != 46) {
1260c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev,
1270c0d06caSMauro Carvalho Chehab "unexpected answer of status request, len %d\n", ret);
1280c0d06caSMauro Carvalho Chehab goto unlock;
1290c0d06caSMauro Carvalho Chehab }
1300c0d06caSMauro Carvalho Chehab #ifdef HDPVR_DEBUG
1310c0d06caSMauro Carvalho Chehab else {
1320c0d06caSMauro Carvalho Chehab v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
1339380e112SAndy Shevchenko "Status request returned, len %d: %46ph\n",
1349380e112SAndy Shevchenko ret, dev->usbc_buf);
1350c0d06caSMauro Carvalho Chehab }
1360c0d06caSMauro Carvalho Chehab #endif
1370c0d06caSMauro Carvalho Chehab
1380c0d06caSMauro Carvalho Chehab dev->fw_ver = dev->usbc_buf[1];
1390c0d06caSMauro Carvalho Chehab
1408b8900b7SHans Verkuil dev->usbc_buf[46] = '\0';
1410c0d06caSMauro Carvalho Chehab v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n",
1420c0d06caSMauro Carvalho Chehab dev->fw_ver, &dev->usbc_buf[2]);
1430c0d06caSMauro Carvalho Chehab
1440c0d06caSMauro Carvalho Chehab if (dev->fw_ver > 0x15) {
1450c0d06caSMauro Carvalho Chehab dev->options.brightness = 0x80;
1460c0d06caSMauro Carvalho Chehab dev->options.contrast = 0x40;
1470c0d06caSMauro Carvalho Chehab dev->options.hue = 0xf;
1480c0d06caSMauro Carvalho Chehab dev->options.saturation = 0x40;
1490c0d06caSMauro Carvalho Chehab dev->options.sharpness = 0x80;
1500c0d06caSMauro Carvalho Chehab }
1510c0d06caSMauro Carvalho Chehab
1520c0d06caSMauro Carvalho Chehab switch (dev->fw_ver) {
1530c0d06caSMauro Carvalho Chehab case HDPVR_FIRMWARE_VERSION:
1540c0d06caSMauro Carvalho Chehab dev->flags &= ~HDPVR_FLAG_AC3_CAP;
1550c0d06caSMauro Carvalho Chehab break;
1560c0d06caSMauro Carvalho Chehab case HDPVR_FIRMWARE_VERSION_AC3:
1570c0d06caSMauro Carvalho Chehab case HDPVR_FIRMWARE_VERSION_0X12:
1580c0d06caSMauro Carvalho Chehab case HDPVR_FIRMWARE_VERSION_0X15:
159c7a2c84aSHans Verkuil case HDPVR_FIRMWARE_VERSION_0X1E:
1600c0d06caSMauro Carvalho Chehab dev->flags |= HDPVR_FLAG_AC3_CAP;
1610c0d06caSMauro Carvalho Chehab break;
1620c0d06caSMauro Carvalho Chehab default:
1634d5ded75SMauro Carvalho Chehab v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might not work.\n");
1640c0d06caSMauro Carvalho Chehab if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3)
1650c0d06caSMauro Carvalho Chehab dev->flags |= HDPVR_FLAG_AC3_CAP;
1660c0d06caSMauro Carvalho Chehab else
1670c0d06caSMauro Carvalho Chehab dev->flags &= ~HDPVR_FLAG_AC3_CAP;
1680c0d06caSMauro Carvalho Chehab }
1690c0d06caSMauro Carvalho Chehab
1700c0d06caSMauro Carvalho Chehab response = dev->usbc_buf+38;
1710c0d06caSMauro Carvalho Chehab #ifdef HDPVR_DEBUG
1729380e112SAndy Shevchenko v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %8ph\n",
1739380e112SAndy Shevchenko response);
1740c0d06caSMauro Carvalho Chehab #endif
1750c0d06caSMauro Carvalho Chehab challenge(response);
1760c0d06caSMauro Carvalho Chehab #ifdef HDPVR_DEBUG
1779380e112SAndy Shevchenko v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %8ph\n",
1789380e112SAndy Shevchenko response);
1790c0d06caSMauro Carvalho Chehab #endif
1800c0d06caSMauro Carvalho Chehab
1810c0d06caSMauro Carvalho Chehab msleep(100);
1820c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev->udev,
1830c0d06caSMauro Carvalho Chehab usb_sndctrlpipe(dev->udev, 0),
1840c0d06caSMauro Carvalho Chehab 0xd1, 0x00 | request_type,
1850c0d06caSMauro Carvalho Chehab 0x0000, 0x0000,
1860c0d06caSMauro Carvalho Chehab response, 8,
1870c0d06caSMauro Carvalho Chehab 10000);
1880c0d06caSMauro Carvalho Chehab v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
1890c0d06caSMauro Carvalho Chehab "magic request returned %d\n", ret);
1900c0d06caSMauro Carvalho Chehab
1910c0d06caSMauro Carvalho Chehab retval = ret != 8;
1920c0d06caSMauro Carvalho Chehab unlock:
1930c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->usbc_mutex);
1940c0d06caSMauro Carvalho Chehab return retval;
1950c0d06caSMauro Carvalho Chehab }
1960c0d06caSMauro Carvalho Chehab
hdpvr_device_init(struct hdpvr_device * dev)1970c0d06caSMauro Carvalho Chehab static int hdpvr_device_init(struct hdpvr_device *dev)
1980c0d06caSMauro Carvalho Chehab {
1990c0d06caSMauro Carvalho Chehab int ret;
2000c0d06caSMauro Carvalho Chehab u8 *buf;
2010c0d06caSMauro Carvalho Chehab
2020c0d06caSMauro Carvalho Chehab if (device_authorization(dev))
2030c0d06caSMauro Carvalho Chehab return -EACCES;
2040c0d06caSMauro Carvalho Chehab
2050c0d06caSMauro Carvalho Chehab /* default options for init */
2060c0d06caSMauro Carvalho Chehab hdpvr_set_options(dev);
2070c0d06caSMauro Carvalho Chehab
2080c0d06caSMauro Carvalho Chehab /* set filter options */
2090c0d06caSMauro Carvalho Chehab mutex_lock(&dev->usbc_mutex);
2100c0d06caSMauro Carvalho Chehab buf = dev->usbc_buf;
2110c0d06caSMauro Carvalho Chehab buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00;
2120c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev->udev,
2130c0d06caSMauro Carvalho Chehab usb_sndctrlpipe(dev->udev, 0),
2140c0d06caSMauro Carvalho Chehab 0x01, 0x38,
2150c0d06caSMauro Carvalho Chehab CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX,
2160c0d06caSMauro Carvalho Chehab buf, 4,
2170c0d06caSMauro Carvalho Chehab 1000);
2180c0d06caSMauro Carvalho Chehab v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
2190c0d06caSMauro Carvalho Chehab "control request returned %d\n", ret);
2200c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->usbc_mutex);
2210c0d06caSMauro Carvalho Chehab
2220c0d06caSMauro Carvalho Chehab /* enable fan and bling leds */
2230c0d06caSMauro Carvalho Chehab mutex_lock(&dev->usbc_mutex);
2240c0d06caSMauro Carvalho Chehab buf[0] = 0x1;
2250c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev->udev,
2260c0d06caSMauro Carvalho Chehab usb_sndctrlpipe(dev->udev, 0),
2270c0d06caSMauro Carvalho Chehab 0xd4, 0x38, 0, 0, buf, 1,
2280c0d06caSMauro Carvalho Chehab 1000);
2290c0d06caSMauro Carvalho Chehab v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
2300c0d06caSMauro Carvalho Chehab "control request returned %d\n", ret);
2310c0d06caSMauro Carvalho Chehab
2320c0d06caSMauro Carvalho Chehab /* boost analog audio */
2330c0d06caSMauro Carvalho Chehab buf[0] = boost_audio;
2340c0d06caSMauro Carvalho Chehab ret = usb_control_msg(dev->udev,
2350c0d06caSMauro Carvalho Chehab usb_sndctrlpipe(dev->udev, 0),
2360c0d06caSMauro Carvalho Chehab 0xd5, 0x38, 0, 0, buf, 1,
2370c0d06caSMauro Carvalho Chehab 1000);
2380c0d06caSMauro Carvalho Chehab v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
2390c0d06caSMauro Carvalho Chehab "control request returned %d\n", ret);
2400c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->usbc_mutex);
2410c0d06caSMauro Carvalho Chehab
2420c0d06caSMauro Carvalho Chehab dev->status = STATUS_IDLE;
2430c0d06caSMauro Carvalho Chehab return 0;
2440c0d06caSMauro Carvalho Chehab }
2450c0d06caSMauro Carvalho Chehab
2460c0d06caSMauro Carvalho Chehab static const struct hdpvr_options hdpvr_default_options = {
2470c0d06caSMauro Carvalho Chehab .video_std = HDPVR_60HZ,
2480c0d06caSMauro Carvalho Chehab .video_input = HDPVR_COMPONENT,
2490c0d06caSMauro Carvalho Chehab .audio_input = HDPVR_RCA_BACK,
2500c0d06caSMauro Carvalho Chehab .bitrate = 65, /* 6 mbps */
2510c0d06caSMauro Carvalho Chehab .peak_bitrate = 90, /* 9 mbps */
2520c0d06caSMauro Carvalho Chehab .bitrate_mode = HDPVR_CONSTANT,
2530c0d06caSMauro Carvalho Chehab .gop_mode = HDPVR_SIMPLE_IDR_GOP,
2540c0d06caSMauro Carvalho Chehab .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC,
2550c0d06caSMauro Carvalho Chehab /* original picture controls for firmware version <= 0x15 */
2560c0d06caSMauro Carvalho Chehab /* updated in device_authorization() for newer firmware */
2570c0d06caSMauro Carvalho Chehab .brightness = 0x86,
2580c0d06caSMauro Carvalho Chehab .contrast = 0x80,
2590c0d06caSMauro Carvalho Chehab .hue = 0x80,
2600c0d06caSMauro Carvalho Chehab .saturation = 0x80,
2610c0d06caSMauro Carvalho Chehab .sharpness = 0x80,
2620c0d06caSMauro Carvalho Chehab };
2630c0d06caSMauro Carvalho Chehab
hdpvr_probe(struct usb_interface * interface,const struct usb_device_id * id)2640c0d06caSMauro Carvalho Chehab static int hdpvr_probe(struct usb_interface *interface,
2650c0d06caSMauro Carvalho Chehab const struct usb_device_id *id)
2660c0d06caSMauro Carvalho Chehab {
2670c0d06caSMauro Carvalho Chehab struct hdpvr_device *dev;
2680c0d06caSMauro Carvalho Chehab struct usb_host_interface *iface_desc;
2690c0d06caSMauro Carvalho Chehab struct usb_endpoint_descriptor *endpoint;
270b97baa3eSArnd Bergmann #if IS_ENABLED(CONFIG_I2C)
2710c0d06caSMauro Carvalho Chehab struct i2c_client *client;
272b97baa3eSArnd Bergmann #endif
2730c0d06caSMauro Carvalho Chehab size_t buffer_size;
2740c0d06caSMauro Carvalho Chehab int i;
275d4a6a953SLuke Nowakowski-Krijger int dev_num;
2760c0d06caSMauro Carvalho Chehab int retval = -ENOMEM;
2770c0d06caSMauro Carvalho Chehab
2780c0d06caSMauro Carvalho Chehab /* allocate memory for our device state and initialize it */
2790c0d06caSMauro Carvalho Chehab dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2800c0d06caSMauro Carvalho Chehab if (!dev) {
2810c0d06caSMauro Carvalho Chehab dev_err(&interface->dev, "Out of memory\n");
2820c0d06caSMauro Carvalho Chehab goto error;
2830c0d06caSMauro Carvalho Chehab }
2840c0d06caSMauro Carvalho Chehab
2852e923a05SAlexey Khoroshilov /* init video transfer queues first of all */
2862e923a05SAlexey Khoroshilov /* to prevent oops in hdpvr_delete() on error paths */
2872e923a05SAlexey Khoroshilov INIT_LIST_HEAD(&dev->free_buff_list);
2882e923a05SAlexey Khoroshilov INIT_LIST_HEAD(&dev->rec_buff_list);
2892e923a05SAlexey Khoroshilov
2900c0d06caSMauro Carvalho Chehab /* register v4l2_device early so it can be used for printks */
2910c0d06caSMauro Carvalho Chehab if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
2920c0d06caSMauro Carvalho Chehab dev_err(&interface->dev, "v4l2_device_register failed\n");
293c0f71bbbSArvind Yadav goto error_free_dev;
2940c0d06caSMauro Carvalho Chehab }
2950c0d06caSMauro Carvalho Chehab
2960c0d06caSMauro Carvalho Chehab mutex_init(&dev->io_mutex);
2970c0d06caSMauro Carvalho Chehab mutex_init(&dev->i2c_mutex);
2980c0d06caSMauro Carvalho Chehab mutex_init(&dev->usbc_mutex);
2990c0d06caSMauro Carvalho Chehab dev->usbc_buf = kmalloc(64, GFP_KERNEL);
3000c0d06caSMauro Carvalho Chehab if (!dev->usbc_buf) {
3010c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev, "Out of memory\n");
302c0f71bbbSArvind Yadav goto error_v4l2_unregister;
3030c0d06caSMauro Carvalho Chehab }
3040c0d06caSMauro Carvalho Chehab
3050c0d06caSMauro Carvalho Chehab init_waitqueue_head(&dev->wait_buffer);
3060c0d06caSMauro Carvalho Chehab init_waitqueue_head(&dev->wait_data);
3070c0d06caSMauro Carvalho Chehab
3080c0d06caSMauro Carvalho Chehab dev->options = hdpvr_default_options;
3090c0d06caSMauro Carvalho Chehab
3100c0d06caSMauro Carvalho Chehab if (default_video_input < HDPVR_VIDEO_INPUTS)
3110c0d06caSMauro Carvalho Chehab dev->options.video_input = default_video_input;
3120c0d06caSMauro Carvalho Chehab
3130c0d06caSMauro Carvalho Chehab if (default_audio_input < HDPVR_AUDIO_INPUTS) {
3140c0d06caSMauro Carvalho Chehab dev->options.audio_input = default_audio_input;
3150c0d06caSMauro Carvalho Chehab if (default_audio_input == HDPVR_SPDIF)
3160c0d06caSMauro Carvalho Chehab dev->options.audio_codec =
3170c0d06caSMauro Carvalho Chehab V4L2_MPEG_AUDIO_ENCODING_AC3;
3180c0d06caSMauro Carvalho Chehab }
3190c0d06caSMauro Carvalho Chehab
3200c0d06caSMauro Carvalho Chehab dev->udev = usb_get_dev(interface_to_usbdev(interface));
3210c0d06caSMauro Carvalho Chehab
3220c0d06caSMauro Carvalho Chehab /* set up the endpoint information */
3230c0d06caSMauro Carvalho Chehab /* use only the first bulk-in and bulk-out endpoints */
3240c0d06caSMauro Carvalho Chehab iface_desc = interface->cur_altsetting;
3250c0d06caSMauro Carvalho Chehab for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
3260c0d06caSMauro Carvalho Chehab endpoint = &iface_desc->endpoint[i].desc;
3270c0d06caSMauro Carvalho Chehab
3280c0d06caSMauro Carvalho Chehab if (!dev->bulk_in_endpointAddr &&
3290c0d06caSMauro Carvalho Chehab usb_endpoint_is_bulk_in(endpoint)) {
3300c0d06caSMauro Carvalho Chehab /* USB interface description is buggy, reported max
3310c0d06caSMauro Carvalho Chehab * packet size is 512 bytes, windows driver uses 8192 */
3320c0d06caSMauro Carvalho Chehab buffer_size = 8192;
3330c0d06caSMauro Carvalho Chehab dev->bulk_in_size = buffer_size;
3340c0d06caSMauro Carvalho Chehab dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
3350c0d06caSMauro Carvalho Chehab }
3360c0d06caSMauro Carvalho Chehab
3370c0d06caSMauro Carvalho Chehab }
3380c0d06caSMauro Carvalho Chehab if (!dev->bulk_in_endpointAddr) {
3390c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
340c0f71bbbSArvind Yadav goto error_put_usb;
3410c0d06caSMauro Carvalho Chehab }
3420c0d06caSMauro Carvalho Chehab
3430c0d06caSMauro Carvalho Chehab /* init the device */
3440c0d06caSMauro Carvalho Chehab if (hdpvr_device_init(dev)) {
3450c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev, "device init failed\n");
346c0f71bbbSArvind Yadav goto error_put_usb;
3470c0d06caSMauro Carvalho Chehab }
3480c0d06caSMauro Carvalho Chehab
3490c0d06caSMauro Carvalho Chehab mutex_lock(&dev->io_mutex);
3500c0d06caSMauro Carvalho Chehab if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
3510c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->io_mutex);
3520c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev,
3530c0d06caSMauro Carvalho Chehab "allocating transfer buffers failed\n");
354c0f71bbbSArvind Yadav goto error_put_usb;
3550c0d06caSMauro Carvalho Chehab }
3560c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->io_mutex);
3570c0d06caSMauro Carvalho Chehab
3589ecf9b08SPeter Senna Tschudin #if IS_ENABLED(CONFIG_I2C)
3590c0d06caSMauro Carvalho Chehab retval = hdpvr_register_i2c_adapter(dev);
3600c0d06caSMauro Carvalho Chehab if (retval < 0) {
3610c0d06caSMauro Carvalho Chehab v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
362c0f71bbbSArvind Yadav goto error_free_buffers;
3630c0d06caSMauro Carvalho Chehab }
3640c0d06caSMauro Carvalho Chehab
365ab5222edSSean Young client = hdpvr_register_ir_i2c(dev);
366*f263c851SWolfram Sang if (IS_ERR(client)) {
367ab5222edSSean Young v4l2_err(&dev->v4l2_dev, "i2c IR device register failed\n");
368*f263c851SWolfram Sang retval = PTR_ERR(client);
3690c0d06caSMauro Carvalho Chehab goto reg_fail;
3700c0d06caSMauro Carvalho Chehab }
3710c0d06caSMauro Carvalho Chehab #endif
3720c0d06caSMauro Carvalho Chehab
373d4a6a953SLuke Nowakowski-Krijger dev_num = atomic_inc_return(&dev_nr);
374d4a6a953SLuke Nowakowski-Krijger if (dev_num >= HDPVR_MAX) {
375d4a6a953SLuke Nowakowski-Krijger v4l2_err(&dev->v4l2_dev,
376d4a6a953SLuke Nowakowski-Krijger "max device number reached, device register failed\n");
377d4a6a953SLuke Nowakowski-Krijger atomic_dec(&dev_nr);
378d4a6a953SLuke Nowakowski-Krijger retval = -ENODEV;
379d4a6a953SLuke Nowakowski-Krijger goto reg_fail;
380d4a6a953SLuke Nowakowski-Krijger }
381d4a6a953SLuke Nowakowski-Krijger
382280847b5SHans Verkuil retval = hdpvr_register_videodev(dev, &interface->dev,
383d4a6a953SLuke Nowakowski-Krijger video_nr[dev_num]);
384280847b5SHans Verkuil if (retval < 0) {
385280847b5SHans Verkuil v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
3862e923a05SAlexey Khoroshilov goto reg_fail;
387280847b5SHans Verkuil }
388280847b5SHans Verkuil
3890c0d06caSMauro Carvalho Chehab /* let the user know what node this device is now attached to */
3900c0d06caSMauro Carvalho Chehab v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
3914b30409bSHans Verkuil video_device_node_name(&dev->video_dev));
3920c0d06caSMauro Carvalho Chehab return 0;
3930c0d06caSMauro Carvalho Chehab
3940c0d06caSMauro Carvalho Chehab reg_fail:
3959ecf9b08SPeter Senna Tschudin #if IS_ENABLED(CONFIG_I2C)
3960c0d06caSMauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adapter);
397c0f71bbbSArvind Yadav error_free_buffers:
3980c0d06caSMauro Carvalho Chehab #endif
399c0f71bbbSArvind Yadav hdpvr_free_buffers(dev);
400c0f71bbbSArvind Yadav error_put_usb:
401c0f71bbbSArvind Yadav usb_put_dev(dev->udev);
402c0f71bbbSArvind Yadav kfree(dev->usbc_buf);
403c0f71bbbSArvind Yadav error_v4l2_unregister:
404c0f71bbbSArvind Yadav v4l2_device_unregister(&dev->v4l2_dev);
405c0f71bbbSArvind Yadav error_free_dev:
406c0f71bbbSArvind Yadav kfree(dev);
4070c0d06caSMauro Carvalho Chehab error:
4080c0d06caSMauro Carvalho Chehab return retval;
4090c0d06caSMauro Carvalho Chehab }
4100c0d06caSMauro Carvalho Chehab
hdpvr_disconnect(struct usb_interface * interface)4110c0d06caSMauro Carvalho Chehab static void hdpvr_disconnect(struct usb_interface *interface)
4120c0d06caSMauro Carvalho Chehab {
4130c0d06caSMauro Carvalho Chehab struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
4140c0d06caSMauro Carvalho Chehab
4150c0d06caSMauro Carvalho Chehab v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
4164b30409bSHans Verkuil video_device_node_name(&dev->video_dev));
4170c0d06caSMauro Carvalho Chehab /* prevent more I/O from starting and stop any ongoing */
4180c0d06caSMauro Carvalho Chehab mutex_lock(&dev->io_mutex);
4190c0d06caSMauro Carvalho Chehab dev->status = STATUS_DISCONNECTED;
4200c0d06caSMauro Carvalho Chehab wake_up_interruptible(&dev->wait_data);
4210c0d06caSMauro Carvalho Chehab wake_up_interruptible(&dev->wait_buffer);
4220c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->io_mutex);
4230c0d06caSMauro Carvalho Chehab v4l2_device_disconnect(&dev->v4l2_dev);
4240c0d06caSMauro Carvalho Chehab msleep(100);
4255612e191SBhaktipriya Shridhar flush_work(&dev->worker);
4260c0d06caSMauro Carvalho Chehab mutex_lock(&dev->io_mutex);
4270c0d06caSMauro Carvalho Chehab hdpvr_cancel_queue(dev);
4280c0d06caSMauro Carvalho Chehab mutex_unlock(&dev->io_mutex);
4299ecf9b08SPeter Senna Tschudin #if IS_ENABLED(CONFIG_I2C)
4300c0d06caSMauro Carvalho Chehab i2c_del_adapter(&dev->i2c_adapter);
4310c0d06caSMauro Carvalho Chehab #endif
4324b30409bSHans Verkuil video_unregister_device(&dev->video_dev);
4330c0d06caSMauro Carvalho Chehab atomic_dec(&dev_nr);
4340c0d06caSMauro Carvalho Chehab }
4350c0d06caSMauro Carvalho Chehab
4360c0d06caSMauro Carvalho Chehab
4370c0d06caSMauro Carvalho Chehab static struct usb_driver hdpvr_usb_driver = {
4380c0d06caSMauro Carvalho Chehab .name = "hdpvr",
4390c0d06caSMauro Carvalho Chehab .probe = hdpvr_probe,
4400c0d06caSMauro Carvalho Chehab .disconnect = hdpvr_disconnect,
4410c0d06caSMauro Carvalho Chehab .id_table = hdpvr_table,
4420c0d06caSMauro Carvalho Chehab };
4430c0d06caSMauro Carvalho Chehab
4440c0d06caSMauro Carvalho Chehab module_usb_driver(hdpvr_usb_driver);
4450c0d06caSMauro Carvalho Chehab
4460c0d06caSMauro Carvalho Chehab MODULE_LICENSE("GPL");
4470c0d06caSMauro Carvalho Chehab MODULE_VERSION("0.2.1");
4480c0d06caSMauro Carvalho Chehab MODULE_AUTHOR("Janne Grunau");
4490c0d06caSMauro Carvalho Chehab MODULE_DESCRIPTION("Hauppauge HD PVR driver");
450