Commit c9114031 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] tvaudio: convert to the control framework

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 71df09bc
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <media/tvaudio.h> #include <media/tvaudio.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
#include <media/i2c-addr.h> #include <media/i2c-addr.h>
...@@ -91,13 +92,13 @@ struct CHIPDESC { ...@@ -91,13 +92,13 @@ struct CHIPDESC {
audiocmd init; audiocmd init;
/* which register has which value */ /* which register has which value */
int leftreg,rightreg,treblereg,bassreg; int leftreg, rightreg, treblereg, bassreg;
/* initialize with (defaults to 65535/32768/32768 */ /* initialize with (defaults to 65535/32768/32768 */
int volinit, trebleinit, bassinit; int volinit, trebleinit, bassinit;
/* functions to convert the values (v4l -> chip) */ /* functions to convert the values (v4l -> chip) */
getvalue volfunc,treblefunc,bassfunc; getvalue volfunc, treblefunc, bassfunc;
/* get/set mode */ /* get/set mode */
getrxsubchans getrxsubchans; getrxsubchans getrxsubchans;
...@@ -113,6 +114,12 @@ struct CHIPDESC { ...@@ -113,6 +114,12 @@ struct CHIPDESC {
/* current state of the chip */ /* current state of the chip */
struct CHIPSTATE { struct CHIPSTATE {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
struct {
/* volume/balance cluster */
struct v4l2_ctrl *volume;
struct v4l2_ctrl *balance;
};
/* chip-specific description - should point to /* chip-specific description - should point to
an entry at CHIPDESC table */ an entry at CHIPDESC table */
...@@ -122,7 +129,7 @@ struct CHIPSTATE { ...@@ -122,7 +129,7 @@ struct CHIPSTATE {
audiocmd shadow; audiocmd shadow;
/* current settings */ /* current settings */
u16 volume, balance, treble, bass, muted; u16 muted;
int prevmode; int prevmode;
int radio; int radio;
int input; int input;
...@@ -138,6 +145,11 @@ static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd) ...@@ -138,6 +145,11 @@ static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd)
return container_of(sd, struct CHIPSTATE, sd); return container_of(sd, struct CHIPSTATE, sd);
} }
static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
{
return &container_of(ctrl->handler, struct CHIPSTATE, hdl)->sd;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* i2c I/O functions */ /* i2c I/O functions */
...@@ -1679,91 +1691,27 @@ static struct CHIPDESC chiplist[] = { ...@@ -1679,91 +1691,27 @@ static struct CHIPDESC chiplist[] = {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
static int tvaudio_g_ctrl(struct v4l2_subdev *sd, static int tvaudio_s_ctrl(struct v4l2_ctrl *ctrl)
struct v4l2_control *ctrl)
{
struct CHIPSTATE *chip = to_state(sd);
struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (!(desc->flags & CHIP_HAS_INPUTSEL))
break;
ctrl->value=chip->muted;
return 0;
case V4L2_CID_AUDIO_VOLUME:
if (!(desc->flags & CHIP_HAS_VOLUME))
break;
ctrl->value = chip->volume;
return 0;
case V4L2_CID_AUDIO_BALANCE:
if (!(desc->flags & CHIP_HAS_VOLUME))
break;
ctrl->value = chip->balance;
return 0;
case V4L2_CID_AUDIO_BASS:
if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
ctrl->value = chip->bass;
return 0;
case V4L2_CID_AUDIO_TREBLE:
if (!(desc->flags & CHIP_HAS_BASSTREBLE))
break;
ctrl->value = chip->treble;
return 0;
}
return -EINVAL;
}
static int tvaudio_s_ctrl(struct v4l2_subdev *sd,
struct v4l2_control *ctrl)
{ {
struct v4l2_subdev *sd = to_sd(ctrl);
struct CHIPSTATE *chip = to_state(sd); struct CHIPSTATE *chip = to_state(sd);
struct CHIPDESC *desc = chip->desc; struct CHIPDESC *desc = chip->desc;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
if (!(desc->flags & CHIP_HAS_INPUTSEL)) chip->muted = ctrl->val;
break;
if (ctrl->value < 0 || ctrl->value >= 2)
return -ERANGE;
chip->muted = ctrl->value;
if (chip->muted) if (chip->muted)
chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask); chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
else else
chip_write_masked(chip,desc->inputreg, chip_write_masked(chip,desc->inputreg,
desc->inputmap[chip->input],desc->inputmask); desc->inputmap[chip->input],desc->inputmask);
return 0; return 0;
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME: {
{
u32 volume, balance;
u32 left, right;
if (!(desc->flags & CHIP_HAS_VOLUME))
break;
volume = ctrl->value;
chip->volume = volume;
balance = chip->balance;
left = (min(65536U - balance, 32768U) * volume) / 32768U;
right = (min(balance, 32768U) * volume) / 32768U;
chip_write(chip, desc->leftreg, desc->volfunc(left));
chip_write(chip, desc->rightreg, desc->volfunc(right));
return 0;
}
case V4L2_CID_AUDIO_BALANCE:
{
u32 volume, balance; u32 volume, balance;
u32 left, right; u32 left, right;
if (!(desc->flags & CHIP_HAS_VOLUME)) volume = chip->volume->val;
break; balance = chip->balance->val;
balance = ctrl->value;
chip->balance = balance;
volume = chip->volume;
left = (min(65536U - balance, 32768U) * volume) / 32768U; left = (min(65536U - balance, 32768U) * volume) / 32768U;
right = (min(balance, 32768U) * volume) / 32768U; right = (min(balance, 32768U) * volume) / 32768U;
...@@ -1772,18 +1720,10 @@ static int tvaudio_s_ctrl(struct v4l2_subdev *sd, ...@@ -1772,18 +1720,10 @@ static int tvaudio_s_ctrl(struct v4l2_subdev *sd,
return 0; return 0;
} }
case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_BASS:
if (!(desc->flags & CHIP_HAS_BASSTREBLE)) chip_write(chip, desc->bassreg, desc->bassfunc(ctrl->val));
break;
chip->bass = ctrl->value;
chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
return 0; return 0;
case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_TREBLE:
if (!(desc->flags & CHIP_HAS_BASSTREBLE)) chip_write(chip, desc->treblereg, desc->treblefunc(ctrl->val));
break;
chip->treble = ctrl->value;
chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
...@@ -1802,35 +1742,6 @@ static int tvaudio_s_radio(struct v4l2_subdev *sd) ...@@ -1802,35 +1742,6 @@ static int tvaudio_s_radio(struct v4l2_subdev *sd)
return 0; return 0;
} }
static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
struct CHIPSTATE *chip = to_state(sd);
struct CHIPDESC *desc = chip->desc;
switch (qc->id) {
case V4L2_CID_AUDIO_MUTE:
if (desc->flags & CHIP_HAS_INPUTSEL)
return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
break;
case V4L2_CID_AUDIO_VOLUME:
if (desc->flags & CHIP_HAS_VOLUME)
return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
break;
case V4L2_CID_AUDIO_BALANCE:
if (desc->flags & CHIP_HAS_VOLUME)
return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
break;
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
if (desc->flags & CHIP_HAS_BASSTREBLE)
return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
break;
default:
break;
}
return -EINVAL;
}
static int tvaudio_s_routing(struct v4l2_subdev *sd, static int tvaudio_s_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config) u32 input, u32 output, u32 config)
{ {
...@@ -1934,13 +1845,32 @@ static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide ...@@ -1934,13 +1845,32 @@ static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0); return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0);
} }
static int tvaudio_log_status(struct v4l2_subdev *sd)
{
struct CHIPSTATE *chip = to_state(sd);
struct CHIPDESC *desc = chip->desc;
v4l2_info(sd, "Chip: %s\n", desc->name);
v4l2_ctrl_handler_log_status(&chip->hdl, sd->name);
return 0;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static const struct v4l2_ctrl_ops tvaudio_ctrl_ops = {
.s_ctrl = tvaudio_s_ctrl,
};
static const struct v4l2_subdev_core_ops tvaudio_core_ops = { static const struct v4l2_subdev_core_ops tvaudio_core_ops = {
.log_status = tvaudio_log_status,
.g_chip_ident = tvaudio_g_chip_ident, .g_chip_ident = tvaudio_g_chip_ident,
.queryctrl = tvaudio_queryctrl, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.g_ctrl = tvaudio_g_ctrl, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ctrl = tvaudio_s_ctrl, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
.g_ctrl = v4l2_subdev_g_ctrl,
.s_ctrl = v4l2_subdev_s_ctrl,
.queryctrl = v4l2_subdev_queryctrl,
.querymenu = v4l2_subdev_querymenu,
.s_std = tvaudio_s_std, .s_std = tvaudio_s_std,
}; };
...@@ -2025,6 +1955,10 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * ...@@ -2025,6 +1955,10 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
else else
chip_cmd(chip, "init", &desc->init); chip_cmd(chip, "init", &desc->init);
v4l2_ctrl_handler_init(&chip->hdl, 5);
if (desc->flags & CHIP_HAS_INPUTSEL)
v4l2_ctrl_new_std(&chip->hdl, &tvaudio_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
if (desc->flags & CHIP_HAS_VOLUME) { if (desc->flags & CHIP_HAS_VOLUME) {
if (!desc->volfunc) { if (!desc->volfunc) {
/* This shouldn't be happen. Warn user, but keep working /* This shouldn't be happen. Warn user, but keep working
...@@ -2033,12 +1967,14 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * ...@@ -2033,12 +1967,14 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
v4l2_info(sd, "volume callback undefined!\n"); v4l2_info(sd, "volume callback undefined!\n");
desc->flags &= ~CHIP_HAS_VOLUME; desc->flags &= ~CHIP_HAS_VOLUME;
} else { } else {
chip->volume = desc->volinit ? desc->volinit : 65535; chip->volume = v4l2_ctrl_new_std(&chip->hdl,
chip->balance = 32768; &tvaudio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
chip_write(chip, desc->leftreg, 0, 65535, 65535 / 100,
desc->volfunc(chip->volume)); desc->volinit ? desc->volinit : 65535);
chip_write(chip, desc->rightreg, chip->balance = v4l2_ctrl_new_std(&chip->hdl,
desc->volfunc(chip->volume)); &tvaudio_ctrl_ops, V4L2_CID_AUDIO_BALANCE,
0, 65535, 65535 / 100, 32768);
v4l2_ctrl_cluster(2, &chip->volume);
} }
} }
if (desc->flags & CHIP_HAS_BASSTREBLE) { if (desc->flags & CHIP_HAS_BASSTREBLE) {
...@@ -2049,17 +1985,28 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * ...@@ -2049,17 +1985,28 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
v4l2_info(sd, "bass/treble callbacks undefined!\n"); v4l2_info(sd, "bass/treble callbacks undefined!\n");
desc->flags &= ~CHIP_HAS_BASSTREBLE; desc->flags &= ~CHIP_HAS_BASSTREBLE;
} else { } else {
chip->treble = desc->trebleinit ? v4l2_ctrl_new_std(&chip->hdl,
desc->trebleinit : 32768; &tvaudio_ctrl_ops, V4L2_CID_AUDIO_BASS,
chip->bass = desc->bassinit ? 0, 65535, 65535 / 100,
desc->bassinit : 32768; desc->bassinit ? desc->bassinit : 32768);
chip_write(chip, desc->bassreg, v4l2_ctrl_new_std(&chip->hdl,
desc->bassfunc(chip->bass)); &tvaudio_ctrl_ops, V4L2_CID_AUDIO_TREBLE,
chip_write(chip, desc->treblereg, 0, 65535, 65535 / 100,
desc->treblefunc(chip->treble)); desc->trebleinit ? desc->trebleinit : 32768);
} }
} }
sd->ctrl_handler = &chip->hdl;
if (chip->hdl.error) {
int err = chip->hdl.error;
v4l2_ctrl_handler_free(&chip->hdl);
kfree(chip);
return err;
}
/* set controls to the default values */
v4l2_ctrl_handler_setup(&chip->hdl);
chip->thread = NULL; chip->thread = NULL;
init_timer(&chip->wt); init_timer(&chip->wt);
if (desc->flags & CHIP_NEED_CHECKMODE) { if (desc->flags & CHIP_NEED_CHECKMODE) {
...@@ -2095,6 +2042,7 @@ static int tvaudio_remove(struct i2c_client *client) ...@@ -2095,6 +2042,7 @@ static int tvaudio_remove(struct i2c_client *client)
} }
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&chip->hdl);
kfree(chip); kfree(chip);
return 0; return 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