diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-06-10 03:51:42 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-06-17 08:25:51 -0400 |
commit | bb732ccca29123850ffcacefe51cf2bc7d16e88c (patch) | |
tree | fae27af65020dc3218896ea4e7b5b3bc164deeeb /drivers/media/pci/saa7134/saa6752hs.c | |
parent | 04de560296158c481570a020748d1239e493617b (diff) |
[media] saa6752hs: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/pci/saa7134/saa6752hs.c')
-rw-r--r-- | drivers/media/pci/saa7134/saa6752hs.c | 457 |
1 files changed, 122 insertions, 335 deletions
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index 244b2868dfc8..8adb7b02ab5a 100644 --- a/drivers/media/pci/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
36 | #include <media/v4l2-device.h> | 36 | #include <media/v4l2-device.h> |
37 | #include <media/v4l2-ctrls.h> | ||
37 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
38 | #include <linux/init.h> | 39 | #include <linux/init.h> |
39 | #include <linux/crc32.h> | 40 | #include <linux/crc32.h> |
@@ -91,6 +92,12 @@ static const struct v4l2_format v4l2_format_table[] = | |||
91 | 92 | ||
92 | struct saa6752hs_state { | 93 | struct saa6752hs_state { |
93 | struct v4l2_subdev sd; | 94 | struct v4l2_subdev sd; |
95 | struct v4l2_ctrl_handler hdl; | ||
96 | struct { /* video bitrate mode control cluster */ | ||
97 | struct v4l2_ctrl *video_bitrate_mode; | ||
98 | struct v4l2_ctrl *video_bitrate; | ||
99 | struct v4l2_ctrl *video_bitrate_peak; | ||
100 | }; | ||
94 | u32 revision; | 101 | u32 revision; |
95 | int has_ac3; | 102 | int has_ac3; |
96 | struct saa6752hs_mpeg_params params; | 103 | struct saa6752hs_mpeg_params params; |
@@ -360,316 +367,72 @@ static int saa6752hs_set_bitrate(struct i2c_client *client, | |||
360 | return 0; | 367 | return 0; |
361 | } | 368 | } |
362 | 369 | ||
363 | 370 | static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl) | |
364 | static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, | ||
365 | struct v4l2_ext_control *ctrl) | ||
366 | { | 371 | { |
372 | struct saa6752hs_state *h = | ||
373 | container_of(ctrl->handler, struct saa6752hs_state, hdl); | ||
374 | |||
367 | switch (ctrl->id) { | 375 | switch (ctrl->id) { |
368 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
369 | ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; | ||
370 | break; | ||
371 | case V4L2_CID_MPEG_STREAM_PID_PMT: | ||
372 | ctrl->value = params->ts_pid_pmt; | ||
373 | break; | ||
374 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | ||
375 | ctrl->value = params->ts_pid_audio; | ||
376 | break; | ||
377 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | ||
378 | ctrl->value = params->ts_pid_video; | ||
379 | break; | ||
380 | case V4L2_CID_MPEG_STREAM_PID_PCR: | ||
381 | ctrl->value = params->ts_pid_pcr; | ||
382 | break; | ||
383 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
384 | ctrl->value = params->au_encoding; | ||
385 | break; | ||
386 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
387 | ctrl->value = params->au_l2_bitrate; | ||
388 | break; | ||
389 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
390 | if (!has_ac3) | ||
391 | return -EINVAL; | ||
392 | ctrl->value = params->au_ac3_bitrate; | ||
393 | break; | ||
394 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
395 | ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | ||
396 | break; | ||
397 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
398 | ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
399 | break; | ||
400 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
401 | ctrl->value = params->vi_aspect; | ||
402 | break; | ||
403 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
404 | ctrl->value = params->vi_bitrate * 1000; | ||
405 | break; | ||
406 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
407 | ctrl->value = params->vi_bitrate_peak * 1000; | ||
408 | break; | ||
409 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 376 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
410 | ctrl->value = params->vi_bitrate_mode; | 377 | /* peak bitrate shall be >= normal bitrate */ |
378 | if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && | ||
379 | h->video_bitrate_peak->val < h->video_bitrate->val) | ||
380 | h->video_bitrate_peak->val = h->video_bitrate->val; | ||
411 | break; | 381 | break; |
412 | default: | ||
413 | return -EINVAL; | ||
414 | } | 382 | } |
415 | return 0; | 383 | return 0; |
416 | } | 384 | } |
417 | 385 | ||
418 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, | 386 | static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl) |
419 | struct v4l2_ext_control *ctrl, int set) | ||
420 | { | 387 | { |
421 | int old = 0, new; | 388 | struct saa6752hs_state *h = |
389 | container_of(ctrl->handler, struct saa6752hs_state, hdl); | ||
390 | struct saa6752hs_mpeg_params *params = &h->params; | ||
422 | 391 | ||
423 | new = ctrl->value; | ||
424 | switch (ctrl->id) { | 392 | switch (ctrl->id) { |
425 | case V4L2_CID_MPEG_STREAM_TYPE: | 393 | case V4L2_CID_MPEG_STREAM_TYPE: |
426 | old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; | ||
427 | if (set && new != old) | ||
428 | return -ERANGE; | ||
429 | new = old; | ||
430 | break; | 394 | break; |
431 | case V4L2_CID_MPEG_STREAM_PID_PMT: | 395 | case V4L2_CID_MPEG_STREAM_PID_PMT: |
432 | old = params->ts_pid_pmt; | 396 | params->ts_pid_pmt = ctrl->val; |
433 | if (set && new > MPEG_PID_MAX) | ||
434 | return -ERANGE; | ||
435 | if (new > MPEG_PID_MAX) | ||
436 | new = MPEG_PID_MAX; | ||
437 | params->ts_pid_pmt = new; | ||
438 | break; | 397 | break; |
439 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | 398 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: |
440 | old = params->ts_pid_audio; | 399 | params->ts_pid_audio = ctrl->val; |
441 | if (set && new > MPEG_PID_MAX) | ||
442 | return -ERANGE; | ||
443 | if (new > MPEG_PID_MAX) | ||
444 | new = MPEG_PID_MAX; | ||
445 | params->ts_pid_audio = new; | ||
446 | break; | 400 | break; |
447 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | 401 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: |
448 | old = params->ts_pid_video; | 402 | params->ts_pid_video = ctrl->val; |
449 | if (set && new > MPEG_PID_MAX) | ||
450 | return -ERANGE; | ||
451 | if (new > MPEG_PID_MAX) | ||
452 | new = MPEG_PID_MAX; | ||
453 | params->ts_pid_video = new; | ||
454 | break; | 403 | break; |
455 | case V4L2_CID_MPEG_STREAM_PID_PCR: | 404 | case V4L2_CID_MPEG_STREAM_PID_PCR: |
456 | old = params->ts_pid_pcr; | 405 | params->ts_pid_pcr = ctrl->val; |
457 | if (set && new > MPEG_PID_MAX) | ||
458 | return -ERANGE; | ||
459 | if (new > MPEG_PID_MAX) | ||
460 | new = MPEG_PID_MAX; | ||
461 | params->ts_pid_pcr = new; | ||
462 | break; | 406 | break; |
463 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 407 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
464 | old = params->au_encoding; | 408 | params->au_encoding = ctrl->val; |
465 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && | ||
466 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) | ||
467 | return -ERANGE; | ||
468 | params->au_encoding = new; | ||
469 | break; | 409 | break; |
470 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 410 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
471 | old = params->au_l2_bitrate; | 411 | params->au_l2_bitrate = ctrl->val; |
472 | if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && | ||
473 | new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) | ||
474 | return -ERANGE; | ||
475 | if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) | ||
476 | new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; | ||
477 | else | ||
478 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | ||
479 | params->au_l2_bitrate = new; | ||
480 | break; | 412 | break; |
481 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | 413 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
482 | if (!has_ac3) | 414 | params->au_ac3_bitrate = ctrl->val; |
483 | return -EINVAL; | ||
484 | old = params->au_ac3_bitrate; | ||
485 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
486 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
487 | return -ERANGE; | ||
488 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
489 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
490 | else | ||
491 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
492 | params->au_ac3_bitrate = new; | ||
493 | break; | 415 | break; |
494 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 416 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
495 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | ||
496 | if (set && new != old) | ||
497 | return -ERANGE; | ||
498 | new = old; | ||
499 | break; | 417 | break; |
500 | case V4L2_CID_MPEG_VIDEO_ENCODING: | 418 | case V4L2_CID_MPEG_VIDEO_ENCODING: |
501 | old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
502 | if (set && new != old) | ||
503 | return -ERANGE; | ||
504 | new = old; | ||
505 | break; | 419 | break; |
506 | case V4L2_CID_MPEG_VIDEO_ASPECT: | 420 | case V4L2_CID_MPEG_VIDEO_ASPECT: |
507 | old = params->vi_aspect; | 421 | params->vi_aspect = ctrl->val; |
508 | if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && | ||
509 | new != V4L2_MPEG_VIDEO_ASPECT_4x3) | ||
510 | return -ERANGE; | ||
511 | if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) | ||
512 | new = V4L2_MPEG_VIDEO_ASPECT_4x3; | ||
513 | params->vi_aspect = new; | ||
514 | break; | ||
515 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
516 | old = params->vi_bitrate * 1000; | ||
517 | new = 1000 * (new / 1000); | ||
518 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
519 | return -ERANGE; | ||
520 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
521 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
522 | params->vi_bitrate = new / 1000; | ||
523 | break; | ||
524 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
525 | old = params->vi_bitrate_peak * 1000; | ||
526 | new = 1000 * (new / 1000); | ||
527 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
528 | return -ERANGE; | ||
529 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
530 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
531 | params->vi_bitrate_peak = new / 1000; | ||
532 | break; | 422 | break; |
533 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 423 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
534 | old = params->vi_bitrate_mode; | 424 | params->vi_bitrate_mode = ctrl->val; |
535 | params->vi_bitrate_mode = new; | 425 | params->vi_bitrate = h->video_bitrate->val / 1000; |
426 | params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000; | ||
427 | v4l2_ctrl_activate(h->video_bitrate_peak, | ||
428 | ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | ||
536 | break; | 429 | break; |
537 | default: | 430 | default: |
538 | return -EINVAL; | 431 | return -EINVAL; |
539 | } | 432 | } |
540 | ctrl->value = new; | ||
541 | return 0; | 433 | return 0; |
542 | } | 434 | } |
543 | 435 | ||
544 | |||
545 | static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) | ||
546 | { | ||
547 | struct saa6752hs_state *h = to_state(sd); | ||
548 | struct saa6752hs_mpeg_params *params = &h->params; | ||
549 | int err; | ||
550 | |||
551 | switch (qctrl->id) { | ||
552 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
553 | return v4l2_ctrl_query_fill(qctrl, | ||
554 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
555 | h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : | ||
556 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
557 | 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
558 | |||
559 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
560 | return v4l2_ctrl_query_fill(qctrl, | ||
561 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, | ||
562 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | ||
563 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | ||
564 | |||
565 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
566 | if (!h->has_ac3) | ||
567 | return -EINVAL; | ||
568 | return v4l2_ctrl_query_fill(qctrl, | ||
569 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
570 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, | ||
571 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K); | ||
572 | |||
573 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
574 | return v4l2_ctrl_query_fill(qctrl, | ||
575 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | ||
576 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1, | ||
577 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); | ||
578 | |||
579 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
580 | return v4l2_ctrl_query_fill(qctrl, | ||
581 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, | ||
582 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | ||
583 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
584 | |||
585 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
586 | return v4l2_ctrl_query_fill(qctrl, | ||
587 | V4L2_MPEG_VIDEO_ASPECT_4x3, | ||
588 | V4L2_MPEG_VIDEO_ASPECT_16x9, 1, | ||
589 | V4L2_MPEG_VIDEO_ASPECT_4x3); | ||
590 | |||
591 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
592 | err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); | ||
593 | if (err == 0 && | ||
594 | params->vi_bitrate_mode == | ||
595 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) | ||
596 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
597 | return err; | ||
598 | |||
599 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
600 | return v4l2_ctrl_query_fill(qctrl, | ||
601 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS, | ||
602 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1, | ||
603 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS); | ||
604 | |||
605 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
606 | return v4l2_ctrl_query_fill(qctrl, | ||
607 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | ||
608 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, | ||
609 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | ||
610 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
611 | return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); | ||
612 | case V4L2_CID_MPEG_STREAM_PID_PMT: | ||
613 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); | ||
614 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | ||
615 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); | ||
616 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | ||
617 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); | ||
618 | case V4L2_CID_MPEG_STREAM_PID_PCR: | ||
619 | return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); | ||
620 | |||
621 | default: | ||
622 | break; | ||
623 | } | ||
624 | return -EINVAL; | ||
625 | } | ||
626 | |||
627 | static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) | ||
628 | { | ||
629 | static const u32 mpeg_audio_encoding[] = { | ||
630 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
631 | V4L2_CTRL_MENU_IDS_END | ||
632 | }; | ||
633 | static const u32 mpeg_audio_ac3_encoding[] = { | ||
634 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
635 | V4L2_MPEG_AUDIO_ENCODING_AC3, | ||
636 | V4L2_CTRL_MENU_IDS_END | ||
637 | }; | ||
638 | static u32 mpeg_audio_l2_bitrate[] = { | ||
639 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, | ||
640 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, | ||
641 | V4L2_CTRL_MENU_IDS_END | ||
642 | }; | ||
643 | static u32 mpeg_audio_ac3_bitrate[] = { | ||
644 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
645 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
646 | V4L2_CTRL_MENU_IDS_END | ||
647 | }; | ||
648 | struct saa6752hs_state *h = to_state(sd); | ||
649 | struct v4l2_queryctrl qctrl; | ||
650 | int err; | ||
651 | |||
652 | qctrl.id = qmenu->id; | ||
653 | err = saa6752hs_queryctrl(sd, &qctrl); | ||
654 | if (err) | ||
655 | return err; | ||
656 | switch (qmenu->id) { | ||
657 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | ||
658 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
659 | mpeg_audio_l2_bitrate); | ||
660 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
661 | if (!h->has_ac3) | ||
662 | return -EINVAL; | ||
663 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
664 | mpeg_audio_ac3_bitrate); | ||
665 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
666 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
667 | h->has_ac3 ? mpeg_audio_ac3_encoding : | ||
668 | mpeg_audio_encoding); | ||
669 | } | ||
670 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); | ||
671 | } | ||
672 | |||
673 | static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) | 436 | static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) |
674 | { | 437 | { |
675 | unsigned char buf[9], buf2[4]; | 438 | unsigned char buf[9], buf2[4]; |
@@ -791,58 +554,6 @@ static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) | |||
791 | return 0; | 554 | return 0; |
792 | } | 555 | } |
793 | 556 | ||
794 | static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) | ||
795 | { | ||
796 | struct saa6752hs_state *h = to_state(sd); | ||
797 | struct saa6752hs_mpeg_params params; | ||
798 | int i; | ||
799 | |||
800 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
801 | return -EINVAL; | ||
802 | |||
803 | params = h->params; | ||
804 | for (i = 0; i < ctrls->count; i++) { | ||
805 | int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set); | ||
806 | |||
807 | if (err) { | ||
808 | ctrls->error_idx = i; | ||
809 | return err; | ||
810 | } | ||
811 | } | ||
812 | if (set) | ||
813 | h->params = params; | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) | ||
818 | { | ||
819 | return saa6752hs_do_ext_ctrls(sd, ctrls, 1); | ||
820 | } | ||
821 | |||
822 | static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) | ||
823 | { | ||
824 | return saa6752hs_do_ext_ctrls(sd, ctrls, 0); | ||
825 | } | ||
826 | |||
827 | static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) | ||
828 | { | ||
829 | struct saa6752hs_state *h = to_state(sd); | ||
830 | int i; | ||
831 | |||
832 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
833 | return -EINVAL; | ||
834 | |||
835 | for (i = 0; i < ctrls->count; i++) { | ||
836 | int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i); | ||
837 | |||
838 | if (err) { | ||
839 | ctrls->error_idx = i; | ||
840 | return err; | ||
841 | } | ||
842 | } | ||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) | 557 | static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) |
847 | { | 558 | { |
848 | struct saa6752hs_state *h = to_state(sd); | 559 | struct saa6752hs_state *h = to_state(sd); |
@@ -914,13 +625,20 @@ static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
914 | 625 | ||
915 | /* ----------------------------------------------------------------------- */ | 626 | /* ----------------------------------------------------------------------- */ |
916 | 627 | ||
628 | static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = { | ||
629 | .try_ctrl = saa6752hs_try_ctrl, | ||
630 | .s_ctrl = saa6752hs_s_ctrl, | ||
631 | }; | ||
632 | |||
917 | static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { | 633 | static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { |
918 | .init = saa6752hs_init, | 634 | .init = saa6752hs_init, |
919 | .queryctrl = saa6752hs_queryctrl, | 635 | .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, |
920 | .querymenu = saa6752hs_querymenu, | 636 | .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, |
921 | .g_ext_ctrls = saa6752hs_g_ext_ctrls, | 637 | .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, |
922 | .s_ext_ctrls = saa6752hs_s_ext_ctrls, | 638 | .g_ctrl = v4l2_subdev_g_ctrl, |
923 | .try_ext_ctrls = saa6752hs_try_ext_ctrls, | 639 | .s_ctrl = v4l2_subdev_s_ctrl, |
640 | .queryctrl = v4l2_subdev_queryctrl, | ||
641 | .querymenu = v4l2_subdev_querymenu, | ||
924 | .s_std = saa6752hs_s_std, | 642 | .s_std = saa6752hs_s_std, |
925 | }; | 643 | }; |
926 | 644 | ||
@@ -939,6 +657,7 @@ static int saa6752hs_probe(struct i2c_client *client, | |||
939 | { | 657 | { |
940 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | 658 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); |
941 | struct v4l2_subdev *sd; | 659 | struct v4l2_subdev *sd; |
660 | struct v4l2_ctrl_handler *hdl; | ||
942 | u8 addr = 0x13; | 661 | u8 addr = 0x13; |
943 | u8 data[12]; | 662 | u8 data[12]; |
944 | 663 | ||
@@ -955,9 +674,84 @@ static int saa6752hs_probe(struct i2c_client *client, | |||
955 | h->has_ac3 = 0; | 674 | h->has_ac3 = 0; |
956 | if (h->revision == 0x0206) { | 675 | if (h->revision == 0x0206) { |
957 | h->has_ac3 = 1; | 676 | h->has_ac3 = 1; |
958 | v4l_info(client, "support AC-3\n"); | 677 | v4l_info(client, "supports AC-3\n"); |
959 | } | 678 | } |
960 | h->params = param_defaults; | 679 | h->params = param_defaults; |
680 | |||
681 | hdl = &h->hdl; | ||
682 | v4l2_ctrl_handler_init(hdl, 14); | ||
683 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
684 | V4L2_CID_MPEG_AUDIO_ENCODING, | ||
685 | h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : | ||
686 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
687 | 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
688 | |||
689 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
690 | V4L2_CID_MPEG_AUDIO_L2_BITRATE, | ||
691 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, | ||
692 | ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) | | ||
693 | (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)), | ||
694 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | ||
695 | |||
696 | if (h->has_ac3) | ||
697 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
698 | V4L2_CID_MPEG_AUDIO_AC3_BITRATE, | ||
699 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
700 | ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | | ||
701 | (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)), | ||
702 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K); | ||
703 | |||
704 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
705 | V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, | ||
706 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | ||
707 | ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000), | ||
708 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); | ||
709 | |||
710 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
711 | V4L2_CID_MPEG_VIDEO_ENCODING, | ||
712 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, | ||
713 | ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2), | ||
714 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
715 | |||
716 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
717 | V4L2_CID_MPEG_VIDEO_ASPECT, | ||
718 | V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01, | ||
719 | V4L2_MPEG_VIDEO_ASPECT_4x3); | ||
720 | |||
721 | h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
722 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | ||
723 | 1000000, 27000000, 1000, 8000000); | ||
724 | |||
725 | v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
726 | V4L2_CID_MPEG_STREAM_TYPE, | ||
727 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS, | ||
728 | ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS), | ||
729 | V4L2_MPEG_STREAM_TYPE_MPEG2_TS); | ||
730 | |||
731 | h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, | ||
732 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | ||
733 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, | ||
734 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | ||
735 | h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
736 | V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000); | ||
737 | v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
738 | V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16); | ||
739 | v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
740 | V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260); | ||
741 | v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
742 | V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256); | ||
743 | v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, | ||
744 | V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259); | ||
745 | sd->ctrl_handler = hdl; | ||
746 | if (hdl->error) { | ||
747 | int err = hdl->error; | ||
748 | |||
749 | v4l2_ctrl_handler_free(hdl); | ||
750 | kfree(h); | ||
751 | return err; | ||
752 | } | ||
753 | v4l2_ctrl_cluster(3, &h->video_bitrate_mode); | ||
754 | v4l2_ctrl_handler_setup(hdl); | ||
961 | h->standard = 0; /* Assume 625 input lines */ | 755 | h->standard = 0; /* Assume 625 input lines */ |
962 | return 0; | 756 | return 0; |
963 | } | 757 | } |
@@ -967,6 +761,7 @@ static int saa6752hs_remove(struct i2c_client *client) | |||
967 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | 761 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
968 | 762 | ||
969 | v4l2_device_unregister_subdev(sd); | 763 | v4l2_device_unregister_subdev(sd); |
764 | v4l2_ctrl_handler_free(&to_state(sd)->hdl); | ||
970 | kfree(to_state(sd)); | 765 | kfree(to_state(sd)); |
971 | return 0; | 766 | return 0; |
972 | } | 767 | } |
@@ -988,11 +783,3 @@ static struct i2c_driver saa6752hs_driver = { | |||
988 | }; | 783 | }; |
989 | 784 | ||
990 | module_i2c_driver(saa6752hs_driver); | 785 | module_i2c_driver(saa6752hs_driver); |
991 | |||
992 | /* | ||
993 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
994 | * --------------------------------------------------------------------------- | ||
995 | * Local variables: | ||
996 | * c-basic-offset: 8 | ||
997 | * End: | ||
998 | */ | ||