aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-07-19 09:45:49 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:17:42 -0400
commita98f6af96ec5b22453054b36eaa325ebf20ea429 (patch)
treedea0ff3ea72d6bcf4b8b2ff5b54df340c6683016 /drivers/media/video/em28xx/em28xx-video.c
parented10daaeb3512165505eda8bb311edabea5cb485 (diff)
V4L/DVB (12274): em28xx-video: better implement ac97 control ioctls
In the past, some devices with saa711x had their parameters controlled directly inside em28xx driver, instead of using their proper module for it. Due to that, the ac97 controls were mixed with saa711x ones. Older patches removed all saa711x controls, but we still need to control ac97 devices on em28xx, since we don't have a separate v4l2 device for it. The proper way to address is to create a separate ac97 v4l2 device. While we don't have it, we should clean up the code to allow having a better view of what is part of em28xx core code and what's due to ac97 control inside it. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c117
1 files changed, 68 insertions, 49 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index e612e43b0ef1..7ed3051554c1 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -133,7 +133,7 @@ static struct v4l2_queryctrl ac97_qctrl[] = {
133 .maximum = 0x1f, 133 .maximum = 0x1f,
134 .step = 0x1, 134 .step = 0x1,
135 .default_value = 0x1f, 135 .default_value = 0x1f,
136 .flags = 0, 136 .flags = V4L2_CTRL_FLAG_SLIDER,
137 }, { 137 }, {
138 .id = V4L2_CID_AUDIO_MUTE, 138 .id = V4L2_CID_AUDIO_MUTE,
139 .type = V4L2_CTRL_TYPE_BOOLEAN, 139 .type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -609,10 +609,29 @@ static void res_free(struct em28xx_fh *fh)
609} 609}
610 610
611/* 611/*
612 * em28xx_get_ctrl() 612 * ac97_queryctrl()
613 * return the current saturation, brightness or contrast, mute state 613 * return the ac97 supported controls
614 */ 614 */
615static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) 615static int ac97_queryctrl(struct v4l2_queryctrl *qc)
616{
617 int i;
618
619 for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
620 if (qc->id && qc->id == ac97_qctrl[i].id) {
621 memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
622 return 0;
623 }
624 }
625
626 /* Control is not ac97 related */
627 return 1;
628}
629
630/*
631 * ac97_get_ctrl()
632 * return the current values for ac97 mute and volume
633 */
634static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
616{ 635{
617 switch (ctrl->id) { 636 switch (ctrl->id) {
618 case V4L2_CID_AUDIO_MUTE: 637 case V4L2_CID_AUDIO_MUTE:
@@ -622,29 +641,41 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
622 ctrl->value = dev->volume; 641 ctrl->value = dev->volume;
623 return 0; 642 return 0;
624 default: 643 default:
625 return -EINVAL; 644 /* Control is not ac97 related */
645 return 1;
626 } 646 }
627} 647}
628 648
629/* 649/*
630 * em28xx_set_ctrl() 650 * ac97_set_ctrl()
631 * mute or set new saturation, brightness or contrast 651 * set values for ac97 mute and volume
632 */ 652 */
633static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) 653static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
634{ 654{
655 int i;
656
657 for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++)
658 if (ctrl->id == ac97_qctrl[i].id)
659 goto handle;
660
661 /* Announce that hasn't handle it */
662 return 1;
663
664handle:
665 if (ctrl->value < ac97_qctrl[i].minimum ||
666 ctrl->value > ac97_qctrl[i].maximum)
667 return -ERANGE;
668
635 switch (ctrl->id) { 669 switch (ctrl->id) {
636 case V4L2_CID_AUDIO_MUTE: 670 case V4L2_CID_AUDIO_MUTE:
637 if (ctrl->value != dev->mute) { 671 dev->mute = ctrl->value;
638 dev->mute = ctrl->value; 672 break;
639 return em28xx_audio_analog_set(dev);
640 }
641 return 0;
642 case V4L2_CID_AUDIO_VOLUME: 673 case V4L2_CID_AUDIO_VOLUME:
643 dev->volume = ctrl->value; 674 dev->volume = ctrl->value;
644 return em28xx_audio_analog_set(dev); 675 break;
645 default:
646 return -EINVAL;
647 } 676 }
677
678 return em28xx_audio_analog_set(dev);
648} 679}
649 680
650static int check_dev(struct em28xx *dev) 681static int check_dev(struct em28xx *dev)
@@ -1038,7 +1069,6 @@ static int vidioc_queryctrl(struct file *file, void *priv,
1038 struct em28xx_fh *fh = priv; 1069 struct em28xx_fh *fh = priv;
1039 struct em28xx *dev = fh->dev; 1070 struct em28xx *dev = fh->dev;
1040 int id = qc->id; 1071 int id = qc->id;
1041 int i;
1042 int rc; 1072 int rc;
1043 1073
1044 rc = check_dev(dev); 1074 rc = check_dev(dev);
@@ -1049,15 +1079,14 @@ static int vidioc_queryctrl(struct file *file, void *priv,
1049 1079
1050 qc->id = id; 1080 qc->id = id;
1051 1081
1052 if (!dev->board.has_msp34xx) { 1082 /* enumberate AC97 controls */
1053 for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { 1083 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
1054 if (qc->id && qc->id == ac97_qctrl[i].id) { 1084 rc = ac97_queryctrl(qc);
1055 memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); 1085 if (!rc)
1056 return 0; 1086 return 0;
1057 }
1058 }
1059 } 1087 }
1060 1088
1089 /* enumberate V4L2 device controls */
1061 mutex_lock(&dev->lock); 1090 mutex_lock(&dev->lock);
1062 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); 1091 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
1063 mutex_unlock(&dev->lock); 1092 mutex_unlock(&dev->lock);
@@ -1082,14 +1111,16 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
1082 1111
1083 mutex_lock(&dev->lock); 1112 mutex_lock(&dev->lock);
1084 1113
1085 if (dev->board.has_msp34xx) 1114 /* Set an AC97 control */
1115 if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
1116 rc = ac97_get_ctrl(dev, ctrl);
1117 else
1118 rc = 1;
1119
1120 /* It were not an AC97 control. Sends it to the v4l2 dev interface */
1121 if (rc == 1) {
1086 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); 1122 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
1087 else { 1123 rc = 0;
1088 rc = em28xx_get_ctrl(dev, ctrl);
1089 if (rc < 0) {
1090 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
1091 rc = 0;
1092 }
1093 } 1124 }
1094 1125
1095 mutex_unlock(&dev->lock); 1126 mutex_unlock(&dev->lock);
@@ -1101,7 +1132,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1101{ 1132{
1102 struct em28xx_fh *fh = priv; 1133 struct em28xx_fh *fh = priv;
1103 struct em28xx *dev = fh->dev; 1134 struct em28xx *dev = fh->dev;
1104 u8 i;
1105 int rc; 1135 int rc;
1106 1136
1107 rc = check_dev(dev); 1137 rc = check_dev(dev);
@@ -1110,27 +1140,16 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1110 1140
1111 mutex_lock(&dev->lock); 1141 mutex_lock(&dev->lock);
1112 1142
1113 if (dev->board.has_msp34xx) 1143 /* Set an AC97 control */
1114 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); 1144 if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
1115 else { 1145 rc = ac97_set_ctrl(dev, ctrl);
1146 else
1116 rc = 1; 1147 rc = 1;
1117 for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
1118 if (ctrl->id == ac97_qctrl[i].id) {
1119 if (ctrl->value < ac97_qctrl[i].minimum ||
1120 ctrl->value > ac97_qctrl[i].maximum) {
1121 rc = -ERANGE;
1122 break;
1123 }
1124
1125 rc = em28xx_set_ctrl(dev, ctrl);
1126 break;
1127 }
1128 }
1129 }
1130 1148
1131 /* Control not found - try to send it to the attached devices */ 1149 /* It were not an AC97 control. Sends it to the v4l2 dev interface */
1132 if (rc == 1) { 1150 if (rc == 1) {
1133 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); 1151 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
1152 /* FIXME: should be returning a meaninful value */
1134 rc = 0; 1153 rc = 0;
1135 } 1154 }
1136 1155