diff options
| -rw-r--r-- | drivers/media/video/cx2341x.c | 747 | ||||
| -rw-r--r-- | include/media/cx2341x.h | 97 |
2 files changed, 732 insertions, 112 deletions
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 2bf44ef10fec..e5c3c8da4be3 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
| @@ -38,6 +38,145 @@ static int debug; | |||
| 38 | module_param(debug, int, 0644); | 38 | module_param(debug, int, 0644); |
| 39 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 39 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
| 40 | 40 | ||
| 41 | /********************** COMMON CODE *********************/ | ||
| 42 | |||
| 43 | /* definitions for audio properties bits 29-28 */ | ||
| 44 | #define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0 | ||
| 45 | #define CX2341X_AUDIO_ENCODING_METHOD_AC3 1 | ||
| 46 | #define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2 | ||
| 47 | |||
| 48 | static const char *cx2341x_get_name(u32 id) | ||
| 49 | { | ||
| 50 | switch (id) { | ||
| 51 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 52 | return "Spatial Filter Mode"; | ||
| 53 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
| 54 | return "Spatial Filter"; | ||
| 55 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
| 56 | return "Spatial Luma Filter Type"; | ||
| 57 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
| 58 | return "Spatial Chroma Filter Type"; | ||
| 59 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 60 | return "Temporal Filter Mode"; | ||
| 61 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
| 62 | return "Temporal Filter"; | ||
| 63 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 64 | return "Median Filter Type"; | ||
| 65 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
| 66 | return "Median Luma Filter Maximum"; | ||
| 67 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
| 68 | return "Median Luma Filter Minimum"; | ||
| 69 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
| 70 | return "Median Chroma Filter Maximum"; | ||
| 71 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
| 72 | return "Median Chroma Filter Minimum"; | ||
| 73 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: | ||
| 74 | return "Insert Navigation Packets"; | ||
| 75 | } | ||
| 76 | return NULL; | ||
| 77 | } | ||
| 78 | |||
| 79 | static const char **cx2341x_get_menu(u32 id) | ||
| 80 | { | ||
| 81 | static const char *cx2341x_video_spatial_filter_mode_menu[] = { | ||
| 82 | "Manual", | ||
| 83 | "Auto", | ||
| 84 | NULL | ||
| 85 | }; | ||
| 86 | |||
| 87 | static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { | ||
| 88 | "Off", | ||
| 89 | "1D Horizontal", | ||
| 90 | "1D Vertical", | ||
| 91 | "2D H/V Separable", | ||
| 92 | "2D Symmetric non-separable", | ||
| 93 | NULL | ||
| 94 | }; | ||
| 95 | |||
| 96 | static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { | ||
| 97 | "Off", | ||
| 98 | "1D Horizontal", | ||
| 99 | NULL | ||
| 100 | }; | ||
| 101 | |||
| 102 | static const char *cx2341x_video_temporal_filter_mode_menu[] = { | ||
| 103 | "Manual", | ||
| 104 | "Auto", | ||
| 105 | NULL | ||
| 106 | }; | ||
| 107 | |||
| 108 | static const char *cx2341x_video_median_filter_type_menu[] = { | ||
| 109 | "Off", | ||
| 110 | "Horizontal", | ||
| 111 | "Vertical", | ||
| 112 | "Horizontal/Vertical", | ||
| 113 | "Diagonal", | ||
| 114 | NULL | ||
| 115 | }; | ||
| 116 | |||
| 117 | switch (id) { | ||
| 118 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 119 | return cx2341x_video_spatial_filter_mode_menu; | ||
| 120 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
| 121 | return cx2341x_video_luma_spatial_filter_type_menu; | ||
| 122 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
| 123 | return cx2341x_video_chroma_spatial_filter_type_menu; | ||
| 124 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 125 | return cx2341x_video_temporal_filter_mode_menu; | ||
| 126 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 127 | return cx2341x_video_median_filter_type_menu; | ||
| 128 | } | ||
| 129 | return NULL; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | ||
| 133 | s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags) | ||
| 134 | { | ||
| 135 | *name = cx2341x_get_name(id); | ||
| 136 | *flags = 0; | ||
| 137 | |||
| 138 | switch (id) { | ||
| 139 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 140 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
| 141 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
| 142 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 143 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 144 | *type = V4L2_CTRL_TYPE_MENU; | ||
| 145 | *min = 0; | ||
| 146 | *step = 0; | ||
| 147 | break; | ||
| 148 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: | ||
| 149 | *type = V4L2_CTRL_TYPE_BOOLEAN; | ||
| 150 | *min = 0; | ||
| 151 | *max = *step = 1; | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | *type = V4L2_CTRL_TYPE_INTEGER; | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | switch (id) { | ||
| 158 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 159 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 160 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 161 | *flags |= V4L2_CTRL_FLAG_UPDATE; | ||
| 162 | break; | ||
| 163 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
| 164 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | ||
| 165 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
| 166 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | ||
| 167 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | ||
| 168 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | ||
| 169 | *flags |= V4L2_CTRL_FLAG_SLIDER; | ||
| 170 | break; | ||
| 171 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
| 172 | *flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 173 | break; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | |||
| 178 | /********************** OLD CODE *********************/ | ||
| 179 | |||
| 41 | /* Must be sorted from low to high control ID! */ | 180 | /* Must be sorted from low to high control ID! */ |
| 42 | const u32 cx2341x_mpeg_ctrls[] = { | 181 | const u32 cx2341x_mpeg_ctrls[] = { |
| 43 | V4L2_CID_MPEG_CLASS, | 182 | V4L2_CID_MPEG_CLASS, |
| @@ -134,8 +273,6 @@ static const struct cx2341x_mpeg_params default_params = { | |||
| 134 | .video_chroma_median_filter_top = 255, | 273 | .video_chroma_median_filter_top = 255, |
| 135 | .video_chroma_median_filter_bottom = 0, | 274 | .video_chroma_median_filter_bottom = 0, |
| 136 | }; | 275 | }; |
| 137 | |||
| 138 | |||
| 139 | /* Map the control ID to the correct field in the cx2341x_mpeg_params | 276 | /* Map the control ID to the correct field in the cx2341x_mpeg_params |
| 140 | struct. Return -EINVAL if the ID is unknown, else return 0. */ | 277 | struct. Return -EINVAL if the ID is unknown, else return 0. */ |
| 141 | static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, | 278 | static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params, |
| @@ -415,83 +552,33 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, | |||
| 415 | { | 552 | { |
| 416 | const char *name; | 553 | const char *name; |
| 417 | 554 | ||
| 418 | qctrl->flags = 0; | ||
| 419 | switch (qctrl->id) { | 555 | switch (qctrl->id) { |
| 420 | /* MPEG controls */ | 556 | /* MPEG controls */ |
| 421 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | 557 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: |
| 422 | name = "Spatial Filter Mode"; | ||
| 423 | break; | ||
| 424 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | 558 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: |
| 425 | name = "Spatial Filter"; | ||
| 426 | break; | ||
| 427 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | 559 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: |
| 428 | name = "Spatial Luma Filter Type"; | ||
| 429 | break; | ||
| 430 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | 560 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: |
| 431 | name = "Spatial Chroma Filter Type"; | ||
| 432 | break; | ||
| 433 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | 561 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: |
| 434 | name = "Temporal Filter Mode"; | ||
| 435 | break; | ||
| 436 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: | 562 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: |
| 437 | name = "Temporal Filter"; | ||
| 438 | break; | ||
| 439 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | 563 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: |
| 440 | name = "Median Filter Type"; | ||
| 441 | break; | ||
| 442 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | 564 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: |
| 443 | name = "Median Luma Filter Maximum"; | ||
| 444 | break; | ||
| 445 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: | 565 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: |
| 446 | name = "Median Luma Filter Minimum"; | ||
| 447 | break; | ||
| 448 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: | 566 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: |
| 449 | name = "Median Chroma Filter Maximum"; | ||
| 450 | break; | ||
| 451 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: | 567 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: |
| 452 | name = "Median Chroma Filter Minimum"; | ||
| 453 | break; | ||
| 454 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: | 568 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: |
| 455 | name = "Insert Navigation Packets"; | 569 | cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type, |
| 456 | break; | 570 | &min, &max, &step, &def, &qctrl->flags); |
| 571 | qctrl->minimum = min; | ||
| 572 | qctrl->maximum = max; | ||
| 573 | qctrl->step = step; | ||
| 574 | qctrl->default_value = def; | ||
| 575 | qctrl->reserved[0] = qctrl->reserved[1] = 0; | ||
| 576 | strlcpy(qctrl->name, name, sizeof(qctrl->name)); | ||
| 577 | return 0; | ||
| 457 | 578 | ||
| 458 | default: | 579 | default: |
| 459 | return v4l2_ctrl_query_fill(qctrl, min, max, step, def); | 580 | return v4l2_ctrl_query_fill(qctrl, min, max, step, def); |
| 460 | } | 581 | } |
| 461 | switch (qctrl->id) { | ||
| 462 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 463 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
| 464 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | ||
| 465 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 466 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 467 | qctrl->type = V4L2_CTRL_TYPE_MENU; | ||
| 468 | min = 0; | ||
| 469 | step = 1; | ||
| 470 | break; | ||
| 471 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: | ||
| 472 | qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; | ||
| 473 | min = 0; | ||
| 474 | max = 1; | ||
| 475 | step = 1; | ||
| 476 | break; | ||
| 477 | default: | ||
| 478 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | switch (qctrl->id) { | ||
| 482 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | ||
| 483 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | ||
| 484 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | ||
| 485 | qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; | ||
| 486 | break; | ||
| 487 | } | ||
| 488 | qctrl->minimum = min; | ||
| 489 | qctrl->maximum = max; | ||
| 490 | qctrl->step = step; | ||
| 491 | qctrl->default_value = def; | ||
| 492 | qctrl->reserved[0] = qctrl->reserved[1] = 0; | ||
| 493 | snprintf(qctrl->name, sizeof(qctrl->name), name); | ||
| 494 | return 0; | ||
| 495 | } | 582 | } |
| 496 | 583 | ||
| 497 | int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, | 584 | int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, |
| @@ -797,42 +884,6 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) | |||
| 797 | NULL | 884 | NULL |
| 798 | }; | 885 | }; |
| 799 | 886 | ||
| 800 | static const char *cx2341x_video_spatial_filter_mode_menu[] = { | ||
| 801 | "Manual", | ||
| 802 | "Auto", | ||
| 803 | NULL | ||
| 804 | }; | ||
| 805 | |||
| 806 | static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { | ||
| 807 | "Off", | ||
| 808 | "1D Horizontal", | ||
| 809 | "1D Vertical", | ||
| 810 | "2D H/V Separable", | ||
| 811 | "2D Symmetric non-separable", | ||
| 812 | NULL | ||
| 813 | }; | ||
| 814 | |||
| 815 | static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { | ||
| 816 | "Off", | ||
| 817 | "1D Horizontal", | ||
| 818 | NULL | ||
| 819 | }; | ||
| 820 | |||
| 821 | static const char *cx2341x_video_temporal_filter_mode_menu[] = { | ||
| 822 | "Manual", | ||
| 823 | "Auto", | ||
| 824 | NULL | ||
| 825 | }; | ||
| 826 | |||
| 827 | static const char *cx2341x_video_median_filter_type_menu[] = { | ||
| 828 | "Off", | ||
| 829 | "Horizontal", | ||
| 830 | "Vertical", | ||
| 831 | "Horizontal/Vertical", | ||
| 832 | "Diagonal", | ||
| 833 | NULL | ||
| 834 | }; | ||
| 835 | |||
| 836 | switch (id) { | 887 | switch (id) { |
| 837 | case V4L2_CID_MPEG_STREAM_TYPE: | 888 | case V4L2_CID_MPEG_STREAM_TYPE: |
| 838 | return (p->capabilities & CX2341X_CAP_HAS_TS) ? | 889 | return (p->capabilities & CX2341X_CAP_HAS_TS) ? |
| @@ -844,26 +895,17 @@ const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id) | |||
| 844 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | 895 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: |
| 845 | return NULL; | 896 | return NULL; |
| 846 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: | 897 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: |
| 847 | return cx2341x_video_spatial_filter_mode_menu; | ||
| 848 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | 898 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: |
| 849 | return cx2341x_video_luma_spatial_filter_type_menu; | ||
| 850 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: | 899 | case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: |
| 851 | return cx2341x_video_chroma_spatial_filter_type_menu; | ||
| 852 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: | 900 | case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: |
| 853 | return cx2341x_video_temporal_filter_mode_menu; | ||
| 854 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: | 901 | case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: |
| 855 | return cx2341x_video_median_filter_type_menu; | 902 | return cx2341x_get_menu(id); |
| 856 | default: | 903 | default: |
| 857 | return v4l2_ctrl_get_menu(id); | 904 | return v4l2_ctrl_get_menu(id); |
| 858 | } | 905 | } |
| 859 | } | 906 | } |
| 860 | EXPORT_SYMBOL(cx2341x_ctrl_get_menu); | 907 | EXPORT_SYMBOL(cx2341x_ctrl_get_menu); |
| 861 | 908 | ||
| 862 | /* definitions for audio properties bits 29-28 */ | ||
| 863 | #define CX2341X_AUDIO_ENCODING_METHOD_MPEG 0 | ||
| 864 | #define CX2341X_AUDIO_ENCODING_METHOD_AC3 1 | ||
| 865 | #define CX2341X_AUDIO_ENCODING_METHOD_LPCM 2 | ||
| 866 | |||
| 867 | static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) | 909 | static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) |
| 868 | { | 910 | { |
| 869 | params->audio_properties = | 911 | params->audio_properties = |
| @@ -1195,9 +1237,490 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) | |||
| 1195 | } | 1237 | } |
| 1196 | EXPORT_SYMBOL(cx2341x_log_status); | 1238 | EXPORT_SYMBOL(cx2341x_log_status); |
| 1197 | 1239 | ||
| 1198 | /* | ||
| 1199 | * Local variables: | ||
| 1200 | * c-basic-offset: 8 | ||
| 1201 | * End: | ||
| 1202 | */ | ||
| 1203 | 1240 | ||
| 1241 | |||
| 1242 | /********************** NEW CODE *********************/ | ||
| 1243 | |||
| 1244 | static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl) | ||
| 1245 | { | ||
| 1246 | return container_of(ctrl->handler, struct cx2341x_handler, hdl); | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | static int cx2341x_hdl_api(struct cx2341x_handler *hdl, | ||
| 1250 | u32 cmd, int args, ...) | ||
| 1251 | { | ||
| 1252 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
| 1253 | va_list vargs; | ||
| 1254 | int i; | ||
| 1255 | |||
| 1256 | va_start(vargs, args); | ||
| 1257 | |||
| 1258 | for (i = 0; i < args; i++) | ||
| 1259 | data[i] = va_arg(vargs, int); | ||
| 1260 | va_end(vargs); | ||
| 1261 | return hdl->func(hdl->priv, cmd, args, 0, data); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | /* ctrl->handler->lock is held, so it is safe to access cur.val */ | ||
| 1265 | static inline int cx2341x_neq(struct v4l2_ctrl *ctrl) | ||
| 1266 | { | ||
| 1267 | return ctrl && ctrl->val != ctrl->cur.val; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1271 | { | ||
| 1272 | struct cx2341x_handler *hdl = to_cxhdl(ctrl); | ||
| 1273 | s32 val = ctrl->val; | ||
| 1274 | |||
| 1275 | switch (ctrl->id) { | ||
| 1276 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: { | ||
| 1277 | /* video gop cluster */ | ||
| 1278 | int b = val + 1; | ||
| 1279 | int gop = hdl->video_gop_size->val; | ||
| 1280 | |||
| 1281 | gop = b * ((gop + b - 1) / b); | ||
| 1282 | |||
| 1283 | /* Max GOP size = 34 */ | ||
| 1284 | while (gop > 34) | ||
| 1285 | gop -= b; | ||
| 1286 | hdl->video_gop_size->val = gop; | ||
| 1287 | break; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
| 1291 | /* stream type cluster */ | ||
| 1292 | hdl->video_encoding->val = | ||
| 1293 | (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || | ||
| 1294 | hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? | ||
| 1295 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : | ||
| 1296 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
| 1297 | if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) | ||
| 1298 | /* MPEG-1 implies CBR */ | ||
| 1299 | hdl->video_bitrate_mode->val = | ||
| 1300 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; | ||
| 1301 | /* peak bitrate shall be >= normal bitrate */ | ||
| 1302 | if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && | ||
| 1303 | hdl->video_bitrate_peak->val < hdl->video_bitrate->val) | ||
| 1304 | hdl->video_bitrate_peak->val = hdl->video_bitrate->val; | ||
| 1305 | break; | ||
| 1306 | } | ||
| 1307 | return 0; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 1311 | { | ||
| 1312 | static const int mpeg_stream_type[] = { | ||
| 1313 | 0, /* MPEG-2 PS */ | ||
| 1314 | 1, /* MPEG-2 TS */ | ||
| 1315 | 2, /* MPEG-1 SS */ | ||
| 1316 | 14, /* DVD */ | ||
| 1317 | 11, /* VCD */ | ||
| 1318 | 12, /* SVCD */ | ||
| 1319 | }; | ||
| 1320 | struct cx2341x_handler *hdl = to_cxhdl(ctrl); | ||
| 1321 | s32 val = ctrl->val; | ||
| 1322 | u32 props; | ||
| 1323 | int err; | ||
| 1324 | |||
| 1325 | switch (ctrl->id) { | ||
| 1326 | case V4L2_CID_MPEG_STREAM_VBI_FMT: | ||
| 1327 | if (hdl->ops && hdl->ops->s_stream_vbi_fmt) | ||
| 1328 | return hdl->ops->s_stream_vbi_fmt(hdl, val); | ||
| 1329 | return 0; | ||
| 1330 | |||
| 1331 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
| 1332 | return cx2341x_hdl_api(hdl, | ||
| 1333 | CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1); | ||
| 1334 | |||
| 1335 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: | ||
| 1336 | return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val); | ||
| 1337 | |||
| 1338 | case V4L2_CID_MPEG_AUDIO_MUTE: | ||
| 1339 | return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val); | ||
| 1340 | |||
| 1341 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: | ||
| 1342 | return cx2341x_hdl_api(hdl, | ||
| 1343 | CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val); | ||
| 1344 | |||
| 1345 | case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: | ||
| 1346 | return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val); | ||
| 1347 | |||
| 1348 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
| 1349 | /* audio properties cluster */ | ||
| 1350 | props = (hdl->audio_sampling_freq->val << 0) | | ||
| 1351 | (hdl->audio_mode->val << 8) | | ||
| 1352 | (hdl->audio_mode_extension->val << 10) | | ||
| 1353 | (hdl->audio_crc->val << 14); | ||
| 1354 | if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) | ||
| 1355 | props |= 3 << 12; | ||
| 1356 | else | ||
| 1357 | props |= hdl->audio_emphasis->val << 12; | ||
| 1358 | |||
| 1359 | if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) { | ||
| 1360 | props |= | ||
| 1361 | #if 1 | ||
| 1362 | /* Not sure if this MPEG Layer II setting is required */ | ||
| 1363 | ((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) | | ||
| 1364 | #endif | ||
| 1365 | (hdl->audio_ac3_bitrate->val << 4) | | ||
| 1366 | (CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28); | ||
| 1367 | } else { | ||
| 1368 | /* Assuming MPEG Layer II */ | ||
| 1369 | props |= | ||
| 1370 | ((3 - hdl->audio_encoding->val) << 2) | | ||
| 1371 | ((1 + hdl->audio_l2_bitrate->val) << 4); | ||
| 1372 | } | ||
| 1373 | err = cx2341x_hdl_api(hdl, | ||
| 1374 | CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props); | ||
| 1375 | if (err) | ||
| 1376 | return err; | ||
| 1377 | |||
| 1378 | hdl->audio_properties = props; | ||
| 1379 | if (hdl->audio_ac3_bitrate) { | ||
| 1380 | int is_ac3 = hdl->audio_encoding->val == | ||
| 1381 | V4L2_MPEG_AUDIO_ENCODING_AC3; | ||
| 1382 | |||
| 1383 | v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3); | ||
| 1384 | v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3); | ||
| 1385 | } | ||
| 1386 | v4l2_ctrl_activate(hdl->audio_mode_extension, | ||
| 1387 | hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO); | ||
| 1388 | if (cx2341x_neq(hdl->audio_sampling_freq) && | ||
| 1389 | hdl->ops && hdl->ops->s_audio_sampling_freq) | ||
| 1390 | return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val); | ||
| 1391 | if (cx2341x_neq(hdl->audio_mode) && | ||
| 1392 | hdl->ops && hdl->ops->s_audio_mode) | ||
| 1393 | return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val); | ||
| 1394 | return 0; | ||
| 1395 | |||
| 1396 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | ||
| 1397 | /* video gop cluster */ | ||
| 1398 | return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2, | ||
| 1399 | hdl->video_gop_size->val, | ||
| 1400 | hdl->video_b_frames->val + 1); | ||
| 1401 | |||
| 1402 | case V4L2_CID_MPEG_STREAM_TYPE: | ||
| 1403 | /* stream type cluster */ | ||
| 1404 | err = cx2341x_hdl_api(hdl, | ||
| 1405 | CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]); | ||
| 1406 | if (err) | ||
| 1407 | return err; | ||
| 1408 | |||
| 1409 | err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5, | ||
| 1410 | hdl->video_bitrate_mode->val, | ||
| 1411 | hdl->video_bitrate->val, | ||
| 1412 | hdl->video_bitrate_peak->val / 400, 0, 0); | ||
| 1413 | if (err) | ||
| 1414 | return err; | ||
| 1415 | |||
| 1416 | v4l2_ctrl_activate(hdl->video_bitrate_mode, | ||
| 1417 | hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1); | ||
| 1418 | v4l2_ctrl_activate(hdl->video_bitrate_peak, | ||
| 1419 | hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); | ||
| 1420 | if (cx2341x_neq(hdl->video_encoding) && | ||
| 1421 | hdl->ops && hdl->ops->s_video_encoding) | ||
| 1422 | return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val); | ||
| 1423 | return 0; | ||
| 1424 | |||
| 1425 | case V4L2_CID_MPEG_VIDEO_MUTE: | ||
| 1426 | /* video mute cluster */ | ||
| 1427 | return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1, | ||
| 1428 | hdl->video_mute->val | | ||
| 1429 | (hdl->video_mute_yuv->val << 8)); | ||
| 1430 | |||
| 1431 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: { | ||
| 1432 | int active_filter; | ||
| 1433 | |||
| 1434 | /* video filter mode */ | ||
| 1435 | err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, | ||
| 1436 | hdl->video_spatial_filter_mode->val | | ||
| 1437 | (hdl->video_temporal_filter_mode->val << 1), | ||
| 1438 | hdl->video_median_filter_type->val); | ||
| 1439 | if (err) | ||
| 1440 | return err; | ||
| 1441 | |||
| 1442 | active_filter = hdl->video_spatial_filter_mode->val != | ||
| 1443 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO; | ||
| 1444 | v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter); | ||
| 1445 | v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter); | ||
| 1446 | v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter); | ||
| 1447 | active_filter = hdl->video_temporal_filter_mode->val != | ||
| 1448 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO; | ||
| 1449 | v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter); | ||
| 1450 | active_filter = hdl->video_median_filter_type->val != | ||
| 1451 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF; | ||
| 1452 | v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter); | ||
| 1453 | v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter); | ||
| 1454 | v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter); | ||
| 1455 | v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter); | ||
| 1456 | return 0; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: | ||
| 1460 | /* video filter type cluster */ | ||
| 1461 | return cx2341x_hdl_api(hdl, | ||
| 1462 | CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, | ||
| 1463 | hdl->video_luma_spatial_filter_type->val, | ||
| 1464 | hdl->video_chroma_spatial_filter_type->val); | ||
| 1465 | |||
| 1466 | case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: | ||
| 1467 | /* video filter cluster */ | ||
| 1468 | return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, | ||
| 1469 | hdl->video_spatial_filter->val, | ||
| 1470 | hdl->video_temporal_filter->val); | ||
| 1471 | |||
| 1472 | case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: | ||
| 1473 | /* video median cluster */ | ||
| 1474 | return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4, | ||
| 1475 | hdl->video_luma_median_filter_bottom->val, | ||
| 1476 | hdl->video_luma_median_filter_top->val, | ||
| 1477 | hdl->video_chroma_median_filter_bottom->val, | ||
| 1478 | hdl->video_chroma_median_filter_top->val); | ||
| 1479 | } | ||
| 1480 | return -EINVAL; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | static const struct v4l2_ctrl_ops cx2341x_ops = { | ||
| 1484 | .try_ctrl = cx2341x_try_ctrl, | ||
| 1485 | .s_ctrl = cx2341x_s_ctrl, | ||
| 1486 | }; | ||
| 1487 | |||
| 1488 | static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, | ||
| 1489 | u32 id, s32 min, s32 max, s32 step, s32 def) | ||
| 1490 | { | ||
| 1491 | struct v4l2_ctrl_config cfg; | ||
| 1492 | |||
| 1493 | cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags); | ||
| 1494 | cfg.ops = &cx2341x_ops; | ||
| 1495 | cfg.id = id; | ||
| 1496 | cfg.min = min; | ||
| 1497 | cfg.max = max; | ||
| 1498 | cfg.def = def; | ||
| 1499 | if (cfg.type == V4L2_CTRL_TYPE_MENU) { | ||
| 1500 | cfg.step = 0; | ||
| 1501 | cfg.menu_skip_mask = step; | ||
| 1502 | cfg.qmenu = cx2341x_get_menu(id); | ||
| 1503 | } else { | ||
| 1504 | cfg.step = step; | ||
| 1505 | cfg.menu_skip_mask = 0; | ||
| 1506 | } | ||
| 1507 | return v4l2_ctrl_new_custom(hdl, &cfg, NULL); | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl, | ||
| 1511 | u32 id, s32 min, s32 max, s32 step, s32 def) | ||
| 1512 | { | ||
| 1513 | return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def); | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl, | ||
| 1517 | u32 id, s32 max, s32 mask, s32 def) | ||
| 1518 | { | ||
| 1519 | return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def); | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | int cx2341x_handler_init(struct cx2341x_handler *cxhdl, | ||
| 1523 | unsigned nr_of_controls_hint) | ||
| 1524 | { | ||
| 1525 | struct v4l2_ctrl_handler *hdl = &cxhdl->hdl; | ||
| 1526 | u32 caps = cxhdl->capabilities; | ||
| 1527 | int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI; | ||
| 1528 | int has_ac3 = caps & CX2341X_CAP_HAS_AC3; | ||
| 1529 | int has_ts = caps & CX2341X_CAP_HAS_TS; | ||
| 1530 | |||
| 1531 | cxhdl->width = 720; | ||
| 1532 | cxhdl->height = 480; | ||
| 1533 | |||
| 1534 | v4l2_ctrl_handler_init(hdl, nr_of_controls_hint); | ||
| 1535 | |||
| 1536 | /* Add controls in ascending control ID order for fastest | ||
| 1537 | insertion time. */ | ||
| 1538 | cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl, | ||
| 1539 | V4L2_CID_MPEG_STREAM_TYPE, | ||
| 1540 | V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2, | ||
| 1541 | V4L2_MPEG_STREAM_TYPE_MPEG2_PS); | ||
| 1542 | cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl, | ||
| 1543 | V4L2_CID_MPEG_STREAM_VBI_FMT, | ||
| 1544 | V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2, | ||
| 1545 | V4L2_MPEG_STREAM_VBI_FMT_NONE); | ||
| 1546 | cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl, | ||
| 1547 | V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, | ||
| 1548 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0, | ||
| 1549 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); | ||
| 1550 | cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl, | ||
| 1551 | V4L2_CID_MPEG_AUDIO_ENCODING, | ||
| 1552 | V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2, | ||
| 1553 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
| 1554 | cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl, | ||
| 1555 | V4L2_CID_MPEG_AUDIO_L2_BITRATE, | ||
| 1556 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff, | ||
| 1557 | V4L2_MPEG_AUDIO_L2_BITRATE_224K); | ||
| 1558 | cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl, | ||
| 1559 | V4L2_CID_MPEG_AUDIO_MODE, | ||
| 1560 | V4L2_MPEG_AUDIO_MODE_MONO, 0, | ||
| 1561 | V4L2_MPEG_AUDIO_MODE_STEREO); | ||
| 1562 | cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl, | ||
| 1563 | V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, | ||
| 1564 | V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0, | ||
| 1565 | V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); | ||
| 1566 | cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl, | ||
| 1567 | V4L2_CID_MPEG_AUDIO_EMPHASIS, | ||
| 1568 | V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0, | ||
| 1569 | V4L2_MPEG_AUDIO_EMPHASIS_NONE); | ||
| 1570 | cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl, | ||
| 1571 | V4L2_CID_MPEG_AUDIO_CRC, | ||
| 1572 | V4L2_MPEG_AUDIO_CRC_CRC16, 0, | ||
| 1573 | V4L2_MPEG_AUDIO_CRC_NONE); | ||
| 1574 | |||
| 1575 | cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0); | ||
| 1576 | if (has_ac3) | ||
| 1577 | cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl, | ||
| 1578 | V4L2_CID_MPEG_AUDIO_AC3_BITRATE, | ||
| 1579 | V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03, | ||
| 1580 | V4L2_MPEG_AUDIO_AC3_BITRATE_224K); | ||
| 1581 | cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl, | ||
| 1582 | V4L2_CID_MPEG_VIDEO_ENCODING, | ||
| 1583 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0, | ||
| 1584 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
| 1585 | cx2341x_ctrl_new_menu(hdl, | ||
| 1586 | V4L2_CID_MPEG_VIDEO_ASPECT, | ||
| 1587 | V4L2_MPEG_VIDEO_ASPECT_221x100, 0, | ||
| 1588 | V4L2_MPEG_VIDEO_ASPECT_4x3); | ||
| 1589 | cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl, | ||
| 1590 | V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2); | ||
| 1591 | cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl, | ||
| 1592 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, | ||
| 1593 | 1, 34, 1, cxhdl->is_50hz ? 12 : 15); | ||
| 1594 | cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1); | ||
| 1595 | cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl, | ||
| 1596 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | ||
| 1597 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, | ||
| 1598 | V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); | ||
| 1599 | cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl, | ||
| 1600 | V4L2_CID_MPEG_VIDEO_BITRATE, | ||
| 1601 | 0, 27000000, 1, 6000000); | ||
| 1602 | cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl, | ||
| 1603 | V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, | ||
| 1604 | 0, 27000000, 1, 8000000); | ||
| 1605 | cx2341x_ctrl_new_std(hdl, | ||
| 1606 | V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0); | ||
| 1607 | cxhdl->video_mute = cx2341x_ctrl_new_std(hdl, | ||
| 1608 | V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0); | ||
| 1609 | cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl, | ||
| 1610 | V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080); | ||
| 1611 | |||
| 1612 | /* CX23415/6 specific */ | ||
| 1613 | cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl, | ||
| 1614 | V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, | ||
| 1615 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, | ||
| 1616 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0, | ||
| 1617 | V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); | ||
| 1618 | cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl, | ||
| 1619 | V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, | ||
| 1620 | 0, 15, 1, 0); | ||
| 1621 | cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, | ||
| 1622 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, | ||
| 1623 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, | ||
| 1624 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, | ||
| 1625 | 0, | ||
| 1626 | V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR); | ||
| 1627 | cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl, | ||
| 1628 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, | ||
| 1629 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, | ||
| 1630 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, | ||
| 1631 | 0, | ||
| 1632 | V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR); | ||
| 1633 | cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl, | ||
| 1634 | V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, | ||
| 1635 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, | ||
| 1636 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, | ||
| 1637 | 0, | ||
| 1638 | V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); | ||
| 1639 | cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl, | ||
| 1640 | V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, | ||
| 1641 | 0, 31, 1, 8); | ||
| 1642 | cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl, | ||
| 1643 | V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, | ||
| 1644 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, | ||
| 1645 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, | ||
| 1646 | 0, | ||
| 1647 | V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); | ||
| 1648 | cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, | ||
| 1649 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, | ||
| 1650 | 0, 255, 1, 0); | ||
| 1651 | cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl, | ||
| 1652 | V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, | ||
| 1653 | 0, 255, 1, 255); | ||
| 1654 | cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl, | ||
| 1655 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, | ||
| 1656 | 0, 255, 1, 0); | ||
| 1657 | cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl, | ||
| 1658 | V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, | ||
| 1659 | 0, 255, 1, 255); | ||
| 1660 | cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS, | ||
| 1661 | 0, 1, 1, 0); | ||
| 1662 | |||
| 1663 | if (hdl->error) { | ||
| 1664 | int err = hdl->error; | ||
| 1665 | |||
| 1666 | v4l2_ctrl_handler_free(hdl); | ||
| 1667 | return err; | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq); | ||
| 1671 | v4l2_ctrl_cluster(2, &cxhdl->video_b_frames); | ||
| 1672 | v4l2_ctrl_cluster(5, &cxhdl->stream_type); | ||
| 1673 | v4l2_ctrl_cluster(2, &cxhdl->video_mute); | ||
| 1674 | v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode); | ||
| 1675 | v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type); | ||
| 1676 | v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter); | ||
| 1677 | v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top); | ||
| 1678 | |||
| 1679 | return 0; | ||
| 1680 | } | ||
| 1681 | EXPORT_SYMBOL(cx2341x_handler_init); | ||
| 1682 | |||
| 1683 | void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz) | ||
| 1684 | { | ||
| 1685 | cxhdl->is_50hz = is_50hz; | ||
| 1686 | cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15; | ||
| 1687 | } | ||
| 1688 | EXPORT_SYMBOL(cx2341x_handler_set_50hz); | ||
| 1689 | |||
| 1690 | int cx2341x_handler_setup(struct cx2341x_handler *cxhdl) | ||
| 1691 | { | ||
| 1692 | int h = cxhdl->height; | ||
| 1693 | int w = cxhdl->width; | ||
| 1694 | int err; | ||
| 1695 | |||
| 1696 | err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0); | ||
| 1697 | if (err) | ||
| 1698 | return err; | ||
| 1699 | err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz); | ||
| 1700 | if (err) | ||
| 1701 | return err; | ||
| 1702 | |||
| 1703 | if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { | ||
| 1704 | w /= 2; | ||
| 1705 | h /= 2; | ||
| 1706 | } | ||
| 1707 | err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); | ||
| 1708 | if (err) | ||
| 1709 | return err; | ||
| 1710 | return v4l2_ctrl_handler_setup(&cxhdl->hdl); | ||
| 1711 | } | ||
| 1712 | EXPORT_SYMBOL(cx2341x_handler_setup); | ||
| 1713 | |||
| 1714 | void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy) | ||
| 1715 | { | ||
| 1716 | v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy); | ||
| 1717 | v4l2_ctrl_grab(cxhdl->audio_encoding, busy); | ||
| 1718 | v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy); | ||
| 1719 | v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy); | ||
| 1720 | v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy); | ||
| 1721 | v4l2_ctrl_grab(cxhdl->stream_type, busy); | ||
| 1722 | v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy); | ||
| 1723 | v4l2_ctrl_grab(cxhdl->video_bitrate, busy); | ||
| 1724 | v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy); | ||
| 1725 | } | ||
| 1726 | EXPORT_SYMBOL(cx2341x_handler_set_busy); | ||
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h index 9ebe8558b9b6..8d08ebfe20b7 100644 --- a/include/media/cx2341x.h +++ b/include/media/cx2341x.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #ifndef CX2341X_H | 19 | #ifndef CX2341X_H |
| 20 | #define CX2341X_H | 20 | #define CX2341X_H |
| 21 | 21 | ||
| 22 | #include <media/v4l2-ctrls.h> | ||
| 23 | |||
| 22 | enum cx2341x_port { | 24 | enum cx2341x_port { |
| 23 | CX2341X_PORT_MEMORY = 0, | 25 | CX2341X_PORT_MEMORY = 0, |
| 24 | CX2341X_PORT_STREAMING = 1, | 26 | CX2341X_PORT_STREAMING = 1, |
| @@ -99,6 +101,101 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, | |||
| 99 | void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); | 101 | void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); |
| 100 | void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix); | 102 | void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix); |
| 101 | 103 | ||
| 104 | struct cx2341x_handler; | ||
| 105 | |||
| 106 | struct cx2341x_handler_ops { | ||
| 107 | /* needed for the video clock freq */ | ||
| 108 | int (*s_audio_sampling_freq)(struct cx2341x_handler *hdl, u32 val); | ||
| 109 | /* needed for dualwatch */ | ||
| 110 | int (*s_audio_mode)(struct cx2341x_handler *hdl, u32 val); | ||
| 111 | /* needed for setting up the video resolution */ | ||
| 112 | int (*s_video_encoding)(struct cx2341x_handler *hdl, u32 val); | ||
| 113 | /* needed for setting up the sliced vbi insertion data structures */ | ||
| 114 | int (*s_stream_vbi_fmt)(struct cx2341x_handler *hdl, u32 val); | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct cx2341x_handler { | ||
| 118 | u32 capabilities; | ||
| 119 | enum cx2341x_port port; | ||
| 120 | u16 width; | ||
| 121 | u16 height; | ||
| 122 | u16 is_50hz; | ||
| 123 | u32 audio_properties; | ||
| 124 | |||
| 125 | struct v4l2_ctrl_handler hdl; | ||
| 126 | void *priv; | ||
| 127 | cx2341x_mbox_func func; | ||
| 128 | const struct cx2341x_handler_ops *ops; | ||
| 129 | |||
| 130 | struct v4l2_ctrl *stream_vbi_fmt; | ||
| 131 | |||
| 132 | struct { | ||
| 133 | /* audio cluster */ | ||
| 134 | struct v4l2_ctrl *audio_sampling_freq; | ||
| 135 | struct v4l2_ctrl *audio_encoding; | ||
| 136 | struct v4l2_ctrl *audio_l2_bitrate; | ||
| 137 | struct v4l2_ctrl *audio_mode; | ||
| 138 | struct v4l2_ctrl *audio_mode_extension; | ||
| 139 | struct v4l2_ctrl *audio_emphasis; | ||
| 140 | struct v4l2_ctrl *audio_crc; | ||
| 141 | struct v4l2_ctrl *audio_ac3_bitrate; | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct { | ||
| 145 | /* video gop cluster */ | ||
| 146 | struct v4l2_ctrl *video_b_frames; | ||
| 147 | struct v4l2_ctrl *video_gop_size; | ||
| 148 | }; | ||
| 149 | |||
| 150 | struct { | ||
| 151 | /* stream type cluster */ | ||
| 152 | struct v4l2_ctrl *stream_type; | ||
| 153 | struct v4l2_ctrl *video_encoding; | ||
| 154 | struct v4l2_ctrl *video_bitrate_mode; | ||
| 155 | struct v4l2_ctrl *video_bitrate; | ||
| 156 | struct v4l2_ctrl *video_bitrate_peak; | ||
| 157 | }; | ||
| 158 | |||
| 159 | struct { | ||
| 160 | /* video mute cluster */ | ||
| 161 | struct v4l2_ctrl *video_mute; | ||
| 162 | struct v4l2_ctrl *video_mute_yuv; | ||
| 163 | }; | ||
| 164 | |||
| 165 | struct { | ||
| 166 | /* video filter mode cluster */ | ||
| 167 | struct v4l2_ctrl *video_spatial_filter_mode; | ||
| 168 | struct v4l2_ctrl *video_temporal_filter_mode; | ||
| 169 | struct v4l2_ctrl *video_median_filter_type; | ||
| 170 | }; | ||
| 171 | |||
| 172 | struct { | ||
| 173 | /* video filter type cluster */ | ||
| 174 | struct v4l2_ctrl *video_luma_spatial_filter_type; | ||
| 175 | struct v4l2_ctrl *video_chroma_spatial_filter_type; | ||
| 176 | }; | ||
| 177 | |||
| 178 | struct { | ||
| 179 | /* video filter cluster */ | ||
| 180 | struct v4l2_ctrl *video_spatial_filter; | ||
| 181 | struct v4l2_ctrl *video_temporal_filter; | ||
| 182 | }; | ||
| 183 | |||
| 184 | struct { | ||
| 185 | /* video median cluster */ | ||
| 186 | struct v4l2_ctrl *video_luma_median_filter_top; | ||
| 187 | struct v4l2_ctrl *video_luma_median_filter_bottom; | ||
| 188 | struct v4l2_ctrl *video_chroma_median_filter_top; | ||
| 189 | struct v4l2_ctrl *video_chroma_median_filter_bottom; | ||
| 190 | }; | ||
| 191 | }; | ||
| 192 | |||
| 193 | int cx2341x_handler_init(struct cx2341x_handler *cxhdl, | ||
| 194 | unsigned nr_of_controls_hint); | ||
| 195 | void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz); | ||
| 196 | int cx2341x_handler_setup(struct cx2341x_handler *cxhdl); | ||
| 197 | void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy); | ||
| 198 | |||
| 102 | /* Firmware names */ | 199 | /* Firmware names */ |
| 103 | #define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw" | 200 | #define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw" |
| 104 | /* Decoder firmware for the cx23415 only */ | 201 | /* Decoder firmware for the cx23415 only */ |
