diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2011-12-15 08:32:53 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-02-14 10:44:41 -0500 |
commit | debf80014fc1e8d02b3fd57e5fae0d315ac2cb04 (patch) | |
tree | b4275b68e02eab7865d5b61fd9ca4ac1ee9408a4 | |
parent | 77bd4c0ff1671214ee026c175b4a5e1cc8776a0a (diff) |
[media] ivtv: implement new decoder controls
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/ivtv/ivtv-controls.c | 62 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-controls.h | 2 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 35 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 12 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 67 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 5 |
6 files changed, 124 insertions, 59 deletions
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index b31ee1bceef8..e2901184db09 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
22 | #include "ivtv-ioctl.h" | 22 | #include "ivtv-ioctl.h" |
23 | #include "ivtv-controls.h" | 23 | #include "ivtv-controls.h" |
24 | #include "ivtv-mailbox.h" | ||
24 | 25 | ||
25 | static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) | 26 | static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) |
26 | { | 27 | { |
@@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_ops = { | |||
99 | .s_video_encoding = ivtv_s_video_encoding, | 100 | .s_video_encoding = ivtv_s_video_encoding, |
100 | .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, | 101 | .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, |
101 | }; | 102 | }; |
103 | |||
104 | int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) | ||
105 | { | ||
106 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
107 | |||
108 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
109 | *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | | ||
110 | (u64)itv->last_dec_timing[1]; | ||
111 | *frame = itv->last_dec_timing[0]; | ||
112 | return 0; | ||
113 | } | ||
114 | *pts = 0; | ||
115 | *frame = 0; | ||
116 | if (atomic_read(&itv->decoding)) { | ||
117 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
118 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
119 | return -EIO; | ||
120 | } | ||
121 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
122 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
123 | *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; | ||
124 | *frame = data[0]; | ||
125 | /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ | ||
126 | } | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | ||
131 | { | ||
132 | struct ivtv *itv = container_of(ctrl->handler, struct ivtv, hdl_out); | ||
133 | |||
134 | switch (ctrl->id) { | ||
135 | /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME | ||
136 | control cluster */ | ||
137 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: | ||
138 | return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, | ||
139 | &itv->ctrl_frame->val64); | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) | ||
145 | { | ||
146 | struct ivtv *itv = container_of(ctrl->handler, struct ivtv, hdl_out); | ||
147 | |||
148 | switch (ctrl->id) { | ||
149 | /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK | ||
150 | control cluster */ | ||
151 | case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: | ||
152 | itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; | ||
153 | itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; | ||
154 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
155 | break; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { | ||
161 | .s_ctrl = ivtv_s_ctrl, | ||
162 | .g_volatile_ctrl = ivtv_g_volatile_ctrl, | ||
163 | }; | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h index d12893dd0183..3999e6358312 100644 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ b/drivers/media/video/ivtv/ivtv-controls.h | |||
@@ -22,5 +22,7 @@ | |||
22 | #define IVTV_CONTROLS_H | 22 | #define IVTV_CONTROLS_H |
23 | 23 | ||
24 | extern struct cx2341x_handler_ops ivtv_cxhdl_ops; | 24 | extern struct cx2341x_handler_ops ivtv_cxhdl_ops; |
25 | extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; | ||
26 | int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); | ||
25 | 27 | ||
26 | #endif | 28 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 48d1d47ed04f..107e9e6d6a52 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
744 | 744 | ||
745 | itv->cur_dma_stream = -1; | 745 | itv->cur_dma_stream = -1; |
746 | itv->cur_pio_stream = -1; | 746 | itv->cur_pio_stream = -1; |
747 | itv->audio_stereo_mode = AUDIO_STEREO; | ||
748 | itv->audio_bilingual_mode = AUDIO_MONO_LEFT; | ||
749 | 747 | ||
750 | /* Ctrls */ | 748 | /* Ctrls */ |
751 | itv->speed = 1000; | 749 | itv->speed = 1000; |
@@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, | |||
1200 | itv->tuner_std = itv->std; | 1198 | itv->tuner_std = itv->std; |
1201 | 1199 | ||
1202 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | 1200 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
1201 | v4l2_ctrl_handler_init(&itv->hdl_out, 50); | ||
1202 | itv->ctrl_pts = v4l2_ctrl_new_std(&itv->hdl_out, &ivtv_hdl_out_ops, | ||
1203 | V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); | ||
1204 | itv->ctrl_frame = v4l2_ctrl_new_std(&itv->hdl_out, &ivtv_hdl_out_ops, | ||
1205 | V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); | ||
1206 | /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, | ||
1207 | mask that menu item. */ | ||
1208 | itv->ctrl_audio_playback = | ||
1209 | v4l2_ctrl_new_std_menu(&itv->hdl_out, &ivtv_hdl_out_ops, | ||
1210 | V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, | ||
1211 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, | ||
1212 | 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, | ||
1213 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); | ||
1214 | itv->ctrl_audio_multilingual_playback = | ||
1215 | v4l2_ctrl_new_std_menu(&itv->hdl_out, &ivtv_hdl_out_ops, | ||
1216 | V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, | ||
1217 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, | ||
1218 | 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, | ||
1219 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); | ||
1220 | v4l2_ctrl_add_handler(&itv->hdl_out, &itv->cxhdl.hdl); | ||
1221 | if (itv->hdl_out.error) { | ||
1222 | retval = itv->hdl_out.error; | ||
1223 | goto free_i2c; | ||
1224 | } | ||
1225 | v4l2_ctrl_cluster(2, &itv->ctrl_pts); | ||
1226 | v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); | ||
1203 | ivtv_call_all(itv, video, s_std_output, itv->std); | 1227 | ivtv_call_all(itv, video, s_std_output, itv->std); |
1204 | /* Turn off the output signal. The mpeg decoder is not yet | 1228 | /* Turn off the output signal. The mpeg decoder is not yet |
1205 | active so without this you would get a green image until the | 1229 | active so without this you would get a green image until the |
@@ -1236,6 +1260,9 @@ free_streams: | |||
1236 | free_irq: | 1260 | free_irq: |
1237 | free_irq(itv->pdev->irq, (void *)itv); | 1261 | free_irq(itv->pdev->irq, (void *)itv); |
1238 | free_i2c: | 1262 | free_i2c: |
1263 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
1264 | v4l2_ctrl_handler_free(&itv->hdl_out); | ||
1265 | v4l2_ctrl_handler_free(&itv->cxhdl.hdl); | ||
1239 | exit_ivtv_i2c(itv); | 1266 | exit_ivtv_i2c(itv); |
1240 | free_io: | 1267 | free_io: |
1241 | ivtv_iounmap(itv); | 1268 | ivtv_iounmap(itv); |
@@ -1391,6 +1418,10 @@ static void ivtv_remove(struct pci_dev *pdev) | |||
1391 | ivtv_streams_cleanup(itv, 1); | 1418 | ivtv_streams_cleanup(itv, 1); |
1392 | ivtv_udma_free(itv); | 1419 | ivtv_udma_free(itv); |
1393 | 1420 | ||
1421 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) | ||
1422 | v4l2_ctrl_handler_free(&itv->hdl_out); | ||
1423 | v4l2_ctrl_handler_free(&itv->cxhdl.hdl); | ||
1424 | |||
1394 | exit_ivtv_i2c(itv); | 1425 | exit_ivtv_i2c(itv); |
1395 | 1426 | ||
1396 | free_irq(itv->pdev->irq, (void *)itv); | 1427 | free_irq(itv->pdev->irq, (void *)itv); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 20845d65d343..f83857aedbd1 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -631,6 +631,17 @@ struct ivtv { | |||
631 | 631 | ||
632 | struct v4l2_device v4l2_dev; | 632 | struct v4l2_device v4l2_dev; |
633 | struct cx2341x_handler cxhdl; | 633 | struct cx2341x_handler cxhdl; |
634 | struct { | ||
635 | /* PTS/Frame count control cluster */ | ||
636 | struct v4l2_ctrl *ctrl_pts; | ||
637 | struct v4l2_ctrl *ctrl_frame; | ||
638 | }; | ||
639 | struct { | ||
640 | /* Audio Playback control cluster */ | ||
641 | struct v4l2_ctrl *ctrl_audio_playback; | ||
642 | struct v4l2_ctrl *ctrl_audio_multilingual_playback; | ||
643 | }; | ||
644 | struct v4l2_ctrl_handler hdl_out; | ||
634 | struct v4l2_ctrl_handler hdl_gpio; | 645 | struct v4l2_ctrl_handler hdl_gpio; |
635 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ | 646 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ |
636 | u16 instance; | 647 | u16 instance; |
@@ -650,7 +661,6 @@ struct ivtv { | |||
650 | u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ | 661 | u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ |
651 | u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ | 662 | u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ |
652 | 663 | ||
653 | |||
654 | /* Locking */ | 664 | /* Locking */ |
655 | spinlock_t lock; /* lock access to this struct */ | 665 | spinlock_t lock; /* lock access to this struct */ |
656 | struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ | 666 | struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 13020a7e5db9..cd8032693e6d 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -1510,13 +1510,6 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1510 | "YUV Frames", | 1510 | "YUV Frames", |
1511 | "Passthrough", | 1511 | "Passthrough", |
1512 | }; | 1512 | }; |
1513 | static const char * const audio_modes[5] = { | ||
1514 | "Stereo", | ||
1515 | "Left", | ||
1516 | "Right", | ||
1517 | "Mono", | ||
1518 | "Swapped" | ||
1519 | }; | ||
1520 | static const char * const alpha_mode[4] = { | 1513 | static const char * const alpha_mode[4] = { |
1521 | "None", | 1514 | "None", |
1522 | "Global", | 1515 | "Global", |
@@ -1545,9 +1538,6 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1545 | ivtv_get_output(itv, itv->active_output, &vidout); | 1538 | ivtv_get_output(itv, itv->active_output, &vidout); |
1546 | ivtv_get_audio_output(itv, 0, &audout); | 1539 | ivtv_get_audio_output(itv, 0, &audout); |
1547 | IVTV_INFO("Video Output: %s\n", vidout.name); | 1540 | IVTV_INFO("Video Output: %s\n", vidout.name); |
1548 | IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, | ||
1549 | audio_modes[itv->audio_stereo_mode], | ||
1550 | audio_modes[itv->audio_bilingual_mode]); | ||
1551 | if (mode < 0 || mode > OUT_PASSTHROUGH) | 1541 | if (mode < 0 || mode > OUT_PASSTHROUGH) |
1552 | mode = OUT_NONE; | 1542 | mode = OUT_NONE; |
1553 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); | 1543 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); |
@@ -1560,7 +1550,10 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1560 | } | 1550 | } |
1561 | IVTV_INFO("Tuner: %s\n", | 1551 | IVTV_INFO("Tuner: %s\n", |
1562 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); | 1552 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); |
1563 | v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name); | 1553 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) |
1554 | v4l2_ctrl_handler_log_status(&itv->hdl_out, itv->v4l2_dev.name); | ||
1555 | else | ||
1556 | v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name); | ||
1564 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); | 1557 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); |
1565 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | 1558 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
1566 | struct ivtv_stream *s = &itv->streams[i]; | 1559 | struct ivtv_stream *s = &itv->streams[i]; |
@@ -1633,8 +1626,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1633 | } | 1626 | } |
1634 | 1627 | ||
1635 | case VIDEO_GET_PTS: { | 1628 | case VIDEO_GET_PTS: { |
1636 | u32 data[CX2341X_MBOX_MAX_DATA]; | 1629 | s64 *pts = arg; |
1637 | u64 *pts = arg; | 1630 | s64 frame; |
1638 | 1631 | ||
1639 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); | 1632 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); |
1640 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | 1633 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { |
@@ -1643,29 +1636,12 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1643 | } | 1636 | } |
1644 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 1637 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1645 | return -EINVAL; | 1638 | return -EINVAL; |
1646 | 1639 | return ivtv_g_pts_frame(itv, pts, &frame); | |
1647 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1648 | *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | | ||
1649 | (u64)itv->last_dec_timing[1]; | ||
1650 | break; | ||
1651 | } | ||
1652 | *pts = 0; | ||
1653 | if (atomic_read(&itv->decoding)) { | ||
1654 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1655 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1656 | return -EIO; | ||
1657 | } | ||
1658 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1659 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1660 | *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; | ||
1661 | /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ | ||
1662 | } | ||
1663 | break; | ||
1664 | } | 1640 | } |
1665 | 1641 | ||
1666 | case VIDEO_GET_FRAME_COUNT: { | 1642 | case VIDEO_GET_FRAME_COUNT: { |
1667 | u32 data[CX2341X_MBOX_MAX_DATA]; | 1643 | s64 *frame = arg; |
1668 | u64 *frame = arg; | 1644 | s64 pts; |
1669 | 1645 | ||
1670 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); | 1646 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); |
1671 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | 1647 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { |
@@ -1674,22 +1650,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1674 | } | 1650 | } |
1675 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 1651 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1676 | return -EINVAL; | 1652 | return -EINVAL; |
1677 | 1653 | return ivtv_g_pts_frame(itv, &pts, frame); | |
1678 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1679 | *frame = itv->last_dec_timing[0]; | ||
1680 | break; | ||
1681 | } | ||
1682 | *frame = 0; | ||
1683 | if (atomic_read(&itv->decoding)) { | ||
1684 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1685 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1686 | return -EIO; | ||
1687 | } | ||
1688 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1689 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1690 | *frame = data[0]; | ||
1691 | } | ||
1692 | break; | ||
1693 | } | 1654 | } |
1694 | 1655 | ||
1695 | case VIDEO_PLAY: { | 1656 | case VIDEO_PLAY: { |
@@ -1804,17 +1765,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1804 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); | 1765 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); |
1805 | if (iarg > AUDIO_STEREO_SWAPPED) | 1766 | if (iarg > AUDIO_STEREO_SWAPPED) |
1806 | return -EINVAL; | 1767 | return -EINVAL; |
1807 | itv->audio_stereo_mode = iarg; | 1768 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg); |
1808 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1809 | return 0; | ||
1810 | 1769 | ||
1811 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | 1770 | case AUDIO_BILINGUAL_CHANNEL_SELECT: |
1812 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | 1771 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); |
1813 | if (iarg > AUDIO_STEREO_SWAPPED) | 1772 | if (iarg > AUDIO_STEREO_SWAPPED) |
1814 | return -EINVAL; | 1773 | return -EINVAL; |
1815 | itv->audio_bilingual_mode = iarg; | 1774 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg); |
1816 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1817 | return 0; | ||
1818 | 1775 | ||
1819 | default: | 1776 | default: |
1820 | return -EINVAL; | 1777 | return -EINVAL; |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 034c0112431f..9cc037c12609 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -223,7 +223,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
223 | 223 | ||
224 | s->vdev->num = num; | 224 | s->vdev->num = num; |
225 | s->vdev->v4l2_dev = &itv->v4l2_dev; | 225 | s->vdev->v4l2_dev = &itv->v4l2_dev; |
226 | s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; | 226 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) |
227 | s->vdev->ctrl_handler = &itv->hdl_out; | ||
228 | else | ||
229 | s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; | ||
227 | s->vdev->fops = ivtv_stream_info[type].fops; | 230 | s->vdev->fops = ivtv_stream_info[type].fops; |
228 | s->vdev->release = video_device_release; | 231 | s->vdev->release = video_device_release; |
229 | s->vdev->tvnorms = V4L2_STD_ALL; | 232 | s->vdev->tvnorms = V4L2_STD_ALL; |