From e0adc6a155bb772f75bb7ce705a226d2c758198b Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 18 Mar 2009 22:10:04 +0100 Subject: V4L2 Driver for the Hauppauge HD PVR usb capture device From: Janne Grunau 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. Priority: normal Signed-off-by: Janne Grunau Tested-by: Jarod Wilson --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 201 ++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 linux/drivers/media/video/hdpvr/hdpvr-control.c (limited to 'linux/drivers/media/video/hdpvr/hdpvr-control.c') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c new file mode 100644 index 000000000..ecf02c621 --- /dev/null +++ b/linux/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 +#include +#include +#include +#include +#include +#include + +#include + +#include + +#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; +} -- cgit v1.2.3 From a053ae2d2e29f959bc6fd2ec190963df9a24a48e Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 19 Mar 2009 23:00:35 +0100 Subject: fix mispelled Hauppauge in HD PVR and PVR USB2 driver comments Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers/media/video/hdpvr/hdpvr-control.c') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index ecf02c621..51de74aeb 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -1,5 +1,5 @@ /* - * Hauppage HD PVR USB driver - video 4 linux 2 interface + * Hauppauge HD PVR USB driver - video 4 linux 2 interface * * Copyright (C) 2008 Janne Grunau (j@jannau.net) * -- cgit v1.2.3 From 9cd596ebf1895fbde84391135359f7d7cc401fe4 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 28 Mar 2009 00:09:40 +0100 Subject: hdpvr: convert printing macros to v4l2_* with struct v4l2_device From: Janne Grunau it gives us a nice and unique prefix per device Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux/drivers/media/video/hdpvr/hdpvr-control.c') diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index 51de74aeb..06791749d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -40,9 +40,9 @@ int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) 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); + 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; } @@ -57,7 +57,7 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); if (!vidinf) { - dev_err(&dev->udev->dev, "out of memory"); + v4l2_err(&dev->v4l2_dev, "out of memory\n"); goto err; } @@ -78,8 +78,8 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) 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); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get video info returned: %d, %s\n", ret, print_buf); } #endif mutex_unlock(&dev->usbc_mutex); @@ -111,9 +111,9 @@ int get_input_lines_info(struct hdpvr_device *dev) 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); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "get input lines info returned: %d, %s\n", ret, + print_buf); } #endif lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; @@ -155,8 +155,8 @@ int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, dev->usbc_buf[1] = 1; else { mutex_unlock(&dev->usbc_mutex); - dev_err(&dev->udev->dev, "invalid audio codec %d\n", - codec); + v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", + codec); ret = -EINVAL; goto error; } -- cgit v1.2.3