summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/hdpvr/hdpvr-control.c
diff options
context:
space:
mode:
authorJanne Grunau <j@jannau.net>2009-03-18 18:10:04 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:43:28 -0300
commit9aba42efe85bc7a55e3fed0747ce14abc9ee96e7 (patch)
treeee27b9d4844da17b4d4bb80132991f29d04ff265 /drivers/media/video/hdpvr/hdpvr-control.c
parent8c84cfda3e37540abc38f42383b03dd69829faee (diff)
V4L/DVB (11096): V4L2 Driver for the Hauppauge HD PVR usb capture device
The device encodes component video up to 1080i to a MPEG-TS stream with H.264 video and stereo AAC audio. Newer firmwares accept also AC3 (up to 5.1) audio over optical SPDIF without reencoding. Firmware upgrade is unimplemeted but rather unimportant since the firmware sits on a flash chip. The I2C adapter to drive the integrated infrared receiver/sender is currently disabled due to a conflict with cx18-based devices. Tested-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Janne Grunau <j@jannau.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/hdpvr/hdpvr-control.c')
-rw-r--r--drivers/media/video/hdpvr/hdpvr-control.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c
new file mode 100644
index 00000000000..ecf02c621f1
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-control.c
@@ -0,0 +1,201 @@
+/*
+ * Hauppage 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;
+
+ msleep(10);
+
+ 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);
+ dev_dbg(&dev->udev->dev,
+ "config call request for value 0x%x returned %d\n", value,
+ ret);
+
+ return ret < 0 ? ret : 0;
+}
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
+{
+ struct hdpvr_video_info *vidinf = NULL;
+#ifdef HDPVR_DEBUG
+ char print_buf[15];
+#endif
+ int ret;
+
+ vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
+ if (!vidinf) {
+ dev_err(&dev->udev->dev, "out of memory");
+ goto err;
+ }
+
+ 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);
+ if (ret == 5) {
+ 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];
+ }
+
+#ifdef HDPVR_DEBUG
+ if (hdpvr_debug & MSG_INFO) {
+ hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf,
+ sizeof(print_buf), 0);
+ dev_dbg(&dev->udev->dev, "get video info returned: %d, %s\n",
+ ret, print_buf);
+ }
+#endif
+ mutex_unlock(&dev->usbc_mutex);
+
+ if (!vidinf->width || !vidinf->height || !vidinf->fps) {
+ kfree(vidinf);
+ vidinf = NULL;
+ }
+err:
+ return vidinf;
+}
+
+int get_input_lines_info(struct hdpvr_device *dev)
+{
+#ifdef HDPVR_DEBUG
+ char print_buf[9];
+#endif
+ 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) {
+ hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf,
+ sizeof(print_buf), 0);
+ dev_dbg(&dev->udev->dev,
+ "get input lines info returned: %d, %s\n", ret,
+ print_buf);
+ }
+#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);
+ dev_err(&dev->udev->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,
+ dev->options.audio_input+1);
+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;
+}