diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-13 23:13:22 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 15:25:07 -0400 |
commit | 0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch) | |
tree | e759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/usb/hdpvr | |
parent | 84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff) |
[media] rename most media/video usb drivers to media/usb
Rename all USB drivers with their own directory under
drivers/media/video into drivers/media/usb and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/hdpvr')
-rw-r--r-- | drivers/media/usb/hdpvr/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/Makefile | 7 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-control.c | 200 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-core.c | 472 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-i2c.c | 231 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr-video.c | 1289 | ||||
-rw-r--r-- | drivers/media/usb/hdpvr/hdpvr.h | 317 |
7 files changed, 2526 insertions, 0 deletions
diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig new file mode 100644 index 000000000000..de247f3c7d05 --- /dev/null +++ b/drivers/media/usb/hdpvr/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | |||
2 | config VIDEO_HDPVR | ||
3 | tristate "Hauppauge HD PVR support" | ||
4 | depends on VIDEO_DEV | ||
5 | ---help--- | ||
6 | This is a video4linux driver for Hauppauge's HD PVR USB device. | ||
7 | |||
8 | To compile this driver as a module, choose M here: the | ||
9 | module will be called hdpvr | ||
10 | |||
diff --git a/drivers/media/usb/hdpvr/Makefile b/drivers/media/usb/hdpvr/Makefile new file mode 100644 index 000000000000..52f057f24e39 --- /dev/null +++ b/drivers/media/usb/hdpvr/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o | ||
4 | |||
5 | ccflags-y += -Idrivers/media/video | ||
6 | |||
7 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c new file mode 100644 index 000000000000..ae8f229d1141 --- /dev/null +++ b/drivers/media/usb/hdpvr/hdpvr-control.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * Hauppauge HD PVR USB driver - video 4 linux 2 interface | ||
3 | * | ||
4 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/usb.h> | ||
18 | #include <linux/mutex.h> | ||
19 | |||
20 | #include <linux/videodev2.h> | ||
21 | |||
22 | #include <media/v4l2-common.h> | ||
23 | |||
24 | #include "hdpvr.h" | ||
25 | |||
26 | |||
27 | int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) | ||
28 | { | ||
29 | int ret; | ||
30 | char request_type = 0x38, snd_request = 0x01; | ||
31 | |||
32 | mutex_lock(&dev->usbc_mutex); | ||
33 | dev->usbc_buf[0] = valbuf; | ||
34 | ret = usb_control_msg(dev->udev, | ||
35 | usb_sndctrlpipe(dev->udev, 0), | ||
36 | snd_request, 0x00 | request_type, | ||
37 | value, CTRL_DEFAULT_INDEX, | ||
38 | dev->usbc_buf, 1, 10000); | ||
39 | |||
40 | mutex_unlock(&dev->usbc_mutex); | ||
41 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
42 | "config call request for value 0x%x returned %d\n", value, | ||
43 | ret); | ||
44 | |||
45 | return ret < 0 ? ret : 0; | ||
46 | } | ||
47 | |||
48 | struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) | ||
49 | { | ||
50 | struct hdpvr_video_info *vidinf = NULL; | ||
51 | #ifdef HDPVR_DEBUG | ||
52 | char print_buf[15]; | ||
53 | #endif | ||
54 | int ret; | ||
55 | |||
56 | vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); | ||
57 | if (!vidinf) { | ||
58 | v4l2_err(&dev->v4l2_dev, "out of memory\n"); | ||
59 | goto err; | ||
60 | } | ||
61 | |||
62 | mutex_lock(&dev->usbc_mutex); | ||
63 | ret = usb_control_msg(dev->udev, | ||
64 | usb_rcvctrlpipe(dev->udev, 0), | ||
65 | 0x81, 0x80 | 0x38, | ||
66 | 0x1400, 0x0003, | ||
67 | dev->usbc_buf, 5, | ||
68 | 1000); | ||
69 | if (ret == 5) { | ||
70 | vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; | ||
71 | vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; | ||
72 | vidinf->fps = dev->usbc_buf[4]; | ||
73 | } | ||
74 | |||
75 | #ifdef HDPVR_DEBUG | ||
76 | if (hdpvr_debug & MSG_INFO) { | ||
77 | hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, | ||
78 | sizeof(print_buf), 0); | ||
79 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
80 | "get video info returned: %d, %s\n", ret, print_buf); | ||
81 | } | ||
82 | #endif | ||
83 | mutex_unlock(&dev->usbc_mutex); | ||
84 | |||
85 | if (!vidinf->width || !vidinf->height || !vidinf->fps) { | ||
86 | kfree(vidinf); | ||
87 | vidinf = NULL; | ||
88 | } | ||
89 | err: | ||
90 | return vidinf; | ||
91 | } | ||
92 | |||
93 | int get_input_lines_info(struct hdpvr_device *dev) | ||
94 | { | ||
95 | #ifdef HDPVR_DEBUG | ||
96 | char print_buf[9]; | ||
97 | #endif | ||
98 | int ret, lines; | ||
99 | |||
100 | mutex_lock(&dev->usbc_mutex); | ||
101 | ret = usb_control_msg(dev->udev, | ||
102 | usb_rcvctrlpipe(dev->udev, 0), | ||
103 | 0x81, 0x80 | 0x38, | ||
104 | 0x1800, 0x0003, | ||
105 | dev->usbc_buf, 3, | ||
106 | 1000); | ||
107 | |||
108 | #ifdef HDPVR_DEBUG | ||
109 | if (hdpvr_debug & MSG_INFO) { | ||
110 | hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, | ||
111 | sizeof(print_buf), 0); | ||
112 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
113 | "get input lines info returned: %d, %s\n", ret, | ||
114 | print_buf); | ||
115 | } | ||
116 | #else | ||
117 | (void)ret; /* suppress compiler warning */ | ||
118 | #endif | ||
119 | lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; | ||
120 | mutex_unlock(&dev->usbc_mutex); | ||
121 | return lines; | ||
122 | } | ||
123 | |||
124 | |||
125 | int hdpvr_set_bitrate(struct hdpvr_device *dev) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | mutex_lock(&dev->usbc_mutex); | ||
130 | memset(dev->usbc_buf, 0, 4); | ||
131 | dev->usbc_buf[0] = dev->options.bitrate; | ||
132 | dev->usbc_buf[2] = dev->options.peak_bitrate; | ||
133 | |||
134 | ret = usb_control_msg(dev->udev, | ||
135 | usb_sndctrlpipe(dev->udev, 0), | ||
136 | 0x01, 0x38, CTRL_BITRATE_VALUE, | ||
137 | CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000); | ||
138 | mutex_unlock(&dev->usbc_mutex); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, | ||
144 | enum v4l2_mpeg_audio_encoding codec) | ||
145 | { | ||
146 | int ret = 0; | ||
147 | |||
148 | if (dev->flags & HDPVR_FLAG_AC3_CAP) { | ||
149 | mutex_lock(&dev->usbc_mutex); | ||
150 | memset(dev->usbc_buf, 0, 2); | ||
151 | dev->usbc_buf[0] = input; | ||
152 | if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC) | ||
153 | dev->usbc_buf[1] = 0; | ||
154 | else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3) | ||
155 | dev->usbc_buf[1] = 1; | ||
156 | else { | ||
157 | mutex_unlock(&dev->usbc_mutex); | ||
158 | v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", | ||
159 | codec); | ||
160 | ret = -EINVAL; | ||
161 | goto error; | ||
162 | } | ||
163 | |||
164 | ret = usb_control_msg(dev->udev, | ||
165 | usb_sndctrlpipe(dev->udev, 0), | ||
166 | 0x01, 0x38, CTRL_AUDIO_INPUT_VALUE, | ||
167 | CTRL_DEFAULT_INDEX, dev->usbc_buf, 2, | ||
168 | 1000); | ||
169 | mutex_unlock(&dev->usbc_mutex); | ||
170 | if (ret == 2) | ||
171 | ret = 0; | ||
172 | } else | ||
173 | ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input); | ||
174 | error: | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | int hdpvr_set_options(struct hdpvr_device *dev) | ||
179 | { | ||
180 | hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); | ||
181 | |||
182 | hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, | ||
183 | dev->options.video_input+1); | ||
184 | |||
185 | hdpvr_set_audio(dev, dev->options.audio_input+1, | ||
186 | dev->options.audio_codec); | ||
187 | |||
188 | hdpvr_set_bitrate(dev); | ||
189 | hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, | ||
190 | dev->options.bitrate_mode); | ||
191 | hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); | ||
192 | |||
193 | hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); | ||
194 | hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); | ||
195 | hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); | ||
196 | hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); | ||
197 | hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c new file mode 100644 index 000000000000..304f43ef59eb --- /dev/null +++ b/drivers/media/usb/hdpvr/hdpvr-core.c | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * Hauppauge HD PVR USB driver | ||
3 | * | ||
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
5 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
6 | * Copyright (C) 2008 John Poet | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation, version 2. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/uaccess.h> | ||
20 | #include <linux/atomic.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/i2c.h> | ||
24 | |||
25 | #include <linux/videodev2.h> | ||
26 | #include <media/v4l2-dev.h> | ||
27 | #include <media/v4l2-common.h> | ||
28 | |||
29 | #include "hdpvr.h" | ||
30 | |||
31 | static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET}; | ||
32 | module_param_array(video_nr, int, NULL, 0); | ||
33 | MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); | ||
34 | |||
35 | /* holds the number of currently registered devices */ | ||
36 | static atomic_t dev_nr = ATOMIC_INIT(-1); | ||
37 | |||
38 | int hdpvr_debug; | ||
39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); | ||
40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); | ||
41 | |||
42 | static uint default_video_input = HDPVR_VIDEO_INPUTS; | ||
43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); | ||
44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " | ||
45 | "1=S-Video / 2=Composite"); | ||
46 | |||
47 | static uint default_audio_input = HDPVR_AUDIO_INPUTS; | ||
48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); | ||
49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " | ||
50 | "1=RCA front / 2=S/PDIF"); | ||
51 | |||
52 | static bool boost_audio; | ||
53 | module_param(boost_audio, bool, S_IRUGO|S_IWUSR); | ||
54 | MODULE_PARM_DESC(boost_audio, "boost the audio signal"); | ||
55 | |||
56 | |||
57 | /* table of devices that work with this driver */ | ||
58 | static struct usb_device_id hdpvr_table[] = { | ||
59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, | ||
60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, | ||
61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, | ||
62 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) }, | ||
63 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) }, | ||
64 | { } /* Terminating entry */ | ||
65 | }; | ||
66 | MODULE_DEVICE_TABLE(usb, hdpvr_table); | ||
67 | |||
68 | |||
69 | void hdpvr_delete(struct hdpvr_device *dev) | ||
70 | { | ||
71 | hdpvr_free_buffers(dev); | ||
72 | |||
73 | if (dev->video_dev) | ||
74 | video_device_release(dev->video_dev); | ||
75 | |||
76 | usb_put_dev(dev->udev); | ||
77 | } | ||
78 | |||
79 | static void challenge(u8 *bytes) | ||
80 | { | ||
81 | u64 *i64P, tmp64; | ||
82 | uint i, idx; | ||
83 | |||
84 | for (idx = 0; idx < 32; ++idx) { | ||
85 | |||
86 | if (idx & 0x3) | ||
87 | bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3]; | ||
88 | |||
89 | switch (idx & 0x3) { | ||
90 | case 0x3: | ||
91 | bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5]; | ||
92 | bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9; | ||
93 | break; | ||
94 | case 0x1: | ||
95 | bytes[0] *= 8; | ||
96 | bytes[0] += 7*idx + 4; | ||
97 | bytes[6] += bytes[3] * 3; | ||
98 | break; | ||
99 | case 0x0: | ||
100 | bytes[3 - (idx >> 3)] = bytes[idx >> 2]; | ||
101 | bytes[5] += bytes[6] * 3; | ||
102 | for (i = 0; i < 3; i++) | ||
103 | bytes[3] *= bytes[3] + 1; | ||
104 | break; | ||
105 | case 0x2: | ||
106 | for (i = 0; i < 3; i++) | ||
107 | bytes[1] *= bytes[6] + 1; | ||
108 | for (i = 0; i < 3; i++) { | ||
109 | i64P = (u64 *)bytes; | ||
110 | tmp64 = le64_to_cpup(i64P); | ||
111 | tmp64 <<= bytes[7] & 0x0f; | ||
112 | *i64P += cpu_to_le64(tmp64); | ||
113 | } | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* try to init the device like the windows driver */ | ||
120 | static int device_authorization(struct hdpvr_device *dev) | ||
121 | { | ||
122 | |||
123 | int ret, retval = -ENOMEM; | ||
124 | char request_type = 0x38, rcv_request = 0x81; | ||
125 | char *response; | ||
126 | #ifdef HDPVR_DEBUG | ||
127 | size_t buf_size = 46; | ||
128 | char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); | ||
129 | if (!print_buf) { | ||
130 | v4l2_err(&dev->v4l2_dev, "Out of memory\n"); | ||
131 | return retval; | ||
132 | } | ||
133 | #endif | ||
134 | |||
135 | mutex_lock(&dev->usbc_mutex); | ||
136 | ret = usb_control_msg(dev->udev, | ||
137 | usb_rcvctrlpipe(dev->udev, 0), | ||
138 | rcv_request, 0x80 | request_type, | ||
139 | 0x0400, 0x0003, | ||
140 | dev->usbc_buf, 46, | ||
141 | 10000); | ||
142 | if (ret != 46) { | ||
143 | v4l2_err(&dev->v4l2_dev, | ||
144 | "unexpected answer of status request, len %d\n", ret); | ||
145 | goto unlock; | ||
146 | } | ||
147 | #ifdef HDPVR_DEBUG | ||
148 | else { | ||
149 | hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, | ||
150 | 5*buf_size+1, 0); | ||
151 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
152 | "Status request returned, len %d: %s\n", | ||
153 | ret, print_buf); | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | dev->fw_ver = dev->usbc_buf[1]; | ||
158 | |||
159 | v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n", | ||
160 | dev->fw_ver, &dev->usbc_buf[2]); | ||
161 | |||
162 | if (dev->fw_ver > 0x15) { | ||
163 | dev->options.brightness = 0x80; | ||
164 | dev->options.contrast = 0x40; | ||
165 | dev->options.hue = 0xf; | ||
166 | dev->options.saturation = 0x40; | ||
167 | dev->options.sharpness = 0x80; | ||
168 | } | ||
169 | |||
170 | switch (dev->fw_ver) { | ||
171 | case HDPVR_FIRMWARE_VERSION: | ||
172 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; | ||
173 | break; | ||
174 | case HDPVR_FIRMWARE_VERSION_AC3: | ||
175 | case HDPVR_FIRMWARE_VERSION_0X12: | ||
176 | case HDPVR_FIRMWARE_VERSION_0X15: | ||
177 | dev->flags |= HDPVR_FLAG_AC3_CAP; | ||
178 | break; | ||
179 | default: | ||
180 | v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might" | ||
181 | " not work.\n"); | ||
182 | if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3) | ||
183 | dev->flags |= HDPVR_FLAG_AC3_CAP; | ||
184 | else | ||
185 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; | ||
186 | } | ||
187 | |||
188 | response = dev->usbc_buf+38; | ||
189 | #ifdef HDPVR_DEBUG | ||
190 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); | ||
191 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", | ||
192 | print_buf); | ||
193 | #endif | ||
194 | challenge(response); | ||
195 | #ifdef HDPVR_DEBUG | ||
196 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); | ||
197 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", | ||
198 | print_buf); | ||
199 | #endif | ||
200 | |||
201 | msleep(100); | ||
202 | ret = usb_control_msg(dev->udev, | ||
203 | usb_sndctrlpipe(dev->udev, 0), | ||
204 | 0xd1, 0x00 | request_type, | ||
205 | 0x0000, 0x0000, | ||
206 | response, 8, | ||
207 | 10000); | ||
208 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
209 | "magic request returned %d\n", ret); | ||
210 | |||
211 | retval = ret != 8; | ||
212 | unlock: | ||
213 | mutex_unlock(&dev->usbc_mutex); | ||
214 | return retval; | ||
215 | } | ||
216 | |||
217 | static int hdpvr_device_init(struct hdpvr_device *dev) | ||
218 | { | ||
219 | int ret; | ||
220 | u8 *buf; | ||
221 | struct hdpvr_video_info *vidinf; | ||
222 | |||
223 | if (device_authorization(dev)) | ||
224 | return -EACCES; | ||
225 | |||
226 | /* default options for init */ | ||
227 | hdpvr_set_options(dev); | ||
228 | |||
229 | /* set filter options */ | ||
230 | mutex_lock(&dev->usbc_mutex); | ||
231 | buf = dev->usbc_buf; | ||
232 | buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00; | ||
233 | ret = usb_control_msg(dev->udev, | ||
234 | usb_sndctrlpipe(dev->udev, 0), | ||
235 | 0x01, 0x38, | ||
236 | CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, | ||
237 | buf, 4, | ||
238 | 1000); | ||
239 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
240 | "control request returned %d\n", ret); | ||
241 | mutex_unlock(&dev->usbc_mutex); | ||
242 | |||
243 | vidinf = get_video_info(dev); | ||
244 | if (!vidinf) | ||
245 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
246 | "no valid video signal or device init failed\n"); | ||
247 | else | ||
248 | kfree(vidinf); | ||
249 | |||
250 | /* enable fan and bling leds */ | ||
251 | mutex_lock(&dev->usbc_mutex); | ||
252 | buf[0] = 0x1; | ||
253 | ret = usb_control_msg(dev->udev, | ||
254 | usb_sndctrlpipe(dev->udev, 0), | ||
255 | 0xd4, 0x38, 0, 0, buf, 1, | ||
256 | 1000); | ||
257 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
258 | "control request returned %d\n", ret); | ||
259 | |||
260 | /* boost analog audio */ | ||
261 | buf[0] = boost_audio; | ||
262 | ret = usb_control_msg(dev->udev, | ||
263 | usb_sndctrlpipe(dev->udev, 0), | ||
264 | 0xd5, 0x38, 0, 0, buf, 1, | ||
265 | 1000); | ||
266 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
267 | "control request returned %d\n", ret); | ||
268 | mutex_unlock(&dev->usbc_mutex); | ||
269 | |||
270 | dev->status = STATUS_IDLE; | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static const struct hdpvr_options hdpvr_default_options = { | ||
275 | .video_std = HDPVR_60HZ, | ||
276 | .video_input = HDPVR_COMPONENT, | ||
277 | .audio_input = HDPVR_RCA_BACK, | ||
278 | .bitrate = 65, /* 6 mbps */ | ||
279 | .peak_bitrate = 90, /* 9 mbps */ | ||
280 | .bitrate_mode = HDPVR_CONSTANT, | ||
281 | .gop_mode = HDPVR_SIMPLE_IDR_GOP, | ||
282 | .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, | ||
283 | /* original picture controls for firmware version <= 0x15 */ | ||
284 | /* updated in device_authorization() for newer firmware */ | ||
285 | .brightness = 0x86, | ||
286 | .contrast = 0x80, | ||
287 | .hue = 0x80, | ||
288 | .saturation = 0x80, | ||
289 | .sharpness = 0x80, | ||
290 | }; | ||
291 | |||
292 | static int hdpvr_probe(struct usb_interface *interface, | ||
293 | const struct usb_device_id *id) | ||
294 | { | ||
295 | struct hdpvr_device *dev; | ||
296 | struct usb_host_interface *iface_desc; | ||
297 | struct usb_endpoint_descriptor *endpoint; | ||
298 | struct i2c_client *client; | ||
299 | size_t buffer_size; | ||
300 | int i; | ||
301 | int retval = -ENOMEM; | ||
302 | |||
303 | /* allocate memory for our device state and initialize it */ | ||
304 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
305 | if (!dev) { | ||
306 | dev_err(&interface->dev, "Out of memory\n"); | ||
307 | goto error; | ||
308 | } | ||
309 | |||
310 | dev->workqueue = 0; | ||
311 | |||
312 | /* register v4l2_device early so it can be used for printks */ | ||
313 | if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { | ||
314 | dev_err(&interface->dev, "v4l2_device_register failed\n"); | ||
315 | goto error; | ||
316 | } | ||
317 | |||
318 | mutex_init(&dev->io_mutex); | ||
319 | mutex_init(&dev->i2c_mutex); | ||
320 | mutex_init(&dev->usbc_mutex); | ||
321 | dev->usbc_buf = kmalloc(64, GFP_KERNEL); | ||
322 | if (!dev->usbc_buf) { | ||
323 | v4l2_err(&dev->v4l2_dev, "Out of memory\n"); | ||
324 | goto error; | ||
325 | } | ||
326 | |||
327 | init_waitqueue_head(&dev->wait_buffer); | ||
328 | init_waitqueue_head(&dev->wait_data); | ||
329 | |||
330 | dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); | ||
331 | if (!dev->workqueue) | ||
332 | goto error; | ||
333 | |||
334 | /* init video transfer queues */ | ||
335 | INIT_LIST_HEAD(&dev->free_buff_list); | ||
336 | INIT_LIST_HEAD(&dev->rec_buff_list); | ||
337 | |||
338 | dev->options = hdpvr_default_options; | ||
339 | |||
340 | if (default_video_input < HDPVR_VIDEO_INPUTS) | ||
341 | dev->options.video_input = default_video_input; | ||
342 | |||
343 | if (default_audio_input < HDPVR_AUDIO_INPUTS) { | ||
344 | dev->options.audio_input = default_audio_input; | ||
345 | if (default_audio_input == HDPVR_SPDIF) | ||
346 | dev->options.audio_codec = | ||
347 | V4L2_MPEG_AUDIO_ENCODING_AC3; | ||
348 | } | ||
349 | |||
350 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | ||
351 | |||
352 | /* set up the endpoint information */ | ||
353 | /* use only the first bulk-in and bulk-out endpoints */ | ||
354 | iface_desc = interface->cur_altsetting; | ||
355 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
356 | endpoint = &iface_desc->endpoint[i].desc; | ||
357 | |||
358 | if (!dev->bulk_in_endpointAddr && | ||
359 | usb_endpoint_is_bulk_in(endpoint)) { | ||
360 | /* USB interface description is buggy, reported max | ||
361 | * packet size is 512 bytes, windows driver uses 8192 */ | ||
362 | buffer_size = 8192; | ||
363 | dev->bulk_in_size = buffer_size; | ||
364 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
365 | } | ||
366 | |||
367 | } | ||
368 | if (!dev->bulk_in_endpointAddr) { | ||
369 | v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); | ||
370 | goto error; | ||
371 | } | ||
372 | |||
373 | /* init the device */ | ||
374 | if (hdpvr_device_init(dev)) { | ||
375 | v4l2_err(&dev->v4l2_dev, "device init failed\n"); | ||
376 | goto error; | ||
377 | } | ||
378 | |||
379 | mutex_lock(&dev->io_mutex); | ||
380 | if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { | ||
381 | mutex_unlock(&dev->io_mutex); | ||
382 | v4l2_err(&dev->v4l2_dev, | ||
383 | "allocating transfer buffers failed\n"); | ||
384 | goto error; | ||
385 | } | ||
386 | mutex_unlock(&dev->io_mutex); | ||
387 | |||
388 | if (hdpvr_register_videodev(dev, &interface->dev, | ||
389 | video_nr[atomic_inc_return(&dev_nr)])) { | ||
390 | v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); | ||
391 | goto error; | ||
392 | } | ||
393 | |||
394 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
395 | retval = hdpvr_register_i2c_adapter(dev); | ||
396 | if (retval < 0) { | ||
397 | v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); | ||
398 | goto error; | ||
399 | } | ||
400 | |||
401 | client = hdpvr_register_ir_rx_i2c(dev); | ||
402 | if (!client) { | ||
403 | v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n"); | ||
404 | goto reg_fail; | ||
405 | } | ||
406 | |||
407 | client = hdpvr_register_ir_tx_i2c(dev); | ||
408 | if (!client) { | ||
409 | v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n"); | ||
410 | goto reg_fail; | ||
411 | } | ||
412 | #endif | ||
413 | |||
414 | /* let the user know what node this device is now attached to */ | ||
415 | v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", | ||
416 | video_device_node_name(dev->video_dev)); | ||
417 | return 0; | ||
418 | |||
419 | reg_fail: | ||
420 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
421 | i2c_del_adapter(&dev->i2c_adapter); | ||
422 | #endif | ||
423 | error: | ||
424 | if (dev) { | ||
425 | /* Destroy single thread */ | ||
426 | if (dev->workqueue) | ||
427 | destroy_workqueue(dev->workqueue); | ||
428 | /* this frees allocated memory */ | ||
429 | hdpvr_delete(dev); | ||
430 | } | ||
431 | return retval; | ||
432 | } | ||
433 | |||
434 | static void hdpvr_disconnect(struct usb_interface *interface) | ||
435 | { | ||
436 | struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface)); | ||
437 | |||
438 | v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", | ||
439 | video_device_node_name(dev->video_dev)); | ||
440 | /* prevent more I/O from starting and stop any ongoing */ | ||
441 | mutex_lock(&dev->io_mutex); | ||
442 | dev->status = STATUS_DISCONNECTED; | ||
443 | wake_up_interruptible(&dev->wait_data); | ||
444 | wake_up_interruptible(&dev->wait_buffer); | ||
445 | mutex_unlock(&dev->io_mutex); | ||
446 | v4l2_device_disconnect(&dev->v4l2_dev); | ||
447 | msleep(100); | ||
448 | flush_workqueue(dev->workqueue); | ||
449 | mutex_lock(&dev->io_mutex); | ||
450 | hdpvr_cancel_queue(dev); | ||
451 | mutex_unlock(&dev->io_mutex); | ||
452 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
453 | i2c_del_adapter(&dev->i2c_adapter); | ||
454 | #endif | ||
455 | video_unregister_device(dev->video_dev); | ||
456 | atomic_dec(&dev_nr); | ||
457 | } | ||
458 | |||
459 | |||
460 | static struct usb_driver hdpvr_usb_driver = { | ||
461 | .name = "hdpvr", | ||
462 | .probe = hdpvr_probe, | ||
463 | .disconnect = hdpvr_disconnect, | ||
464 | .id_table = hdpvr_table, | ||
465 | }; | ||
466 | |||
467 | module_usb_driver(hdpvr_usb_driver); | ||
468 | |||
469 | MODULE_LICENSE("GPL"); | ||
470 | MODULE_VERSION("0.2.1"); | ||
471 | MODULE_AUTHOR("Janne Grunau"); | ||
472 | 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 000000000000..82e819fa91c0 --- /dev/null +++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c | |||
@@ -0,0 +1,231 @@ | |||
1 | |||
2 | /* | ||
3 | * Hauppauge HD PVR USB driver | ||
4 | * | ||
5 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
6 | * | ||
7 | * IR device registration code is | ||
8 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License as | ||
12 | * published by the Free Software Foundation, version 2. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
17 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/export.h> | ||
21 | |||
22 | #include "hdpvr.h" | ||
23 | |||
24 | #define CTRL_READ_REQUEST 0xb8 | ||
25 | #define CTRL_WRITE_REQUEST 0x38 | ||
26 | |||
27 | #define REQTYPE_I2C_READ 0xb1 | ||
28 | #define REQTYPE_I2C_WRITE 0xb0 | ||
29 | #define REQTYPE_I2C_WRITE_STATT 0xd0 | ||
30 | |||
31 | #define Z8F0811_IR_TX_I2C_ADDR 0x70 | ||
32 | #define Z8F0811_IR_RX_I2C_ADDR 0x71 | ||
33 | |||
34 | |||
35 | struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev) | ||
36 | { | ||
37 | struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; | ||
38 | struct i2c_board_info hdpvr_ir_tx_i2c_board_info = { | ||
39 | I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR), | ||
40 | }; | ||
41 | |||
42 | init_data->name = "HD-PVR"; | ||
43 | hdpvr_ir_tx_i2c_board_info.platform_data = init_data; | ||
44 | |||
45 | return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info); | ||
46 | } | ||
47 | |||
48 | struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev) | ||
49 | { | ||
50 | struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; | ||
51 | struct i2c_board_info hdpvr_ir_rx_i2c_board_info = { | ||
52 | I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR), | ||
53 | }; | ||
54 | |||
55 | /* Our default information for ir-kbd-i2c.c to use */ | ||
56 | init_data->ir_codes = RC_MAP_HAUPPAUGE; | ||
57 | init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; | ||
58 | init_data->type = RC_TYPE_RC5; | ||
59 | init_data->name = "HD-PVR"; | ||
60 | init_data->polling_interval = 405; /* ms, duplicated from Windows */ | ||
61 | hdpvr_ir_rx_i2c_board_info.platform_data = init_data; | ||
62 | |||
63 | return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info); | ||
64 | } | ||
65 | |||
66 | static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, | ||
67 | unsigned char addr, char *wdata, int wlen, | ||
68 | char *data, int len) | ||
69 | { | ||
70 | int ret; | ||
71 | |||
72 | if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf))) | ||
73 | return -EINVAL; | ||
74 | |||
75 | if (wlen) { | ||
76 | memcpy(&dev->i2c_buf, wdata, wlen); | ||
77 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
78 | REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, | ||
79 | (bus << 8) | addr, 0, &dev->i2c_buf, | ||
80 | wlen, 1000); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
86 | REQTYPE_I2C_READ, CTRL_READ_REQUEST, | ||
87 | (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); | ||
88 | |||
89 | if (ret == len) { | ||
90 | memcpy(data, &dev->i2c_buf, len); | ||
91 | ret = 0; | ||
92 | } else if (ret >= 0) | ||
93 | ret = -EIO; | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, | ||
99 | unsigned char addr, char *data, int len) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | if (len > sizeof(dev->i2c_buf)) | ||
104 | return -EINVAL; | ||
105 | |||
106 | memcpy(&dev->i2c_buf, data, len); | ||
107 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
108 | REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, | ||
109 | (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); | ||
110 | |||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | |||
114 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
115 | REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, | ||
116 | 0, 0, &dev->i2c_buf, 2, 1000); | ||
117 | |||
118 | if ((ret == 2) && (dev->i2c_buf[1] == (len - 1))) | ||
119 | ret = 0; | ||
120 | else if (ret >= 0) | ||
121 | ret = -EIO; | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, | ||
127 | int num) | ||
128 | { | ||
129 | struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); | ||
130 | int retval = 0, addr; | ||
131 | |||
132 | if (num <= 0) | ||
133 | return 0; | ||
134 | |||
135 | mutex_lock(&dev->i2c_mutex); | ||
136 | |||
137 | addr = msgs[0].addr << 1; | ||
138 | |||
139 | if (num == 1) { | ||
140 | if (msgs[0].flags & I2C_M_RD) | ||
141 | retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0, | ||
142 | msgs[0].buf, msgs[0].len); | ||
143 | else | ||
144 | retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf, | ||
145 | msgs[0].len); | ||
146 | } else if (num == 2) { | ||
147 | if (msgs[0].addr != msgs[1].addr) { | ||
148 | v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer " | ||
149 | "with conflicting target addresses\n"); | ||
150 | retval = -EINVAL; | ||
151 | goto out; | ||
152 | } | ||
153 | |||
154 | if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) { | ||
155 | v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with " | ||
156 | "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD, | ||
157 | msgs[1].flags & I2C_M_RD); | ||
158 | retval = -EINVAL; | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Write followed by atomic read is the only complex xfer that | ||
164 | * we actually support here. | ||
165 | */ | ||
166 | retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len, | ||
167 | msgs[1].buf, msgs[1].len); | ||
168 | } else { | ||
169 | v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num); | ||
170 | } | ||
171 | |||
172 | out: | ||
173 | mutex_unlock(&dev->i2c_mutex); | ||
174 | |||
175 | return retval ? retval : num; | ||
176 | } | ||
177 | |||
178 | static u32 hdpvr_functionality(struct i2c_adapter *adapter) | ||
179 | { | ||
180 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
181 | } | ||
182 | |||
183 | static struct i2c_algorithm hdpvr_algo = { | ||
184 | .master_xfer = hdpvr_transfer, | ||
185 | .functionality = hdpvr_functionality, | ||
186 | }; | ||
187 | |||
188 | static struct i2c_adapter hdpvr_i2c_adapter_template = { | ||
189 | .name = "Hauppage HD PVR I2C", | ||
190 | .owner = THIS_MODULE, | ||
191 | .algo = &hdpvr_algo, | ||
192 | }; | ||
193 | |||
194 | static int hdpvr_activate_ir(struct hdpvr_device *dev) | ||
195 | { | ||
196 | char buffer[2]; | ||
197 | |||
198 | mutex_lock(&dev->i2c_mutex); | ||
199 | |||
200 | hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1); | ||
201 | |||
202 | buffer[0] = 0; | ||
203 | buffer[1] = 0x8; | ||
204 | hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); | ||
205 | |||
206 | buffer[1] = 0x18; | ||
207 | hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); | ||
208 | |||
209 | mutex_unlock(&dev->i2c_mutex); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) | ||
215 | { | ||
216 | int retval = -ENOMEM; | ||
217 | |||
218 | hdpvr_activate_ir(dev); | ||
219 | |||
220 | memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template, | ||
221 | sizeof(struct i2c_adapter)); | ||
222 | dev->i2c_adapter.dev.parent = &dev->udev->dev; | ||
223 | |||
224 | i2c_set_adapdata(&dev->i2c_adapter, dev); | ||
225 | |||
226 | retval = i2c_add_adapter(&dev->i2c_adapter); | ||
227 | |||
228 | return retval; | ||
229 | } | ||
230 | |||
231 | #endif | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c new file mode 100644 index 000000000000..0e9e156bb2aa --- /dev/null +++ b/drivers/media/usb/hdpvr/hdpvr-video.c | |||
@@ -0,0 +1,1289 @@ | |||
1 | /* | ||
2 | * Hauppauge HD PVR USB driver - video 4 linux 2 interface | ||
3 | * | ||
4 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | |||
22 | #include <linux/videodev2.h> | ||
23 | #include <media/v4l2-dev.h> | ||
24 | #include <media/v4l2-common.h> | ||
25 | #include <media/v4l2-ioctl.h> | ||
26 | #include "hdpvr.h" | ||
27 | |||
28 | #define BULK_URB_TIMEOUT 90 /* 0.09 seconds */ | ||
29 | |||
30 | #define print_buffer_status() { \ | ||
31 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, \ | ||
32 | "%s:%d buffer stat: %d free, %d proc\n", \ | ||
33 | __func__, __LINE__, \ | ||
34 | list_size(&dev->free_buff_list), \ | ||
35 | list_size(&dev->rec_buff_list)); } | ||
36 | |||
37 | struct hdpvr_fh { | ||
38 | struct hdpvr_device *dev; | ||
39 | }; | ||
40 | |||
41 | static uint list_size(struct list_head *list) | ||
42 | { | ||
43 | struct list_head *tmp; | ||
44 | uint count = 0; | ||
45 | |||
46 | list_for_each(tmp, list) { | ||
47 | count++; | ||
48 | } | ||
49 | |||
50 | return count; | ||
51 | } | ||
52 | |||
53 | /*=========================================================================*/ | ||
54 | /* urb callback */ | ||
55 | static void hdpvr_read_bulk_callback(struct urb *urb) | ||
56 | { | ||
57 | struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context; | ||
58 | struct hdpvr_device *dev = buf->dev; | ||
59 | |||
60 | /* marking buffer as received and wake waiting */ | ||
61 | buf->status = BUFSTAT_READY; | ||
62 | wake_up_interruptible(&dev->wait_data); | ||
63 | } | ||
64 | |||
65 | /*=========================================================================*/ | ||
66 | /* bufffer bits */ | ||
67 | |||
68 | /* function expects dev->io_mutex to be hold by caller */ | ||
69 | int hdpvr_cancel_queue(struct hdpvr_device *dev) | ||
70 | { | ||
71 | struct hdpvr_buffer *buf; | ||
72 | |||
73 | list_for_each_entry(buf, &dev->rec_buff_list, buff_list) { | ||
74 | usb_kill_urb(buf->urb); | ||
75 | buf->status = BUFSTAT_AVAILABLE; | ||
76 | } | ||
77 | |||
78 | list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int hdpvr_free_queue(struct list_head *q) | ||
84 | { | ||
85 | struct list_head *tmp; | ||
86 | struct list_head *p; | ||
87 | struct hdpvr_buffer *buf; | ||
88 | struct urb *urb; | ||
89 | |||
90 | for (p = q->next; p != q;) { | ||
91 | buf = list_entry(p, struct hdpvr_buffer, buff_list); | ||
92 | |||
93 | urb = buf->urb; | ||
94 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | ||
95 | urb->transfer_buffer, urb->transfer_dma); | ||
96 | usb_free_urb(urb); | ||
97 | tmp = p->next; | ||
98 | list_del(p); | ||
99 | kfree(buf); | ||
100 | p = tmp; | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | /* function expects dev->io_mutex to be hold by caller */ | ||
107 | int hdpvr_free_buffers(struct hdpvr_device *dev) | ||
108 | { | ||
109 | hdpvr_cancel_queue(dev); | ||
110 | |||
111 | hdpvr_free_queue(&dev->free_buff_list); | ||
112 | hdpvr_free_queue(&dev->rec_buff_list); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /* function expects dev->io_mutex to be hold by caller */ | ||
118 | int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) | ||
119 | { | ||
120 | uint i; | ||
121 | int retval = -ENOMEM; | ||
122 | u8 *mem; | ||
123 | struct hdpvr_buffer *buf; | ||
124 | struct urb *urb; | ||
125 | |||
126 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
127 | "allocating %u buffers\n", count); | ||
128 | |||
129 | for (i = 0; i < count; i++) { | ||
130 | |||
131 | buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); | ||
132 | if (!buf) { | ||
133 | v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n"); | ||
134 | goto exit; | ||
135 | } | ||
136 | buf->dev = dev; | ||
137 | |||
138 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
139 | if (!urb) { | ||
140 | v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); | ||
141 | goto exit_urb; | ||
142 | } | ||
143 | buf->urb = urb; | ||
144 | |||
145 | mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL, | ||
146 | &urb->transfer_dma); | ||
147 | if (!mem) { | ||
148 | v4l2_err(&dev->v4l2_dev, | ||
149 | "cannot allocate usb transfer buffer\n"); | ||
150 | goto exit_urb_buffer; | ||
151 | } | ||
152 | |||
153 | usb_fill_bulk_urb(buf->urb, dev->udev, | ||
154 | usb_rcvbulkpipe(dev->udev, | ||
155 | dev->bulk_in_endpointAddr), | ||
156 | mem, dev->bulk_in_size, | ||
157 | hdpvr_read_bulk_callback, buf); | ||
158 | |||
159 | buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
160 | buf->status = BUFSTAT_AVAILABLE; | ||
161 | list_add_tail(&buf->buff_list, &dev->free_buff_list); | ||
162 | } | ||
163 | return 0; | ||
164 | exit_urb_buffer: | ||
165 | usb_free_urb(urb); | ||
166 | exit_urb: | ||
167 | kfree(buf); | ||
168 | exit: | ||
169 | hdpvr_free_buffers(dev); | ||
170 | return retval; | ||
171 | } | ||
172 | |||
173 | static int hdpvr_submit_buffers(struct hdpvr_device *dev) | ||
174 | { | ||
175 | struct hdpvr_buffer *buf; | ||
176 | struct urb *urb; | ||
177 | int ret = 0, err_count = 0; | ||
178 | |||
179 | mutex_lock(&dev->io_mutex); | ||
180 | |||
181 | while (dev->status == STATUS_STREAMING && | ||
182 | !list_empty(&dev->free_buff_list)) { | ||
183 | |||
184 | buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, | ||
185 | buff_list); | ||
186 | if (buf->status != BUFSTAT_AVAILABLE) { | ||
187 | v4l2_err(&dev->v4l2_dev, | ||
188 | "buffer not marked as available\n"); | ||
189 | ret = -EFAULT; | ||
190 | goto err; | ||
191 | } | ||
192 | |||
193 | urb = buf->urb; | ||
194 | urb->status = 0; | ||
195 | urb->actual_length = 0; | ||
196 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
197 | if (ret) { | ||
198 | v4l2_err(&dev->v4l2_dev, | ||
199 | "usb_submit_urb in %s returned %d\n", | ||
200 | __func__, ret); | ||
201 | if (++err_count > 2) | ||
202 | break; | ||
203 | continue; | ||
204 | } | ||
205 | buf->status = BUFSTAT_INPROGRESS; | ||
206 | list_move_tail(&buf->buff_list, &dev->rec_buff_list); | ||
207 | } | ||
208 | err: | ||
209 | print_buffer_status(); | ||
210 | mutex_unlock(&dev->io_mutex); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev) | ||
215 | { | ||
216 | struct hdpvr_buffer *buf; | ||
217 | |||
218 | mutex_lock(&dev->io_mutex); | ||
219 | |||
220 | if (list_empty(&dev->rec_buff_list)) { | ||
221 | mutex_unlock(&dev->io_mutex); | ||
222 | return NULL; | ||
223 | } | ||
224 | |||
225 | buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer, | ||
226 | buff_list); | ||
227 | mutex_unlock(&dev->io_mutex); | ||
228 | |||
229 | return buf; | ||
230 | } | ||
231 | |||
232 | static void hdpvr_transmit_buffers(struct work_struct *work) | ||
233 | { | ||
234 | struct hdpvr_device *dev = container_of(work, struct hdpvr_device, | ||
235 | worker); | ||
236 | |||
237 | while (dev->status == STATUS_STREAMING) { | ||
238 | |||
239 | if (hdpvr_submit_buffers(dev)) { | ||
240 | v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n"); | ||
241 | goto error; | ||
242 | } | ||
243 | if (wait_event_interruptible(dev->wait_buffer, | ||
244 | !list_empty(&dev->free_buff_list) || | ||
245 | dev->status != STATUS_STREAMING)) | ||
246 | goto error; | ||
247 | } | ||
248 | |||
249 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
250 | "transmit worker exited\n"); | ||
251 | return; | ||
252 | error: | ||
253 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
254 | "transmit buffers errored\n"); | ||
255 | dev->status = STATUS_ERROR; | ||
256 | } | ||
257 | |||
258 | /* function expects dev->io_mutex to be hold by caller */ | ||
259 | static int hdpvr_start_streaming(struct hdpvr_device *dev) | ||
260 | { | ||
261 | int ret; | ||
262 | struct hdpvr_video_info *vidinf; | ||
263 | |||
264 | if (dev->status == STATUS_STREAMING) | ||
265 | return 0; | ||
266 | else if (dev->status != STATUS_IDLE) | ||
267 | return -EAGAIN; | ||
268 | |||
269 | vidinf = get_video_info(dev); | ||
270 | |||
271 | if (vidinf) { | ||
272 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
273 | "video signal: %dx%d@%dhz\n", vidinf->width, | ||
274 | vidinf->height, vidinf->fps); | ||
275 | kfree(vidinf); | ||
276 | |||
277 | /* start streaming 2 request */ | ||
278 | ret = usb_control_msg(dev->udev, | ||
279 | usb_sndctrlpipe(dev->udev, 0), | ||
280 | 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); | ||
281 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
282 | "encoder start control request returned %d\n", ret); | ||
283 | |||
284 | hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); | ||
285 | |||
286 | dev->status = STATUS_STREAMING; | ||
287 | |||
288 | INIT_WORK(&dev->worker, hdpvr_transmit_buffers); | ||
289 | queue_work(dev->workqueue, &dev->worker); | ||
290 | |||
291 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
292 | "streaming started\n"); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | msleep(250); | ||
297 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
298 | "no video signal at input %d\n", dev->options.video_input); | ||
299 | return -EAGAIN; | ||
300 | } | ||
301 | |||
302 | |||
303 | /* function expects dev->io_mutex to be hold by caller */ | ||
304 | static int hdpvr_stop_streaming(struct hdpvr_device *dev) | ||
305 | { | ||
306 | int actual_length; | ||
307 | uint c = 0; | ||
308 | u8 *buf; | ||
309 | |||
310 | if (dev->status == STATUS_IDLE) | ||
311 | return 0; | ||
312 | else if (dev->status != STATUS_STREAMING) | ||
313 | return -EAGAIN; | ||
314 | |||
315 | buf = kmalloc(dev->bulk_in_size, GFP_KERNEL); | ||
316 | if (!buf) | ||
317 | v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer " | ||
318 | "for emptying the internal device buffer. " | ||
319 | "Next capture start will be slow\n"); | ||
320 | |||
321 | dev->status = STATUS_SHUTTING_DOWN; | ||
322 | hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); | ||
323 | mutex_unlock(&dev->io_mutex); | ||
324 | |||
325 | wake_up_interruptible(&dev->wait_buffer); | ||
326 | msleep(50); | ||
327 | |||
328 | flush_workqueue(dev->workqueue); | ||
329 | |||
330 | mutex_lock(&dev->io_mutex); | ||
331 | /* kill the still outstanding urbs */ | ||
332 | hdpvr_cancel_queue(dev); | ||
333 | |||
334 | /* emptying the device buffer beforeshutting it down */ | ||
335 | while (buf && ++c < 500 && | ||
336 | !usb_bulk_msg(dev->udev, | ||
337 | usb_rcvbulkpipe(dev->udev, | ||
338 | dev->bulk_in_endpointAddr), | ||
339 | buf, dev->bulk_in_size, &actual_length, | ||
340 | BULK_URB_TIMEOUT)) { | ||
341 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
342 | "%2d: got %d bytes\n", c, actual_length); | ||
343 | } | ||
344 | kfree(buf); | ||
345 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
346 | "used %d urbs to empty device buffers\n", c-1); | ||
347 | msleep(10); | ||
348 | |||
349 | dev->status = STATUS_IDLE; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | |||
355 | /*=======================================================================*/ | ||
356 | /* | ||
357 | * video 4 linux 2 file operations | ||
358 | */ | ||
359 | |||
360 | static int hdpvr_open(struct file *file) | ||
361 | { | ||
362 | struct hdpvr_device *dev; | ||
363 | struct hdpvr_fh *fh; | ||
364 | int retval = -ENOMEM; | ||
365 | |||
366 | dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); | ||
367 | if (!dev) { | ||
368 | pr_err("open failing with with ENODEV\n"); | ||
369 | retval = -ENODEV; | ||
370 | goto err; | ||
371 | } | ||
372 | |||
373 | fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); | ||
374 | if (!fh) { | ||
375 | v4l2_err(&dev->v4l2_dev, "Out of memory\n"); | ||
376 | goto err; | ||
377 | } | ||
378 | /* lock the device to allow correctly handling errors | ||
379 | * in resumption */ | ||
380 | mutex_lock(&dev->io_mutex); | ||
381 | dev->open_count++; | ||
382 | mutex_unlock(&dev->io_mutex); | ||
383 | |||
384 | fh->dev = dev; | ||
385 | |||
386 | /* save our object in the file's private structure */ | ||
387 | file->private_data = fh; | ||
388 | |||
389 | retval = 0; | ||
390 | err: | ||
391 | return retval; | ||
392 | } | ||
393 | |||
394 | static int hdpvr_release(struct file *file) | ||
395 | { | ||
396 | struct hdpvr_fh *fh = file->private_data; | ||
397 | struct hdpvr_device *dev = fh->dev; | ||
398 | |||
399 | if (!dev) | ||
400 | return -ENODEV; | ||
401 | |||
402 | mutex_lock(&dev->io_mutex); | ||
403 | if (!(--dev->open_count) && dev->status == STATUS_STREAMING) | ||
404 | hdpvr_stop_streaming(dev); | ||
405 | |||
406 | mutex_unlock(&dev->io_mutex); | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * hdpvr_v4l2_read() | ||
413 | * will allocate buffers when called for the first time | ||
414 | */ | ||
415 | static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, | ||
416 | loff_t *pos) | ||
417 | { | ||
418 | struct hdpvr_fh *fh = file->private_data; | ||
419 | struct hdpvr_device *dev = fh->dev; | ||
420 | struct hdpvr_buffer *buf = NULL; | ||
421 | struct urb *urb; | ||
422 | unsigned int ret = 0; | ||
423 | int rem, cnt; | ||
424 | |||
425 | if (*pos) | ||
426 | return -ESPIPE; | ||
427 | |||
428 | if (!dev) | ||
429 | return -ENODEV; | ||
430 | |||
431 | mutex_lock(&dev->io_mutex); | ||
432 | if (dev->status == STATUS_IDLE) { | ||
433 | if (hdpvr_start_streaming(dev)) { | ||
434 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
435 | "start_streaming failed\n"); | ||
436 | ret = -EIO; | ||
437 | msleep(200); | ||
438 | dev->status = STATUS_IDLE; | ||
439 | mutex_unlock(&dev->io_mutex); | ||
440 | goto err; | ||
441 | } | ||
442 | print_buffer_status(); | ||
443 | } | ||
444 | mutex_unlock(&dev->io_mutex); | ||
445 | |||
446 | /* wait for the first buffer */ | ||
447 | if (!(file->f_flags & O_NONBLOCK)) { | ||
448 | if (wait_event_interruptible(dev->wait_data, | ||
449 | hdpvr_get_next_buffer(dev))) | ||
450 | return -ERESTARTSYS; | ||
451 | } | ||
452 | |||
453 | buf = hdpvr_get_next_buffer(dev); | ||
454 | |||
455 | while (count > 0 && buf) { | ||
456 | |||
457 | if (buf->status != BUFSTAT_READY && | ||
458 | dev->status != STATUS_DISCONNECTED) { | ||
459 | /* return nonblocking */ | ||
460 | if (file->f_flags & O_NONBLOCK) { | ||
461 | if (!ret) | ||
462 | ret = -EAGAIN; | ||
463 | goto err; | ||
464 | } | ||
465 | |||
466 | if (wait_event_interruptible(dev->wait_data, | ||
467 | buf->status == BUFSTAT_READY)) { | ||
468 | ret = -ERESTARTSYS; | ||
469 | goto err; | ||
470 | } | ||
471 | } | ||
472 | |||
473 | if (buf->status != BUFSTAT_READY) | ||
474 | break; | ||
475 | |||
476 | /* set remaining bytes to copy */ | ||
477 | urb = buf->urb; | ||
478 | rem = urb->actual_length - buf->pos; | ||
479 | cnt = rem > count ? count : rem; | ||
480 | |||
481 | if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, | ||
482 | cnt)) { | ||
483 | v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n"); | ||
484 | if (!ret) | ||
485 | ret = -EFAULT; | ||
486 | goto err; | ||
487 | } | ||
488 | |||
489 | buf->pos += cnt; | ||
490 | count -= cnt; | ||
491 | buffer += cnt; | ||
492 | ret += cnt; | ||
493 | |||
494 | /* finished, take next buffer */ | ||
495 | if (buf->pos == urb->actual_length) { | ||
496 | mutex_lock(&dev->io_mutex); | ||
497 | buf->pos = 0; | ||
498 | buf->status = BUFSTAT_AVAILABLE; | ||
499 | |||
500 | list_move_tail(&buf->buff_list, &dev->free_buff_list); | ||
501 | |||
502 | print_buffer_status(); | ||
503 | |||
504 | mutex_unlock(&dev->io_mutex); | ||
505 | |||
506 | wake_up_interruptible(&dev->wait_buffer); | ||
507 | |||
508 | buf = hdpvr_get_next_buffer(dev); | ||
509 | } | ||
510 | } | ||
511 | err: | ||
512 | if (!ret && !buf) | ||
513 | ret = -EAGAIN; | ||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | ||
518 | { | ||
519 | struct hdpvr_buffer *buf = NULL; | ||
520 | struct hdpvr_fh *fh = filp->private_data; | ||
521 | struct hdpvr_device *dev = fh->dev; | ||
522 | unsigned int mask = 0; | ||
523 | |||
524 | mutex_lock(&dev->io_mutex); | ||
525 | |||
526 | if (!video_is_registered(dev->video_dev)) { | ||
527 | mutex_unlock(&dev->io_mutex); | ||
528 | return -EIO; | ||
529 | } | ||
530 | |||
531 | if (dev->status == STATUS_IDLE) { | ||
532 | if (hdpvr_start_streaming(dev)) { | ||
533 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | ||
534 | "start_streaming failed\n"); | ||
535 | dev->status = STATUS_IDLE; | ||
536 | } | ||
537 | |||
538 | print_buffer_status(); | ||
539 | } | ||
540 | mutex_unlock(&dev->io_mutex); | ||
541 | |||
542 | buf = hdpvr_get_next_buffer(dev); | ||
543 | /* only wait if no data is available */ | ||
544 | if (!buf || buf->status != BUFSTAT_READY) { | ||
545 | poll_wait(filp, &dev->wait_data, wait); | ||
546 | buf = hdpvr_get_next_buffer(dev); | ||
547 | } | ||
548 | if (buf && buf->status == BUFSTAT_READY) | ||
549 | mask |= POLLIN | POLLRDNORM; | ||
550 | |||
551 | return mask; | ||
552 | } | ||
553 | |||
554 | |||
555 | static const struct v4l2_file_operations hdpvr_fops = { | ||
556 | .owner = THIS_MODULE, | ||
557 | .open = hdpvr_open, | ||
558 | .release = hdpvr_release, | ||
559 | .read = hdpvr_read, | ||
560 | .poll = hdpvr_poll, | ||
561 | .unlocked_ioctl = video_ioctl2, | ||
562 | }; | ||
563 | |||
564 | /*=======================================================================*/ | ||
565 | /* | ||
566 | * V4L2 ioctl handling | ||
567 | */ | ||
568 | |||
569 | static int vidioc_querycap(struct file *file, void *priv, | ||
570 | struct v4l2_capability *cap) | ||
571 | { | ||
572 | struct hdpvr_device *dev = video_drvdata(file); | ||
573 | |||
574 | strcpy(cap->driver, "hdpvr"); | ||
575 | strcpy(cap->card, "Hauppauge HD PVR"); | ||
576 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
577 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
578 | V4L2_CAP_AUDIO | | ||
579 | V4L2_CAP_READWRITE; | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int vidioc_s_std(struct file *file, void *private_data, | ||
584 | v4l2_std_id *std) | ||
585 | { | ||
586 | struct hdpvr_fh *fh = file->private_data; | ||
587 | struct hdpvr_device *dev = fh->dev; | ||
588 | u8 std_type = 1; | ||
589 | |||
590 | if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) | ||
591 | std_type = 0; | ||
592 | |||
593 | return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type); | ||
594 | } | ||
595 | |||
596 | static const char *iname[] = { | ||
597 | [HDPVR_COMPONENT] = "Component", | ||
598 | [HDPVR_SVIDEO] = "S-Video", | ||
599 | [HDPVR_COMPOSITE] = "Composite", | ||
600 | }; | ||
601 | |||
602 | static int vidioc_enum_input(struct file *file, void *priv, | ||
603 | struct v4l2_input *i) | ||
604 | { | ||
605 | struct hdpvr_fh *fh = file->private_data; | ||
606 | struct hdpvr_device *dev = fh->dev; | ||
607 | unsigned int n; | ||
608 | |||
609 | n = i->index; | ||
610 | if (n >= HDPVR_VIDEO_INPUTS) | ||
611 | return -EINVAL; | ||
612 | |||
613 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
614 | |||
615 | strncpy(i->name, iname[n], sizeof(i->name) - 1); | ||
616 | i->name[sizeof(i->name) - 1] = '\0'; | ||
617 | |||
618 | i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF; | ||
619 | |||
620 | i->std = dev->video_dev->tvnorms; | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int vidioc_s_input(struct file *file, void *private_data, | ||
626 | unsigned int index) | ||
627 | { | ||
628 | struct hdpvr_fh *fh = file->private_data; | ||
629 | struct hdpvr_device *dev = fh->dev; | ||
630 | int retval; | ||
631 | |||
632 | if (index >= HDPVR_VIDEO_INPUTS) | ||
633 | return -EINVAL; | ||
634 | |||
635 | if (dev->status != STATUS_IDLE) | ||
636 | return -EAGAIN; | ||
637 | |||
638 | retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1); | ||
639 | if (!retval) | ||
640 | dev->options.video_input = index; | ||
641 | |||
642 | return retval; | ||
643 | } | ||
644 | |||
645 | static int vidioc_g_input(struct file *file, void *private_data, | ||
646 | unsigned int *index) | ||
647 | { | ||
648 | struct hdpvr_fh *fh = file->private_data; | ||
649 | struct hdpvr_device *dev = fh->dev; | ||
650 | |||
651 | *index = dev->options.video_input; | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | |||
656 | static const char *audio_iname[] = { | ||
657 | [HDPVR_RCA_FRONT] = "RCA front", | ||
658 | [HDPVR_RCA_BACK] = "RCA back", | ||
659 | [HDPVR_SPDIF] = "SPDIF", | ||
660 | }; | ||
661 | |||
662 | static int vidioc_enumaudio(struct file *file, void *priv, | ||
663 | struct v4l2_audio *audio) | ||
664 | { | ||
665 | unsigned int n; | ||
666 | |||
667 | n = audio->index; | ||
668 | if (n >= HDPVR_AUDIO_INPUTS) | ||
669 | return -EINVAL; | ||
670 | |||
671 | audio->capability = V4L2_AUDCAP_STEREO; | ||
672 | |||
673 | strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1); | ||
674 | audio->name[sizeof(audio->name) - 1] = '\0'; | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int vidioc_s_audio(struct file *file, void *private_data, | ||
680 | struct v4l2_audio *audio) | ||
681 | { | ||
682 | struct hdpvr_fh *fh = file->private_data; | ||
683 | struct hdpvr_device *dev = fh->dev; | ||
684 | int retval; | ||
685 | |||
686 | if (audio->index >= HDPVR_AUDIO_INPUTS) | ||
687 | return -EINVAL; | ||
688 | |||
689 | if (dev->status != STATUS_IDLE) | ||
690 | return -EAGAIN; | ||
691 | |||
692 | retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec); | ||
693 | if (!retval) | ||
694 | dev->options.audio_input = audio->index; | ||
695 | |||
696 | return retval; | ||
697 | } | ||
698 | |||
699 | static int vidioc_g_audio(struct file *file, void *private_data, | ||
700 | struct v4l2_audio *audio) | ||
701 | { | ||
702 | struct hdpvr_fh *fh = file->private_data; | ||
703 | struct hdpvr_device *dev = fh->dev; | ||
704 | |||
705 | audio->index = dev->options.audio_input; | ||
706 | audio->capability = V4L2_AUDCAP_STEREO; | ||
707 | strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); | ||
708 | audio->name[sizeof(audio->name) - 1] = '\0'; | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | static const s32 supported_v4l2_ctrls[] = { | ||
713 | V4L2_CID_BRIGHTNESS, | ||
714 | V4L2_CID_CONTRAST, | ||
715 | V4L2_CID_SATURATION, | ||
716 | V4L2_CID_HUE, | ||
717 | V4L2_CID_SHARPNESS, | ||
718 | V4L2_CID_MPEG_AUDIO_ENCODING, | ||
719 | V4L2_CID_MPEG_VIDEO_ENCODING, | ||
720 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | ||
721 | V4L2_CID_MPEG_VIDEO_BITRATE, | ||
722 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | ||
723 | }; | ||
724 | |||
725 | static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, | ||
726 | int ac3, int fw_ver) | ||
727 | { | ||
728 | int err; | ||
729 | |||
730 | if (fw_ver > 0x15) { | ||
731 | switch (qc->id) { | ||
732 | case V4L2_CID_BRIGHTNESS: | ||
733 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
734 | case V4L2_CID_CONTRAST: | ||
735 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); | ||
736 | case V4L2_CID_SATURATION: | ||
737 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); | ||
738 | case V4L2_CID_HUE: | ||
739 | return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf); | ||
740 | case V4L2_CID_SHARPNESS: | ||
741 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
742 | } | ||
743 | } else { | ||
744 | switch (qc->id) { | ||
745 | case V4L2_CID_BRIGHTNESS: | ||
746 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); | ||
747 | case V4L2_CID_CONTRAST: | ||
748 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
749 | case V4L2_CID_SATURATION: | ||
750 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
751 | case V4L2_CID_HUE: | ||
752 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
753 | case V4L2_CID_SHARPNESS: | ||
754 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
755 | } | ||
756 | } | ||
757 | |||
758 | switch (qc->id) { | ||
759 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
760 | return v4l2_ctrl_query_fill( | ||
761 | qc, V4L2_MPEG_AUDIO_ENCODING_AAC, | ||
762 | ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 | ||
763 | : V4L2_MPEG_AUDIO_ENCODING_AAC, | ||
764 | 1, V4L2_MPEG_AUDIO_ENCODING_AAC); | ||
765 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
766 | return v4l2_ctrl_query_fill( | ||
767 | qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, | ||
768 | V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, | ||
769 | V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); | ||
770 | |||
771 | /* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ | ||
772 | /* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ | ||
773 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
774 | return v4l2_ctrl_query_fill( | ||
775 | qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | ||
776 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, | ||
777 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); | ||
778 | |||
779 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
780 | return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, | ||
781 | 6500000); | ||
782 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
783 | err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, | ||
784 | 9000000); | ||
785 | if (!err && opt->bitrate_mode == HDPVR_CONSTANT) | ||
786 | qc->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
787 | return err; | ||
788 | default: | ||
789 | return -EINVAL; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static int vidioc_queryctrl(struct file *file, void *private_data, | ||
794 | struct v4l2_queryctrl *qc) | ||
795 | { | ||
796 | struct hdpvr_fh *fh = file->private_data; | ||
797 | struct hdpvr_device *dev = fh->dev; | ||
798 | int i, next; | ||
799 | u32 id = qc->id; | ||
800 | |||
801 | memset(qc, 0, sizeof(*qc)); | ||
802 | |||
803 | next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); | ||
804 | qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; | ||
805 | |||
806 | for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { | ||
807 | if (next) { | ||
808 | if (qc->id < supported_v4l2_ctrls[i]) | ||
809 | qc->id = supported_v4l2_ctrls[i]; | ||
810 | else | ||
811 | continue; | ||
812 | } | ||
813 | |||
814 | if (qc->id == supported_v4l2_ctrls[i]) | ||
815 | return fill_queryctrl(&dev->options, qc, | ||
816 | dev->flags & HDPVR_FLAG_AC3_CAP, | ||
817 | dev->fw_ver); | ||
818 | |||
819 | if (qc->id < supported_v4l2_ctrls[i]) | ||
820 | break; | ||
821 | } | ||
822 | |||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
826 | static int vidioc_g_ctrl(struct file *file, void *private_data, | ||
827 | struct v4l2_control *ctrl) | ||
828 | { | ||
829 | struct hdpvr_fh *fh = file->private_data; | ||
830 | struct hdpvr_device *dev = fh->dev; | ||
831 | |||
832 | switch (ctrl->id) { | ||
833 | case V4L2_CID_BRIGHTNESS: | ||
834 | ctrl->value = dev->options.brightness; | ||
835 | break; | ||
836 | case V4L2_CID_CONTRAST: | ||
837 | ctrl->value = dev->options.contrast; | ||
838 | break; | ||
839 | case V4L2_CID_SATURATION: | ||
840 | ctrl->value = dev->options.saturation; | ||
841 | break; | ||
842 | case V4L2_CID_HUE: | ||
843 | ctrl->value = dev->options.hue; | ||
844 | break; | ||
845 | case V4L2_CID_SHARPNESS: | ||
846 | ctrl->value = dev->options.sharpness; | ||
847 | break; | ||
848 | default: | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static int vidioc_s_ctrl(struct file *file, void *private_data, | ||
855 | struct v4l2_control *ctrl) | ||
856 | { | ||
857 | struct hdpvr_fh *fh = file->private_data; | ||
858 | struct hdpvr_device *dev = fh->dev; | ||
859 | int retval; | ||
860 | |||
861 | switch (ctrl->id) { | ||
862 | case V4L2_CID_BRIGHTNESS: | ||
863 | retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); | ||
864 | if (!retval) | ||
865 | dev->options.brightness = ctrl->value; | ||
866 | break; | ||
867 | case V4L2_CID_CONTRAST: | ||
868 | retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); | ||
869 | if (!retval) | ||
870 | dev->options.contrast = ctrl->value; | ||
871 | break; | ||
872 | case V4L2_CID_SATURATION: | ||
873 | retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); | ||
874 | if (!retval) | ||
875 | dev->options.saturation = ctrl->value; | ||
876 | break; | ||
877 | case V4L2_CID_HUE: | ||
878 | retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); | ||
879 | if (!retval) | ||
880 | dev->options.hue = ctrl->value; | ||
881 | break; | ||
882 | case V4L2_CID_SHARPNESS: | ||
883 | retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); | ||
884 | if (!retval) | ||
885 | dev->options.sharpness = ctrl->value; | ||
886 | break; | ||
887 | default: | ||
888 | return -EINVAL; | ||
889 | } | ||
890 | |||
891 | return retval; | ||
892 | } | ||
893 | |||
894 | |||
895 | static int hdpvr_get_ctrl(struct hdpvr_options *opt, | ||
896 | struct v4l2_ext_control *ctrl) | ||
897 | { | ||
898 | switch (ctrl->id) { | ||
899 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
900 | ctrl->value = opt->audio_codec; | ||
901 | break; | ||
902 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
903 | ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; | ||
904 | break; | ||
905 | /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ | ||
906 | /* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ | ||
907 | /* break; */ | ||
908 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
909 | ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT | ||
910 | ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR | ||
911 | : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; | ||
912 | break; | ||
913 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
914 | ctrl->value = opt->bitrate * 100000; | ||
915 | break; | ||
916 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
917 | ctrl->value = opt->peak_bitrate * 100000; | ||
918 | break; | ||
919 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
920 | ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; | ||
921 | break; | ||
922 | default: | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static int vidioc_g_ext_ctrls(struct file *file, void *priv, | ||
929 | struct v4l2_ext_controls *ctrls) | ||
930 | { | ||
931 | struct hdpvr_fh *fh = file->private_data; | ||
932 | struct hdpvr_device *dev = fh->dev; | ||
933 | int i, err = 0; | ||
934 | |||
935 | if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | ||
936 | for (i = 0; i < ctrls->count; i++) { | ||
937 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
938 | |||
939 | err = hdpvr_get_ctrl(&dev->options, ctrl); | ||
940 | if (err) { | ||
941 | ctrls->error_idx = i; | ||
942 | break; | ||
943 | } | ||
944 | } | ||
945 | return err; | ||
946 | |||
947 | } | ||
948 | |||
949 | return -EINVAL; | ||
950 | } | ||
951 | |||
952 | |||
953 | static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) | ||
954 | { | ||
955 | int ret = -EINVAL; | ||
956 | |||
957 | switch (ctrl->id) { | ||
958 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
959 | if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || | ||
960 | (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) | ||
961 | ret = 0; | ||
962 | break; | ||
963 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
964 | if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) | ||
965 | ret = 0; | ||
966 | break; | ||
967 | /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ | ||
968 | /* if (ctrl->value == 0 || ctrl->value == 128) */ | ||
969 | /* ret = 0; */ | ||
970 | /* break; */ | ||
971 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
972 | if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || | ||
973 | ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) | ||
974 | ret = 0; | ||
975 | break; | ||
976 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
977 | { | ||
978 | uint bitrate = ctrl->value / 100000; | ||
979 | if (bitrate >= 10 && bitrate <= 135) | ||
980 | ret = 0; | ||
981 | break; | ||
982 | } | ||
983 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
984 | { | ||
985 | uint peak_bitrate = ctrl->value / 100000; | ||
986 | if (peak_bitrate >= 10 && peak_bitrate <= 202) | ||
987 | ret = 0; | ||
988 | break; | ||
989 | } | ||
990 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
991 | if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) | ||
992 | ret = 0; | ||
993 | break; | ||
994 | default: | ||
995 | return -EINVAL; | ||
996 | } | ||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | static int vidioc_try_ext_ctrls(struct file *file, void *priv, | ||
1001 | struct v4l2_ext_controls *ctrls) | ||
1002 | { | ||
1003 | struct hdpvr_fh *fh = file->private_data; | ||
1004 | struct hdpvr_device *dev = fh->dev; | ||
1005 | int i, err = 0; | ||
1006 | |||
1007 | if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | ||
1008 | for (i = 0; i < ctrls->count; i++) { | ||
1009 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
1010 | |||
1011 | err = hdpvr_try_ctrl(ctrl, | ||
1012 | dev->flags & HDPVR_FLAG_AC3_CAP); | ||
1013 | if (err) { | ||
1014 | ctrls->error_idx = i; | ||
1015 | break; | ||
1016 | } | ||
1017 | } | ||
1018 | return err; | ||
1019 | } | ||
1020 | |||
1021 | return -EINVAL; | ||
1022 | } | ||
1023 | |||
1024 | |||
1025 | static int hdpvr_set_ctrl(struct hdpvr_device *dev, | ||
1026 | struct v4l2_ext_control *ctrl) | ||
1027 | { | ||
1028 | struct hdpvr_options *opt = &dev->options; | ||
1029 | int ret = 0; | ||
1030 | |||
1031 | switch (ctrl->id) { | ||
1032 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
1033 | if (dev->flags & HDPVR_FLAG_AC3_CAP) { | ||
1034 | opt->audio_codec = ctrl->value; | ||
1035 | ret = hdpvr_set_audio(dev, opt->audio_input, | ||
1036 | opt->audio_codec); | ||
1037 | } | ||
1038 | break; | ||
1039 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
1040 | break; | ||
1041 | /* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ | ||
1042 | /* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ | ||
1043 | /* opt->gop_mode |= 0x2; */ | ||
1044 | /* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ | ||
1045 | /* opt->gop_mode); */ | ||
1046 | /* } */ | ||
1047 | /* if (ctrl->value == 128 && opt->gop_mode & 0x2) { */ | ||
1048 | /* opt->gop_mode &= ~0x2; */ | ||
1049 | /* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ | ||
1050 | /* opt->gop_mode); */ | ||
1051 | /* } */ | ||
1052 | /* break; */ | ||
1053 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
1054 | if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && | ||
1055 | opt->bitrate_mode != HDPVR_CONSTANT) { | ||
1056 | opt->bitrate_mode = HDPVR_CONSTANT; | ||
1057 | hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, | ||
1058 | opt->bitrate_mode); | ||
1059 | } | ||
1060 | if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && | ||
1061 | opt->bitrate_mode == HDPVR_CONSTANT) { | ||
1062 | opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; | ||
1063 | hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, | ||
1064 | opt->bitrate_mode); | ||
1065 | } | ||
1066 | break; | ||
1067 | case V4L2_CID_MPEG_VIDEO_BITRATE: { | ||
1068 | uint bitrate = ctrl->value / 100000; | ||
1069 | |||
1070 | opt->bitrate = bitrate; | ||
1071 | if (bitrate >= opt->peak_bitrate) | ||
1072 | opt->peak_bitrate = bitrate+1; | ||
1073 | |||
1074 | hdpvr_set_bitrate(dev); | ||
1075 | break; | ||
1076 | } | ||
1077 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { | ||
1078 | uint peak_bitrate = ctrl->value / 100000; | ||
1079 | |||
1080 | if (opt->bitrate_mode == HDPVR_CONSTANT) | ||
1081 | break; | ||
1082 | |||
1083 | if (opt->bitrate < peak_bitrate) { | ||
1084 | opt->peak_bitrate = peak_bitrate; | ||
1085 | hdpvr_set_bitrate(dev); | ||
1086 | } else | ||
1087 | ret = -EINVAL; | ||
1088 | break; | ||
1089 | } | ||
1090 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
1091 | break; | ||
1092 | default: | ||
1093 | return -EINVAL; | ||
1094 | } | ||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1098 | static int vidioc_s_ext_ctrls(struct file *file, void *priv, | ||
1099 | struct v4l2_ext_controls *ctrls) | ||
1100 | { | ||
1101 | struct hdpvr_fh *fh = file->private_data; | ||
1102 | struct hdpvr_device *dev = fh->dev; | ||
1103 | int i, err = 0; | ||
1104 | |||
1105 | if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | ||
1106 | for (i = 0; i < ctrls->count; i++) { | ||
1107 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
1108 | |||
1109 | err = hdpvr_try_ctrl(ctrl, | ||
1110 | dev->flags & HDPVR_FLAG_AC3_CAP); | ||
1111 | if (err) { | ||
1112 | ctrls->error_idx = i; | ||
1113 | break; | ||
1114 | } | ||
1115 | err = hdpvr_set_ctrl(dev, ctrl); | ||
1116 | if (err) { | ||
1117 | ctrls->error_idx = i; | ||
1118 | break; | ||
1119 | } | ||
1120 | } | ||
1121 | return err; | ||
1122 | |||
1123 | } | ||
1124 | |||
1125 | return -EINVAL; | ||
1126 | } | ||
1127 | |||
1128 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, | ||
1129 | struct v4l2_fmtdesc *f) | ||
1130 | { | ||
1131 | |||
1132 | if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1133 | return -EINVAL; | ||
1134 | |||
1135 | f->flags = V4L2_FMT_FLAG_COMPRESSED; | ||
1136 | strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32); | ||
1137 | f->pixelformat = V4L2_PIX_FMT_MPEG; | ||
1138 | |||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, | ||
1143 | struct v4l2_format *f) | ||
1144 | { | ||
1145 | struct hdpvr_fh *fh = file->private_data; | ||
1146 | struct hdpvr_device *dev = fh->dev; | ||
1147 | struct hdpvr_video_info *vid_info; | ||
1148 | |||
1149 | if (!dev) | ||
1150 | return -ENODEV; | ||
1151 | |||
1152 | vid_info = get_video_info(dev); | ||
1153 | if (!vid_info) | ||
1154 | return -EFAULT; | ||
1155 | |||
1156 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1157 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | ||
1158 | f->fmt.pix.width = vid_info->width; | ||
1159 | f->fmt.pix.height = vid_info->height; | ||
1160 | f->fmt.pix.sizeimage = dev->bulk_in_size; | ||
1161 | f->fmt.pix.colorspace = 0; | ||
1162 | f->fmt.pix.bytesperline = 0; | ||
1163 | f->fmt.pix.field = V4L2_FIELD_ANY; | ||
1164 | |||
1165 | kfree(vid_info); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | static int vidioc_encoder_cmd(struct file *filp, void *priv, | ||
1170 | struct v4l2_encoder_cmd *a) | ||
1171 | { | ||
1172 | struct hdpvr_fh *fh = filp->private_data; | ||
1173 | struct hdpvr_device *dev = fh->dev; | ||
1174 | int res; | ||
1175 | |||
1176 | mutex_lock(&dev->io_mutex); | ||
1177 | |||
1178 | memset(&a->raw, 0, sizeof(a->raw)); | ||
1179 | switch (a->cmd) { | ||
1180 | case V4L2_ENC_CMD_START: | ||
1181 | a->flags = 0; | ||
1182 | res = hdpvr_start_streaming(dev); | ||
1183 | break; | ||
1184 | case V4L2_ENC_CMD_STOP: | ||
1185 | res = hdpvr_stop_streaming(dev); | ||
1186 | break; | ||
1187 | default: | ||
1188 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | ||
1189 | "Unsupported encoder cmd %d\n", a->cmd); | ||
1190 | res = -EINVAL; | ||
1191 | } | ||
1192 | mutex_unlock(&dev->io_mutex); | ||
1193 | return res; | ||
1194 | } | ||
1195 | |||
1196 | static int vidioc_try_encoder_cmd(struct file *filp, void *priv, | ||
1197 | struct v4l2_encoder_cmd *a) | ||
1198 | { | ||
1199 | switch (a->cmd) { | ||
1200 | case V4L2_ENC_CMD_START: | ||
1201 | case V4L2_ENC_CMD_STOP: | ||
1202 | return 0; | ||
1203 | default: | ||
1204 | return -EINVAL; | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { | ||
1209 | .vidioc_querycap = vidioc_querycap, | ||
1210 | .vidioc_s_std = vidioc_s_std, | ||
1211 | .vidioc_enum_input = vidioc_enum_input, | ||
1212 | .vidioc_g_input = vidioc_g_input, | ||
1213 | .vidioc_s_input = vidioc_s_input, | ||
1214 | .vidioc_enumaudio = vidioc_enumaudio, | ||
1215 | .vidioc_g_audio = vidioc_g_audio, | ||
1216 | .vidioc_s_audio = vidioc_s_audio, | ||
1217 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1218 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1219 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1220 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, | ||
1221 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, | ||
1222 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, | ||
1223 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
1224 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
1225 | .vidioc_encoder_cmd = vidioc_encoder_cmd, | ||
1226 | .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd, | ||
1227 | }; | ||
1228 | |||
1229 | static void hdpvr_device_release(struct video_device *vdev) | ||
1230 | { | ||
1231 | struct hdpvr_device *dev = video_get_drvdata(vdev); | ||
1232 | |||
1233 | hdpvr_delete(dev); | ||
1234 | mutex_lock(&dev->io_mutex); | ||
1235 | destroy_workqueue(dev->workqueue); | ||
1236 | mutex_unlock(&dev->io_mutex); | ||
1237 | |||
1238 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1239 | |||
1240 | /* deregister I2C adapter */ | ||
1241 | #if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE) | ||
1242 | mutex_lock(&dev->i2c_mutex); | ||
1243 | i2c_del_adapter(&dev->i2c_adapter); | ||
1244 | mutex_unlock(&dev->i2c_mutex); | ||
1245 | #endif /* CONFIG_I2C */ | ||
1246 | |||
1247 | kfree(dev->usbc_buf); | ||
1248 | kfree(dev); | ||
1249 | } | ||
1250 | |||
1251 | static const struct video_device hdpvr_video_template = { | ||
1252 | /* .type = VFL_TYPE_GRABBER, */ | ||
1253 | /* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */ | ||
1254 | .fops = &hdpvr_fops, | ||
1255 | .release = hdpvr_device_release, | ||
1256 | .ioctl_ops = &hdpvr_ioctl_ops, | ||
1257 | .tvnorms = | ||
1258 | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_B | | ||
1259 | V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | | ||
1260 | V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | | ||
1261 | V4L2_STD_PAL_60, | ||
1262 | .current_norm = V4L2_STD_NTSC | V4L2_STD_PAL_M | | ||
1263 | V4L2_STD_PAL_60, | ||
1264 | }; | ||
1265 | |||
1266 | int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, | ||
1267 | int devnum) | ||
1268 | { | ||
1269 | /* setup and register video device */ | ||
1270 | dev->video_dev = video_device_alloc(); | ||
1271 | if (!dev->video_dev) { | ||
1272 | v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); | ||
1273 | goto error; | ||
1274 | } | ||
1275 | |||
1276 | *(dev->video_dev) = hdpvr_video_template; | ||
1277 | strcpy(dev->video_dev->name, "Hauppauge HD PVR"); | ||
1278 | dev->video_dev->parent = parent; | ||
1279 | video_set_drvdata(dev->video_dev, dev); | ||
1280 | |||
1281 | if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { | ||
1282 | v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); | ||
1283 | goto error; | ||
1284 | } | ||
1285 | |||
1286 | return 0; | ||
1287 | error: | ||
1288 | return -ENOMEM; | ||
1289 | } | ||
diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h new file mode 100644 index 000000000000..fea3c6926997 --- /dev/null +++ b/drivers/media/usb/hdpvr/hdpvr.h | |||
@@ -0,0 +1,317 @@ | |||
1 | /* | ||
2 | * Hauppauge HD PVR USB driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Janne Grunau (j@jannau.net) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/usb.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mutex.h> | ||
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/videodev2.h> | ||
17 | |||
18 | #include <media/v4l2-device.h> | ||
19 | #include <media/ir-kbd-i2c.h> | ||
20 | |||
21 | #define HDPVR_MAX 8 | ||
22 | #define HDPVR_I2C_MAX_SIZE 128 | ||
23 | |||
24 | /* Define these values to match your devices */ | ||
25 | #define HD_PVR_VENDOR_ID 0x2040 | ||
26 | #define HD_PVR_PRODUCT_ID 0x4900 | ||
27 | #define HD_PVR_PRODUCT_ID1 0x4901 | ||
28 | #define HD_PVR_PRODUCT_ID2 0x4902 | ||
29 | #define HD_PVR_PRODUCT_ID4 0x4903 | ||
30 | #define HD_PVR_PRODUCT_ID3 0x4982 | ||
31 | |||
32 | #define UNSET (-1U) | ||
33 | |||
34 | #define NUM_BUFFERS 64 | ||
35 | |||
36 | #define HDPVR_FIRMWARE_VERSION 0x08 | ||
37 | #define HDPVR_FIRMWARE_VERSION_AC3 0x0d | ||
38 | #define HDPVR_FIRMWARE_VERSION_0X12 0x12 | ||
39 | #define HDPVR_FIRMWARE_VERSION_0X15 0x15 | ||
40 | |||
41 | /* #define HDPVR_DEBUG */ | ||
42 | |||
43 | extern int hdpvr_debug; | ||
44 | |||
45 | #define MSG_INFO 1 | ||
46 | #define MSG_BUFFER 2 | ||
47 | |||
48 | struct hdpvr_options { | ||
49 | u8 video_std; | ||
50 | u8 video_input; | ||
51 | u8 audio_input; | ||
52 | u8 bitrate; /* in 100kbps */ | ||
53 | u8 peak_bitrate; /* in 100kbps */ | ||
54 | u8 bitrate_mode; | ||
55 | u8 gop_mode; | ||
56 | enum v4l2_mpeg_audio_encoding audio_codec; | ||
57 | u8 brightness; | ||
58 | u8 contrast; | ||
59 | u8 hue; | ||
60 | u8 saturation; | ||
61 | u8 sharpness; | ||
62 | }; | ||
63 | |||
64 | /* Structure to hold all of our device specific stuff */ | ||
65 | struct hdpvr_device { | ||
66 | /* the v4l device for this device */ | ||
67 | struct video_device *video_dev; | ||
68 | /* the usb device for this device */ | ||
69 | struct usb_device *udev; | ||
70 | /* v4l2-device unused */ | ||
71 | struct v4l2_device v4l2_dev; | ||
72 | |||
73 | /* the max packet size of the bulk endpoint */ | ||
74 | size_t bulk_in_size; | ||
75 | /* the address of the bulk in endpoint */ | ||
76 | __u8 bulk_in_endpointAddr; | ||
77 | |||
78 | /* holds the current device status */ | ||
79 | __u8 status; | ||
80 | /* count the number of openers */ | ||
81 | uint open_count; | ||
82 | |||
83 | /* holds the cureent set options */ | ||
84 | struct hdpvr_options options; | ||
85 | |||
86 | uint flags; | ||
87 | |||
88 | /* synchronize I/O */ | ||
89 | struct mutex io_mutex; | ||
90 | /* available buffers */ | ||
91 | struct list_head free_buff_list; | ||
92 | /* in progress buffers */ | ||
93 | struct list_head rec_buff_list; | ||
94 | /* waitqueue for buffers */ | ||
95 | wait_queue_head_t wait_buffer; | ||
96 | /* waitqueue for data */ | ||
97 | wait_queue_head_t wait_data; | ||
98 | /**/ | ||
99 | struct workqueue_struct *workqueue; | ||
100 | /**/ | ||
101 | struct work_struct worker; | ||
102 | |||
103 | /* I2C adapter */ | ||
104 | struct i2c_adapter i2c_adapter; | ||
105 | /* I2C lock */ | ||
106 | struct mutex i2c_mutex; | ||
107 | /* I2C message buffer space */ | ||
108 | char i2c_buf[HDPVR_I2C_MAX_SIZE]; | ||
109 | |||
110 | /* For passing data to ir-kbd-i2c */ | ||
111 | struct IR_i2c_init_data ir_i2c_init_data; | ||
112 | |||
113 | /* usb control transfer buffer and lock */ | ||
114 | struct mutex usbc_mutex; | ||
115 | u8 *usbc_buf; | ||
116 | u8 fw_ver; | ||
117 | }; | ||
118 | |||
119 | static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) | ||
120 | { | ||
121 | return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev); | ||
122 | } | ||
123 | |||
124 | |||
125 | /* buffer one bulk urb of data */ | ||
126 | struct hdpvr_buffer { | ||
127 | struct list_head buff_list; | ||
128 | |||
129 | struct urb *urb; | ||
130 | |||
131 | struct hdpvr_device *dev; | ||
132 | |||
133 | uint pos; | ||
134 | |||
135 | __u8 status; | ||
136 | }; | ||
137 | |||
138 | /* */ | ||
139 | |||
140 | struct hdpvr_video_info { | ||
141 | u16 width; | ||
142 | u16 height; | ||
143 | u8 fps; | ||
144 | }; | ||
145 | |||
146 | enum { | ||
147 | STATUS_UNINITIALIZED = 0, | ||
148 | STATUS_IDLE, | ||
149 | STATUS_STARTING, | ||
150 | STATUS_SHUTTING_DOWN, | ||
151 | STATUS_STREAMING, | ||
152 | STATUS_ERROR, | ||
153 | STATUS_DISCONNECTED, | ||
154 | }; | ||
155 | |||
156 | enum { | ||
157 | HDPVR_FLAG_AC3_CAP = 1, | ||
158 | }; | ||
159 | |||
160 | enum { | ||
161 | BUFSTAT_UNINITIALIZED = 0, | ||
162 | BUFSTAT_AVAILABLE, | ||
163 | BUFSTAT_INPROGRESS, | ||
164 | BUFSTAT_READY, | ||
165 | }; | ||
166 | |||
167 | #define CTRL_START_STREAMING_VALUE 0x0700 | ||
168 | #define CTRL_STOP_STREAMING_VALUE 0x0800 | ||
169 | #define CTRL_BITRATE_VALUE 0x1000 | ||
170 | #define CTRL_BITRATE_MODE_VALUE 0x1200 | ||
171 | #define CTRL_GOP_MODE_VALUE 0x1300 | ||
172 | #define CTRL_VIDEO_INPUT_VALUE 0x1500 | ||
173 | #define CTRL_VIDEO_STD_TYPE 0x1700 | ||
174 | #define CTRL_AUDIO_INPUT_VALUE 0x2500 | ||
175 | #define CTRL_BRIGHTNESS 0x2900 | ||
176 | #define CTRL_CONTRAST 0x2a00 | ||
177 | #define CTRL_HUE 0x2b00 | ||
178 | #define CTRL_SATURATION 0x2c00 | ||
179 | #define CTRL_SHARPNESS 0x2d00 | ||
180 | #define CTRL_LOW_PASS_FILTER_VALUE 0x3100 | ||
181 | |||
182 | #define CTRL_DEFAULT_INDEX 0x0003 | ||
183 | |||
184 | |||
185 | /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00 | ||
186 | * BITRATE SETTING | ||
187 | * 1st and 2nd byte (little endian): average bitrate in 100 000 bit/s | ||
188 | * min: 1 mbit/s, max: 13.5 mbit/s | ||
189 | * 3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s | ||
190 | * min: average + 100kbit/s, | ||
191 | * max: 20.2 mbit/s | ||
192 | */ | ||
193 | |||
194 | /* :0 s 38 01 1200 0003 0001 1 = 02 | ||
195 | * BIT RATE MODE | ||
196 | * constant = 1, variable (peak) = 2, variable (average) = 3 | ||
197 | */ | ||
198 | |||
199 | /* :0 s 38 01 1300 0003 0001 1 = 03 | ||
200 | * GOP MODE (2 bit) | ||
201 | * low bit 0/1: advanced/simple GOP | ||
202 | * high bit 0/1: IDR(4/32/128) / no IDR (4/32/0) | ||
203 | */ | ||
204 | |||
205 | /* :0 s 38 01 1700 0003 0001 1 = 00 | ||
206 | * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz | ||
207 | */ | ||
208 | |||
209 | /* :0 s 38 01 3100 0003 0004 4 = 03030000 | ||
210 | * FILTER CONTROL | ||
211 | * 1st byte luma low pass filter strength, | ||
212 | * 2nd byte chroma low pass filter strength, | ||
213 | * 3rd byte MF enable chroma, min=0, max=1 | ||
214 | * 4th byte n | ||
215 | */ | ||
216 | |||
217 | |||
218 | /* :0 s 38 b9 0001 0000 0000 0 */ | ||
219 | |||
220 | |||
221 | |||
222 | /* :0 s 38 d3 0000 0000 0001 1 = 00 */ | ||
223 | /* ret = usb_control_msg(dev->udev, */ | ||
224 | /* usb_sndctrlpipe(dev->udev, 0), */ | ||
225 | /* 0xd3, 0x38, */ | ||
226 | /* 0, 0, */ | ||
227 | /* "\0", 1, */ | ||
228 | /* 1000); */ | ||
229 | |||
230 | /* info("control request returned %d", ret); */ | ||
231 | /* msleep(5000); */ | ||
232 | |||
233 | |||
234 | /* :0 s b8 81 1400 0003 0005 5 < | ||
235 | * :0 0 5 = d0024002 19 | ||
236 | * QUERY FRAME SIZE AND RATE | ||
237 | * 1st and 2nd byte (little endian): horizontal resolution | ||
238 | * 3rd and 4th byte (little endian): vertical resolution | ||
239 | * 5th byte: frame rate | ||
240 | */ | ||
241 | |||
242 | /* :0 s b8 81 1800 0003 0003 3 < | ||
243 | * :0 0 3 = 030104 | ||
244 | * QUERY SIGNAL AND DETECTED LINES, maybe INPUT | ||
245 | */ | ||
246 | |||
247 | enum hdpvr_video_std { | ||
248 | HDPVR_60HZ = 0, | ||
249 | HDPVR_50HZ, | ||
250 | }; | ||
251 | |||
252 | enum hdpvr_video_input { | ||
253 | HDPVR_COMPONENT = 0, | ||
254 | HDPVR_SVIDEO, | ||
255 | HDPVR_COMPOSITE, | ||
256 | HDPVR_VIDEO_INPUTS | ||
257 | }; | ||
258 | |||
259 | enum hdpvr_audio_inputs { | ||
260 | HDPVR_RCA_BACK = 0, | ||
261 | HDPVR_RCA_FRONT, | ||
262 | HDPVR_SPDIF, | ||
263 | HDPVR_AUDIO_INPUTS | ||
264 | }; | ||
265 | |||
266 | enum hdpvr_bitrate_mode { | ||
267 | HDPVR_CONSTANT = 1, | ||
268 | HDPVR_VARIABLE_PEAK, | ||
269 | HDPVR_VARIABLE_AVERAGE, | ||
270 | }; | ||
271 | |||
272 | enum hdpvr_gop_mode { | ||
273 | HDPVR_ADVANCED_IDR_GOP = 0, | ||
274 | HDPVR_SIMPLE_IDR_GOP, | ||
275 | HDPVR_ADVANCED_NOIDR_GOP, | ||
276 | HDPVR_SIMPLE_NOIDR_GOP, | ||
277 | }; | ||
278 | |||
279 | void hdpvr_delete(struct hdpvr_device *dev); | ||
280 | |||
281 | /*========================================================================*/ | ||
282 | /* hardware control functions */ | ||
283 | int hdpvr_set_options(struct hdpvr_device *dev); | ||
284 | |||
285 | int hdpvr_set_bitrate(struct hdpvr_device *dev); | ||
286 | |||
287 | int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, | ||
288 | enum v4l2_mpeg_audio_encoding codec); | ||
289 | |||
290 | int hdpvr_config_call(struct hdpvr_device *dev, uint value, | ||
291 | unsigned char valbuf); | ||
292 | |||
293 | struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); | ||
294 | |||
295 | /* :0 s b8 81 1800 0003 0003 3 < */ | ||
296 | /* :0 0 3 = 0301ff */ | ||
297 | int get_input_lines_info(struct hdpvr_device *dev); | ||
298 | |||
299 | |||
300 | /*========================================================================*/ | ||
301 | /* v4l2 registration */ | ||
302 | int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, | ||
303 | int devnumber); | ||
304 | |||
305 | int hdpvr_cancel_queue(struct hdpvr_device *dev); | ||
306 | |||
307 | /*========================================================================*/ | ||
308 | /* i2c adapter registration */ | ||
309 | int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); | ||
310 | |||
311 | struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev); | ||
312 | struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev); | ||
313 | |||
314 | /*========================================================================*/ | ||
315 | /* buffer management */ | ||
316 | int hdpvr_free_buffers(struct hdpvr_device *dev); | ||
317 | int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count); | ||