This code allows free programming of some registers of the mb86a20s demodulator. All registers that need changes received an identification (REGXXXX_IDCFG). Signed-off-by: Manoel Pinheiro <pinusdtv@xxxxxxxxxxx> --- drivers/media/dvb/frontends/mb86a20s.c | 203 ++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/mb86a20s.h | 100 ++++++++++++++++ 2 files changed, 303 insertions(+), 0 deletions(-) diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c index f3c4013..bc7e868 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -1,6 +1,7 @@ /* * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver * + * Copyright (C) 2011 Manoel Pinheiro <pinusdtv@xxxxxxxxxxxx> * Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@xxxxxxxxxx> * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@xxxxxxxxxx> * @@ -45,8 +46,19 @@ struct mb86a20s_state { struct dvb_frontend frontend; bool need_init; + int config_regs_size; + const struct mb86a20s_config_regs_val *config_regs; }; +struct mb86a20s_config_regs { + u8 id_cfg; + u8 type; /* 0=8 bits wo/sub, 1=8 bits w/sub + * 2=16 bits wo/sub, 3=16 bits w/sub, 4=24 bits */ + u8 reg; + u8 subreg; + u32 init_val; +}; + struct regdata { u8 reg; u8 data; @@ -309,6 +321,104 @@ static struct regdata mb86a20s_reset_reception[] = { { 0x08, 0x00 }, }; +/* + * Initial registers for Pixelview USB hybrid PV-B308U + */ +static struct mb86a20s_config_regs mb86a20s_init_regs[] = { + { REGNONE_IDCFG, 0x00, 0x70, 0x00, 0x0f }, + { REGNONE_IDCFG, 0x00, 0x70, 0x00, 0xff }, + { REGNONE_IDCFG, 0x00, 0x08, 0x00, 0x01 }, + { REG09_IDCFG, 0x00, 0x09, 0x00, 0x3e }, + { REG50D1_IDCFG, 0x01, 0x50, 0xd1, 0x22 }, + { REG39_IDCFG, 0x00, 0x39, 0x00, 0x01 }, + { REG71_IDCFG, 0x00, 0x71, 0x00, 0x00 }, + { REG282A_IDCFG, 0x04, 0x28, 0x2a, 0xff80 }, + { REG2820_IDCFG, 0x04, 0x28, 0x20, 0x33dfa9 }, + { REG2822_IDCFG, 0x04, 0x28, 0x22, 0x1ff0 }, + { REGNONE_IDCFG, 0x00, 0x3b, 0x00, 0x21 }, + { REG3C_IDCFG, 0x00, 0x3c, 0x00, 0x3a }, + { REG01_IDCFG, 0x00, 0x01, 0x00, 0x0d }, + { REG0408_IDCFG, 0x01, 0x04, 0x08, 0x05 }, + { REG040E_IDCFG, 0x03, 0x04, 0x0e, 0x0014 }, + { REG040B_IDCFG, 0x01, 0x04, 0x0b, 0x8c }, + { REG0400_IDCFG, 0x03, 0x04, 0x00, 0x0007 }, + { REG0402_IDCFG, 0x03, 0x04, 0x02, 0x0fa0 }, + { REG0409_IDCFG, 0x01, 0x04, 0x09, 0x00 }, + { REG040A_IDCFG, 0x01, 0x04, 0x0a, 0xff }, + { REG0427_IDCFG, 0x01, 0x04, 0x27, 0x64 }, + { REG0428_IDCFG, 0x01, 0x04, 0x28, 0x00 }, + { REG041E_IDCFG, 0x01, 0x04, 0x1e, 0xff }, + { REG0429_IDCFG, 0x01, 0x04, 0x29, 0x0a }, + { REG0432_IDCFG, 0x01, 0x04, 0x32, 0x0a }, + { REG0414_IDCFG, 0x01, 0x04, 0x14, 0x02 }, + { REG0404_IDCFG, 0x03, 0x04, 0x04, 0x0022 }, + { REG0406_IDCFG, 0x03, 0x04, 0x06, 0x0ed8 }, + { REG0412_IDCFG, 0x01, 0x04, 0x12, 0x00 }, + { REG0413_IDCFG, 0x01, 0x04, 0x13, 0xff }, + { REG0415_IDCFG, 0x01, 0x04, 0x15, 0x4e }, + { REG0416_IDCFG, 0x01, 0x04, 0x16, 0x20 }, + { REGNONE_IDCFG, 0x00, 0x52, 0x00, 0x01 }, + { REG50A7_IDCFG, 0x04, 0x50, 0xa7, 0xffff }, + { REG50AA_IDCFG, 0x04, 0x50, 0xaa,0xffff }, + { REG50AD_IDCFG, 0x04, 0x50, 0xad, 0xffff }, + { REGNONE_IDCFG, 0x00, 0x5e, 0x00, 0x07 }, + { REG50DC_IDCFG, 0x03, 0x50, 0xdc, 0x01f4 }, + { REG50DE_IDCFG, 0x03, 0x50, 0xde, 0x01f4 }, + { REG50E0_IDCFG, 0x03, 0x50, 0xe0, 0x01f4 }, + { REG50B0_IDCFG, 0x01, 0x50, 0xb0, 0x07 }, + { REG50B2_IDCFG, 0x03, 0x50, 0xb2, 0xffff }, + { REG50B4_IDCFG, 0x03, 0x50, 0xb4, 0xffff }, + { REG50B6_IDCFG, 0x03, 0x50, 0xb6, 0xffff }, + { REG5050_IDCFG, 0x01, 0x50, 0x50, 0x02 }, + { REG5051_IDCFG, 0x01, 0x50, 0x51, 0x04 }, + { REG45_IDCFG, 0x00, 0x45, 0x00, 0x04 }, + { REGNONE_IDCFG, 0x00, 0x48, 0x00, 0x04 }, + { REG50D5_IDCFG, 0x01, 0x50, 0xd5, 0x01 }, + { REG50D6_IDCFG, 0x01, 0x50, 0xd6, 0x1f }, + { REG50D2_IDCFG, 0x01, 0x50, 0xd2, 0x03 }, + { REG50D7_IDCFG, 0x01, 0x50, 0xd7, 0x3f }, + { REG2874_IDCFG, 0x04, 0x28, 0x74, 0x0040 }, + { REG2846_IDCFG, 0x04, 0x28, 0x46, 0x2c0c }, + { REG0440_IDCFG, 0x01, 0x04, 0x40, 0x01 }, + { REG2800_IDCFG, 0x01, 0x28, 0x00, 0x10 }, + { REG2805_IDCFG, 0x01, 0x28, 0x05, 0x02 }, + { REGNONE_IDCFG, 0x00, 0x1c, 0x00, 0x01 }, + { REG2806_IDCFG, 0x04, 0x28, 0x06, 0x0003 }, + { REG2807_IDCFG, 0x04, 0x28, 0x07, 0x000d }, + { REG2808_IDCFG, 0x04, 0x28, 0x08, 0x0002 }, + { REG2809_IDCFG, 0x04, 0x28, 0x09, 0x0001 }, + { REG280A_IDCFG, 0x04, 0x28, 0x0a, 0x0021 }, + { REG280B_IDCFG, 0x04, 0x28, 0x0b, 0x0029 }, + { REG280C_IDCFG, 0x04, 0x28, 0x0c, 0x0016 }, + { REG280D_IDCFG, 0x04, 0x28, 0x0d, 0x0031 }, + { REG280E_IDCFG, 0x04, 0x28, 0x0e, 0x000e }, + { REG280F_IDCFG, 0x04, 0x28, 0x0f, 0x004e }, + { REG2810_IDCFG, 0x04, 0x28, 0x10, 0x0046 }, + { REG2811_IDCFG, 0x04, 0x28, 0x11, 0x000f }, + { REG2812_IDCFG, 0x04, 0x28, 0x12, 0x0056 }, + { REG2813_IDCFG, 0x04, 0x28, 0x13, 0x0035 }, + { REG2814_IDCFG, 0x04, 0x28, 0x14, 0x01be }, + { REG2815_IDCFG, 0x04, 0x28, 0x15, 0x0184 }, + { REG2816_IDCFG, 0x04, 0x28, 0x16, 0x03ee }, + { REG2817_IDCFG, 0x04, 0x28, 0x17, 0x0098 }, + { REG2818_IDCFG, 0x04, 0x28, 0x18, 0x009f }, + { REG2819_IDCFG, 0x04, 0x28, 0x19, 0x07b2 }, + { REG281A_IDCFG, 0x04, 0x28, 0x1a, 0x06c2 }, + { REG281B_IDCFG, 0x04, 0x28, 0x1b, 0x074a }, + { REG281C_IDCFG, 0x04, 0x28, 0x1c, 0x01bc }, + { REG281D_IDCFG, 0x04, 0x28, 0x1d, 0x04ba }, + { REG281E_IDCFG, 0x04, 0x28, 0x1e, 0x0614 }, + { REG501E_IDCFG, 0x01, 0x50, 0x1e, 0x5d }, + { REG5022_IDCFG, 0x01, 0x50, 0x22, 0x00 }, + { REG5023_IDCFG, 0x01, 0x50, 0x23, 0xc8 }, + { REG5024_IDCFG, 0x01, 0x50, 0x24, 0x00 }, + { REG5025_IDCFG, 0x01, 0x50, 0x25, 0xf0 }, + { REG5026_IDCFG, 0x01, 0x50, 0x26, 0x00 }, + { REG5027_IDCFG, 0x01, 0x50, 0x27, 0xc3 }, + { REG5039_IDCFG, 0x01, 0x50, 0x39, 0x02 }, + { REG286A_IDCFG, 0x04, 0x28, 0x6a, 0x0000 } +}; + static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, u8 i2c_addr, int reg, int data) { @@ -381,12 +491,103 @@ static int mb86a20s_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) return mb86a20s_writereg(state, 0xfe, 1); } +static u32 get_config_reg_val(struct mb86a20s_state *state, u8 id_cfg, u32 default_val) +{ + int i; + + if (state->config_regs != NULL) { + for (i = 0; i < state->config_regs_size; i++) { + if (state->config_regs[i].id_cfg == id_cfg) + return state->config_regs[i].init_val; + } + } + return default_val; +} + +static int mb86a20s_regs_init(struct mb86a20s_state *state) +{ + int i, i2, rc, count; + char buf[12]; + + state->need_init = 1; + + for (i = 0; i < ARRAY_SIZE(mb86a20s_init_regs); i++) { + struct mb86a20s_config_regs *reg_val = &mb86a20s_init_regs[i]; + u32 val = reg_val->init_val; + if (reg_val->id_cfg != REGNONE_IDCFG && state->config_regs) + val = get_config_reg_val(state, reg_val->id_cfg, val); + + buf[0] = reg_val->reg; + count = 1; + switch (reg_val->type) { + case 1: + buf[count++] = reg_val->subreg; + if (buf[0] == 0x28) + buf[count++] = 0x2b; + else + buf[count++] = buf[0] + 1; + break; + case 2: + buf[count++] = (u8)(val >> 0x08); + buf[count++] = buf[0] + 1; + buf[count++] = (u8)val; + break; + case 3: + buf[count++] = reg_val->subreg; + buf[count++] = buf[0] + 1; + buf[count++] = (u8)(val >> 0x08); + buf[count++] = buf[0]; + buf[count++] = reg_val->subreg + 1; + buf[count++] = buf[0] + 1; + break; + case 4: + if (buf[0] == 0x28) { + buf[count++] = reg_val->subreg; + buf[count++] = 0x29; + buf[count++] = (u8)(val >> 0x10); + buf[count++] = 0x2a; + buf[count++] = (u8)(val >> 0x08); + buf[count++] = 0x2b; + } + else if (buf[0] == 0x50) { + buf[count++] = reg_val->subreg; + buf[count++] = buf[0] + 1; + buf[count++] = (u8)(val >> 0x10); + buf[count++] = buf[0]; + buf[count++] = reg_val->subreg + 1; + buf[count++] = buf[0] + 1; + buf[count++] = (u8)(val >> 0x08); + buf[count++] = buf[0]; + buf[count++] = reg_val->subreg + 2; + buf[count++] = buf[0] + 1; + } + else + return -1; + break; + } + buf[count++] = (u8)val; + i2 = 0; + while (i2 < count) + { + rc = mb86a20s_writereg(state, buf[i2], buf[i2 + 1]); + if (rc < 0) + return rc; + i2 += 2; + } + } + state->need_init = 0; + return 0; +} + static int mb86a20s_initfe(struct dvb_frontend *fe) { struct mb86a20s_state *state = fe->demodulator_priv; int rc; u8 regD5 = 1; + if (state->config_regs) + return mb86a20s_regs_init(state); + dprintk("\n"); if (fe->ops.i2c_gate_ctrl) @@ -593,6 +794,8 @@ struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, /* setup the state */ state->config = config; state->i2c = i2c; + state->config_regs_size = config->config_regs_size; + state->config_regs = config->config_regs; /* create dvb_frontend */ memcpy(&state->frontend.ops, &mb86a20s_ops, diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h index bf22e77..385d886 100644 --- a/drivers/media/dvb/frontends/mb86a20s.h +++ b/drivers/media/dvb/frontends/mb86a20s.h @@ -18,6 +18,104 @@ #include <linux/dvb/frontend.h> +/* + * These IDCFG are unique identifiers for registers that can be assigned new values. + * New identifiers may be added to this list in ascending order. + * The unique identifier that cannot have its value changed is REGNONE_IDCFG + * which must be equal to zero. + * The values for IDCFG must be between 0x01 and 0xff (8 bits), for while. + */ +#define REGNONE_IDCFG 0x00 /* do not change this ID */ +#define REG01_IDCFG 0x01 +#define REG0400_IDCFG 0x02 +#define REG0402_IDCFG 0x03 +#define REG0404_IDCFG 0x04 +#define REG0406_IDCFG 0x05 +#define REG0408_IDCFG 0x06 +#define REG0409_IDCFG 0x07 +#define REG040A_IDCFG 0x08 +#define REG040B_IDCFG 0x09 +#define REG040E_IDCFG 0x0a +#define REG0412_IDCFG 0x0b +#define REG0413_IDCFG 0x0c +#define REG0414_IDCFG 0x0d +#define REG0415_IDCFG 0x0e +#define REG0416_IDCFG 0x0f +#define REG041E_IDCFG 0x10 +#define REG0427_IDCFG 0x11 +#define REG0428_IDCFG 0x12 +#define REG0429_IDCFG 0x13 +#define REG0432_IDCFG 0x14 +#define REG0440_IDCFG 0x15 +#define REG09_IDCFG 0x16 +#define REG2800_IDCFG 0x17 +#define REG2805_IDCFG 0x18 +#define REG2806_IDCFG 0x19 +#define REG2807_IDCFG 0x1a +#define REG2808_IDCFG 0x1b +#define REG2809_IDCFG 0x1c +#define REG280A_IDCFG 0x1d +#define REG280B_IDCFG 0x1e +#define REG280C_IDCFG 0x1f +#define REG280D_IDCFG 0x20 +#define REG280E_IDCFG 0x21 +#define REG280F_IDCFG 0x22 +#define REG2810_IDCFG 0x23 +#define REG2811_IDCFG 0x24 +#define REG2812_IDCFG 0x25 +#define REG2813_IDCFG 0x26 +#define REG2814_IDCFG 0x27 +#define REG2815_IDCFG 0x28 +#define REG2816_IDCFG 0x29 +#define REG2817_IDCFG 0x2a +#define REG2818_IDCFG 0x2b +#define REG2819_IDCFG 0x2c +#define REG281A_IDCFG 0x2d +#define REG281B_IDCFG 0x2e +#define REG281C_IDCFG 0x2f +#define REG281D_IDCFG 0x30 +#define REG281E_IDCFG 0x31 +#define REG2820_IDCFG 0x32 +#define REG2822_IDCFG 0x33 +#define REG282A_IDCFG 0x34 +#define REG2846_IDCFG 0x35 +#define REG286A_IDCFG 0x36 +#define REG2874_IDCFG 0x37 +#define REG39_IDCFG 0x38 +#define REG3C_IDCFG 0x39 +#define REG45_IDCFG 0x3a +#define REG501E_IDCFG 0x3b +#define REG5022_IDCFG 0x3c +#define REG5023_IDCFG 0x3d +#define REG5024_IDCFG 0x3e +#define REG5025_IDCFG 0x3f +#define REG5026_IDCFG 0x40 +#define REG5027_IDCFG 0x41 +#define REG5039_IDCFG 0x42 +#define REG5050_IDCFG 0x43 +#define REG5051_IDCFG 0x44 +#define REG50A7_IDCFG 0x45 +#define REG50AA_IDCFG 0x46 +#define REG50AD_IDCFG 0x47 +#define REG50B0_IDCFG 0x48 +#define REG50B2_IDCFG 0x49 +#define REG50B4_IDCFG 0x4a +#define REG50B6_IDCFG 0x4b +#define REG50D1_IDCFG 0x4c +#define REG50D2_IDCFG 0x4d +#define REG50D5_IDCFG 0x4e +#define REG50D6_IDCFG 0x4f +#define REG50D7_IDCFG 0x50 +#define REG50DC_IDCFG 0x51 +#define REG50DE_IDCFG 0x52 +#define REG50E0_IDCFG 0x53 +#define REG71_IDCFG 0x54 + +struct mb86a20s_config_regs_val { + u8 id_cfg; + u32 init_val; +}; + /** * struct mb86a20s_config - Define the per-device attributes of the frontend * @@ -27,6 +125,8 @@ struct mb86a20s_config { u8 demod_address; bool is_serial; + int config_regs_size; + const struct mb86a20s_config_regs_val *config_regs; }; #if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html