mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-11 07:04:04 +08:00
V4L/DVB (6962): tda18271: allow device-specific configuration of IF frequency and std bits
Allow drivers to pass device-specific configuration parameters during attach. If these parameters are omitted, default values will be used. Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
59067f7ed4
commit
f21e0d7f05
@ -768,12 +768,12 @@ static int tda18271_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
struct tda18271_std_map *std_map = priv->std;
|
||||
struct tda18271_std_map *std_map = &priv->std;
|
||||
u8 std;
|
||||
u32 bw, sgIF = 0;
|
||||
u32 freq = params->frequency;
|
||||
|
||||
BUG_ON(!priv->tune || !priv->std);
|
||||
BUG_ON(!priv->tune);
|
||||
|
||||
priv->mode = TDA18271_DIGITAL;
|
||||
|
||||
@ -832,12 +832,12 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
|
||||
struct analog_parameters *params)
|
||||
{
|
||||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
struct tda18271_std_map *std_map = priv->std;
|
||||
struct tda18271_std_map *std_map = &priv->std;
|
||||
char *mode;
|
||||
u8 std;
|
||||
u32 sgIF, freq = params->frequency * 62500;
|
||||
|
||||
BUG_ON(!priv->tune || !priv->std);
|
||||
BUG_ON(!priv->tune);
|
||||
|
||||
priv->mode = TDA18271_ANALOG;
|
||||
|
||||
@ -901,6 +901,69 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
#define tda18271_update_std(std_cfg, name) do { \
|
||||
if (map->std_cfg.if_freq + map->std_cfg.std_bits > 0) { \
|
||||
tda_dbg("Using custom std config for %s\n", name); \
|
||||
memcpy(&std->std_cfg, &map->std_cfg, \
|
||||
sizeof(struct tda18271_std_map_item)); \
|
||||
} } while (0)
|
||||
|
||||
#define tda18271_dump_std_item(std_cfg, name) do { \
|
||||
tda_dbg("(%s) if freq = %d, std bits = 0x%02x\n", \
|
||||
name, std->std_cfg.if_freq, std->std_cfg.std_bits); \
|
||||
} while (0)
|
||||
|
||||
static int tda18271_dump_std_map(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
struct tda18271_std_map *std = &priv->std;
|
||||
|
||||
tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
|
||||
tda18271_dump_std_item(atv_b, "pal b");
|
||||
tda18271_dump_std_item(atv_dk, "pal dk");
|
||||
tda18271_dump_std_item(atv_gh, "pal gh");
|
||||
tda18271_dump_std_item(atv_i, "pal i");
|
||||
tda18271_dump_std_item(atv_l, "pal l");
|
||||
tda18271_dump_std_item(atv_lc, "pal l'");
|
||||
tda18271_dump_std_item(atv_mn, "atv mn");
|
||||
tda18271_dump_std_item(atsc_6, "atsc 6");
|
||||
tda18271_dump_std_item(dvbt_6, "dvbt 6");
|
||||
tda18271_dump_std_item(dvbt_7, "dvbt 7");
|
||||
tda18271_dump_std_item(dvbt_8, "dvbt 8");
|
||||
tda18271_dump_std_item(qam_6, "qam 6");
|
||||
tda18271_dump_std_item(qam_8, "qam 8");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda18271_update_std_map(struct dvb_frontend *fe,
|
||||
struct tda18271_std_map *map)
|
||||
{
|
||||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
struct tda18271_std_map *std = &priv->std;
|
||||
|
||||
if (!map)
|
||||
return -EINVAL;
|
||||
|
||||
tda18271_update_std(atv_b, "atv b");
|
||||
tda18271_update_std(atv_dk, "atv dk");
|
||||
tda18271_update_std(atv_gh, "atv gh");
|
||||
tda18271_update_std(atv_i, "atv i");
|
||||
tda18271_update_std(atv_l, "atv l");
|
||||
tda18271_update_std(atv_lc, "atv l'");
|
||||
tda18271_update_std(atv_mn, "atv mn");
|
||||
tda18271_update_std(atsc_6, "atsc 6");
|
||||
tda18271_update_std(dvbt_6, "dvbt 6");
|
||||
tda18271_update_std(dvbt_7, "dvbt 7");
|
||||
tda18271_update_std(dvbt_8, "dvbt 8");
|
||||
tda18271_update_std(qam_6, "qam 6");
|
||||
tda18271_update_std(qam_8, "qam 8");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda18271_get_id(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda18271_priv *priv = fe->tuner_priv;
|
||||
@ -951,7 +1014,7 @@ static struct dvb_tuner_ops tda18271_tuner_ops = {
|
||||
|
||||
struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
||||
struct i2c_adapter *i2c,
|
||||
enum tda18271_i2c_gate gate)
|
||||
struct tda18271_config *cfg)
|
||||
{
|
||||
struct tda18271_priv *priv = NULL;
|
||||
|
||||
@ -961,7 +1024,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
||||
|
||||
priv->i2c_addr = addr;
|
||||
priv->i2c_adap = i2c;
|
||||
priv->gate = gate;
|
||||
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
|
||||
priv->cal_initialized = false;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
@ -975,6 +1038,13 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
||||
memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
/* override default std map with values in config struct */
|
||||
if ((cfg) && (cfg->std_map))
|
||||
tda18271_update_std_map(fe, cfg->std_map);
|
||||
|
||||
if (tda18271_debug & DBG_MAP)
|
||||
tda18271_dump_std_map(fe);
|
||||
|
||||
tda18271_init_regs(fe);
|
||||
|
||||
return fe;
|
||||
|
@ -84,27 +84,6 @@ struct tda18271_rf_tracking_filter_cal {
|
||||
int rf_b2;
|
||||
};
|
||||
|
||||
struct tda18271_std_map_item {
|
||||
u32 if_freq;
|
||||
u8 std_bits;
|
||||
};
|
||||
|
||||
struct tda18271_std_map {
|
||||
struct tda18271_std_map_item atv_b;
|
||||
struct tda18271_std_map_item atv_dk;
|
||||
struct tda18271_std_map_item atv_gh;
|
||||
struct tda18271_std_map_item atv_i;
|
||||
struct tda18271_std_map_item atv_l;
|
||||
struct tda18271_std_map_item atv_lc;
|
||||
struct tda18271_std_map_item atv_mn;
|
||||
struct tda18271_std_map_item atsc_6;
|
||||
struct tda18271_std_map_item dvbt_6;
|
||||
struct tda18271_std_map_item dvbt_7;
|
||||
struct tda18271_std_map_item dvbt_8;
|
||||
struct tda18271_std_map_item qam_6;
|
||||
struct tda18271_std_map_item qam_8;
|
||||
};
|
||||
|
||||
enum tda18271_mode {
|
||||
TDA18271_ANALOG,
|
||||
TDA18271_DIGITAL,
|
||||
@ -128,8 +107,8 @@ struct tda18271_priv {
|
||||
|
||||
unsigned int cal_initialized:1;
|
||||
|
||||
struct tda18271_std_map *std;
|
||||
struct tda18271_map_layout *maps;
|
||||
struct tda18271_std_map std;
|
||||
struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
|
||||
|
||||
int (*tune) (struct dvb_frontend *fe,
|
||||
|
@ -1194,11 +1194,11 @@ static struct tda18271_std_map tda18271c1_std_map = {
|
||||
.atv_l = { .if_freq = 7750000, .std_bits = 0x0f },
|
||||
.atv_lc = { .if_freq = 1250000, .std_bits = 0x0f },
|
||||
.atv_mn = { .if_freq = 5750000, .std_bits = 0x0d },
|
||||
.atsc_6 = { .if_freq = 5380000, .std_bits = 0x1b },
|
||||
.dvbt_6 = { .if_freq = 3300000, .std_bits = 0x1b },
|
||||
.dvbt_7 = { .if_freq = 3800000, .std_bits = 0x19 },
|
||||
.dvbt_8 = { .if_freq = 4300000, .std_bits = 0x1a },
|
||||
.qam_6 = { .if_freq = 4000000, .std_bits = 0x18 },
|
||||
.atsc_6 = { .if_freq = 3250000, .std_bits = 0x1c },
|
||||
.dvbt_6 = { .if_freq = 3300000, .std_bits = 0x1c },
|
||||
.dvbt_7 = { .if_freq = 3800000, .std_bits = 0x1d },
|
||||
.dvbt_8 = { .if_freq = 4300000, .std_bits = 0x1e },
|
||||
.qam_6 = { .if_freq = 4000000, .std_bits = 0x1d },
|
||||
.qam_8 = { .if_freq = 5000000, .std_bits = 0x1f },
|
||||
};
|
||||
|
||||
@ -1210,7 +1210,7 @@ static struct tda18271_std_map tda18271c2_std_map = {
|
||||
.atv_l = { .if_freq = 6900000, .std_bits = 0x0e },
|
||||
.atv_lc = { .if_freq = 1250000, .std_bits = 0x0e },
|
||||
.atv_mn = { .if_freq = 5400000, .std_bits = 0x0c },
|
||||
.atsc_6 = { .if_freq = 5380000, .std_bits = 0x1b },
|
||||
.atsc_6 = { .if_freq = 3250000, .std_bits = 0x1c },
|
||||
.dvbt_6 = { .if_freq = 3300000, .std_bits = 0x1c },
|
||||
.dvbt_7 = { .if_freq = 3500000, .std_bits = 0x1c },
|
||||
.dvbt_8 = { .if_freq = 4000000, .std_bits = 0x1d },
|
||||
@ -1256,11 +1256,13 @@ int tda18271_assign_map_layout(struct dvb_frontend *fe)
|
||||
switch (priv->id) {
|
||||
case TDA18271HDC1:
|
||||
priv->maps = &tda18271c1_map_layout;
|
||||
priv->std = &tda18271c1_std_map;
|
||||
memcpy(&priv->std, &tda18271c1_std_map,
|
||||
sizeof(struct tda18271_std_map));
|
||||
break;
|
||||
case TDA18271HDC2:
|
||||
priv->maps = &tda18271c2_map_layout;
|
||||
priv->std = &tda18271c2_std_map;
|
||||
memcpy(&priv->std, &tda18271c2_std_map,
|
||||
sizeof(struct tda18271_std_map));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -24,21 +24,47 @@
|
||||
#include <linux/i2c.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
struct tda18271_std_map_item {
|
||||
u32 if_freq;
|
||||
u8 std_bits;
|
||||
};
|
||||
|
||||
struct tda18271_std_map {
|
||||
struct tda18271_std_map_item atv_b;
|
||||
struct tda18271_std_map_item atv_dk;
|
||||
struct tda18271_std_map_item atv_gh;
|
||||
struct tda18271_std_map_item atv_i;
|
||||
struct tda18271_std_map_item atv_l;
|
||||
struct tda18271_std_map_item atv_lc;
|
||||
struct tda18271_std_map_item atv_mn;
|
||||
struct tda18271_std_map_item atsc_6;
|
||||
struct tda18271_std_map_item dvbt_6;
|
||||
struct tda18271_std_map_item dvbt_7;
|
||||
struct tda18271_std_map_item dvbt_8;
|
||||
struct tda18271_std_map_item qam_6;
|
||||
struct tda18271_std_map_item qam_8;
|
||||
};
|
||||
|
||||
enum tda18271_i2c_gate {
|
||||
TDA18271_GATE_AUTO = 0,
|
||||
TDA18271_GATE_ANALOG,
|
||||
TDA18271_GATE_DIGITAL,
|
||||
};
|
||||
|
||||
struct tda18271_config {
|
||||
struct tda18271_std_map *std_map;
|
||||
enum tda18271_i2c_gate gate;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
||||
struct i2c_adapter *i2c,
|
||||
enum tda18271_i2c_gate gate);
|
||||
struct tda18271_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
|
||||
u8 addr,
|
||||
struct i2c_adapter *i2c,
|
||||
enum tda18271_i2c_gate gate)
|
||||
struct tda18271_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
|
@ -183,6 +183,16 @@ static struct tda829x_config tda829x_no_probe = {
|
||||
.probe_tuner = TDA829X_DONT_PROBE,
|
||||
};
|
||||
|
||||
static struct tda18271_std_map hauppauge_tda18271_std_map = {
|
||||
.atsc_6 = { .if_freq = 5380000, .std_bits = 0x1b },
|
||||
.qam_6 = { .if_freq = 4000000, .std_bits = 0x18 },
|
||||
};
|
||||
|
||||
static struct tda18271_config hauppauge_tda18271_config = {
|
||||
.std_map = &hauppauge_tda18271_std_map,
|
||||
.gate = TDA18271_GATE_ANALOG,
|
||||
};
|
||||
|
||||
static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
|
||||
{
|
||||
struct cx23885_tsport *port = ptr;
|
||||
@ -248,7 +258,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
&tda829x_no_probe);
|
||||
dvb_attach(tda18271_attach, port->dvb.frontend,
|
||||
0x60, &dev->i2c_bus[1].i2c_adap,
|
||||
TDA18271_GATE_ANALOG);
|
||||
&hauppauge_tda18271_config);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
|
@ -509,6 +509,10 @@ static void tda829x_release(struct dvb_frontend *fe)
|
||||
fe->analog_demod_priv = NULL;
|
||||
}
|
||||
|
||||
static struct tda18271_config tda829x_tda18271_config = {
|
||||
.gate = TDA18271_GATE_ANALOG,
|
||||
};
|
||||
|
||||
static int tda829x_find_tuner(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda8290_priv *priv = fe->analog_demod_priv;
|
||||
@ -574,7 +578,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
|
||||
priv->ver |= TDA18271;
|
||||
tda18271_attach(fe, priv->tda827x_addr,
|
||||
priv->i2c_props.adap,
|
||||
TDA18271_GATE_ANALOG);
|
||||
&tda829x_tda18271_config);
|
||||
} else {
|
||||
if ((data & 0x3c) == 0)
|
||||
priv->ver |= TDA8275;
|
||||
|
Loading…
Reference in New Issue
Block a user