v4.19.13 snapshot.
diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig
new file mode 100644
index 0000000..d73d9a1
--- /dev/null
+++ b/drivers/media/usb/hdpvr/Kconfig
@@ -0,0 +1,10 @@
+
+config VIDEO_HDPVR
+	tristate "Hauppauge HD PVR support"
+	depends on VIDEO_DEV && VIDEO_V4L2
+	---help---
+	  This is a video4linux driver for Hauppauge's HD PVR USB device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hdpvr
+
diff --git a/drivers/media/usb/hdpvr/Makefile b/drivers/media/usb/hdpvr/Makefile
new file mode 100644
index 0000000..644dd99
--- /dev/null
+++ b/drivers/media/usb/hdpvr/Makefile
@@ -0,0 +1,3 @@
+hdpvr-objs	:= hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
+
+obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c
new file mode 100644
index 0000000..6e86032
--- /dev/null
+++ b/drivers/media/usb/hdpvr/hdpvr-control.c
@@ -0,0 +1,181 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
+{
+	int ret;
+	char request_type = 0x38, snd_request = 0x01;
+
+	mutex_lock(&dev->usbc_mutex);
+	dev->usbc_buf[0] = valbuf;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      snd_request, 0x00 | request_type,
+			      value, CTRL_DEFAULT_INDEX,
+			      dev->usbc_buf, 1, 10000);
+
+	mutex_unlock(&dev->usbc_mutex);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "config call request for value 0x%x returned %d\n", value,
+		 ret);
+
+	return ret < 0 ? ret : 0;
+}
+
+int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf)
+{
+	int ret;
+
+	vidinf->valid = false;
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1400, 0x0003,
+			      dev->usbc_buf, 5,
+			      1000);
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO)
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "get video info returned: %d, %5ph\n", ret,
+			 dev->usbc_buf);
+#endif
+	mutex_unlock(&dev->usbc_mutex);
+
+	if (ret < 0)
+		return ret;
+
+	vidinf->width	= dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+	vidinf->height	= dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
+	vidinf->fps	= dev->usbc_buf[4];
+	vidinf->valid   = vidinf->width && vidinf->height && vidinf->fps;
+
+	return 0;
+}
+
+int get_input_lines_info(struct hdpvr_device *dev)
+{
+	int ret, lines;
+
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1800, 0x0003,
+			      dev->usbc_buf, 3,
+			      1000);
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO)
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "get input lines info returned: %d, %3ph\n", ret,
+			 dev->usbc_buf);
+#else
+	(void)ret;	/* suppress compiler warning */
+#endif
+	lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+	mutex_unlock(&dev->usbc_mutex);
+	return lines;
+}
+
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev)
+{
+	int ret;
+
+	mutex_lock(&dev->usbc_mutex);
+	memset(dev->usbc_buf, 0, 4);
+	dev->usbc_buf[0] = dev->options.bitrate;
+	dev->usbc_buf[2] = dev->options.peak_bitrate;
+
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0x01, 0x38, CTRL_BITRATE_VALUE,
+			      CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000);
+	mutex_unlock(&dev->usbc_mutex);
+
+	return ret;
+}
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+		    enum v4l2_mpeg_audio_encoding codec)
+{
+	int ret = 0;
+
+	if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+		mutex_lock(&dev->usbc_mutex);
+		memset(dev->usbc_buf, 0, 2);
+		dev->usbc_buf[0] = input;
+		if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC)
+			dev->usbc_buf[1] = 0;
+		else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3)
+			dev->usbc_buf[1] = 1;
+		else {
+			mutex_unlock(&dev->usbc_mutex);
+			v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n",
+				 codec);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		ret = usb_control_msg(dev->udev,
+				      usb_sndctrlpipe(dev->udev, 0),
+				      0x01, 0x38, CTRL_AUDIO_INPUT_VALUE,
+				      CTRL_DEFAULT_INDEX, dev->usbc_buf, 2,
+				      1000);
+		mutex_unlock(&dev->usbc_mutex);
+		if (ret == 2)
+			ret = 0;
+	} else
+		ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input);
+error:
+	return ret;
+}
+
+int hdpvr_set_options(struct hdpvr_device *dev)
+{
+	hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std);
+
+	hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE,
+			 dev->options.video_input+1);
+
+	hdpvr_set_audio(dev, dev->options.audio_input+1,
+		       dev->options.audio_codec);
+
+	hdpvr_set_bitrate(dev);
+	hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+			 dev->options.bitrate_mode);
+	hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode);
+
+	hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness);
+	hdpvr_config_call(dev, CTRL_CONTRAST,   dev->options.contrast);
+	hdpvr_config_call(dev, CTRL_HUE,        dev->options.hue);
+	hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation);
+	hdpvr_config_call(dev, CTRL_SHARPNESS,  dev->options.sharpness);
+
+	return 0;
+}
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
new file mode 100644
index 0000000..29ac7fc
--- /dev/null
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -0,0 +1,442 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ * Copyright (C) 2008      John Poet
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET};
+module_param_array(video_nr, int, NULL, 0);
+MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
+
+/* holds the number of currently registered devices */
+static atomic_t dev_nr = ATOMIC_INIT(-1);
+
+int hdpvr_debug;
+module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hdpvr_debug, "enable debugging output");
+
+static uint default_video_input = HDPVR_VIDEO_INPUTS;
+module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / 1=S-Video / 2=Composite");
+
+static uint default_audio_input = HDPVR_AUDIO_INPUTS;
+module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / 1=RCA front / 2=S/PDIF");
+
+static bool boost_audio;
+module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(boost_audio, "boost the audio signal");
+
+
+/* table of devices that work with this driver */
+static const struct usb_device_id hdpvr_table[] = {
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, hdpvr_table);
+
+
+void hdpvr_delete(struct hdpvr_device *dev)
+{
+	hdpvr_free_buffers(dev);
+	usb_put_dev(dev->udev);
+}
+
+static void challenge(u8 *bytes)
+{
+	__le64 *i64P;
+	u64 tmp64;
+	uint i, idx;
+
+	for (idx = 0; idx < 32; ++idx) {
+
+		if (idx & 0x3)
+			bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3];
+
+		switch (idx & 0x3) {
+		case 0x3:
+			bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5];
+			bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9;
+			break;
+		case 0x1:
+			bytes[0] *= 8;
+			bytes[0] += 7*idx + 4;
+			bytes[6] += bytes[3] * 3;
+			break;
+		case 0x0:
+			bytes[3 - (idx >> 3)] = bytes[idx >> 2];
+			bytes[5] += bytes[6] * 3;
+			for (i = 0; i < 3; i++)
+				bytes[3] *= bytes[3] + 1;
+			break;
+		case 0x2:
+			for (i = 0; i < 3; i++)
+				bytes[1] *= bytes[6] + 1;
+			for (i = 0; i < 3; i++) {
+				i64P = (__le64 *)bytes;
+				tmp64 = le64_to_cpup(i64P);
+				tmp64 = tmp64 + (tmp64 << (bytes[7] & 0x0f));
+				*i64P = cpu_to_le64(tmp64);
+			}
+			break;
+		}
+	}
+}
+
+/* try to init the device like the windows driver */
+static int device_authorization(struct hdpvr_device *dev)
+{
+
+	int ret, retval = -ENOMEM;
+	char request_type = 0x38, rcv_request = 0x81;
+	char *response;
+
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      rcv_request, 0x80 | request_type,
+			      0x0400, 0x0003,
+			      dev->usbc_buf, 46,
+			      10000);
+	if (ret != 46) {
+		v4l2_err(&dev->v4l2_dev,
+			 "unexpected answer of status request, len %d\n", ret);
+		goto unlock;
+	}
+#ifdef HDPVR_DEBUG
+	else {
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "Status request returned, len %d: %46ph\n",
+			 ret, dev->usbc_buf);
+	}
+#endif
+
+	dev->fw_ver = dev->usbc_buf[1];
+
+	v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n",
+			  dev->fw_ver, &dev->usbc_buf[2]);
+
+	if (dev->fw_ver > 0x15) {
+		dev->options.brightness	= 0x80;
+		dev->options.contrast	= 0x40;
+		dev->options.hue	= 0xf;
+		dev->options.saturation	= 0x40;
+		dev->options.sharpness	= 0x80;
+	}
+
+	switch (dev->fw_ver) {
+	case HDPVR_FIRMWARE_VERSION:
+		dev->flags &= ~HDPVR_FLAG_AC3_CAP;
+		break;
+	case HDPVR_FIRMWARE_VERSION_AC3:
+	case HDPVR_FIRMWARE_VERSION_0X12:
+	case HDPVR_FIRMWARE_VERSION_0X15:
+	case HDPVR_FIRMWARE_VERSION_0X1E:
+		dev->flags |= HDPVR_FLAG_AC3_CAP;
+		break;
+	default:
+		v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might not work.\n");
+		if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3)
+			dev->flags |= HDPVR_FLAG_AC3_CAP;
+		else
+			dev->flags &= ~HDPVR_FLAG_AC3_CAP;
+	}
+
+	response = dev->usbc_buf+38;
+#ifdef HDPVR_DEBUG
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %8ph\n",
+		 response);
+#endif
+	challenge(response);
+#ifdef HDPVR_DEBUG
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %8ph\n",
+		 response);
+#endif
+
+	msleep(100);
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd1, 0x00 | request_type,
+			      0x0000, 0x0000,
+			      response, 8,
+			      10000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "magic request returned %d\n", ret);
+
+	retval = ret != 8;
+unlock:
+	mutex_unlock(&dev->usbc_mutex);
+	return retval;
+}
+
+static int hdpvr_device_init(struct hdpvr_device *dev)
+{
+	int ret;
+	u8 *buf;
+
+	if (device_authorization(dev))
+		return -EACCES;
+
+	/* default options for init */
+	hdpvr_set_options(dev);
+
+	/* set filter options */
+	mutex_lock(&dev->usbc_mutex);
+	buf = dev->usbc_buf;
+	buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0x01, 0x38,
+			      CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX,
+			      buf, 4,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+	mutex_unlock(&dev->usbc_mutex);
+
+	/* enable fan and bling leds */
+	mutex_lock(&dev->usbc_mutex);
+	buf[0] = 0x1;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd4, 0x38, 0, 0, buf, 1,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+
+	/* boost analog audio */
+	buf[0] = boost_audio;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd5, 0x38, 0, 0, buf, 1,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+	mutex_unlock(&dev->usbc_mutex);
+
+	dev->status = STATUS_IDLE;
+	return 0;
+}
+
+static const struct hdpvr_options hdpvr_default_options = {
+	.video_std	= HDPVR_60HZ,
+	.video_input	= HDPVR_COMPONENT,
+	.audio_input	= HDPVR_RCA_BACK,
+	.bitrate	= 65, /* 6 mbps */
+	.peak_bitrate	= 90, /* 9 mbps */
+	.bitrate_mode	= HDPVR_CONSTANT,
+	.gop_mode	= HDPVR_SIMPLE_IDR_GOP,
+	.audio_codec	= V4L2_MPEG_AUDIO_ENCODING_AAC,
+	/* original picture controls for firmware version <= 0x15 */
+	/* updated in device_authorization() for newer firmware */
+	.brightness	= 0x86,
+	.contrast	= 0x80,
+	.hue		= 0x80,
+	.saturation	= 0x80,
+	.sharpness	= 0x80,
+};
+
+static int hdpvr_probe(struct usb_interface *interface,
+		       const struct usb_device_id *id)
+{
+	struct hdpvr_device *dev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+#if IS_ENABLED(CONFIG_I2C)
+	struct i2c_client *client;
+#endif
+	size_t buffer_size;
+	int i;
+	int retval = -ENOMEM;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&interface->dev, "Out of memory\n");
+		goto error;
+	}
+
+	/* init video transfer queues first of all */
+	/* to prevent oops in hdpvr_delete() on error paths */
+	INIT_LIST_HEAD(&dev->free_buff_list);
+	INIT_LIST_HEAD(&dev->rec_buff_list);
+
+	/* register v4l2_device early so it can be used for printks */
+	if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
+		dev_err(&interface->dev, "v4l2_device_register failed\n");
+		goto error_free_dev;
+	}
+
+	mutex_init(&dev->io_mutex);
+	mutex_init(&dev->i2c_mutex);
+	mutex_init(&dev->usbc_mutex);
+	dev->usbc_buf = kmalloc(64, GFP_KERNEL);
+	if (!dev->usbc_buf) {
+		v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+		goto error_v4l2_unregister;
+	}
+
+	init_waitqueue_head(&dev->wait_buffer);
+	init_waitqueue_head(&dev->wait_data);
+
+	dev->options = hdpvr_default_options;
+
+	if (default_video_input < HDPVR_VIDEO_INPUTS)
+		dev->options.video_input = default_video_input;
+
+	if (default_audio_input < HDPVR_AUDIO_INPUTS) {
+		dev->options.audio_input = default_audio_input;
+		if (default_audio_input == HDPVR_SPDIF)
+			dev->options.audio_codec =
+				V4L2_MPEG_AUDIO_ENCODING_AC3;
+	}
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* set up the endpoint information */
+	/* use only the first bulk-in and bulk-out endpoints */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (!dev->bulk_in_endpointAddr &&
+		    usb_endpoint_is_bulk_in(endpoint)) {
+			/* USB interface description is buggy, reported max
+			 * packet size is 512 bytes, windows driver uses 8192 */
+			buffer_size = 8192;
+			dev->bulk_in_size = buffer_size;
+			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+		}
+
+	}
+	if (!dev->bulk_in_endpointAddr) {
+		v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
+		goto error_put_usb;
+	}
+
+	/* init the device */
+	if (hdpvr_device_init(dev)) {
+		v4l2_err(&dev->v4l2_dev, "device init failed\n");
+		goto error_put_usb;
+	}
+
+	mutex_lock(&dev->io_mutex);
+	if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
+		mutex_unlock(&dev->io_mutex);
+		v4l2_err(&dev->v4l2_dev,
+			 "allocating transfer buffers failed\n");
+		goto error_put_usb;
+	}
+	mutex_unlock(&dev->io_mutex);
+
+#if IS_ENABLED(CONFIG_I2C)
+	retval = hdpvr_register_i2c_adapter(dev);
+	if (retval < 0) {
+		v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
+		goto error_free_buffers;
+	}
+
+	client = hdpvr_register_ir_i2c(dev);
+	if (!client) {
+		v4l2_err(&dev->v4l2_dev, "i2c IR device register failed\n");
+		retval = -ENODEV;
+		goto reg_fail;
+	}
+#endif
+
+	retval = hdpvr_register_videodev(dev, &interface->dev,
+				    video_nr[atomic_inc_return(&dev_nr)]);
+	if (retval < 0) {
+		v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
+		goto reg_fail;
+	}
+
+	/* let the user know what node this device is now attached to */
+	v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
+		  video_device_node_name(&dev->video_dev));
+	return 0;
+
+reg_fail:
+#if IS_ENABLED(CONFIG_I2C)
+	i2c_del_adapter(&dev->i2c_adapter);
+error_free_buffers:
+#endif
+	hdpvr_free_buffers(dev);
+error_put_usb:
+	usb_put_dev(dev->udev);
+	kfree(dev->usbc_buf);
+error_v4l2_unregister:
+	v4l2_device_unregister(&dev->v4l2_dev);
+error_free_dev:
+	kfree(dev);
+error:
+	return retval;
+}
+
+static void hdpvr_disconnect(struct usb_interface *interface)
+{
+	struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
+
+	v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
+		  video_device_node_name(&dev->video_dev));
+	/* prevent more I/O from starting and stop any ongoing */
+	mutex_lock(&dev->io_mutex);
+	dev->status = STATUS_DISCONNECTED;
+	wake_up_interruptible(&dev->wait_data);
+	wake_up_interruptible(&dev->wait_buffer);
+	mutex_unlock(&dev->io_mutex);
+	v4l2_device_disconnect(&dev->v4l2_dev);
+	msleep(100);
+	flush_work(&dev->worker);
+	mutex_lock(&dev->io_mutex);
+	hdpvr_cancel_queue(dev);
+	mutex_unlock(&dev->io_mutex);
+#if IS_ENABLED(CONFIG_I2C)
+	i2c_del_adapter(&dev->i2c_adapter);
+#endif
+	video_unregister_device(&dev->video_dev);
+	atomic_dec(&dev_nr);
+}
+
+
+static struct usb_driver hdpvr_usb_driver = {
+	.name =		"hdpvr",
+	.probe =	hdpvr_probe,
+	.disconnect =	hdpvr_disconnect,
+	.id_table =	hdpvr_table,
+};
+
+module_usb_driver(hdpvr_usb_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2.1");
+MODULE_AUTHOR("Janne Grunau");
+MODULE_DESCRIPTION("Hauppauge HD PVR driver");
diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c
new file mode 100644
index 0000000..5a3cb61
--- /dev/null
+++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c
@@ -0,0 +1,214 @@
+
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ * IR device registration code is
+ * Copyright (C) 2010	Andy Walls <awalls@md.metrocast.net>
+ *
+ *	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, version 2.
+ *
+ */
+
+#if IS_ENABLED(CONFIG_I2C)
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include "hdpvr.h"
+
+#define CTRL_READ_REQUEST	0xb8
+#define CTRL_WRITE_REQUEST	0x38
+
+#define REQTYPE_I2C_READ	0xb1
+#define REQTYPE_I2C_WRITE	0xb0
+#define REQTYPE_I2C_WRITE_STATT	0xd0
+
+#define Z8F0811_IR_TX_I2C_ADDR	0x70
+#define Z8F0811_IR_RX_I2C_ADDR	0x71
+
+
+struct i2c_client *hdpvr_register_ir_i2c(struct hdpvr_device *dev)
+{
+	struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+	struct i2c_board_info info = {
+		I2C_BOARD_INFO("ir_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
+	};
+
+	/* Our default information for ir-kbd-i2c.c to use */
+	init_data->ir_codes = RC_MAP_HAUPPAUGE;
+	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+	init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
+			  RC_PROTO_BIT_RC6_6A_32;
+	init_data->name = "HD-PVR";
+	init_data->polling_interval = 405; /* ms, duplicated from Windows */
+	info.platform_data = init_data;
+
+	return i2c_new_device(&dev->i2c_adapter, &info);
+}
+
+static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
+			  unsigned char addr, char *wdata, int wlen,
+			  char *data, int len)
+{
+	int ret;
+
+	if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
+		return -EINVAL;
+
+	if (wlen) {
+		memcpy(&dev->i2c_buf, wdata, wlen);
+		ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+				      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+				      (bus << 8) | addr, 0, &dev->i2c_buf,
+				      wlen, 1000);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
+			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
+
+	if (ret == len) {
+		memcpy(data, &dev->i2c_buf, len);
+		ret = 0;
+	} else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
+			   unsigned char addr, char *data, int len)
+{
+	int ret;
+
+	if (len > sizeof(dev->i2c_buf))
+		return -EINVAL;
+
+	memcpy(&dev->i2c_buf, data, len);
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
+
+	if (ret < 0)
+		return ret;
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
+			      0, 0, &dev->i2c_buf, 2, 1000);
+
+	if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
+			  int num)
+{
+	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
+	int retval = 0, addr;
+
+	mutex_lock(&dev->i2c_mutex);
+
+	addr = msgs[0].addr << 1;
+
+	if (num == 1) {
+		if (msgs[0].flags & I2C_M_RD)
+			retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
+						msgs[0].buf, msgs[0].len);
+		else
+			retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
+						 msgs[0].len);
+	} else if (num == 2) {
+		if (msgs[0].addr != msgs[1].addr) {
+			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer with conflicting target addresses\n");
+			retval = -EINVAL;
+			goto out;
+		}
+
+		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
+			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with r0=%d, r1=%d\n",
+				  msgs[0].flags & I2C_M_RD,
+				  msgs[1].flags & I2C_M_RD);
+			retval = -EINVAL;
+			goto out;
+		}
+
+		/*
+		 * Write followed by atomic read is the only complex xfer that
+		 * we actually support here.
+		 */
+		retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
+					msgs[1].buf, msgs[1].len);
+	} else {
+		v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
+	}
+
+out:
+	mutex_unlock(&dev->i2c_mutex);
+
+	return retval ? retval : num;
+}
+
+static u32 hdpvr_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm hdpvr_algo = {
+	.master_xfer   = hdpvr_transfer,
+	.functionality = hdpvr_functionality,
+};
+
+static const struct i2c_adapter hdpvr_i2c_adapter_template = {
+	.name   = "Hauppauge HD PVR I2C",
+	.owner  = THIS_MODULE,
+	.algo   = &hdpvr_algo,
+};
+
+static int hdpvr_activate_ir(struct hdpvr_device *dev)
+{
+	char buffer[2];
+
+	mutex_lock(&dev->i2c_mutex);
+
+	hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
+
+	buffer[0] = 0;
+	buffer[1] = 0x8;
+	hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+	buffer[1] = 0x18;
+	hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+	mutex_unlock(&dev->i2c_mutex);
+
+	return 0;
+}
+
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
+{
+	int retval = -ENOMEM;
+
+	hdpvr_activate_ir(dev);
+
+	dev->i2c_adapter = hdpvr_i2c_adapter_template;
+	dev->i2c_adapter.dev.parent = &dev->udev->dev;
+
+	i2c_set_adapdata(&dev->i2c_adapter, dev);
+
+	retval = i2c_add_adapter(&dev->i2c_adapter);
+
+	return retval;
+}
+
+#endif
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
new file mode 100644
index 0000000..1b89c77
--- /dev/null
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -0,0 +1,1255 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include "hdpvr.h"
+
+#define BULK_URB_TIMEOUT   90 /* 0.09 seconds */
+
+#define print_buffer_status() { \
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,	\
+			 "%s:%d buffer stat: %d free, %d proc\n",	\
+			 __func__, __LINE__,				\
+			 list_size(&dev->free_buff_list),		\
+			 list_size(&dev->rec_buff_list)); }
+
+static const struct v4l2_dv_timings hdpvr_dv_timings[] = {
+	V4L2_DV_BT_CEA_720X480I59_94,
+	V4L2_DV_BT_CEA_720X576I50,
+	V4L2_DV_BT_CEA_720X480P59_94,
+	V4L2_DV_BT_CEA_720X576P50,
+	V4L2_DV_BT_CEA_1280X720P50,
+	V4L2_DV_BT_CEA_1280X720P60,
+	V4L2_DV_BT_CEA_1920X1080I50,
+	V4L2_DV_BT_CEA_1920X1080I60,
+};
+
+/* Use 480i59 as the default timings */
+#define HDPVR_DEF_DV_TIMINGS_IDX (0)
+
+struct hdpvr_fh {
+	struct v4l2_fh fh;
+	bool legacy_mode;
+};
+
+static uint list_size(struct list_head *list)
+{
+	struct list_head *tmp;
+	uint count = 0;
+
+	list_for_each(tmp, list) {
+		count++;
+	}
+
+	return count;
+}
+
+/*=========================================================================*/
+/* urb callback */
+static void hdpvr_read_bulk_callback(struct urb *urb)
+{
+	struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context;
+	struct hdpvr_device *dev = buf->dev;
+
+	/* marking buffer as received and wake waiting */
+	buf->status = BUFSTAT_READY;
+	wake_up_interruptible(&dev->wait_data);
+}
+
+/*=========================================================================*/
+/* buffer bits */
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_cancel_queue(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+
+	list_for_each_entry(buf, &dev->rec_buff_list, buff_list) {
+		usb_kill_urb(buf->urb);
+		buf->status = BUFSTAT_AVAILABLE;
+	}
+
+	list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev);
+
+	return 0;
+}
+
+static int hdpvr_free_queue(struct list_head *q)
+{
+	struct list_head *tmp;
+	struct list_head *p;
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+
+	for (p = q->next; p != q;) {
+		buf = list_entry(p, struct hdpvr_buffer, buff_list);
+
+		urb = buf->urb;
+		usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+				  urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		tmp = p->next;
+		list_del(p);
+		kfree(buf);
+		p = tmp;
+	}
+
+	return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_free_buffers(struct hdpvr_device *dev)
+{
+	hdpvr_cancel_queue(dev);
+
+	hdpvr_free_queue(&dev->free_buff_list);
+	hdpvr_free_queue(&dev->rec_buff_list);
+
+	return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
+{
+	uint i;
+	int retval = -ENOMEM;
+	u8 *mem;
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "allocating %u buffers\n", count);
+
+	for (i = 0; i < count; i++) {
+
+		buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL);
+		if (!buf) {
+			v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n");
+			goto exit;
+		}
+		buf->dev = dev;
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb)
+			goto exit_urb;
+		buf->urb = urb;
+
+		mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL,
+					 &urb->transfer_dma);
+		if (!mem) {
+			v4l2_err(&dev->v4l2_dev,
+				 "cannot allocate usb transfer buffer\n");
+			goto exit_urb_buffer;
+		}
+
+		usb_fill_bulk_urb(buf->urb, dev->udev,
+				  usb_rcvbulkpipe(dev->udev,
+						  dev->bulk_in_endpointAddr),
+				  mem, dev->bulk_in_size,
+				  hdpvr_read_bulk_callback, buf);
+
+		buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		buf->status = BUFSTAT_AVAILABLE;
+		list_add_tail(&buf->buff_list, &dev->free_buff_list);
+	}
+	return 0;
+exit_urb_buffer:
+	usb_free_urb(urb);
+exit_urb:
+	kfree(buf);
+exit:
+	hdpvr_free_buffers(dev);
+	return retval;
+}
+
+static int hdpvr_submit_buffers(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+	int ret = 0, err_count = 0;
+
+	mutex_lock(&dev->io_mutex);
+
+	while (dev->status == STATUS_STREAMING &&
+	       !list_empty(&dev->free_buff_list)) {
+
+		buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer,
+				 buff_list);
+		if (buf->status != BUFSTAT_AVAILABLE) {
+			v4l2_err(&dev->v4l2_dev,
+				 "buffer not marked as available\n");
+			ret = -EFAULT;
+			goto err;
+		}
+
+		urb = buf->urb;
+		urb->status = 0;
+		urb->actual_length = 0;
+		ret = usb_submit_urb(urb, GFP_KERNEL);
+		if (ret) {
+			v4l2_err(&dev->v4l2_dev,
+				 "usb_submit_urb in %s returned %d\n",
+				 __func__, ret);
+			if (++err_count > 2)
+				break;
+			continue;
+		}
+		buf->status = BUFSTAT_INPROGRESS;
+		list_move_tail(&buf->buff_list, &dev->rec_buff_list);
+	}
+err:
+	print_buffer_status();
+	mutex_unlock(&dev->io_mutex);
+	return ret;
+}
+
+static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+
+	mutex_lock(&dev->io_mutex);
+
+	if (list_empty(&dev->rec_buff_list)) {
+		mutex_unlock(&dev->io_mutex);
+		return NULL;
+	}
+
+	buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer,
+			 buff_list);
+	mutex_unlock(&dev->io_mutex);
+
+	return buf;
+}
+
+static void hdpvr_transmit_buffers(struct work_struct *work)
+{
+	struct hdpvr_device *dev = container_of(work, struct hdpvr_device,
+						worker);
+
+	while (dev->status == STATUS_STREAMING) {
+
+		if (hdpvr_submit_buffers(dev)) {
+			v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n");
+			goto error;
+		}
+		if (wait_event_interruptible(dev->wait_buffer,
+				!list_empty(&dev->free_buff_list) ||
+					     dev->status != STATUS_STREAMING))
+			goto error;
+	}
+
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "transmit worker exited\n");
+	return;
+error:
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "transmit buffers errored\n");
+	dev->status = STATUS_ERROR;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_start_streaming(struct hdpvr_device *dev)
+{
+	int ret;
+	struct hdpvr_video_info vidinf;
+
+	if (dev->status == STATUS_STREAMING)
+		return 0;
+	if (dev->status != STATUS_IDLE)
+		return -EAGAIN;
+
+	ret = get_video_info(dev, &vidinf);
+	if (ret < 0)
+		return ret;
+
+	if (!vidinf.valid) {
+		msleep(250);
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+				"no video signal at input %d\n", dev->options.video_input);
+		return -EAGAIN;
+	}
+
+	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			"video signal: %dx%d@%dhz\n", vidinf.width,
+			vidinf.height, vidinf.fps);
+
+	/* start streaming 2 request */
+	ret = usb_control_msg(dev->udev,
+			usb_sndctrlpipe(dev->udev, 0),
+			0xb8, 0x38, 0x1, 0, NULL, 0, 8000);
+	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			"encoder start control request returned %d\n", ret);
+	if (ret < 0)
+		return ret;
+
+	ret = hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00);
+	if (ret)
+		return ret;
+
+	dev->status = STATUS_STREAMING;
+
+	INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
+	schedule_work(&dev->worker);
+
+	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			"streaming started\n");
+
+	return 0;
+}
+
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_stop_streaming(struct hdpvr_device *dev)
+{
+	int actual_length;
+	uint c = 0;
+	u8 *buf;
+
+	if (dev->status == STATUS_IDLE)
+		return 0;
+	else if (dev->status != STATUS_STREAMING)
+		return -EAGAIN;
+
+	buf = kmalloc(dev->bulk_in_size, GFP_KERNEL);
+	if (!buf)
+		v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer for emptying the internal device buffer. Next capture start will be slow\n");
+
+	dev->status = STATUS_SHUTTING_DOWN;
+	hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00);
+	mutex_unlock(&dev->io_mutex);
+
+	wake_up_interruptible(&dev->wait_buffer);
+	msleep(50);
+
+	flush_work(&dev->worker);
+
+	mutex_lock(&dev->io_mutex);
+	/* kill the still outstanding urbs */
+	hdpvr_cancel_queue(dev);
+
+	/* emptying the device buffer beforeshutting it down */
+	while (buf && ++c < 500 &&
+	       !usb_bulk_msg(dev->udev,
+			     usb_rcvbulkpipe(dev->udev,
+					     dev->bulk_in_endpointAddr),
+			     buf, dev->bulk_in_size, &actual_length,
+			     BULK_URB_TIMEOUT)) {
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			 "%2d: got %d bytes\n", c, actual_length);
+	}
+	kfree(buf);
+	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+		 "used %d urbs to empty device buffers\n", c-1);
+	msleep(10);
+
+	dev->status = STATUS_IDLE;
+
+	return 0;
+}
+
+
+/*=======================================================================*/
+/*
+ * video 4 linux 2 file operations
+ */
+
+static int hdpvr_open(struct file *file)
+{
+	struct hdpvr_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+
+	if (fh == NULL)
+		return -ENOMEM;
+	fh->legacy_mode = true;
+	v4l2_fh_init(&fh->fh, video_devdata(file));
+	v4l2_fh_add(&fh->fh);
+	file->private_data = fh;
+	return 0;
+}
+
+static int hdpvr_release(struct file *file)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+
+	mutex_lock(&dev->io_mutex);
+	if (file->private_data == dev->owner) {
+		hdpvr_stop_streaming(dev);
+		dev->owner = NULL;
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	return v4l2_fh_release(file);
+}
+
+/*
+ * hdpvr_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
+			  loff_t *pos)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_buffer *buf = NULL;
+	struct urb *urb;
+	unsigned int ret = 0;
+	int rem, cnt;
+
+	if (*pos)
+		return -ESPIPE;
+
+	mutex_lock(&dev->io_mutex);
+	if (dev->status == STATUS_IDLE) {
+		if (hdpvr_start_streaming(dev)) {
+			v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+				 "start_streaming failed\n");
+			ret = -EIO;
+			msleep(200);
+			dev->status = STATUS_IDLE;
+			mutex_unlock(&dev->io_mutex);
+			goto err;
+		}
+		dev->owner = file->private_data;
+		print_buffer_status();
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	/* wait for the first buffer */
+	if (!(file->f_flags & O_NONBLOCK)) {
+		if (wait_event_interruptible(dev->wait_data,
+					     hdpvr_get_next_buffer(dev)))
+			return -ERESTARTSYS;
+	}
+
+	buf = hdpvr_get_next_buffer(dev);
+
+	while (count > 0 && buf) {
+
+		if (buf->status != BUFSTAT_READY &&
+		    dev->status != STATUS_DISCONNECTED) {
+			int err;
+			/* return nonblocking */
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				goto err;
+			}
+
+			err = wait_event_interruptible_timeout(dev->wait_data,
+				buf->status == BUFSTAT_READY,
+				msecs_to_jiffies(1000));
+			if (err < 0) {
+				ret = err;
+				goto err;
+			}
+			if (!err) {
+				v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+					"timeout: restart streaming\n");
+				hdpvr_stop_streaming(dev);
+				msecs_to_jiffies(4000);
+				err = hdpvr_start_streaming(dev);
+				if (err) {
+					ret = err;
+					goto err;
+				}
+			}
+		}
+
+		if (buf->status != BUFSTAT_READY)
+			break;
+
+		/* set remaining bytes to copy */
+		urb = buf->urb;
+		rem = urb->actual_length - buf->pos;
+		cnt = rem > count ? count : rem;
+
+		if (copy_to_user(buffer, urb->transfer_buffer + buf->pos,
+				 cnt)) {
+			v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n");
+			if (!ret)
+				ret = -EFAULT;
+			goto err;
+		}
+
+		buf->pos += cnt;
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+
+		/* finished, take next buffer */
+		if (buf->pos == urb->actual_length) {
+			mutex_lock(&dev->io_mutex);
+			buf->pos = 0;
+			buf->status = BUFSTAT_AVAILABLE;
+
+			list_move_tail(&buf->buff_list, &dev->free_buff_list);
+
+			print_buffer_status();
+
+			mutex_unlock(&dev->io_mutex);
+
+			wake_up_interruptible(&dev->wait_buffer);
+
+			buf = hdpvr_get_next_buffer(dev);
+		}
+	}
+err:
+	if (!ret && !buf)
+		ret = -EAGAIN;
+	return ret;
+}
+
+static __poll_t hdpvr_poll(struct file *filp, poll_table *wait)
+{
+	__poll_t req_events = poll_requested_events(wait);
+	struct hdpvr_buffer *buf = NULL;
+	struct hdpvr_device *dev = video_drvdata(filp);
+	__poll_t mask = v4l2_ctrl_poll(filp, wait);
+
+	if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
+		return mask;
+
+	mutex_lock(&dev->io_mutex);
+
+	if (dev->status == STATUS_IDLE) {
+		if (hdpvr_start_streaming(dev)) {
+			v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+				 "start_streaming failed\n");
+			dev->status = STATUS_IDLE;
+		} else {
+			dev->owner = filp->private_data;
+		}
+
+		print_buffer_status();
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	buf = hdpvr_get_next_buffer(dev);
+	/* only wait if no data is available */
+	if (!buf || buf->status != BUFSTAT_READY) {
+		poll_wait(filp, &dev->wait_data, wait);
+		buf = hdpvr_get_next_buffer(dev);
+	}
+	if (buf && buf->status == BUFSTAT_READY)
+		mask |= EPOLLIN | EPOLLRDNORM;
+
+	return mask;
+}
+
+
+static const struct v4l2_file_operations hdpvr_fops = {
+	.owner		= THIS_MODULE,
+	.open		= hdpvr_open,
+	.release	= hdpvr_release,
+	.read		= hdpvr_read,
+	.poll		= hdpvr_poll,
+	.unlocked_ioctl	= video_ioctl2,
+};
+
+/*=======================================================================*/
+/*
+ * V4L2 ioctl handling
+ */
+
+static int vidioc_querycap(struct file *file, void  *priv,
+			   struct v4l2_capability *cap)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+
+	strcpy(cap->driver, "hdpvr");
+	strcpy(cap->card, "Hauppauge HD PVR");
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO |
+			    V4L2_CAP_READWRITE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *_fh,
+			v4l2_std_id std)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+	u8 std_type = 1;
+
+	if (!fh->legacy_mode && dev->options.video_input == HDPVR_COMPONENT)
+		return -ENODATA;
+	if (dev->status != STATUS_IDLE)
+		return -EBUSY;
+	if (std & V4L2_STD_525_60)
+		std_type = 0;
+	dev->cur_std = std;
+	dev->width = 720;
+	dev->height = std_type ? 576 : 480;
+
+	return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type);
+}
+
+static int vidioc_g_std(struct file *file, void *_fh,
+			v4l2_std_id *std)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+
+	if (!fh->legacy_mode && dev->options.video_input == HDPVR_COMPONENT)
+		return -ENODATA;
+	*std = dev->cur_std;
+	return 0;
+}
+
+static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_video_info vid_info;
+	struct hdpvr_fh *fh = _fh;
+	int ret;
+
+	*a = V4L2_STD_UNKNOWN;
+	if (dev->options.video_input == HDPVR_COMPONENT)
+		return fh->legacy_mode ? 0 : -ENODATA;
+	ret = get_video_info(dev, &vid_info);
+	if (vid_info.valid && vid_info.width == 720 &&
+	    (vid_info.height == 480 || vid_info.height == 576)) {
+		*a = (vid_info.height == 480) ?
+			V4L2_STD_525_60 : V4L2_STD_625_50;
+	}
+	return ret;
+}
+
+static int vidioc_s_dv_timings(struct file *file, void *_fh,
+				    struct v4l2_dv_timings *timings)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+	int i;
+
+	fh->legacy_mode = false;
+	if (dev->options.video_input)
+		return -ENODATA;
+	if (dev->status != STATUS_IDLE)
+		return -EBUSY;
+	for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++)
+		if (v4l2_match_dv_timings(timings, hdpvr_dv_timings + i, 0, false))
+			break;
+	if (i == ARRAY_SIZE(hdpvr_dv_timings))
+		return -EINVAL;
+	dev->cur_dv_timings = hdpvr_dv_timings[i];
+	dev->width = hdpvr_dv_timings[i].bt.width;
+	dev->height = hdpvr_dv_timings[i].bt.height;
+	return 0;
+}
+
+static int vidioc_g_dv_timings(struct file *file, void *_fh,
+				    struct v4l2_dv_timings *timings)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+
+	fh->legacy_mode = false;
+	if (dev->options.video_input)
+		return -ENODATA;
+	*timings = dev->cur_dv_timings;
+	return 0;
+}
+
+static int vidioc_query_dv_timings(struct file *file, void *_fh,
+				    struct v4l2_dv_timings *timings)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+	struct hdpvr_video_info vid_info;
+	bool interlaced;
+	int ret = 0;
+	int i;
+
+	fh->legacy_mode = false;
+	if (dev->options.video_input)
+		return -ENODATA;
+	ret = get_video_info(dev, &vid_info);
+	if (ret)
+		return ret;
+	if (!vid_info.valid)
+		return -ENOLCK;
+	interlaced = vid_info.fps <= 30;
+	for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) {
+		const struct v4l2_bt_timings *bt = &hdpvr_dv_timings[i].bt;
+		unsigned hsize;
+		unsigned vsize;
+		unsigned fps;
+
+		hsize = V4L2_DV_BT_FRAME_WIDTH(bt);
+		vsize = V4L2_DV_BT_FRAME_HEIGHT(bt);
+		fps = (unsigned)bt->pixelclock / (hsize * vsize);
+		if (bt->width != vid_info.width ||
+		    bt->height != vid_info.height ||
+		    bt->interlaced != interlaced ||
+		    (fps != vid_info.fps && fps + 1 != vid_info.fps))
+			continue;
+		*timings = hdpvr_dv_timings[i];
+		break;
+	}
+	if (i == ARRAY_SIZE(hdpvr_dv_timings))
+		ret = -ERANGE;
+
+	return ret;
+}
+
+static int vidioc_enum_dv_timings(struct file *file, void *_fh,
+				    struct v4l2_enum_dv_timings *timings)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+
+	fh->legacy_mode = false;
+	memset(timings->reserved, 0, sizeof(timings->reserved));
+	if (dev->options.video_input)
+		return -ENODATA;
+	if (timings->index >= ARRAY_SIZE(hdpvr_dv_timings))
+		return -EINVAL;
+	timings->timings = hdpvr_dv_timings[timings->index];
+	return 0;
+}
+
+static int vidioc_dv_timings_cap(struct file *file, void *_fh,
+				    struct v4l2_dv_timings_cap *cap)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+
+	fh->legacy_mode = false;
+	if (dev->options.video_input)
+		return -ENODATA;
+	cap->type = V4L2_DV_BT_656_1120;
+	cap->bt.min_width = 720;
+	cap->bt.max_width = 1920;
+	cap->bt.min_height = 480;
+	cap->bt.max_height = 1080;
+	cap->bt.min_pixelclock = 27000000;
+	cap->bt.max_pixelclock = 74250000;
+	cap->bt.standards = V4L2_DV_BT_STD_CEA861;
+	cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE;
+	return 0;
+}
+
+static const char *iname[] = {
+	[HDPVR_COMPONENT] = "Component",
+	[HDPVR_SVIDEO]    = "S-Video",
+	[HDPVR_COMPOSITE] = "Composite",
+};
+
+static int vidioc_enum_input(struct file *file, void *_fh, struct v4l2_input *i)
+{
+	unsigned int n;
+
+	n = i->index;
+	if (n >= HDPVR_VIDEO_INPUTS)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+
+	strncpy(i->name, iname[n], sizeof(i->name) - 1);
+	i->name[sizeof(i->name) - 1] = '\0';
+
+	i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF;
+
+	i->capabilities = n ? V4L2_IN_CAP_STD : V4L2_IN_CAP_DV_TIMINGS;
+	i->std = n ? V4L2_STD_ALL : 0;
+
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *_fh,
+			  unsigned int index)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	int retval;
+
+	if (index >= HDPVR_VIDEO_INPUTS)
+		return -EINVAL;
+
+	if (dev->status != STATUS_IDLE)
+		return -EBUSY;
+
+	retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1);
+	if (!retval) {
+		dev->options.video_input = index;
+		/*
+		 * Unfortunately gstreamer calls ENUMSTD and bails out if it
+		 * won't find any formats, even though component input is
+		 * selected. This means that we have to leave tvnorms at
+		 * V4L2_STD_ALL. We cannot use the 'legacy' trick since
+		 * tvnorms is set at the device node level and not at the
+		 * filehandle level.
+		 *
+		 * Comment this out for now, but if the legacy mode can be
+		 * removed in the future, then this code should be enabled
+		 * again.
+		dev->video_dev.tvnorms =
+			(index != HDPVR_COMPONENT) ? V4L2_STD_ALL : 0;
+		 */
+	}
+
+	return retval;
+}
+
+static int vidioc_g_input(struct file *file, void *private_data,
+			  unsigned int *index)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+
+	*index = dev->options.video_input;
+	return 0;
+}
+
+
+static const char *audio_iname[] = {
+	[HDPVR_RCA_FRONT] = "RCA front",
+	[HDPVR_RCA_BACK]  = "RCA back",
+	[HDPVR_SPDIF]     = "SPDIF",
+};
+
+static int vidioc_enumaudio(struct file *file, void *priv,
+				struct v4l2_audio *audio)
+{
+	unsigned int n;
+
+	n = audio->index;
+	if (n >= HDPVR_AUDIO_INPUTS)
+		return -EINVAL;
+
+	audio->capability = V4L2_AUDCAP_STEREO;
+
+	strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1);
+	audio->name[sizeof(audio->name) - 1] = '\0';
+
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *private_data,
+			  const struct v4l2_audio *audio)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	int retval;
+
+	if (audio->index >= HDPVR_AUDIO_INPUTS)
+		return -EINVAL;
+
+	if (dev->status != STATUS_IDLE)
+		return -EBUSY;
+
+	retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec);
+	if (!retval)
+		dev->options.audio_input = audio->index;
+
+	return retval;
+}
+
+static int vidioc_g_audio(struct file *file, void *private_data,
+			  struct v4l2_audio *audio)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+
+	audio->index = dev->options.audio_input;
+	audio->capability = V4L2_AUDCAP_STEREO;
+	strlcpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
+	audio->name[sizeof(audio->name) - 1] = '\0';
+	return 0;
+}
+
+static int hdpvr_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct hdpvr_device *dev =
+		container_of(ctrl->handler, struct hdpvr_device, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+		    dev->video_bitrate->val >= dev->video_bitrate_peak->val)
+			dev->video_bitrate_peak->val =
+					dev->video_bitrate->val + 100000;
+		break;
+	}
+	return 0;
+}
+
+static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct hdpvr_device *dev =
+		container_of(ctrl->handler, struct hdpvr_device, hdl);
+	struct hdpvr_options *opt = &dev->options;
+	int ret = -EINVAL;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ret = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->val);
+		if (ret)
+			break;
+		dev->options.brightness = ctrl->val;
+		return 0;
+	case V4L2_CID_CONTRAST:
+		ret = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->val);
+		if (ret)
+			break;
+		dev->options.contrast = ctrl->val;
+		return 0;
+	case V4L2_CID_SATURATION:
+		ret = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->val);
+		if (ret)
+			break;
+		dev->options.saturation = ctrl->val;
+		return 0;
+	case V4L2_CID_HUE:
+		ret = hdpvr_config_call(dev, CTRL_HUE, ctrl->val);
+		if (ret)
+			break;
+		dev->options.hue = ctrl->val;
+		return 0;
+	case V4L2_CID_SHARPNESS:
+		ret = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->val);
+		if (ret)
+			break;
+		dev->options.sharpness = ctrl->val;
+		return 0;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+			opt->audio_codec = ctrl->val;
+			return hdpvr_set_audio(dev, opt->audio_input + 1,
+					      opt->audio_codec);
+		}
+		return 0;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		return 0;
+/*	case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/*		if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */
+/*			opt->gop_mode |= 0x2; */
+/*			hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/*					  opt->gop_mode); */
+/*		} */
+/*		if (ctrl->value == 128 && opt->gop_mode & 0x2) { */
+/*			opt->gop_mode &= ~0x2; */
+/*			hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/*					  opt->gop_mode); */
+/*		} */
+/*		break; */
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
+		uint peak_bitrate = dev->video_bitrate_peak->val / 100000;
+		uint bitrate = dev->video_bitrate->val / 100000;
+
+		if (ctrl->is_new) {
+			if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+				opt->bitrate_mode = HDPVR_CONSTANT;
+			else
+				opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE;
+			hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+					  opt->bitrate_mode);
+			v4l2_ctrl_activate(dev->video_bitrate_peak,
+				ctrl->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+		}
+
+		if (dev->video_bitrate_peak->is_new ||
+		    dev->video_bitrate->is_new) {
+			opt->bitrate = bitrate;
+			opt->peak_bitrate = peak_bitrate;
+			hdpvr_set_bitrate(dev);
+		}
+		return 0;
+	}
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return 0;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
+				    struct v4l2_fmtdesc *f)
+{
+	if (f->index != 0)
+		return -EINVAL;
+
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+	strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32);
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
+				struct v4l2_format *f)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+	struct hdpvr_fh *fh = _fh;
+	int ret;
+
+	/*
+	 * The original driver would always returns the current detected
+	 * resolution as the format (and EFAULT if it couldn't be detected).
+	 * With the introduction of VIDIOC_QUERY_DV_TIMINGS there is now a
+	 * better way of doing this, but to stay compatible with existing
+	 * applications we assume legacy mode every time an application opens
+	 * the device. Only if one of the new DV_TIMINGS ioctls is called
+	 * will the filehandle go into 'normal' mode where g_fmt returns the
+	 * last set format.
+	 */
+	if (fh->legacy_mode) {
+		struct hdpvr_video_info vid_info;
+
+		ret = get_video_info(dev, &vid_info);
+		if (ret < 0)
+			return ret;
+		if (!vid_info.valid)
+			return -EFAULT;
+		f->fmt.pix.width = vid_info.width;
+		f->fmt.pix.height = vid_info.height;
+	} else {
+		f->fmt.pix.width = dev->width;
+		f->fmt.pix.height = dev->height;
+	}
+	f->fmt.pix.pixelformat	= V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.sizeimage	= dev->bulk_in_size;
+	f->fmt.pix.bytesperline	= 0;
+	if (f->fmt.pix.width == 720) {
+		/* SDTV formats */
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+		f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	} else {
+		/* HDTV formats */
+		f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+	}
+	return 0;
+}
+
+static int vidioc_encoder_cmd(struct file *filp, void *priv,
+			       struct v4l2_encoder_cmd *a)
+{
+	struct hdpvr_device *dev = video_drvdata(filp);
+	int res = 0;
+
+	mutex_lock(&dev->io_mutex);
+	a->flags = 0;
+
+	switch (a->cmd) {
+	case V4L2_ENC_CMD_START:
+		if (dev->owner && filp->private_data != dev->owner) {
+			res = -EBUSY;
+			break;
+		}
+		if (dev->status == STATUS_STREAMING)
+			break;
+		res = hdpvr_start_streaming(dev);
+		if (!res)
+			dev->owner = filp->private_data;
+		else
+			dev->status = STATUS_IDLE;
+		break;
+	case V4L2_ENC_CMD_STOP:
+		if (dev->owner && filp->private_data != dev->owner) {
+			res = -EBUSY;
+			break;
+		}
+		if (dev->status == STATUS_IDLE)
+			break;
+		res = hdpvr_stop_streaming(dev);
+		if (!res)
+			dev->owner = NULL;
+		break;
+	default:
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "Unsupported encoder cmd %d\n", a->cmd);
+		res = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&dev->io_mutex);
+	return res;
+}
+
+static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
+					struct v4l2_encoder_cmd *a)
+{
+	a->flags = 0;
+	switch (a->cmd) {
+	case V4L2_ENC_CMD_START:
+	case V4L2_ENC_CMD_STOP:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
+	.vidioc_querycap	= vidioc_querycap,
+	.vidioc_s_std		= vidioc_s_std,
+	.vidioc_g_std		= vidioc_g_std,
+	.vidioc_querystd	= vidioc_querystd,
+	.vidioc_s_dv_timings	= vidioc_s_dv_timings,
+	.vidioc_g_dv_timings	= vidioc_g_dv_timings,
+	.vidioc_query_dv_timings= vidioc_query_dv_timings,
+	.vidioc_enum_dv_timings	= vidioc_enum_dv_timings,
+	.vidioc_dv_timings_cap	= vidioc_dv_timings_cap,
+	.vidioc_enum_input	= vidioc_enum_input,
+	.vidioc_g_input		= vidioc_g_input,
+	.vidioc_s_input		= vidioc_s_input,
+	.vidioc_enumaudio	= vidioc_enumaudio,
+	.vidioc_g_audio		= vidioc_g_audio,
+	.vidioc_s_audio		= vidioc_s_audio,
+	.vidioc_enum_fmt_vid_cap= vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
+	.vidioc_encoder_cmd	= vidioc_encoder_cmd,
+	.vidioc_try_encoder_cmd	= vidioc_try_encoder_cmd,
+	.vidioc_log_status	= v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static void hdpvr_device_release(struct video_device *vdev)
+{
+	struct hdpvr_device *dev = video_get_drvdata(vdev);
+
+	hdpvr_delete(dev);
+	mutex_lock(&dev->io_mutex);
+	flush_work(&dev->worker);
+	mutex_unlock(&dev->io_mutex);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	v4l2_ctrl_handler_free(&dev->hdl);
+
+	/* deregister I2C adapter */
+#if IS_ENABLED(CONFIG_I2C)
+	mutex_lock(&dev->i2c_mutex);
+	i2c_del_adapter(&dev->i2c_adapter);
+	mutex_unlock(&dev->i2c_mutex);
+#endif /* CONFIG_I2C */
+
+	kfree(dev->usbc_buf);
+	kfree(dev);
+}
+
+static const struct video_device hdpvr_video_template = {
+	.fops			= &hdpvr_fops,
+	.release		= hdpvr_device_release,
+	.ioctl_ops		= &hdpvr_ioctl_ops,
+	.tvnorms		= V4L2_STD_ALL,
+};
+
+static const struct v4l2_ctrl_ops hdpvr_ctrl_ops = {
+	.try_ctrl = hdpvr_try_ctrl,
+	.s_ctrl = hdpvr_s_ctrl,
+};
+
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+			    int devnum)
+{
+	struct v4l2_ctrl_handler *hdl = &dev->hdl;
+	bool ac3 = dev->flags & HDPVR_FLAG_AC3_CAP;
+	int res;
+
+	dev->cur_std = V4L2_STD_525_60;
+	dev->width = 720;
+	dev->height = 480;
+	dev->cur_dv_timings = hdpvr_dv_timings[HDPVR_DEF_DV_TIMINGS_IDX];
+	v4l2_ctrl_handler_init(hdl, 11);
+	if (dev->fw_ver > 0x15) {
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x80);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x40);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x40);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_HUE, 0x0, 0x1e, 1, 0xf);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80);
+	} else {
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0x0, 0xff, 1, 0x86);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_CONTRAST, 0x0, 0xff, 1, 0x80);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_SATURATION, 0x0, 0xff, 1, 0x80);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_HUE, 0x0, 0xff, 1, 0x80);
+		v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+			V4L2_CID_SHARPNESS, 0x0, 0xff, 1, 0x80);
+	}
+
+	v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_STREAM_TYPE,
+		V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+		0x1, V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
+	v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_AUDIO_ENCODING,
+		ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC,
+		0x7, ac3 ? dev->options.audio_codec : V4L2_MPEG_AUDIO_ENCODING_AAC);
+	v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_ENCODING,
+		V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3,
+		V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
+
+	dev->video_mode = v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+		V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+
+	dev->video_bitrate = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE,
+		1000000, 13500000, 100000, 6500000);
+	dev->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &hdpvr_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+		1100000, 20200000, 100000, 9000000);
+	dev->v4l2_dev.ctrl_handler = hdl;
+	if (hdl->error) {
+		res = hdl->error;
+		v4l2_err(&dev->v4l2_dev, "Could not register controls\n");
+		goto error;
+	}
+	v4l2_ctrl_cluster(3, &dev->video_mode);
+	res = v4l2_ctrl_handler_setup(hdl);
+	if (res < 0) {
+		v4l2_err(&dev->v4l2_dev, "Could not setup controls\n");
+		goto error;
+	}
+
+	/* setup and register video device */
+	dev->video_dev = hdpvr_video_template;
+	strcpy(dev->video_dev.name, "Hauppauge HD PVR");
+	dev->video_dev.v4l2_dev = &dev->v4l2_dev;
+	video_set_drvdata(&dev->video_dev, dev);
+
+	res = video_register_device(&dev->video_dev, VFL_TYPE_GRABBER, devnum);
+	if (res < 0) {
+		v4l2_err(&dev->v4l2_dev, "video_device registration failed\n");
+		goto error;
+	}
+
+	return 0;
+error:
+	v4l2_ctrl_handler_free(hdl);
+	return res;
+}
diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h
new file mode 100644
index 0000000..1d65b41
--- /dev/null
+++ b/drivers/media/usb/hdpvr/hdpvr.h
@@ -0,0 +1,328 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/i2c/ir-kbd-i2c.h>
+
+#define HDPVR_MAX 8
+#define HDPVR_I2C_MAX_SIZE 128
+
+/* Define these values to match your devices */
+#define HD_PVR_VENDOR_ID	0x2040
+#define HD_PVR_PRODUCT_ID	0x4900
+#define HD_PVR_PRODUCT_ID1	0x4901
+#define HD_PVR_PRODUCT_ID2	0x4902
+#define HD_PVR_PRODUCT_ID4	0x4903
+#define HD_PVR_PRODUCT_ID3	0x4982
+
+#define UNSET    (-1U)
+
+#define NUM_BUFFERS 64
+
+#define HDPVR_FIRMWARE_VERSION		0x08
+#define HDPVR_FIRMWARE_VERSION_AC3	0x0d
+#define HDPVR_FIRMWARE_VERSION_0X12	0x12
+#define HDPVR_FIRMWARE_VERSION_0X15	0x15
+#define HDPVR_FIRMWARE_VERSION_0X1E	0x1e
+
+/* #define HDPVR_DEBUG */
+
+extern int hdpvr_debug;
+
+#define MSG_INFO	1
+#define MSG_BUFFER	2
+
+struct hdpvr_options {
+	u8	video_std;
+	u8	video_input;
+	u8	audio_input;
+	u8	bitrate;	/* in 100kbps */
+	u8	peak_bitrate;	/* in 100kbps */
+	u8	bitrate_mode;
+	u8	gop_mode;
+	enum v4l2_mpeg_audio_encoding	audio_codec;
+	u8	brightness;
+	u8	contrast;
+	u8	hue;
+	u8	saturation;
+	u8	sharpness;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct hdpvr_device {
+	/* the v4l device for this device */
+	struct video_device	video_dev;
+	/* the control handler for this device */
+	struct v4l2_ctrl_handler hdl;
+	/* the usb device for this device */
+	struct usb_device	*udev;
+	/* v4l2-device unused */
+	struct v4l2_device	v4l2_dev;
+	struct { /* video mode/bitrate control cluster */
+		struct v4l2_ctrl *video_mode;
+		struct v4l2_ctrl *video_bitrate;
+		struct v4l2_ctrl *video_bitrate_peak;
+	};
+	/* v4l2 format */
+	uint width, height;
+
+	/* the max packet size of the bulk endpoint */
+	size_t			bulk_in_size;
+	/* the address of the bulk in endpoint */
+	__u8			bulk_in_endpointAddr;
+
+	/* holds the current device status */
+	__u8			status;
+
+	/* holds the current set options */
+	struct hdpvr_options	options;
+	v4l2_std_id		cur_std;
+	struct v4l2_dv_timings	cur_dv_timings;
+
+	uint			flags;
+
+	/* synchronize I/O */
+	struct mutex		io_mutex;
+	/* available buffers */
+	struct list_head	free_buff_list;
+	/* in progress buffers */
+	struct list_head	rec_buff_list;
+	/* waitqueue for buffers */
+	wait_queue_head_t	wait_buffer;
+	/* waitqueue for data */
+	wait_queue_head_t	wait_data;
+	/**/
+	struct work_struct	worker;
+	/* current stream owner */
+	struct v4l2_fh		*owner;
+
+	/* I2C adapter */
+	struct i2c_adapter	i2c_adapter;
+	/* I2C lock */
+	struct mutex		i2c_mutex;
+	/* I2C message buffer space */
+	char			i2c_buf[HDPVR_I2C_MAX_SIZE];
+
+	/* For passing data to ir-kbd-i2c */
+	struct IR_i2c_init_data	ir_i2c_init_data;
+
+	/* usb control transfer buffer and lock */
+	struct mutex		usbc_mutex;
+	u8			*usbc_buf;
+	u8			fw_ver;
+};
+
+static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev);
+}
+
+
+/* buffer one bulk urb of data */
+struct hdpvr_buffer {
+	struct list_head	buff_list;
+
+	struct urb		*urb;
+
+	struct hdpvr_device	*dev;
+
+	uint			pos;
+
+	__u8			status;
+};
+
+/* */
+
+struct hdpvr_video_info {
+	u16	width;
+	u16	height;
+	u8	fps;
+	bool	valid;
+};
+
+enum {
+	STATUS_UNINITIALIZED	= 0,
+	STATUS_IDLE,
+	STATUS_STARTING,
+	STATUS_SHUTTING_DOWN,
+	STATUS_STREAMING,
+	STATUS_ERROR,
+	STATUS_DISCONNECTED,
+};
+
+enum {
+	HDPVR_FLAG_AC3_CAP = 1,
+};
+
+enum {
+	BUFSTAT_UNINITIALIZED = 0,
+	BUFSTAT_AVAILABLE,
+	BUFSTAT_INPROGRESS,
+	BUFSTAT_READY,
+};
+
+#define CTRL_START_STREAMING_VALUE	0x0700
+#define CTRL_STOP_STREAMING_VALUE	0x0800
+#define CTRL_BITRATE_VALUE		0x1000
+#define CTRL_BITRATE_MODE_VALUE		0x1200
+#define CTRL_GOP_MODE_VALUE		0x1300
+#define CTRL_VIDEO_INPUT_VALUE		0x1500
+#define CTRL_VIDEO_STD_TYPE		0x1700
+#define CTRL_AUDIO_INPUT_VALUE		0x2500
+#define CTRL_BRIGHTNESS			0x2900
+#define CTRL_CONTRAST			0x2a00
+#define CTRL_HUE			0x2b00
+#define CTRL_SATURATION			0x2c00
+#define CTRL_SHARPNESS			0x2d00
+#define CTRL_LOW_PASS_FILTER_VALUE	0x3100
+
+#define CTRL_DEFAULT_INDEX		0x0003
+
+
+	/* :0 s 38 01 1000 0003 0004 4 = 0a00ca00
+	 * BITRATE SETTING
+	 *   1st and 2nd byte (little endian): average bitrate in 100 000 bit/s
+	 *                                     min: 1 mbit/s, max: 13.5 mbit/s
+	 *   3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s
+	 *                                     min: average + 100kbit/s,
+	 *                                      max: 20.2 mbit/s
+	 */
+
+	/* :0 s 38 01 1200 0003 0001 1 = 02
+	 * BIT RATE MODE
+	 *  constant = 1, variable (peak) = 2, variable (average) = 3
+	 */
+
+	/* :0 s 38 01 1300 0003 0001 1 = 03
+	 * GOP MODE (2 bit)
+	 *    low bit 0/1: advanced/simple GOP
+	 *   high bit 0/1: IDR(4/32/128) / no IDR (4/32/0)
+	 */
+
+	/* :0 s 38 01 1700 0003 0001 1 = 00
+	 * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz
+	 */
+
+	/* :0 s 38 01 3100 0003 0004 4 = 03030000
+	 * FILTER CONTROL
+	 *   1st byte luma low pass filter strength,
+	 *   2nd byte chroma low pass filter strength,
+	 *   3rd byte MF enable chroma, min=0, max=1
+	 *   4th byte n
+	 */
+
+
+	/* :0 s 38 b9 0001 0000 0000 0 */
+
+
+
+/* :0 s 38 d3 0000 0000 0001 1 = 00 */
+/*		ret = usb_control_msg(dev->udev, */
+/*				      usb_sndctrlpipe(dev->udev, 0), */
+/*				      0xd3, 0x38, */
+/*				      0, 0, */
+/*				      "\0", 1, */
+/*				      1000); */
+
+/*		info("control request returned %d", ret); */
+/*		msleep(5000); */
+
+
+	/* :0 s b8 81 1400 0003 0005 5 <
+	 * :0 0 5 = d0024002 19
+	 * QUERY FRAME SIZE AND RATE
+	 *   1st and 2nd byte (little endian): horizontal resolution
+	 *   3rd and 4th byte (little endian): vertical resolution
+	 *   5th byte: frame rate
+	 */
+
+	/* :0 s b8 81 1800 0003 0003 3 <
+	 * :0 0 3 = 030104
+	 * QUERY SIGNAL AND DETECTED LINES, maybe INPUT
+	 */
+
+enum hdpvr_video_std {
+	HDPVR_60HZ = 0,
+	HDPVR_50HZ,
+};
+
+enum hdpvr_video_input {
+	HDPVR_COMPONENT = 0,
+	HDPVR_SVIDEO,
+	HDPVR_COMPOSITE,
+	HDPVR_VIDEO_INPUTS
+};
+
+enum hdpvr_audio_inputs {
+	HDPVR_RCA_BACK = 0,
+	HDPVR_RCA_FRONT,
+	HDPVR_SPDIF,
+	HDPVR_AUDIO_INPUTS
+};
+
+enum hdpvr_bitrate_mode {
+	HDPVR_CONSTANT = 1,
+	HDPVR_VARIABLE_PEAK,
+	HDPVR_VARIABLE_AVERAGE,
+};
+
+enum hdpvr_gop_mode {
+	HDPVR_ADVANCED_IDR_GOP = 0,
+	HDPVR_SIMPLE_IDR_GOP,
+	HDPVR_ADVANCED_NOIDR_GOP,
+	HDPVR_SIMPLE_NOIDR_GOP,
+};
+
+void hdpvr_delete(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* hardware control functions */
+int hdpvr_set_options(struct hdpvr_device *dev);
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev);
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+		    enum v4l2_mpeg_audio_encoding codec);
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value,
+		      unsigned char valbuf);
+
+int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vid_info);
+
+/* :0 s b8 81 1800 0003 0003 3 < */
+/* :0 0 3 = 0301ff */
+int get_input_lines_info(struct hdpvr_device *dev);
+
+
+/*========================================================================*/
+/* v4l2 registration */
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+			    int devnumber);
+
+int hdpvr_cancel_queue(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* i2c adapter registration */
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
+
+struct i2c_client *hdpvr_register_ir_i2c(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* buffer management */
+int hdpvr_free_buffers(struct hdpvr_device *dev);
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count);