Commit a98f6af9 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ed10daae
......@@ -133,7 +133,7 @@ static struct v4l2_queryctrl ac97_qctrl[] = {
.maximum = 0x1f,
.step = 0x1,
.default_value = 0x1f,
.flags = 0,
.flags = V4L2_CTRL_FLAG_SLIDER,
}, {
.id = V4L2_CID_AUDIO_MUTE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
......@@ -609,10 +609,29 @@ static void res_free(struct em28xx_fh *fh)
}
/*
* em28xx_get_ctrl()
* return the current saturation, brightness or contrast, mute state
* ac97_queryctrl()
* return the ac97 supported controls
*/
static int ac97_queryctrl(struct v4l2_queryctrl *qc)
{
int i;
for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
if (qc->id && qc->id == ac97_qctrl[i].id) {
memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
return 0;
}
}
/* Control is not ac97 related */
return 1;
}
/*
* ac97_get_ctrl()
* return the current values for ac97 mute and volume
*/
static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
{
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
......@@ -622,29 +641,41 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
ctrl->value = dev->volume;
return 0;
default:
return -EINVAL;
/* Control is not ac97 related */
return 1;
}
}
/*
* em28xx_set_ctrl()
* mute or set new saturation, brightness or contrast
* ac97_set_ctrl()
* set values for ac97 mute and volume
*/
static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
{
int i;
for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++)
if (ctrl->id == ac97_qctrl[i].id)
goto handle;
/* Announce that hasn't handle it */
return 1;
handle:
if (ctrl->value < ac97_qctrl[i].minimum ||
ctrl->value > ac97_qctrl[i].maximum)
return -ERANGE;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value != dev->mute) {
dev->mute = ctrl->value;
return em28xx_audio_analog_set(dev);
}
return 0;
break;
case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->value;
return em28xx_audio_analog_set(dev);
default:
return -EINVAL;
break;
}
return em28xx_audio_analog_set(dev);
}
static int check_dev(struct em28xx *dev)
......@@ -1038,7 +1069,6 @@ static int vidioc_queryctrl(struct file *file, void *priv,
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
int id = qc->id;
int i;
int rc;
rc = check_dev(dev);
......@@ -1049,15 +1079,14 @@ static int vidioc_queryctrl(struct file *file, void *priv,
qc->id = id;
if (!dev->board.has_msp34xx) {
for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
if (qc->id && qc->id == ac97_qctrl[i].id) {
memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
/* enumberate AC97 controls */
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
rc = ac97_queryctrl(qc);
if (!rc)
return 0;
}
}
}
/* enumberate V4L2 device controls */
mutex_lock(&dev->lock);
v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
mutex_unlock(&dev->lock);
......@@ -1082,15 +1111,17 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
mutex_lock(&dev->lock);
if (dev->board.has_msp34xx)
v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
else {
rc = em28xx_get_ctrl(dev, ctrl);
if (rc < 0) {
/* Set an AC97 control */
if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
rc = ac97_get_ctrl(dev, ctrl);
else
rc = 1;
/* It were not an AC97 control. Sends it to the v4l2 dev interface */
if (rc == 1) {
v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
rc = 0;
}
}
mutex_unlock(&dev->lock);
return rc;
......@@ -1101,7 +1132,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
u8 i;
int rc;
rc = check_dev(dev);
......@@ -1110,27 +1140,16 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
mutex_lock(&dev->lock);
if (dev->board.has_msp34xx)
v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
else {
/* Set an AC97 control */
if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
rc = ac97_set_ctrl(dev, ctrl);
else
rc = 1;
for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
if (ctrl->id == ac97_qctrl[i].id) {
if (ctrl->value < ac97_qctrl[i].minimum ||
ctrl->value > ac97_qctrl[i].maximum) {
rc = -ERANGE;
break;
}
rc = em28xx_set_ctrl(dev, ctrl);
break;
}
}
}
/* Control not found - try to send it to the attached devices */
/* It were not an AC97 control. Sends it to the v4l2 dev interface */
if (rc == 1) {
v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
/* FIXME: should be returning a meaninful value */
rc = 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment