diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-06-27 20:18:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:14:23 -0400 |
commit | 8b53b39d6228cda41b7ddfc9d094a072afca6655 (patch) | |
tree | b6ad8f7d5708e5ef4021895342c91af378f04097 /drivers/media/video | |
parent | e5e4cd8df61e602202f588dd545364dba37b4cc7 (diff) |
V4L/DVB (8151): saa7134-empress: fix MPEG control support
The MPEG controls could not be enumerated and so could not be read or set
through the v4l2-ctl utility or shown in control panels.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/saa7134/saa6752hs.c | 102 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-empress.c | 74 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-i2c.c | 2 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134.h | 1 |
4 files changed, 174 insertions, 5 deletions
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 002e70a33a4f..fc32c3f68af1 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -448,6 +448,104 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
448 | return 0; | 448 | return 0; |
449 | } | 449 | } |
450 | 450 | ||
451 | static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | ||
452 | struct v4l2_queryctrl *qctrl) | ||
453 | { | ||
454 | int err; | ||
455 | |||
456 | switch (qctrl->id) { | ||
457 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
458 | return v4l2_ctrl_query_fill(qctrl, | ||
459 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
460 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, | ||
461 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
462 | |||
463 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
464 | return v4l2_ctrl_query_fill(qctrl, | ||
465 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, | ||
466 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | ||
467 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | ||
468 | |||
469 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
470 | return v4l2_ctrl_query_fill(qctrl, | ||
471 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | ||
472 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1, | ||
473 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); | ||
474 | |||
475 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
476 | return v4l2_ctrl_query_fill(qctrl, | ||
477 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, | ||
478 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | ||
479 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
480 | |||
481 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
482 | return v4l2_ctrl_query_fill(qctrl, | ||
483 | V4L2_MPEG_VIDEO_ASPECT_4x3, | ||
484 | V4L2_MPEG_VIDEO_ASPECT_16x9, 1, | ||
485 | V4L2_MPEG_VIDEO_ASPECT_4x3); | ||
486 | |||
487 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
488 | err = v4l2_ctrl_query_fill_std(qctrl); | ||
489 | if (err == 0 && | ||
490 | params->vi_bitrate_mode == | ||
491 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | ||
492 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
493 | return err; | ||
494 | |||
495 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
496 | return v4l2_ctrl_query_fill(qctrl, | ||
497 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS, | ||
498 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1, | ||
499 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS); | ||
500 | |||
501 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
502 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
503 | case V4L2_CID_MPEG_STREAM_PID_PMT: | ||
504 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | ||
505 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | ||
506 | case V4L2_CID_MPEG_STREAM_PID_PCR: | ||
507 | return v4l2_ctrl_query_fill_std(qctrl); | ||
508 | |||
509 | default: | ||
510 | break; | ||
511 | } | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | |||
515 | static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params, | ||
516 | struct v4l2_querymenu *qmenu) | ||
517 | { | ||
518 | static const char *mpeg_audio_l2_bitrate[] = { | ||
519 | "", | ||
520 | "", | ||
521 | "", | ||
522 | "", | ||
523 | "", | ||
524 | "", | ||
525 | "", | ||
526 | "", | ||
527 | "", | ||
528 | "", | ||
529 | "", | ||
530 | "256 kbps", | ||
531 | "", | ||
532 | "384 kbps", | ||
533 | NULL | ||
534 | }; | ||
535 | struct v4l2_queryctrl qctrl; | ||
536 | int err; | ||
537 | |||
538 | qctrl.id = qmenu->id; | ||
539 | err = saa6752hs_qctrl(params, &qctrl); | ||
540 | if (err) | ||
541 | return err; | ||
542 | if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE) | ||
543 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | ||
544 | mpeg_audio_l2_bitrate); | ||
545 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | ||
546 | v4l2_ctrl_get_menu(qmenu->id)); | ||
547 | } | ||
548 | |||
451 | static int saa6752hs_init(struct i2c_client* client) | 549 | static int saa6752hs_init(struct i2c_client* client) |
452 | { | 550 | { |
453 | unsigned char buf[9], buf2[4]; | 551 | unsigned char buf[9], buf2[4]; |
@@ -662,6 +760,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
662 | } | 760 | } |
663 | h->params = params; | 761 | h->params = params; |
664 | break; | 762 | break; |
763 | case VIDIOC_QUERYCTRL: | ||
764 | return saa6752hs_qctrl(&h->params, arg); | ||
765 | case VIDIOC_QUERYMENU: | ||
766 | return saa6752hs_qmenu(&h->params, arg); | ||
665 | case VIDIOC_G_FMT: | 767 | case VIDIOC_G_FMT: |
666 | { | 768 | { |
667 | struct v4l2_format *f = arg; | 769 | struct v4l2_format *f = arg; |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index e11700eb3e5a..2a5ab957542d 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -294,10 +294,20 @@ static int empress_streamoff(struct file *file, void *priv, | |||
294 | return videobuf_streamoff(&dev->empress_tsq); | 294 | return videobuf_streamoff(&dev->empress_tsq); |
295 | } | 295 | } |
296 | 296 | ||
297 | static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
298 | unsigned int cmd, void *arg) | ||
299 | { | ||
300 | if (dev->mpeg_i2c_client == NULL) | ||
301 | return -EINVAL; | ||
302 | return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, | ||
303 | cmd, arg); | ||
304 | } | ||
305 | |||
297 | static int empress_s_ext_ctrls(struct file *file, void *priv, | 306 | static int empress_s_ext_ctrls(struct file *file, void *priv, |
298 | struct v4l2_ext_controls *ctrls) | 307 | struct v4l2_ext_controls *ctrls) |
299 | { | 308 | { |
300 | struct saa7134_dev *dev = file->private_data; | 309 | struct saa7134_dev *dev = file->private_data; |
310 | int err; | ||
301 | 311 | ||
302 | /* count == 0 is abused in saa6752hs.c, so that special | 312 | /* count == 0 is abused in saa6752hs.c, so that special |
303 | case is handled here explicitly. */ | 313 | case is handled here explicitly. */ |
@@ -307,10 +317,10 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, | |||
307 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 317 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
308 | return -EINVAL; | 318 | return -EINVAL; |
309 | 319 | ||
310 | saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, ctrls); | 320 | err = saa7134_i2c_call_saa6752(dev, VIDIOC_S_EXT_CTRLS, ctrls); |
311 | ts_init_encoder(dev); | 321 | ts_init_encoder(dev); |
312 | 322 | ||
313 | return 0; | 323 | return err; |
314 | } | 324 | } |
315 | 325 | ||
316 | static int empress_g_ext_ctrls(struct file *file, void *priv, | 326 | static int empress_g_ext_ctrls(struct file *file, void *priv, |
@@ -320,9 +330,62 @@ static int empress_g_ext_ctrls(struct file *file, void *priv, | |||
320 | 330 | ||
321 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 331 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
322 | return -EINVAL; | 332 | return -EINVAL; |
323 | saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, ctrls); | 333 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls); |
334 | } | ||
324 | 335 | ||
325 | return 0; | 336 | static int empress_queryctrl(struct file *file, void *priv, |
337 | struct v4l2_queryctrl *c) | ||
338 | { | ||
339 | static const u32 user_ctrls[] = { | ||
340 | V4L2_CID_USER_CLASS, | ||
341 | V4L2_CID_BRIGHTNESS, | ||
342 | V4L2_CID_CONTRAST, | ||
343 | V4L2_CID_SATURATION, | ||
344 | V4L2_CID_HUE, | ||
345 | V4L2_CID_AUDIO_VOLUME, | ||
346 | V4L2_CID_AUDIO_MUTE, | ||
347 | V4L2_CID_HFLIP, | ||
348 | 0 | ||
349 | }; | ||
350 | |||
351 | static const u32 mpeg_ctrls[] = { | ||
352 | V4L2_CID_MPEG_CLASS, | ||
353 | V4L2_CID_MPEG_STREAM_TYPE, | ||
354 | V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, | ||
355 | V4L2_CID_MPEG_AUDIO_ENCODING, | ||
356 | V4L2_CID_MPEG_AUDIO_L2_BITRATE, | ||
357 | V4L2_CID_MPEG_VIDEO_ENCODING, | ||
358 | V4L2_CID_MPEG_VIDEO_ASPECT, | ||
359 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | ||
360 | V4L2_CID_MPEG_VIDEO_BITRATE, | ||
361 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | ||
362 | 0 | ||
363 | }; | ||
364 | static const u32 *ctrl_classes[] = { | ||
365 | user_ctrls, | ||
366 | mpeg_ctrls, | ||
367 | NULL | ||
368 | }; | ||
369 | struct saa7134_dev *dev = file->private_data; | ||
370 | |||
371 | c->id = v4l2_ctrl_next(ctrl_classes, c->id); | ||
372 | if (c->id == 0) | ||
373 | return -EINVAL; | ||
374 | if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS) | ||
375 | return v4l2_ctrl_query_fill_std(c); | ||
376 | if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) | ||
377 | return saa7134_queryctrl(file, priv, c); | ||
378 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYCTRL, c); | ||
379 | } | ||
380 | |||
381 | static int empress_querymenu(struct file *file, void *priv, | ||
382 | struct v4l2_querymenu *c) | ||
383 | { | ||
384 | struct saa7134_dev *dev = file->private_data; | ||
385 | |||
386 | if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG) | ||
387 | return -EINVAL; | ||
388 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); | ||
326 | } | 389 | } |
327 | 390 | ||
328 | static const struct file_operations ts_fops = | 391 | static const struct file_operations ts_fops = |
@@ -363,7 +426,8 @@ static struct video_device saa7134_empress_template = | |||
363 | .vidioc_g_input = empress_g_input, | 426 | .vidioc_g_input = empress_g_input, |
364 | .vidioc_s_input = empress_s_input, | 427 | .vidioc_s_input = empress_s_input, |
365 | 428 | ||
366 | .vidioc_queryctrl = saa7134_queryctrl, | 429 | .vidioc_queryctrl = empress_queryctrl, |
430 | .vidioc_querymenu = empress_querymenu, | ||
367 | .vidioc_g_ctrl = saa7134_g_ctrl, | 431 | .vidioc_g_ctrl = saa7134_g_ctrl, |
368 | .vidioc_s_ctrl = saa7134_s_ctrl, | 432 | .vidioc_s_ctrl = saa7134_s_ctrl, |
369 | 433 | ||
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index d8af3863f2d3..5f713e637683 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -327,6 +327,8 @@ static int attach_inform(struct i2c_client *client) | |||
327 | 327 | ||
328 | d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", | 328 | d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", |
329 | client->driver->driver.name, client->addr, client->name); | 329 | client->driver->driver.name, client->addr, client->name); |
330 | if (client->addr == 0x20 && client->driver && client->driver->command) | ||
331 | dev->mpeg_i2c_client = client; | ||
330 | 332 | ||
331 | /* Am I an i2c remote control? */ | 333 | /* Am I an i2c remote control? */ |
332 | 334 | ||
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 0a94be7afc1e..4e491ad389ac 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -553,6 +553,7 @@ struct saa7134_dev { | |||
553 | struct saa7134_ts ts; | 553 | struct saa7134_ts ts; |
554 | struct saa7134_dmaqueue ts_q; | 554 | struct saa7134_dmaqueue ts_q; |
555 | struct saa7134_mpeg_ops *mops; | 555 | struct saa7134_mpeg_ops *mops; |
556 | struct i2c_client *mpeg_i2c_client; | ||
556 | 557 | ||
557 | /* SAA7134_MPEG_EMPRESS only */ | 558 | /* SAA7134_MPEG_EMPRESS only */ |
558 | struct video_device *empress_dev; | 559 | struct video_device *empress_dev; |