diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-04-27 17:39:37 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-07 14:29:40 -0400 |
commit | 4bd9ff19708ce8d88926121dda98423e36191c58 (patch) | |
tree | a171e65c5d69d6efa76a8a58c9a8381a72a59679 /drivers | |
parent | 77cf393434898d1299c77c32bdd0629b2b4df170 (diff) |
[media] radio-mr800: add hardware seek support
Added hardware seek support based on information gleaned from the
GPLv2 driver available here:
http://sourceforge.net/projects/av-usbradio/
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 255 |
1 files changed, 141 insertions, 114 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0b39a8cfee88..94cb6bc690f5 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -103,13 +103,17 @@ devices, that would be 76 and 91. */ | |||
103 | * List isn't full and will be updated with implementation of new functions | 103 | * List isn't full and will be updated with implementation of new functions |
104 | */ | 104 | */ |
105 | #define AMRADIO_SET_FREQ 0xa4 | 105 | #define AMRADIO_SET_FREQ 0xa4 |
106 | #define AMRADIO_GET_READY_FLAG 0xa5 | ||
106 | #define AMRADIO_GET_SIGNAL 0xa7 | 107 | #define AMRADIO_GET_SIGNAL 0xa7 |
108 | #define AMRADIO_GET_FREQ 0xa8 | ||
109 | #define AMRADIO_SET_SEARCH_UP 0xa9 | ||
110 | #define AMRADIO_SET_SEARCH_DOWN 0xaa | ||
107 | #define AMRADIO_SET_MUTE 0xab | 111 | #define AMRADIO_SET_MUTE 0xab |
112 | #define AMRADIO_SET_RIGHT_MUTE 0xac | ||
113 | #define AMRADIO_SET_LEFT_MUTE 0xad | ||
108 | #define AMRADIO_SET_MONO 0xae | 114 | #define AMRADIO_SET_MONO 0xae |
109 | 115 | #define AMRADIO_SET_SEARCH_LVL 0xb0 | |
110 | /* Comfortable defines for amradio_set_mute */ | 116 | #define AMRADIO_STOP_SEARCH 0xb1 |
111 | #define AMRADIO_START 0x00 | ||
112 | #define AMRADIO_STOP 0x01 | ||
113 | 117 | ||
114 | /* Comfortable defines for amradio_set_stereo */ | 118 | /* Comfortable defines for amradio_set_stereo */ |
115 | #define WANT_STEREO 0x00 | 119 | #define WANT_STEREO 0x00 |
@@ -129,7 +133,7 @@ struct amradio_device { | |||
129 | struct v4l2_device v4l2_dev; | 133 | struct v4l2_device v4l2_dev; |
130 | struct v4l2_ctrl_handler hdl; | 134 | struct v4l2_ctrl_handler hdl; |
131 | 135 | ||
132 | unsigned char *buffer; | 136 | u8 *buffer; |
133 | struct mutex lock; /* buffer locking */ | 137 | struct mutex lock; /* buffer locking */ |
134 | int curfreq; | 138 | int curfreq; |
135 | int stereo; | 139 | int stereo; |
@@ -141,8 +145,8 @@ static inline struct amradio_device *to_amradio_dev(struct v4l2_device *v4l2_dev | |||
141 | return container_of(v4l2_dev, struct amradio_device, v4l2_dev); | 145 | return container_of(v4l2_dev, struct amradio_device, v4l2_dev); |
142 | } | 146 | } |
143 | 147 | ||
144 | /* switch on/off the radio. Send 8 bytes to device */ | 148 | static int amradio_send_cmd(struct amradio_device *radio, u8 cmd, u8 arg, |
145 | static int amradio_set_mute(struct amradio_device *radio, char argument) | 149 | u8 *extra, u8 extralen, bool reply) |
146 | { | 150 | { |
147 | int retval; | 151 | int retval; |
148 | int size; | 152 | int size; |
@@ -150,117 +154,89 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) | |||
150 | radio->buffer[0] = 0x00; | 154 | radio->buffer[0] = 0x00; |
151 | radio->buffer[1] = 0x55; | 155 | radio->buffer[1] = 0x55; |
152 | radio->buffer[2] = 0xaa; | 156 | radio->buffer[2] = 0xaa; |
153 | radio->buffer[3] = 0x00; | 157 | radio->buffer[3] = extralen; |
154 | radio->buffer[4] = AMRADIO_SET_MUTE; | 158 | radio->buffer[4] = cmd; |
155 | radio->buffer[5] = argument; | 159 | radio->buffer[5] = arg; |
156 | radio->buffer[6] = 0x00; | 160 | radio->buffer[6] = 0x00; |
157 | radio->buffer[7] = 0x00; | 161 | radio->buffer[7] = extra || reply ? 8 : 0; |
158 | 162 | ||
159 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | 163 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), |
160 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | 164 | radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); |
161 | 165 | ||
162 | if (retval < 0 || size != BUFFER_LENGTH) { | 166 | if (retval < 0 || size != BUFFER_LENGTH) { |
163 | amradio_dev_warn(&radio->vdev.dev, "set mute failed\n"); | 167 | if (video_is_registered(&radio->vdev)) |
164 | return retval < 0 ? retval : -EIO; | 168 | amradio_dev_warn(&radio->vdev.dev, |
169 | "cmd %02x failed\n", cmd); | ||
170 | return retval ? retval : -EIO; | ||
165 | } | 171 | } |
166 | radio->muted = argument; | 172 | if (!extra && !reply) |
167 | return 0; | 173 | return 0; |
174 | |||
175 | if (extra) { | ||
176 | memcpy(radio->buffer, extra, extralen); | ||
177 | memset(radio->buffer + extralen, 0, 8 - extralen); | ||
178 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
179 | radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
180 | } else { | ||
181 | memset(radio->buffer, 0, 8); | ||
182 | retval = usb_bulk_msg(radio->usbdev, usb_rcvbulkpipe(radio->usbdev, 0x81), | ||
183 | radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
184 | } | ||
185 | if (retval == 0 && size == BUFFER_LENGTH) | ||
186 | return 0; | ||
187 | if (video_is_registered(&radio->vdev) && cmd != AMRADIO_GET_READY_FLAG) | ||
188 | amradio_dev_warn(&radio->vdev.dev, "follow-up to cmd %02x failed\n", cmd); | ||
189 | return retval ? retval : -EIO; | ||
190 | } | ||
191 | |||
192 | /* switch on/off the radio. Send 8 bytes to device */ | ||
193 | static int amradio_set_mute(struct amradio_device *radio, bool mute) | ||
194 | { | ||
195 | int ret = amradio_send_cmd(radio, | ||
196 | AMRADIO_SET_MUTE, mute, NULL, 0, false); | ||
197 | |||
198 | if (!ret) | ||
199 | radio->muted = mute; | ||
200 | return ret; | ||
168 | } | 201 | } |
169 | 202 | ||
170 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ | 203 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ |
171 | static int amradio_setfreq(struct amradio_device *radio, int freq) | 204 | static int amradio_set_freq(struct amradio_device *radio, int freq) |
172 | { | 205 | { |
173 | unsigned short freq_send = 0x10 + (freq >> 3) / 25; | 206 | unsigned short freq_send = 0x10 + (freq >> 3) / 25; |
207 | u8 buf[3]; | ||
174 | int retval; | 208 | int retval; |
175 | int size; | ||
176 | |||
177 | radio->buffer[0] = 0x00; | ||
178 | radio->buffer[1] = 0x55; | ||
179 | radio->buffer[2] = 0xaa; | ||
180 | radio->buffer[3] = 0x03; | ||
181 | radio->buffer[4] = AMRADIO_SET_FREQ; | ||
182 | radio->buffer[5] = 0x00; | ||
183 | radio->buffer[6] = 0x00; | ||
184 | radio->buffer[7] = 0x08; | ||
185 | |||
186 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
187 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
188 | |||
189 | if (retval < 0 || size != BUFFER_LENGTH) | ||
190 | goto out; | ||
191 | 209 | ||
192 | /* frequency is calculated from freq_send and placed in first 2 bytes */ | 210 | /* frequency is calculated from freq_send and placed in first 2 bytes */ |
193 | radio->buffer[0] = (freq_send >> 8) & 0xff; | 211 | buf[0] = (freq_send >> 8) & 0xff; |
194 | radio->buffer[1] = freq_send & 0xff; | 212 | buf[1] = freq_send & 0xff; |
195 | radio->buffer[2] = 0x01; | 213 | buf[2] = 0x01; |
196 | radio->buffer[3] = 0x00; | ||
197 | radio->buffer[4] = 0x00; | ||
198 | /* 5 and 6 bytes of buffer already = 0x00 */ | ||
199 | radio->buffer[7] = 0x00; | ||
200 | |||
201 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
202 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
203 | 214 | ||
204 | if (retval >= 0 && size == BUFFER_LENGTH) { | 215 | retval = amradio_send_cmd(radio, AMRADIO_SET_FREQ, 0, buf, 3, false); |
205 | radio->curfreq = freq; | 216 | if (retval) |
206 | return 0; | 217 | return retval; |
207 | } | 218 | radio->curfreq = freq; |
208 | 219 | msleep(40); | |
209 | out: | 220 | return 0; |
210 | amradio_dev_warn(&radio->vdev.dev, "set frequency failed\n"); | ||
211 | return retval < 0 ? retval : -EIO; | ||
212 | } | 221 | } |
213 | 222 | ||
214 | static int amradio_set_stereo(struct amradio_device *radio, char argument) | 223 | static int amradio_set_stereo(struct amradio_device *radio, bool stereo) |
215 | { | 224 | { |
216 | int retval; | 225 | int ret = amradio_send_cmd(radio, |
217 | int size; | 226 | AMRADIO_SET_MONO, !stereo, NULL, 0, false); |
218 | |||
219 | radio->buffer[0] = 0x00; | ||
220 | radio->buffer[1] = 0x55; | ||
221 | radio->buffer[2] = 0xaa; | ||
222 | radio->buffer[3] = 0x00; | ||
223 | radio->buffer[4] = AMRADIO_SET_MONO; | ||
224 | radio->buffer[5] = argument; | ||
225 | radio->buffer[6] = 0x00; | ||
226 | radio->buffer[7] = 0x00; | ||
227 | 227 | ||
228 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | 228 | if (!ret) |
229 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | 229 | radio->stereo = stereo; |
230 | 230 | return ret; | |
231 | if (retval < 0 || size != BUFFER_LENGTH) { | ||
232 | amradio_dev_warn(&radio->vdev.dev, "set stereo failed\n"); | ||
233 | return retval < 0 ? retval : -EIO; | ||
234 | } | ||
235 | |||
236 | radio->stereo = (argument == WANT_STEREO); | ||
237 | return 0; | ||
238 | } | 231 | } |
239 | 232 | ||
240 | static int amradio_get_stat(struct amradio_device *radio, bool *is_stereo, u32 *signal) | 233 | static int amradio_get_stat(struct amradio_device *radio, bool *is_stereo, u32 *signal) |
241 | { | 234 | { |
242 | int retval; | 235 | int ret = amradio_send_cmd(radio, |
243 | int size; | 236 | AMRADIO_GET_SIGNAL, 0, NULL, 0, true); |
244 | |||
245 | radio->buffer[0] = 0x00; | ||
246 | radio->buffer[1] = 0x55; | ||
247 | radio->buffer[2] = 0xaa; | ||
248 | radio->buffer[3] = 0x00; | ||
249 | radio->buffer[4] = AMRADIO_GET_SIGNAL; | ||
250 | radio->buffer[5] = 0x00; | ||
251 | radio->buffer[6] = 0x00; | ||
252 | radio->buffer[7] = 0x08; | ||
253 | |||
254 | retval = usb_bulk_msg(radio->usbdev, usb_sndbulkpipe(radio->usbdev, 0x02), | ||
255 | radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
256 | if (!retval) | ||
257 | retval = usb_bulk_msg(radio->usbdev, usb_rcvbulkpipe(radio->usbdev, 0x81), | ||
258 | radio->buffer, BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
259 | 237 | ||
260 | if (retval || size != BUFFER_LENGTH) { | 238 | if (ret) |
261 | amradio_dev_warn(&radio->vdev.dev, "get stat failed\n"); | 239 | return ret; |
262 | return retval; | ||
263 | } | ||
264 | *is_stereo = radio->buffer[2] >> 7; | 240 | *is_stereo = radio->buffer[2] >> 7; |
265 | *signal = (radio->buffer[3] & 0xf0) << 8; | 241 | *signal = (radio->buffer[3] & 0xf0) << 8; |
266 | return 0; | 242 | return 0; |
@@ -276,8 +252,9 @@ static void usb_amradio_disconnect(struct usb_interface *intf) | |||
276 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); | 252 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); |
277 | 253 | ||
278 | mutex_lock(&radio->lock); | 254 | mutex_lock(&radio->lock); |
279 | usb_set_intfdata(intf, NULL); | ||
280 | video_unregister_device(&radio->vdev); | 255 | video_unregister_device(&radio->vdev); |
256 | amradio_set_mute(radio, true); | ||
257 | usb_set_intfdata(intf, NULL); | ||
281 | v4l2_device_disconnect(&radio->v4l2_dev); | 258 | v4l2_device_disconnect(&radio->v4l2_dev); |
282 | mutex_unlock(&radio->lock); | 259 | mutex_unlock(&radio->lock); |
283 | v4l2_device_put(&radio->v4l2_dev); | 260 | v4l2_device_put(&radio->v4l2_dev); |
@@ -292,7 +269,8 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
292 | strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); | 269 | strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); |
293 | strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); | 270 | strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); |
294 | usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); | 271 | usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); |
295 | v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; | 272 | v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER | |
273 | V4L2_CAP_HW_FREQ_SEEK; | ||
296 | v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; | 274 | v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; |
297 | return 0; | 275 | return 0; |
298 | } | 276 | } |
@@ -350,7 +328,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
350 | 328 | ||
351 | if (f->tuner != 0) | 329 | if (f->tuner != 0) |
352 | return -EINVAL; | 330 | return -EINVAL; |
353 | return amradio_setfreq(radio, clamp_t(unsigned, f->frequency, | 331 | return amradio_set_freq(radio, clamp_t(unsigned, f->frequency, |
354 | FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL)); | 332 | FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL)); |
355 | } | 333 | } |
356 | 334 | ||
@@ -368,6 +346,59 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
368 | return 0; | 346 | return 0; |
369 | } | 347 | } |
370 | 348 | ||
349 | static int vidioc_s_hw_freq_seek(struct file *file, void *priv, | ||
350 | struct v4l2_hw_freq_seek *seek) | ||
351 | { | ||
352 | static u8 buf[8] = { | ||
353 | 0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08 | ||
354 | }; | ||
355 | struct amradio_device *radio = video_drvdata(file); | ||
356 | unsigned long timeout; | ||
357 | int retval; | ||
358 | |||
359 | if (seek->tuner != 0 || !seek->wrap_around) | ||
360 | return -EINVAL; | ||
361 | |||
362 | retval = amradio_send_cmd(radio, | ||
363 | AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false); | ||
364 | if (retval) | ||
365 | return retval; | ||
366 | amradio_set_freq(radio, radio->curfreq); | ||
367 | retval = amradio_send_cmd(radio, | ||
368 | seek->seek_upward ? AMRADIO_SET_SEARCH_UP : AMRADIO_SET_SEARCH_DOWN, | ||
369 | 0, NULL, 0, false); | ||
370 | if (retval) | ||
371 | return retval; | ||
372 | timeout = jiffies + msecs_to_jiffies(30000); | ||
373 | for (;;) { | ||
374 | if (time_after(jiffies, timeout)) { | ||
375 | retval = -EAGAIN; | ||
376 | break; | ||
377 | } | ||
378 | if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { | ||
379 | retval = -ERESTARTSYS; | ||
380 | break; | ||
381 | } | ||
382 | retval = amradio_send_cmd(radio, AMRADIO_GET_READY_FLAG, | ||
383 | 0, NULL, 0, true); | ||
384 | if (retval) | ||
385 | continue; | ||
386 | amradio_send_cmd(radio, AMRADIO_GET_FREQ, 0, NULL, 0, true); | ||
387 | if (radio->buffer[1] || radio->buffer[2]) { | ||
388 | radio->curfreq = (radio->buffer[1] << 8) | radio->buffer[2]; | ||
389 | radio->curfreq = (radio->curfreq - 0x10) * 200; | ||
390 | amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, | ||
391 | 0, NULL, 0, false); | ||
392 | amradio_set_freq(radio, radio->curfreq); | ||
393 | retval = 0; | ||
394 | break; | ||
395 | } | ||
396 | } | ||
397 | amradio_send_cmd(radio, AMRADIO_STOP_SEARCH, 0, NULL, 0, false); | ||
398 | amradio_set_freq(radio, radio->curfreq); | ||
399 | return retval; | ||
400 | } | ||
401 | |||
371 | static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl) | 402 | static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl) |
372 | { | 403 | { |
373 | struct amradio_device *radio = | 404 | struct amradio_device *radio = |
@@ -375,8 +406,7 @@ static int usb_amradio_s_ctrl(struct v4l2_ctrl *ctrl) | |||
375 | 406 | ||
376 | switch (ctrl->id) { | 407 | switch (ctrl->id) { |
377 | case V4L2_CID_AUDIO_MUTE: | 408 | case V4L2_CID_AUDIO_MUTE: |
378 | return amradio_set_mute(radio, | 409 | return amradio_set_mute(radio, ctrl->val); |
379 | ctrl->val ? AMRADIO_STOP : AMRADIO_START); | ||
380 | } | 410 | } |
381 | 411 | ||
382 | return -EINVAL; | 412 | return -EINVAL; |
@@ -386,19 +416,19 @@ static int usb_amradio_init(struct amradio_device *radio) | |||
386 | { | 416 | { |
387 | int retval; | 417 | int retval; |
388 | 418 | ||
389 | retval = amradio_set_mute(radio, AMRADIO_STOP); | 419 | retval = amradio_set_mute(radio, true); |
390 | if (retval) | 420 | if (retval) |
391 | goto out_err; | 421 | goto out_err; |
392 | 422 | retval = amradio_set_stereo(radio, true); | |
393 | retval = amradio_set_stereo(radio, WANT_STEREO); | ||
394 | if (retval) | 423 | if (retval) |
395 | goto out_err; | 424 | goto out_err; |
396 | 425 | retval = amradio_set_freq(radio, radio->curfreq); | |
397 | goto out; | 426 | if (retval) |
427 | goto out_err; | ||
428 | return 0; | ||
398 | 429 | ||
399 | out_err: | 430 | out_err: |
400 | amradio_dev_err(&radio->vdev.dev, "initialization failed\n"); | 431 | amradio_dev_err(&radio->vdev.dev, "initialization failed\n"); |
401 | out: | ||
402 | return retval; | 432 | return retval; |
403 | } | 433 | } |
404 | 434 | ||
@@ -409,8 +439,8 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) | |||
409 | 439 | ||
410 | mutex_lock(&radio->lock); | 440 | mutex_lock(&radio->lock); |
411 | if (!radio->muted) { | 441 | if (!radio->muted) { |
412 | amradio_set_mute(radio, AMRADIO_STOP); | 442 | amradio_set_mute(radio, true); |
413 | radio->muted = 0; | 443 | radio->muted = false; |
414 | } | 444 | } |
415 | mutex_unlock(&radio->lock); | 445 | mutex_unlock(&radio->lock); |
416 | 446 | ||
@@ -424,15 +454,11 @@ static int usb_amradio_resume(struct usb_interface *intf) | |||
424 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); | 454 | struct amradio_device *radio = to_amradio_dev(usb_get_intfdata(intf)); |
425 | 455 | ||
426 | mutex_lock(&radio->lock); | 456 | mutex_lock(&radio->lock); |
427 | if (radio->stereo) | 457 | amradio_set_stereo(radio, radio->stereo); |
428 | amradio_set_stereo(radio, WANT_STEREO); | 458 | amradio_set_freq(radio, radio->curfreq); |
429 | else | ||
430 | amradio_set_stereo(radio, WANT_MONO); | ||
431 | |||
432 | amradio_setfreq(radio, radio->curfreq); | ||
433 | 459 | ||
434 | if (!radio->muted) | 460 | if (!radio->muted) |
435 | amradio_set_mute(radio, AMRADIO_START); | 461 | amradio_set_mute(radio, false); |
436 | 462 | ||
437 | mutex_unlock(&radio->lock); | 463 | mutex_unlock(&radio->lock); |
438 | 464 | ||
@@ -459,6 +485,7 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { | |||
459 | .vidioc_s_tuner = vidioc_s_tuner, | 485 | .vidioc_s_tuner = vidioc_s_tuner, |
460 | .vidioc_g_frequency = vidioc_g_frequency, | 486 | .vidioc_g_frequency = vidioc_g_frequency, |
461 | .vidioc_s_frequency = vidioc_s_frequency, | 487 | .vidioc_s_frequency = vidioc_s_frequency, |
488 | .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, | ||
462 | .vidioc_log_status = v4l2_ctrl_log_status, | 489 | .vidioc_log_status = v4l2_ctrl_log_status, |
463 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | 490 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, |
464 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | 491 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |