[REVIEW PATCH 14/16] r820t: add manual gain controls
Add gain control for LNA, Mixer and IF. Expose controls via V4L control framework. Cc: Mauro Carvalho Chehab m.che...@samsung.com Signed-off-by: Antti Palosaari cr...@iki.fi --- drivers/media/tuners/r820t.c | 137 ++- drivers/media/tuners/r820t.h | 10 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 319adc4..452a486 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -36,6 +36,7 @@ #include linux/mutex.h #include linux/slab.h #include linux/bitrev.h +#include media/v4l2-ctrls.h #include tuner-i2c.h #include r820t.h @@ -80,6 +81,7 @@ struct r820t_sect_type { struct r820t_priv { struct list_headhybrid_tuner_instance_list; + struct dvb_frontend *fe; const struct r820t_config *cfg; struct tuner_i2c_props i2c_props; struct mutexlock; @@ -100,6 +102,15 @@ struct r820t_priv { enum v4l2_tuner_typetype; v4l2_std_id std; u32 bw; /* in MHz */ + + /* Controls */ + struct v4l2_ctrl_handler hdl; + struct v4l2_ctrl *lna_gain_auto; + struct v4l2_ctrl *lna_gain; + struct v4l2_ctrl *mixer_gain_auto; + struct v4l2_ctrl *mixer_gain; + struct v4l2_ctrl *if_gain_auto; + struct v4l2_ctrl *if_gain; }; struct r820t_freq_range { @@ -2255,8 +2266,10 @@ static int r820t_release(struct dvb_frontend *fe) mutex_lock(r820t_list_mutex); - if (priv) + if (priv) { + v4l2_ctrl_handler_free(priv-hdl); hybrid_tuner_release_state(priv); + } mutex_unlock(r820t_list_mutex); @@ -2265,6 +2278,96 @@ static int r820t_release(struct dvb_frontend *fe) return 0; } +static int r820t_set_lna_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-lna_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x05, 0x00, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x05, + 0x10 | priv-lna_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_set_mixer_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-mixer_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x07, + 0x00 | priv-mixer_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_set_if_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-if_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x0c, 0x10, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x0c, + 0x00 | priv-if_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct r820t_priv *priv = + container_of(ctrl-handler, struct r820t_priv, hdl); + int rc; + + switch (ctrl-id) { + case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: + case V4L2_CID_RF_TUNER_LNA_GAIN: + rc = r820t_set_lna_gain(priv); + break; + case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: + case V4L2_CID_RF_TUNER_MIXER_GAIN: + rc = r820t_set_mixer_gain(priv); + break; + case V4L2_CID_RF_TUNER_IF_GAIN_AUTO: + case V4L2_CID_RF_TUNER_IF_GAIN: + rc = r820t_set_if_gain(priv); + break; + default: + rc = -EINVAL; + } + + return rc; +} + +static const struct v4l2_ctrl_ops r820t_ctrl_ops = { + .s_ctrl = r820t_s_ctrl, +}; + static const struct dvb_tuner_ops r820t_tuner_ops = { .info = { .name = Rafael Micro R820T, @@ -2280,6 +2383,13 @@ static const struct dvb_tuner_ops r820t_tuner_ops = { .get_rf_strength = r820t_signal, }; +struct v4l2_ctrl_handler *r820t_get_ctrl_handler(struct dvb_frontend *fe) +{ + struct r820t_priv *priv = fe-tuner_priv; + return priv-hdl; +} +EXPORT_SYMBOL(r820t_get_ctrl_handler); + struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
[REVIEW PATCH 14/16] r820t: add manual gain controls
Add gain control for LNA, Mixer and IF. Expose controls via V4L control framework. Cc: Mauro Carvalho Chehab m.che...@samsung.com Signed-off-by: Antti Palosaari cr...@iki.fi --- drivers/media/tuners/r820t.c | 137 ++- drivers/media/tuners/r820t.h | 10 2 files changed, 146 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 319adc4..5150a18 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -36,6 +36,7 @@ #include linux/mutex.h #include linux/slab.h #include linux/bitrev.h +#include media/v4l2-ctrls.h #include tuner-i2c.h #include r820t.h @@ -80,6 +81,7 @@ struct r820t_sect_type { struct r820t_priv { struct list_headhybrid_tuner_instance_list; + struct dvb_frontend *fe; const struct r820t_config *cfg; struct tuner_i2c_props i2c_props; struct mutexlock; @@ -100,6 +102,15 @@ struct r820t_priv { enum v4l2_tuner_typetype; v4l2_std_id std; u32 bw; /* in MHz */ + + /* Controls */ + struct v4l2_ctrl_handler hdl; + struct v4l2_ctrl *lna_gain_auto; + struct v4l2_ctrl *lna_gain; + struct v4l2_ctrl *mixer_gain_auto; + struct v4l2_ctrl *mixer_gain; + struct v4l2_ctrl *if_gain_auto; + struct v4l2_ctrl *if_gain; }; struct r820t_freq_range { @@ -2255,8 +2266,10 @@ static int r820t_release(struct dvb_frontend *fe) mutex_lock(r820t_list_mutex); - if (priv) + if (priv) { + v4l2_ctrl_handler_free(priv-hdl); hybrid_tuner_release_state(priv); + } mutex_unlock(r820t_list_mutex); @@ -2265,6 +2278,96 @@ static int r820t_release(struct dvb_frontend *fe) return 0; } +static int r820t_set_lna_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-lna_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x05, 0x00, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x05, + 0x10 | priv-lna_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_set_mixer_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-mixer_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x07, + 0x00 | priv-mixer_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_set_if_gain(struct r820t_priv *priv) +{ + struct dvb_frontend *fe = priv-fe; + int rc; + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 1); + + if (priv-if_gain_auto-val) + rc = r820t_write_reg_mask(priv, 0x0c, 0x10, 0x10); + else + rc = r820t_write_reg_mask(priv, 0x0c, + 0x00 | priv-if_gain-val, 0x1f); + + if (fe-ops.i2c_gate_ctrl) + fe-ops.i2c_gate_ctrl(fe, 0); + + return rc; +} + +static int r820t_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct r820t_priv *priv = + container_of(ctrl-handler, struct r820t_priv, hdl); + int rc; + + switch (ctrl-id) { + case V4L2_CID_LNA_GAIN_AUTO: + case V4L2_CID_LNA_GAIN: + rc = r820t_set_lna_gain(priv); + break; + case V4L2_CID_MIXER_GAIN_AUTO: + case V4L2_CID_MIXER_GAIN: + rc = r820t_set_mixer_gain(priv); + break; + case V4L2_CID_IF_GAIN_AUTO: + case V4L2_CID_IF_GAIN: + rc = r820t_set_if_gain(priv); + break; + default: + rc = -EINVAL; + } + + return rc; +} + +static const struct v4l2_ctrl_ops r820t_ctrl_ops = { + .s_ctrl = r820t_s_ctrl, +}; + static const struct dvb_tuner_ops r820t_tuner_ops = { .info = { .name = Rafael Micro R820T, @@ -2280,6 +2383,13 @@ static const struct dvb_tuner_ops r820t_tuner_ops = { .get_rf_strength = r820t_signal, }; +struct v4l2_ctrl_handler *r820t_get_ctrl_handler(struct dvb_frontend *fe) +{ + struct r820t_priv *priv = fe-tuner_priv; + return priv-hdl; +} +EXPORT_SYMBOL(r820t_get_ctrl_handler); + struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct