Commit | Line | Data |
---|---|---|
9aba42ef | 1 | /* |
e86da6f0 | 2 | * Hauppauge HD PVR USB driver - video 4 linux 2 interface |
9aba42ef JG |
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 | ||
9aba42ef JG |
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); | |
9ef77adf JG |
41 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, |
42 | "config call request for value 0x%x returned %d\n", value, | |
43 | ret); | |
9aba42ef JG |
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) { | |
9ef77adf | 58 | v4l2_err(&dev->v4l2_dev, "out of memory\n"); |
9aba42ef JG |
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); | |
9ef77adf JG |
79 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, |
80 | "get video info returned: %d, %s\n", ret, print_buf); | |
9aba42ef JG |
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); | |
9ef77adf JG |
112 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, |
113 | "get input lines info returned: %d, %s\n", ret, | |
114 | print_buf); | |
9aba42ef | 115 | } |
e92ba283 HV |
116 | #else |
117 | (void)ret; /* suppress compiler warning */ | |
9aba42ef JG |
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); | |
9ef77adf JG |
158 | v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", |
159 | codec); | |
9aba42ef JG |
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 | |
fe023ad1 | 173 | ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input); |
9aba42ef JG |
174 | error: |
175 | return ret; | |
176 | } | |
177 | ||
178 | int hdpvr_set_options(struct hdpvr_device *dev) | |
179 | { | |
1c2ca352 | 180 | hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); |
9aba42ef | 181 | |
1c2ca352 | 182 | hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, |
9aba42ef JG |
183 | dev->options.video_input+1); |
184 | ||
1c2ca352 | 185 | hdpvr_set_audio(dev, dev->options.audio_input+1, |
9aba42ef JG |
186 | dev->options.audio_codec); |
187 | ||
1c2ca352 MCC |
188 | hdpvr_set_bitrate(dev); |
189 | hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, | |
9aba42ef | 190 | dev->options.bitrate_mode); |
1c2ca352 | 191 | hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); |
9aba42ef | 192 | |
1c2ca352 MCC |
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); | |
9aba42ef | 198 | |
1c2ca352 | 199 | return 0; |
9aba42ef | 200 | } |