@@ -1,6 +1,7 @@
/*
* Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
*
+ * Copyright (C) 2011 Manoel Pinheiro <pinusdtv@pdtv.cjb.net>
* Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
* Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
*
@@ -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,
@@ -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) \
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@hotmail.com> --- drivers/media/dvb/frontends/mb86a20s.c | 203 ++++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/mb86a20s.h | 100 ++++++++++++++++ 2 files changed, 303 insertions(+), 0 deletions(-)