aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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