aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2011-12-15 08:32:53 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-02-14 10:44:41 -0500
commitdebf80014fc1e8d02b3fd57e5fae0d315ac2cb04 (patch)
treeb4275b68e02eab7865d5b61fd9ca4ac1ee9408a4
parent77bd4c0ff1671214ee026c175b4a5e1cc8776a0a (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.c62
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c35
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h12
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c67
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c5
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
25static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) 26static 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
104int 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
130static 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
144static 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
160const 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
24extern struct cx2341x_handler_ops ivtv_cxhdl_ops; 24extern struct cx2341x_handler_ops ivtv_cxhdl_ops;
25extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops;
26int 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:
1236free_irq: 1260free_irq:
1237 free_irq(itv->pdev->irq, (void *)itv); 1261 free_irq(itv->pdev->irq, (void *)itv);
1238free_i2c: 1262free_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);
1240free_io: 1267free_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;