diff options
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 117 |
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 | */ |
615 | static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | 615 | static 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 | */ | ||
634 | static 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 | */ |
633 | static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | 653 | static 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 | |||
664 | handle: | ||
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 | ||
650 | static int check_dev(struct em28xx *dev) | 681 | static 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 | ||