From 746d9732dbd5b95c3ba36230e2814fa2c391a311 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 25 Aug 2007 19:08:45 -0300 Subject: V4L/DVB (6433): Move all tda8275/8275a tuning code from tda8290 module into tda827x module Add analog tuning support to tda827x dvb_frontend tuner module. Convert tda8290 module back to native tuner interface. The tda8290 analog demodulator will be handled the same way as tda9887. The tuner.ko module (tuner-core) will pass commands to tda8290 via the tuner_operations interface. tda8290 will communicate with tda827x via the dvb_frontend interface, while passing a pointer to a private data structure. Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 566 ++++++++---------------------------------- 1 file changed, 106 insertions(+), 460 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 0e5cf459d3e..5d30cbcd736 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -23,11 +23,11 @@ #include #include #include -#include "tuner-i2c.h" #include "tda8290.h" +#include "tda827x.h" -static int debug = 0; -module_param(debug, int, 0644); +static int tuner_debug = 0; +module_param_named(debug, tuner_debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); #define PREFIX "tda8290 " @@ -38,332 +38,18 @@ struct tda8290_priv { struct tuner_i2c_props i2c_props; unsigned char tda8290_easy_mode; - unsigned char tda827x_lpsel; + unsigned char tda827x_addr; unsigned char tda827x_ver; - unsigned int sgIF; - - u32 frequency; - - unsigned int *lna_cfg; - int (*tuner_callback) (void *dev, int command,int arg); -}; - -/* ---------------------------------------------------------------------- */ - -struct tda827x_data { - u32 lomax; - u8 spd; - u8 bs; - u8 bp; - u8 cp; - u8 gc3; - u8 div1p5; -}; - /* Note lomax entry is lo / 62500 */ - -static struct tda827x_data tda827x_analog[] = { - { .lomax = 992, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 62 MHz */ - { .lomax = 1056, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1}, /* 66 MHz */ - { .lomax = 1216, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 76 MHz */ - { .lomax = 1344, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0}, /* 84 MHz */ - { .lomax = 1488, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 93 MHz */ - { .lomax = 1568, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 98 MHz */ - { .lomax = 1744, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 109 MHz */ - { .lomax = 1968, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 123 MHz */ - { .lomax = 2128, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 133 MHz */ - { .lomax = 2416, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 151 MHz */ - { .lomax = 2464, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 154 MHz */ - { .lomax = 2896, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 181 MHz */ - { .lomax = 2960, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 185 MHz */ - { .lomax = 3472, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 217 MHz */ - { .lomax = 3904, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 244 MHz */ - { .lomax = 4240, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 265 MHz */ - { .lomax = 4832, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 302 MHz */ - { .lomax = 5184, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 324 MHz */ - { .lomax = 5920, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 370 MHz */ - { .lomax = 7264, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 454 MHz */ - { .lomax = 7888, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 493 MHz */ - { .lomax = 8480, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1}, /* 530 MHz */ - { .lomax = 8864, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0}, /* 554 MHz */ - { .lomax = 9664, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 604 MHz */ - { .lomax = 11088, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 696 MHz */ - { .lomax = 11840, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 740 MHz */ - { .lomax = 13120, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0}, /* 820 MHz */ - { .lomax = 13840, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0}, /* 865 MHz */ - { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} /* End */ + struct tda827x_config cfg; }; -static void tda827x_set_analog_params(struct dvb_frontend *fe, - struct analog_parameters *params) -{ - unsigned char tuner_reg[8]; - unsigned char reg2[2]; - u32 N; - int i; - struct tda8290_priv *priv = fe->tuner_priv; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0}; - unsigned int freq = params->frequency; - - if (params->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; - - N = freq + priv->sgIF; - i = 0; - while (tda827x_analog[i].lomax < N) { - if(tda827x_analog[i + 1].lomax == 0) - break; - i++; - } - - N = N << tda827x_analog[i].spd; - - tuner_reg[0] = 0; - tuner_reg[1] = (unsigned char)(N>>8); - tuner_reg[2] = (unsigned char) N; - tuner_reg[3] = 0x40; - tuner_reg[4] = 0x52 + (priv->tda827x_lpsel << 5); - tuner_reg[5] = (tda827x_analog[i].spd << 6) + (tda827x_analog[i].div1p5 <<5) + - (tda827x_analog[i].bs <<3) + tda827x_analog[i].bp; - tuner_reg[6] = 0x8f + (tda827x_analog[i].gc3 << 4); - tuner_reg[7] = 0x8f; - - msg.buf = tuner_reg; - msg.len = 8; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msg.buf= reg2; - msg.len = 2; - reg2[0] = 0x80; - reg2[1] = 0; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x60; - reg2[1] = 0xbf; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x30; - reg2[1] = tuner_reg[4] + 0x80; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(1); - reg2[0] = 0x30; - reg2[1] = tuner_reg[4] + 4; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(1); - reg2[0] = 0x30; - reg2[1] = tuner_reg[4]; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(550); - reg2[0] = 0x30; - reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_analog[i].cp ; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x60; - reg2[1] = 0x3f; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - reg2[0] = 0x80; - reg2[1] = 0x08; // Vsync en - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -static void tda827x_agcf(struct dvb_frontend *fe) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char data[] = {0x80, 0x0c}; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, - .flags = 0, .len = 2}; - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -/* ---------------------------------------------------------------------- */ - -struct tda827xa_data { - u32 lomax; - u8 svco; - u8 spd; - u8 scr; - u8 sbs; - u8 gc3; -}; - -static struct tda827xa_data tda827xa_analog[] = { - { .lomax = 910, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, /* 56.875 MHz */ - { .lomax = 1076, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 67.25 MHz */ - { .lomax = 1300, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 81.25 MHz */ - { .lomax = 1560, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3}, /* 97.5 MHz */ - { .lomax = 1820, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1}, /* 113.75 MHz */ - { .lomax = 2152, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 134.5 MHz */ - { .lomax = 2464, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 154 MHz */ - { .lomax = 2600, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 162.5 MHz */ - { .lomax = 2928, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1}, /* 183 MHz */ - { .lomax = 3120, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1}, /* 195 MHz */ - { .lomax = 3640, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3}, /* 227.5 MHz */ - { .lomax = 4304, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3}, /* 269 MHz */ - { .lomax = 5200, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1}, /* 325 MHz */ - { .lomax = 6240, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 390 MHz */ - { .lomax = 7280, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3}, /* 455 MHz */ - { .lomax = 8320, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 520 MHz */ - { .lomax = 8608, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1}, /* 538 MHz */ - { .lomax = 8864, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1}, /* 554 MHz */ - { .lomax = 9920, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 620 MHz */ - { .lomax = 10400, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 650 MHz */ - { .lomax = 11200, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 700 MHz */ - { .lomax = 12480, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 780 MHz */ - { .lomax = 13120, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0}, /* 820 MHz */ - { .lomax = 13920, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0}, /* 870 MHz */ - { .lomax = 14576, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0}, /* 911 MHz */ - { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} /* End */ -}; - -static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, - struct analog_parameters *params) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char buf[] = {0x22, 0x01}; - int arg; - struct i2c_msg msg = {.addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = sizeof(buf)}; - - if ((priv->lna_cfg == NULL) || (priv->tuner_callback == NULL)) - return; - - if (*priv->lna_cfg) { - if (high) - tuner_dbg("setting LNA to high gain\n"); - else - tuner_dbg("setting LNA to low gain\n"); - } - switch (*priv->lna_cfg) { - case 0: /* no LNA */ - break; - case 1: /* switch is GPIO 0 of tda8290 */ - case 2: - /* turn Vsync on */ - if (params->std & V4L2_STD_MN) - arg = 1; - else - arg = 0; - if (priv->tuner_callback) - priv->tuner_callback(priv->i2c_props.adap->algo_data, 1, arg); - buf[1] = high ? 0 : 1; - if (*priv->lna_cfg == 2) - buf[1] = high ? 1 : 0; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - break; - case 3: /* switch with GPIO of saa713x */ - if (priv->tuner_callback) - priv->tuner_callback(priv->i2c_props.adap->algo_data, 0, high); - break; - } -} - -static void tda827xa_set_analog_params(struct dvb_frontend *fe, - struct analog_parameters *params) -{ - unsigned char tuner_reg[11]; - u32 N; - int i; - struct tda8290_priv *priv = fe->tuner_priv; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags = 0, .buf = tuner_reg}; - unsigned int freq = params->frequency; - - tda827xa_lna_gain(fe, 1, params); - msleep(10); - - if (params->mode == V4L2_TUNER_RADIO) - freq = freq / 1000; - - N = freq + priv->sgIF; - i = 0; - while (tda827xa_analog[i].lomax < N) { - if(tda827xa_analog[i + 1].lomax == 0) - break; - i++; - } - - N = N << tda827xa_analog[i].spd; - - tuner_reg[0] = 0; - tuner_reg[1] = (unsigned char)(N>>8); - tuner_reg[2] = (unsigned char) N; - tuner_reg[3] = 0; - tuner_reg[4] = 0x16; - tuner_reg[5] = (tda827xa_analog[i].spd << 5) + (tda827xa_analog[i].svco << 3) + - tda827xa_analog[i].sbs; - tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4); - tuner_reg[7] = 0x1c; - tuner_reg[8] = 4; - tuner_reg[9] = 0x20; - tuner_reg[10] = 0x00; - msg.len = 11; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x90; - tuner_reg[1] = 0xff; - tuner_reg[2] = 0xe0; - tuner_reg[3] = 0; - tuner_reg[4] = 0x99 + (priv->tda827x_lpsel << 1); - msg.len = 5; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xa0; - tuner_reg[1] = 0xc0; - msg.len = 2; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x30; - tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msg.flags = I2C_M_RD; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - msg.flags = 0; - tuner_reg[1] >>= 4; - tuner_dbg("AGC2 gain is: %d\n", tuner_reg[1]); - if (tuner_reg[1] < 1) - tda827xa_lna_gain(fe, 0, params); - - msleep(100); - tuner_reg[0] = 0x60; - tuner_reg[1] = 0x3c; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - msleep(163); - tuner_reg[0] = 0x50; - tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0x80; - tuner_reg[1] = 0x28; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xb0; - tuner_reg[1] = 0x01; - i2c_transfer(priv->i2c_props.adap, &msg, 1); - - tuner_reg[0] = 0xc0; - tuner_reg[1] = 0x19 + (priv->tda827x_lpsel << 1); - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - -static void tda827xa_agcf(struct dvb_frontend *fe) -{ - struct tda8290_priv *priv = fe->tuner_priv; - unsigned char data[] = {0x80, 0x2c}; - struct i2c_msg msg = {.addr = priv->tda827x_addr, .buf = data, - .flags = 0, .len = 2}; - i2c_transfer(priv->i2c_props.adap, &msg, 1); -} - /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) +static void tda8290_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -381,58 +67,56 @@ static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) /*---------------------------------------------------------------------*/ -static void set_audio(struct dvb_frontend *fe, - struct analog_parameters *params) +static void set_audio(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; char* mode; - priv->tda827x_lpsel = 0; - if (params->std & V4L2_STD_MN) { - priv->sgIF = 92; + priv->cfg.tda827x_lpsel = 0; + if (t->std & V4L2_STD_MN) { + priv->cfg.sgIF = 92; priv->tda8290_easy_mode = 0x01; - priv->tda827x_lpsel = 1; + priv->cfg.tda827x_lpsel = 1; mode = "MN"; - } else if (params->std & V4L2_STD_B) { - priv->sgIF = 108; + } else if (t->std & V4L2_STD_B) { + priv->cfg.sgIF = 108; priv->tda8290_easy_mode = 0x02; mode = "B"; - } else if (params->std & V4L2_STD_GH) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_GH) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x04; mode = "GH"; - } else if (params->std & V4L2_STD_PAL_I) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_PAL_I) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x08; mode = "I"; - } else if (params->std & V4L2_STD_DK) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_DK) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "DK"; - } else if (params->std & V4L2_STD_SECAM_L) { - priv->sgIF = 124; + } else if (t->std & V4L2_STD_SECAM_L) { + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x20; mode = "L"; - } else if (params->std & V4L2_STD_SECAM_LC) { - priv->sgIF = 20; + } else if (t->std & V4L2_STD_SECAM_LC) { + priv->cfg.sgIF = 20; priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { - priv->sgIF = 124; + priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "xx"; } - if (params->mode == V4L2_TUNER_RADIO) - priv->sgIF = 88; /* if frequency is 5.5 MHz */ + if (t->mode == V4L2_TUNER_RADIO) + priv->cfg.sgIF = 88; /* if frequency is 5.5 MHz */ tuner_dbg("setting tda8290 to system %s\n", mode); } -static int tda8290_set_params(struct dvb_frontend *fe, - struct analog_parameters *params) +static void tda8290_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -455,10 +139,16 @@ static int tda8290_set_params(struct dvb_frontend *fe, pll_stat; int i; - set_audio(fe, params); + struct analog_parameters params = { + .frequency = freq, + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + + set_audio(t); - if (priv->lna_cfg) - tuner_dbg("tda827xa config is 0x%02x\n", *priv->lna_cfg); + tuner_dbg("tda827xa config is 0x%02x\n", t->config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); @@ -474,11 +164,11 @@ static int tda8290_set_params(struct dvb_frontend *fe, tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); - tda8290_i2c_bridge(fe, 1); - if (priv->tda827x_ver != 0) - tda827xa_set_analog_params(fe, params); - else - tda827x_set_analog_params(fe, params); + tda8290_i2c_bridge(t, 1); + + if (t->fe.ops.tuner_ops.set_analog_params) + t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); @@ -507,10 +197,8 @@ static int tda8290_set_params(struct dvb_frontend *fe, if ((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); - if (priv->tda827x_ver != 0) - tda827xa_agcf(fe); - else - tda827x_agcf(fe); + if (priv->cfg.agcf) + priv->cfg.agcf(&t->fe); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); @@ -539,94 +227,61 @@ static int tda8290_set_params(struct dvb_frontend *fe, } } - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); - - priv->frequency = (V4L2_TUNER_RADIO == params->mode) ? - params->frequency * 125 / 2 : params->frequency * 62500; - - return 0; } /*---------------------------------------------------------------------*/ -static int tda8290_has_signal(struct dvb_frontend *fe) +static int tda8290_has_signal(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; - int ret; + struct tda8290_priv *priv = t->priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; - /* for now, report based on afc status */ tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); - - ret = (afc & 0x80) ? 65535 : 0; - - tuner_dbg("AFC status: %d\n", ret); - - return ret; -} - -static int tda8290_get_status(struct dvb_frontend *fe, u32 *status) -{ - *status = 0; - - if (tda8290_has_signal(fe)) - *status = TUNER_STATUS_LOCKED; - - return 0; -} - -static int tda8290_get_rf_strength(struct dvb_frontend *fe, u16 *strength) -{ - *strength = tda8290_has_signal(fe); - - return 0; + return (afc & 0x80)? 65535:0; } /*---------------------------------------------------------------------*/ -static int tda8290_standby(struct dvb_frontend *fe) +static void tda8290_standby(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); if (priv->tda827x_ver != 0) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); - - return 0; } - -static void tda8290_init_if(struct dvb_frontend *fe) +static void tda8290_init_if(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; unsigned char set_GP01_CF[] = { 0x20, 0x0B }; - if ((priv->lna_cfg) && - ((*priv->lna_cfg == 1) || (*priv->lna_cfg == 2))) + if ((t->config == 1) || (t->config == 2)) tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); else tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } -static void tda8290_init_tuner(struct dvb_frontend *fe) +static void tda8290_init_tuner(struct tuner *t) { - struct tda8290_priv *priv = fe->tuner_priv; + struct tda8290_priv *priv = t->priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -636,41 +291,31 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) if (priv->tda827x_ver != 0) msg.buf = tda8275a_init; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); } /*---------------------------------------------------------------------*/ -static int tda8290_release(struct dvb_frontend *fe) +static void tda8290_release(struct tuner *t) { - kfree(fe->tuner_priv); - fe->tuner_priv = NULL; - - return 0; -} + if (t->fe.ops.tuner_ops.release) + t->fe.ops.tuner_ops.release(&t->fe); -static int tda8290_get_frequency(struct dvb_frontend *fe, u32 *frequency) -{ - struct tda8290_priv *priv = fe->tuner_priv; - *frequency = priv->frequency; - return 0; + kfree(t->priv); + t->priv = NULL; } -static struct dvb_tuner_ops tda8290_tuner_ops = { - .sleep = tda8290_standby, - .set_analog_params = tda8290_set_params, - .release = tda8290_release, - .get_frequency = tda8290_get_frequency, - .get_status = tda8290_get_status, - .get_rf_strength = tda8290_get_rf_strength, +static struct tuner_operations tda8290_tuner_ops = { + .set_tv_freq = tda8290_set_freq, + .set_radio_freq = tda8290_set_freq, + .has_signal = tda8290_has_signal, + .standby = tda8290_standby, + .release = tda8290_release, }; -struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, - struct i2c_adapter* i2c_adap, - u8 i2c_addr, - struct tda8290_config *cfg) +int tda8290_attach(struct tuner *t) { struct tda8290_priv *priv = NULL; u8 data; @@ -680,17 +325,15 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) - return NULL; - fe->tuner_priv = priv; - - priv->i2c_props.addr = i2c_addr; - priv->i2c_props.adap = i2c_adap; - if (cfg) { - priv->lna_cfg = cfg->lna_cfg; - priv->tuner_callback = cfg->tuner_callback; - } + return -ENOMEM; + t->priv = priv; + + priv->i2c_props.addr = t->i2c.addr; + priv->i2c_props.adap = t->i2c.adapter; + priv->cfg.config = &t->config; + priv->cfg.tuner_callback = t->tuner_callback; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -706,7 +349,7 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(fe, 0); + tda8290_i2c_bridge(t, 0); if(tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -727,42 +370,45 @@ struct dvb_frontend *tda8290_attach(struct dvb_frontend *fe, priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(fe, 1); + tda8290_i2c_bridge(t, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if( ret != 1) tuner_warn("TDA827x access failed!\n"); - memcpy(&fe->ops.tuner_ops, &tda8290_tuner_ops, - sizeof(struct dvb_tuner_ops)); - if ((data & 0x3c) == 0) { - strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75", - sizeof(fe->ops.tuner_ops.info.name)); - fe->ops.tuner_ops.info.frequency_min = 55000000; - fe->ops.tuner_ops.info.frequency_max = 860000000; - fe->ops.tuner_ops.info.frequency_step = 250000; + strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); priv->tda827x_ver = 0; } else { - strlcpy(fe->ops.tuner_ops.info.name, "tda8290+75a", - sizeof(fe->ops.tuner_ops.info.name)); - fe->ops.tuner_ops.info.frequency_min = 44000000; - fe->ops.tuner_ops.info.frequency_max = 906000000; - fe->ops.tuner_ops.info.frequency_step = 62500; + strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); priv->tda827x_ver = 2; } + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); + + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); - priv->tda827x_lpsel = 0; + memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); - tda8290_init_tuner(fe); - tda8290_init_if(fe); - return fe; + tuner_info("type set to %s\n", t->i2c.name); + + priv->cfg.tda827x_lpsel = 0; + t->mode = V4L2_TUNER_ANALOG_TV; + + tda8290_init_tuner(t); + tda8290_init_if(t); + return 0; } -int tda8290_probe(struct i2c_adapter* i2c_adap, u8 i2c_addr) +int tda8290_probe(struct tuner *t) { struct tuner_i2c_props i2c_props = { - .adap = i2c_adap, - .addr = i2c_addr + .adap = t->i2c.adapter, + .addr = t->i2c.addr }; unsigned char soft_reset[] = { 0x00, 0x00 }; -- cgit v1.2.3-70-g09d2 From 5bea1cd3871351d70cc7624af138f8aa68b7be77 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 09:56:38 -0300 Subject: V4L/DVB (6435): tda8290: add support for NXP TDA18271 tuner and TDA8295 analog demod Add basic support for NXP TDA8295 analog demod and TDA18271 tuner silicon. TDA8295 + TDA8275a not yet tested. TDA8290 + TDA18271 not yet supported. Digital mode of TDA18271 not yet tested & needs more work. Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.tuner | 1 + drivers/media/Kconfig | 3 +- drivers/media/dvb/frontends/Kconfig | 7 + drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda18271.c | 1054 ++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/tda18271.h | 40 ++ drivers/media/video/tda8290.c | 319 ++++++++- drivers/media/video/tda8290.h | 8 + drivers/media/video/tuner-core.c | 5 + drivers/media/video/tuner-types.c | 3 + drivers/media/video/tveeprom.c | 2 +- include/media/tuner.h | 2 + 12 files changed, 1437 insertions(+), 8 deletions(-) create mode 100644 drivers/media/dvb/frontends/tda18271.c create mode 100644 drivers/media/dvb/frontends/tda18271.h (limited to 'drivers/media/video/tda8290.c') diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 84c3ac7c33d..ac47b48715d 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -73,3 +73,4 @@ tuner=71 - Xceive xc2028/xc3028 tuner tuner=72 - Thomson FE6600 tuner=73 - Samsung TCPG 6121P30A tuner=75 - Philips TEA5761 FM Radio +tuner=76 - tda8295+18271 diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index d363d0cae38..e5222938098 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -105,9 +105,10 @@ config TUNER_MT20XX Say Y here to include support for the MT2032 / MT2050 tuner. config TUNER_TDA8290 - tristate "TDA 8290+8275(a) tuner combo" + tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" depends on I2C select DVB_TDA827X + select DVB_TDA18271 default m if VIDEO_TUNER_CUSTOMIZE help Say Y here to include support for Philips TDA8290+8275(a) tuner. diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 59b9ed1f1ae..57178d6e1cf 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -316,6 +316,13 @@ config DVB_TDA827X help A DVB-T silicon tuner module. Say Y when you want to support this tuner. +config DVB_TDA18271 + tristate "NXP TDA18271 silicon tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE + help + A silicon tuner module. Say Y when you want to support this tuner. + config DVB_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 4b8ad1f132a..457effcda5d 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TDA827X) += tda827x.o +obj-$(CONFIG_DVB_TDA18271) += tda18271.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o diff --git a/drivers/media/dvb/frontends/tda18271.c b/drivers/media/dvb/frontends/tda18271.c new file mode 100644 index 00000000000..3395f2bda49 --- /dev/null +++ b/drivers/media/dvb/frontends/tda18271.c @@ -0,0 +1,1054 @@ +/* + tda18271.c - driver for the Philips / NXP TDA18271 silicon tuner + + Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "tda18271.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +#define tuner_dbg(fmt, arg...) do {\ + if (debug > 0) \ + printk(KERN_DEBUG fmt, ##arg); } while (0) + +#define tuner_extra_dbg(fmt, arg...) do {\ + if (debug > 1) \ + printk(KERN_DEBUG fmt, ##arg); } while (0) + +#define R_ID 0x00 /* ID byte */ +#define R_TM 0x01 /* Thermo byte */ +#define R_PL 0x02 /* Power level byte */ +#define R_EP1 0x03 /* Easy Prog byte 1 */ +#define R_EP2 0x04 /* Easy Prog byte 2 */ +#define R_EP3 0x05 /* Easy Prog byte 3 */ +#define R_EP4 0x06 /* Easy Prog byte 4 */ +#define R_EP5 0x07 /* Easy Prog byte 5 */ +#define R_CPD 0x08 /* Cal Post-Divider byte */ +#define R_CD1 0x09 /* Cal Divider byte 1 */ +#define R_CD2 0x0a /* Cal Divider byte 2 */ +#define R_CD3 0x0b /* Cal Divider byte 3 */ +#define R_MPD 0x0c /* Main Post-Divider byte */ +#define R_MD1 0x0d /* Main Divider byte 1 */ +#define R_MD2 0x0e /* Main Divider byte 2 */ +#define R_MD3 0x0f /* Main Divider byte 3 */ +#define R_EB1 0x10 /* Extended byte 1 */ +#define R_EB2 0x11 /* Extended byte 2 */ +#define R_EB3 0x12 /* Extended byte 3 */ +#define R_EB4 0x13 /* Extended byte 4 */ +#define R_EB5 0x14 /* Extended byte 5 */ +#define R_EB6 0x15 /* Extended byte 6 */ +#define R_EB7 0x16 /* Extended byte 7 */ +#define R_EB8 0x17 /* Extended byte 8 */ +#define R_EB9 0x18 /* Extended byte 9 */ +#define R_EB10 0x19 /* Extended byte 10 */ +#define R_EB11 0x1a /* Extended byte 11 */ +#define R_EB12 0x1b /* Extended byte 12 */ +#define R_EB13 0x1c /* Extended byte 13 */ +#define R_EB14 0x1d /* Extended byte 14 */ +#define R_EB15 0x1e /* Extended byte 15 */ +#define R_EB16 0x1f /* Extended byte 16 */ +#define R_EB17 0x20 /* Extended byte 17 */ +#define R_EB18 0x21 /* Extended byte 18 */ +#define R_EB19 0x22 /* Extended byte 19 */ +#define R_EB20 0x23 /* Extended byte 20 */ +#define R_EB21 0x24 /* Extended byte 21 */ +#define R_EB22 0x25 /* Extended byte 22 */ +#define R_EB23 0x26 /* Extended byte 23 */ + +struct tda18271_pll_map { + u32 lomax; + u8 pd; /* post div */ + u8 d; /* div */ +}; + +static struct tda18271_pll_map tda18271_main_pll[] = { + { .lomax = 32000, .pd = 0x5f, .d = 0xf0 }, + { .lomax = 35000, .pd = 0x5e, .d = 0xe0 }, + { .lomax = 37000, .pd = 0x5d, .d = 0xd0 }, + { .lomax = 41000, .pd = 0x5c, .d = 0xc0 }, + { .lomax = 44000, .pd = 0x5b, .d = 0xb0 }, + { .lomax = 49000, .pd = 0x5a, .d = 0xa0 }, + { .lomax = 54000, .pd = 0x59, .d = 0x90 }, + { .lomax = 61000, .pd = 0x58, .d = 0x80 }, + { .lomax = 65000, .pd = 0x4f, .d = 0x78 }, + { .lomax = 70000, .pd = 0x4e, .d = 0x70 }, + { .lomax = 75000, .pd = 0x4d, .d = 0x68 }, + { .lomax = 82000, .pd = 0x4c, .d = 0x60 }, + { .lomax = 89000, .pd = 0x4b, .d = 0x58 }, + { .lomax = 98000, .pd = 0x4a, .d = 0x50 }, + { .lomax = 109000, .pd = 0x49, .d = 0x48 }, + { .lomax = 123000, .pd = 0x48, .d = 0x40 }, + { .lomax = 131000, .pd = 0x3f, .d = 0x3c }, + { .lomax = 141000, .pd = 0x3e, .d = 0x38 }, + { .lomax = 151000, .pd = 0x3d, .d = 0x34 }, + { .lomax = 164000, .pd = 0x3c, .d = 0x30 }, + { .lomax = 179000, .pd = 0x3b, .d = 0x2c }, + { .lomax = 197000, .pd = 0x3a, .d = 0x28 }, + { .lomax = 219000, .pd = 0x39, .d = 0x24 }, + { .lomax = 246000, .pd = 0x38, .d = 0x20 }, + { .lomax = 263000, .pd = 0x2f, .d = 0x1e }, + { .lomax = 282000, .pd = 0x2e, .d = 0x1c }, + { .lomax = 303000, .pd = 0x2d, .d = 0x1a }, + { .lomax = 329000, .pd = 0x2c, .d = 0x18 }, + { .lomax = 359000, .pd = 0x2b, .d = 0x16 }, + { .lomax = 395000, .pd = 0x2a, .d = 0x14 }, + { .lomax = 438000, .pd = 0x29, .d = 0x12 }, + { .lomax = 493000, .pd = 0x28, .d = 0x10 }, + { .lomax = 526000, .pd = 0x1f, .d = 0x0f }, + { .lomax = 564000, .pd = 0x1e, .d = 0x0e }, + { .lomax = 607000, .pd = 0x1d, .d = 0x0d }, + { .lomax = 658000, .pd = 0x1c, .d = 0x0c }, + { .lomax = 718000, .pd = 0x1b, .d = 0x0b }, + { .lomax = 790000, .pd = 0x1a, .d = 0x0a }, + { .lomax = 877000, .pd = 0x19, .d = 0x09 }, + { .lomax = 987000, .pd = 0x18, .d = 0x08 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + +static struct tda18271_pll_map tda18271_cal_pll[] = { + { .lomax = 33000, .pd = 0xdd, .d = 0xd0 }, + { .lomax = 36000, .pd = 0xdc, .d = 0xc0 }, + { .lomax = 40000, .pd = 0xdb, .d = 0xb0 }, + { .lomax = 44000, .pd = 0xda, .d = 0xa0 }, + { .lomax = 49000, .pd = 0xd9, .d = 0x90 }, + { .lomax = 55000, .pd = 0xd8, .d = 0x80 }, + { .lomax = 63000, .pd = 0xd3, .d = 0x70 }, + { .lomax = 67000, .pd = 0xcd, .d = 0x68 }, + { .lomax = 73000, .pd = 0xcc, .d = 0x60 }, + { .lomax = 80000, .pd = 0xcb, .d = 0x58 }, + { .lomax = 88000, .pd = 0xca, .d = 0x50 }, + { .lomax = 98000, .pd = 0xc9, .d = 0x48 }, + { .lomax = 110000, .pd = 0xc8, .d = 0x40 }, + { .lomax = 126000, .pd = 0xc3, .d = 0x38 }, + { .lomax = 135000, .pd = 0xbd, .d = 0x34 }, + { .lomax = 147000, .pd = 0xbc, .d = 0x30 }, + { .lomax = 160000, .pd = 0xbb, .d = 0x2c }, + { .lomax = 176000, .pd = 0xba, .d = 0x28 }, + { .lomax = 196000, .pd = 0xb9, .d = 0x24 }, + { .lomax = 220000, .pd = 0xb8, .d = 0x20 }, + { .lomax = 252000, .pd = 0xb3, .d = 0x1c }, + { .lomax = 271000, .pd = 0xad, .d = 0x1a }, + { .lomax = 294000, .pd = 0xac, .d = 0x18 }, + { .lomax = 321000, .pd = 0xab, .d = 0x16 }, + { .lomax = 353000, .pd = 0xaa, .d = 0x14 }, + { .lomax = 392000, .pd = 0xa9, .d = 0x12 }, + { .lomax = 441000, .pd = 0xa8, .d = 0x10 }, + { .lomax = 505000, .pd = 0xa3, .d = 0x0e }, + { .lomax = 543000, .pd = 0x9d, .d = 0x0d }, + { .lomax = 589000, .pd = 0x9c, .d = 0x0c }, + { .lomax = 642000, .pd = 0x9b, .d = 0x0b }, + { .lomax = 707000, .pd = 0x9a, .d = 0x0a }, + { .lomax = 785000, .pd = 0x99, .d = 0x09 }, + { .lomax = 883000, .pd = 0x98, .d = 0x08 }, + { .lomax = 1010000, .pd = 0x93, .d = 0x07 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + +struct tda18271_map { + u32 rfmax; + u8 val; +}; + +static struct tda18271_map tda18271_bp_filter[] = { + { .rfmax = 62000, .val = 0x00 }, + { .rfmax = 84000, .val = 0x01 }, + { .rfmax = 100000, .val = 0x02 }, + { .rfmax = 140000, .val = 0x03 }, + { .rfmax = 170000, .val = 0x04 }, + { .rfmax = 180000, .val = 0x05 }, + { .rfmax = 865000, .val = 0x06 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_km[] = { + { .rfmax = 61100, .val = 0x74 }, + { .rfmax = 350000, .val = 0x40 }, + { .rfmax = 720000, .val = 0x30 }, + { .rfmax = 865000, .val = 0x40 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_rf_band[] = { + { .rfmax = 47900, .val = 0x00 }, + { .rfmax = 61100, .val = 0x01 }, +/* { .rfmax = 152600, .val = 0x02 }, */ + { .rfmax = 121200, .val = 0x02 }, + { .rfmax = 164700, .val = 0x03 }, + { .rfmax = 203500, .val = 0x04 }, + { .rfmax = 457800, .val = 0x05 }, + { .rfmax = 865000, .val = 0x06 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_gain_taper[] = { + { .rfmax = 45400, .val = 0x1f }, + { .rfmax = 45800, .val = 0x1e }, + { .rfmax = 46200, .val = 0x1d }, + { .rfmax = 46700, .val = 0x1c }, + { .rfmax = 47100, .val = 0x1b }, + { .rfmax = 47500, .val = 0x1a }, + { .rfmax = 47900, .val = 0x19 }, + { .rfmax = 49600, .val = 0x17 }, + { .rfmax = 51200, .val = 0x16 }, + { .rfmax = 52900, .val = 0x15 }, + { .rfmax = 54500, .val = 0x14 }, + { .rfmax = 56200, .val = 0x13 }, + { .rfmax = 57800, .val = 0x12 }, + { .rfmax = 59500, .val = 0x11 }, + { .rfmax = 61100, .val = 0x10 }, + { .rfmax = 67600, .val = 0x0d }, + { .rfmax = 74200, .val = 0x0c }, + { .rfmax = 80700, .val = 0x0b }, + { .rfmax = 87200, .val = 0x0a }, + { .rfmax = 93800, .val = 0x09 }, + { .rfmax = 100300, .val = 0x08 }, + { .rfmax = 106900, .val = 0x07 }, + { .rfmax = 113400, .val = 0x06 }, + { .rfmax = 119900, .val = 0x05 }, + { .rfmax = 126500, .val = 0x04 }, + { .rfmax = 133000, .val = 0x03 }, + { .rfmax = 139500, .val = 0x02 }, + { .rfmax = 146100, .val = 0x01 }, + { .rfmax = 152600, .val = 0x00 }, + { .rfmax = 154300, .val = 0x1f }, + { .rfmax = 156100, .val = 0x1e }, + { .rfmax = 157800, .val = 0x1d }, + { .rfmax = 159500, .val = 0x1c }, + { .rfmax = 161200, .val = 0x1b }, + { .rfmax = 163000, .val = 0x1a }, + { .rfmax = 164700, .val = 0x19 }, + { .rfmax = 170200, .val = 0x17 }, + { .rfmax = 175800, .val = 0x16 }, + { .rfmax = 181300, .val = 0x15 }, + { .rfmax = 186900, .val = 0x14 }, + { .rfmax = 192400, .val = 0x13 }, + { .rfmax = 198000, .val = 0x12 }, + { .rfmax = 203500, .val = 0x11 }, + { .rfmax = 216200, .val = 0x14 }, + { .rfmax = 228900, .val = 0x13 }, + { .rfmax = 241600, .val = 0x12 }, + { .rfmax = 254400, .val = 0x11 }, + { .rfmax = 267100, .val = 0x10 }, + { .rfmax = 279800, .val = 0x0f }, + { .rfmax = 292500, .val = 0x0e }, + { .rfmax = 305200, .val = 0x0d }, + { .rfmax = 317900, .val = 0x0c }, + { .rfmax = 330700, .val = 0x0b }, + { .rfmax = 343400, .val = 0x0a }, + { .rfmax = 356100, .val = 0x09 }, + { .rfmax = 368800, .val = 0x08 }, + { .rfmax = 381500, .val = 0x07 }, + { .rfmax = 394200, .val = 0x06 }, + { .rfmax = 406900, .val = 0x05 }, + { .rfmax = 419700, .val = 0x04 }, + { .rfmax = 432400, .val = 0x03 }, + { .rfmax = 445100, .val = 0x02 }, + { .rfmax = 457800, .val = 0x01 }, + { .rfmax = 476300, .val = 0x19 }, + { .rfmax = 494800, .val = 0x18 }, + { .rfmax = 513300, .val = 0x17 }, + { .rfmax = 531800, .val = 0x16 }, + { .rfmax = 550300, .val = 0x15 }, + { .rfmax = 568900, .val = 0x14 }, + { .rfmax = 587400, .val = 0x13 }, + { .rfmax = 605900, .val = 0x12 }, + { .rfmax = 624400, .val = 0x11 }, + { .rfmax = 642900, .val = 0x10 }, + { .rfmax = 661400, .val = 0x0f }, + { .rfmax = 679900, .val = 0x0e }, + { .rfmax = 698400, .val = 0x0d }, + { .rfmax = 716900, .val = 0x0c }, + { .rfmax = 735400, .val = 0x0b }, + { .rfmax = 753900, .val = 0x0a }, + { .rfmax = 772500, .val = 0x09 }, + { .rfmax = 791000, .val = 0x08 }, + { .rfmax = 809500, .val = 0x07 }, + { .rfmax = 828000, .val = 0x06 }, + { .rfmax = 846500, .val = 0x05 }, + { .rfmax = 865000, .val = 0x04 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +static struct tda18271_map tda18271_rf_cal[] = { + { .rfmax = 41000, .val = 0x1e }, + { .rfmax = 43000, .val = 0x30 }, + { .rfmax = 45000, .val = 0x43 }, + { .rfmax = 46000, .val = 0x4d }, + { .rfmax = 47000, .val = 0x54 }, + { .rfmax = 47900, .val = 0x64 }, + { .rfmax = 49100, .val = 0x20 }, + { .rfmax = 50000, .val = 0x22 }, + { .rfmax = 51000, .val = 0x2a }, + { .rfmax = 53000, .val = 0x32 }, + { .rfmax = 55000, .val = 0x35 }, + { .rfmax = 56000, .val = 0x3c }, + { .rfmax = 57000, .val = 0x3f }, + { .rfmax = 58000, .val = 0x48 }, + { .rfmax = 59000, .val = 0x4d }, + { .rfmax = 60000, .val = 0x58 }, + { .rfmax = 61100, .val = 0x5f }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +/*---------------------------------------------------------------------*/ + +#define TDA18271_NUM_REGS 39 + +#define TDA18271_ANALOG 0 +#define TDA18271_DIGITAL 1 + +struct tda18271_priv { + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + unsigned char tda18271_regs[TDA18271_NUM_REGS]; + int mode; + + u32 frequency; + u32 bandwidth; +}; + +/*---------------------------------------------------------------------*/ + +static void tda18271_dump_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + tuner_dbg("=== TDA18271 REG DUMP ===\n"); + tuner_dbg("ID_BYTE = 0x%x\n", 0xff & regs[R_ID]); + tuner_dbg("THERMO_BYTE = 0x%x\n", 0xff & regs[R_TM]); + tuner_dbg("POWER_LEVEL_BYTE = 0x%x\n", 0xff & regs[R_PL]); + tuner_dbg("EASY_PROG_BYTE_1 = 0x%x\n", 0xff & regs[R_EP1]); + tuner_dbg("EASY_PROG_BYTE_2 = 0x%x\n", 0xff & regs[R_EP2]); + tuner_dbg("EASY_PROG_BYTE_3 = 0x%x\n", 0xff & regs[R_EP3]); + tuner_dbg("EASY_PROG_BYTE_4 = 0x%x\n", 0xff & regs[R_EP4]); + tuner_dbg("EASY_PROG_BYTE_5 = 0x%x\n", 0xff & regs[R_EP5]); + tuner_dbg("CAL_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_CPD]); + tuner_dbg("CAL_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_CD1]); + tuner_dbg("CAL_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_CD2]); + tuner_dbg("CAL_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_CD3]); + tuner_dbg("MAIN_POST_DIV_BYTE = 0x%x\n", 0xff & regs[R_MPD]); + tuner_dbg("MAIN_DIV_BYTE_1 = 0x%x\n", 0xff & regs[R_MD1]); + tuner_dbg("MAIN_DIV_BYTE_2 = 0x%x\n", 0xff & regs[R_MD2]); + tuner_dbg("MAIN_DIV_BYTE_3 = 0x%x\n", 0xff & regs[R_MD3]); +} + +static void tda18271_read_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + unsigned char buf = 0x00; + int ret; + struct i2c_msg msg[] = { + { .addr = priv->i2c_addr, .flags = 0, + .buf = &buf, .len = 1 }, + { .addr = priv->i2c_addr, .flags = I2C_M_RD, + .buf = regs, .len = 16 } + }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* read all registers */ + ret = i2c_transfer(priv->i2c_adap, msg, 2); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 2) + printk("ERROR: %s: i2c_transfer returned: %d\n", + __FUNCTION__, ret); + + if (debug > 1) + tda18271_dump_regs(fe); +} + +static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + unsigned char buf[TDA18271_NUM_REGS+1]; + struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, + .buf = buf, .len = len+1 }; + int i, ret; + + BUG_ON((len == 0) || (idx+len > sizeof(buf))); + + buf[0] = idx; + for (i = 1; i <= len; i++) { + buf[i] = regs[idx-1+i]; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + /* write registers */ + ret = i2c_transfer(priv->i2c_adap, &msg, 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret != 1) + printk(KERN_WARNING "ERROR: %s: i2c_transfer returned: %d\n", + __FUNCTION__, ret); +} + +/*---------------------------------------------------------------------*/ + +static void tda18271_init_regs(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + tda18271_read_regs(fe); + + /* test IR_CAL_OK to see if we need init */ + if ((regs[R_EP1] & 0x08) != 0) + return; + + printk(KERN_INFO "tda18271: initializing registers\n"); + + /* initialize registers */ + regs[R_ID] = 0x83; + regs[R_TM] = 0x08; + regs[R_PL] = 0x80; + regs[R_EP1] = 0xc6; + regs[R_EP2] = 0xdf; + regs[R_EP3] = 0x16; + regs[R_EP4] = 0x60; + regs[R_EP5] = 0x80; + regs[R_CPD] = 0x80; + regs[R_CD1] = 0x00; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0x00; + regs[R_MD1] = 0x00; + regs[R_MD2] = 0x00; + regs[R_MD3] = 0x00; + regs[R_EB1] = 0xff; + regs[R_EB2] = 0x01; + regs[R_EB3] = 0x84; + regs[R_EB4] = 0x41; + regs[R_EB5] = 0x01; + regs[R_EB6] = 0x84; + regs[R_EB7] = 0x40; + regs[R_EB8] = 0x07; + regs[R_EB9] = 0x00; + regs[R_EB10] = 0x00; + regs[R_EB11] = 0x96; + regs[R_EB12] = 0x0f; + regs[R_EB13] = 0xc1; + regs[R_EB14] = 0x00; + regs[R_EB15] = 0x8f; + regs[R_EB16] = 0x00; + regs[R_EB17] = 0x00; + regs[R_EB18] = 0x00; + regs[R_EB19] = 0x00; + regs[R_EB20] = 0x20; + regs[R_EB21] = 0x33; + regs[R_EB22] = 0x48; + regs[R_EB23] = 0xb0; + + tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); + /* setup AGC1 & AGC2 */ + regs[R_EB17] = 0x00; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x03; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x43; + tda18271_write_regs(fe, R_EB17, 1); + regs[R_EB17] = 0x4c; + tda18271_write_regs(fe, R_EB17, 1); + + regs[R_EB20] = 0xa0; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xa7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xe7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xec; + tda18271_write_regs(fe, R_EB20, 1); + + /* image rejection calibration */ + + /* low-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x81; + regs[R_CPD] = 0xcc; + regs[R_CD1] = 0x6c; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0xcd; + regs[R_MD1] = 0x77; + regs[R_MD2] = 0x08; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted low measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x85; + regs[R_CPD] = 0xcb; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0x70; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image low optimization completion */ + + /* mid-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x82; + regs[R_CPD] = 0xa8; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0xa9; + regs[R_MD1] = 0x73; + regs[R_MD2] = 0x1a; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted mid measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x86; + regs[R_CPD] = 0xa8; + regs[R_CD1] = 0x66; + regs[R_CD2] = 0xa0; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image mid optimization completion */ + + /* high-band */ + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x83; + regs[R_CPD] = 0x98; + regs[R_CD1] = 0x65; + regs[R_CD2] = 0x00; + regs[R_CD3] = 0x00; + regs[R_MPD] = 0x99; + regs[R_MD1] = 0x71; + regs[R_MD2] = 0xcd; + regs[R_MD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* pll locking */ + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); + msleep(5); /* wanted high measurement */ + + regs[R_EP3] = 0x1f; + regs[R_EP4] = 0x66; + regs[R_EP5] = 0x87; + regs[R_CPD] = 0x98; + regs[R_CD1] = 0x65; + regs[R_CD2] = 0x50; + regs[R_CD3] = 0x00; + + tda18271_write_regs(fe, R_EP3, 7); + msleep(5); /* pll locking */ + + regs[R_EP2] = 0xdf; + + tda18271_write_regs(fe, R_EP2, 1); + msleep(30); /* image high optimization completion */ + + regs[R_EP4] = 0x64; + tda18271_write_regs(fe, R_EP4, 1); + + regs[R_EP1] = 0xc6; + tda18271_write_regs(fe, R_EP1, 1); +} + +static int tda18271_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u32 div, N = 0; + int i; + + + tuner_dbg("%s: freq = %d, ifc = %d\n", __FUNCTION__, freq, ifc); + + tda18271_init_regs(fe); + /* RF tracking filter calibration */ + + /* calculate BP_Filter */ + i = 0; + while ((tda18271_bp_filter[i].rfmax * 1000) < freq) { + if (tda18271_bp_filter[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("bp filter = 0x%x, i = %d\n", + tda18271_bp_filter[i].val, i); + + regs[R_EP1] &= ~0x07; /* clear bp filter bits */ + regs[R_EP1] |= tda18271_bp_filter[i].val; + tda18271_write_regs(fe, R_EP1, 1); + + regs[R_EB4] &= 0x07; + regs[R_EB4] |= 0x60; + tda18271_write_regs(fe, R_EB4, 1); + + regs[R_EB7] = 0x60; + tda18271_write_regs(fe, R_EB7, 1); + + regs[R_EB14] = 0x00; + tda18271_write_regs(fe, R_EB14, 1); + + regs[R_EB20] = 0xcc; + tda18271_write_regs(fe, R_EB20, 1); + + /* set CAL mode to RF tracking filter calibration */ + regs[R_EB4] |= 0x03; + + /* calculate CAL PLL */ + + switch (priv->mode) { + case TDA18271_ANALOG: + N = freq - 1250000; + break; + case TDA18271_DIGITAL: + N = freq + bw / 2; + break; + } + + i = 0; + while ((tda18271_cal_pll[i].lomax * 1000) < N) { + if (tda18271_cal_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("cal pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_cal_pll[i].pd, tda18271_cal_pll[i].d, i); + + regs[R_CPD] = tda18271_cal_pll[i].pd; + + div = ((tda18271_cal_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_CD1] = 0xff & (div >> 16); + regs[R_CD2] = 0xff & (div >> 8); + regs[R_CD3] = 0xff & div; + + /* calculate MAIN PLL */ + + switch (priv->mode) { + case TDA18271_ANALOG: + N = freq - 250000; + break; + case TDA18271_DIGITAL: + N = freq + bw / 2 + 1000000; + break; + } + + i = 0; + while ((tda18271_main_pll[i].lomax * 1000) < N) { + if (tda18271_main_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + + regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x08; + break; + case TDA18271_DIGITAL: + regs[R_MPD] |= 0x08; + break; + } + + div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_MD1] = 0xff & (div >> 16); + regs[R_MD2] = 0xff & (div >> 8); + regs[R_MD3] = 0xff & div; + + tda18271_write_regs(fe, R_EP3, 11); + msleep(5); /* RF tracking filter calibration initialization */ + + /* search for K,M,CO for RF Calibration */ + i = 0; + while ((tda18271_km[i].rfmax * 1000) < freq) { + if (tda18271_km[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("km = 0x%x, i = %d\n", tda18271_km[i].val, i); + + regs[R_EB13] &= 0x83; + regs[R_EB13] |= tda18271_km[i].val; + tda18271_write_regs(fe, R_EB13, 1); + + /* search for RF_BAND */ + i = 0; + while ((tda18271_rf_band[i].rfmax * 1000) < freq) { + if (tda18271_rf_band[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("rf band = 0x%x, i = %d\n", + tda18271_rf_band[i].val, i); + + regs[R_EP2] &= ~0xe0; /* clear rf band bits */ + regs[R_EP2] |= (tda18271_rf_band[i].val << 5); + + /* search for Gain_Taper */ + i = 0; + while ((tda18271_gain_taper[i].rfmax * 1000) < freq) { + if (tda18271_gain_taper[i + 1].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("gain taper = 0x%x, i = %d\n", + tda18271_gain_taper[i].val, i); + + regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ + regs[R_EP2] |= tda18271_gain_taper[i].val; + + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + + regs[R_EB4] &= 0x07; + regs[R_EB4] |= 0x40; + tda18271_write_regs(fe, R_EB4, 1); + + regs[R_EB7] = 0x40; + tda18271_write_regs(fe, R_EB7, 1); + msleep(10); + + regs[R_EB20] = 0xec; + tda18271_write_regs(fe, R_EB20, 1); + msleep(60); /* RF tracking filter calibration completion */ + + regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + tda18271_write_regs(fe, R_EP4, 1); + + tda18271_write_regs(fe, R_EP1, 1); + + /* RF tracking filer correction for VHF_Low band */ + i = 0; + while ((tda18271_rf_cal[i].rfmax * 1000) < freq) { + if (tda18271_rf_cal[i].rfmax == 0) + break; + i++; + } + tuner_extra_dbg("rf cal = 0x%x, i = %d\n", tda18271_rf_cal[i].val, i); + + /* VHF_Low band only */ + if (tda18271_rf_cal[i].rfmax != 0) { + regs[R_EB14] = tda18271_rf_cal[i].val; + tda18271_write_regs(fe, R_EB14, 1); + } + + /* Channel Configuration */ + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_EB22] = 0x2c; + break; + case TDA18271_DIGITAL: + regs[R_EB22] = 0x37; + break; + } + tda18271_write_regs(fe, R_EB22, 1); + + regs[R_EP1] |= 0x40; /* set dis power level on */ + + /* set standard */ + regs[R_EP3] &= ~0x1f; /* clear std bits */ + + /* see table 22 */ + regs[R_EP3] |= std; + + /* TO DO: * + * ================ * + * FM radio, 0x18 * + * ATSC 6MHz, 0x1c * + * DVB-T 6MHz, 0x1c * + * DVB-T 7MHz, 0x1d * + * DVB-T 8MHz, 0x1e * + * QAM 6MHz, 0x1d * + * QAM 8MHz, 0x1f */ + + regs[R_EP4] &= ~0x03; /* set cal mode to normal */ + + regs[R_EP4] &= ~0x1c; /* clear if level bits */ + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x80; /* IF notch = 0 */ + break; + case TDA18271_DIGITAL: + regs[R_EP4] |= 0x04; + regs[R_MPD] |= 0x80; + break; + } + + regs[R_EP4] &= ~0x80; /* turn this bit on only for fm */ + + /* FIXME: image rejection validity EP5[2:0] */ + + /* calculate MAIN PLL */ + N = freq + ifc; + + i = 0; + while ((tda18271_main_pll[i].lomax * 1000) < N) { + if (tda18271_main_pll[i + 1].lomax == 0) + break; + i++; + } + tuner_extra_dbg("main pll, pd = 0x%x, d = 0x%x, i = %d\n", + tda18271_main_pll[i].pd, tda18271_main_pll[i].d, i); + + regs[R_MPD] = (0x7f & tda18271_main_pll[i].pd); + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x08; + break; + case TDA18271_DIGITAL: + regs[R_MPD] |= 0x08; + break; + } + + div = ((tda18271_main_pll[i].d * (N / 1000)) << 7) / 125; + regs[R_MD1] = 0xff & (div >> 16); + regs[R_MD2] = 0xff & (div >> 8); + regs[R_MD3] = 0xff & div; + + tda18271_write_regs(fe, R_TM, 15); + msleep(5); + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int tda18271_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tda18271_priv *priv = fe->tuner_priv; + u8 std; + u32 bw, sgIF = 0; + + u32 freq = params->frequency; + + priv->mode = TDA18271_DIGITAL; + + /* see table 22 */ + if (fe->ops.info.type == FE_ATSC) { + switch (params->u.vsb.modulation) { + case VSB_8: + case VSB_16: + std = 0x1b; /* device-specific (spec says 0x1c) */ + sgIF = 5380000; + break; + case QAM_64: + case QAM_256: + std = 0x18; /* device-specific (spec says 0x1d) */ + sgIF = 4000000; + break; + default: + printk(KERN_WARNING "%s: modulation not set!\n", + __FUNCTION__); + return -EINVAL; + } + freq += 1750000; /* Adjust to center (+1.75MHZ) */ + bw = 6000000; + } else if (fe->ops.info.type == FE_OFDM) { + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + std = 0x1c; + bw = 6000000; + break; + case BANDWIDTH_7_MHZ: + std = 0x1d; + bw = 7000000; + break; + case BANDWIDTH_8_MHZ: + std = 0x1e; + bw = 8000000; + break; + default: + printk(KERN_WARNING "%s: bandwidth not set!\n", + __FUNCTION__); + return -EINVAL; + } + } else { + printk(KERN_WARNING "%s: modulation type not supported!\n", + __FUNCTION__); + return -EINVAL; + } + + return tda18271_tune(fe, sgIF, freq, bw, std); +} + +static int tda18271_set_analog_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tda18271_priv *priv = fe->tuner_priv; + u8 std; + unsigned int sgIF; + char *mode; + + priv->mode = TDA18271_ANALOG; + + /* see table 22 */ + if (params->std & V4L2_STD_MN) { + std = 0x0d; + sgIF = 92; + mode = "MN"; + } else if (params->std & V4L2_STD_B) { + std = 0x0e; + sgIF = 108; + mode = "B"; + } else if (params->std & V4L2_STD_GH) { + std = 0x0f; + sgIF = 124; + mode = "GH"; + } else if (params->std & V4L2_STD_PAL_I) { + std = 0x0f; + sgIF = 124; + mode = "I"; + } else if (params->std & V4L2_STD_DK) { + std = 0x0f; + sgIF = 124; + mode = "DK"; + } else if (params->std & V4L2_STD_SECAM_L) { + std = 0x0f; + sgIF = 124; + mode = "L"; + } else if (params->std & V4L2_STD_SECAM_LC) { + std = 0x0f; + sgIF = 20; + mode = "LC"; + } else { + std = 0x0f; + sgIF = 124; + mode = "xx"; + } + + if (params->mode == V4L2_TUNER_RADIO) + sgIF = 88; /* if frequency is 5.5 MHz */ + + tuner_dbg("setting tda18271 to system %s\n", mode); + + return tda18271_tune(fe, sgIF * 62500, params->frequency * 62500, + 0, std); +} + +static int tda18271_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct tda18271_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct tda18271_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static struct dvb_tuner_ops tda18271_tuner_ops = { + .info = { + .name = "NXP TDA18271HD", + .frequency_min = 45000000, + .frequency_max = 864000000, + .frequency_step = 62500 + }, + .set_params = tda18271_set_params, + .set_analog_params = tda18271_set_analog_params, + .release = tda18271_release, + .get_frequency = tda18271_get_frequency, + .get_bandwidth = tda18271_get_bandwidth, +}; + +struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, + struct i2c_adapter *i2c) +{ + struct tda18271_priv *priv = NULL; + + tuner_dbg("%s:\n", __FUNCTION__); + priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->i2c_addr = addr; + priv->i2c_adap = i2c; + + memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + + return fe; +} +EXPORT_SYMBOL_GPL(tda18271_attach); +MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); +MODULE_AUTHOR("Michael Krufky "); +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h new file mode 100644 index 00000000000..a8a19a7197f --- /dev/null +++ b/drivers/media/dvb/frontends/tda18271.h @@ -0,0 +1,40 @@ +/* + tda18271.h - header for the Philips / NXP TDA18271 silicon tuner + + Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDA18271_H__ +#define __TDA18271_H__ + +#include +#include "dvb_frontend.h" + +#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); +#else +static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, + u8 addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif + +#endif /* __TDA18271_H__ */ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 5d30cbcd736..a38ed9db640 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -25,8 +25,9 @@ #include #include "tda8290.h" #include "tda827x.h" +#include "tda18271.h" -static int tuner_debug = 0; +static int tuner_debug; module_param_named(debug, tuner_debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); @@ -65,6 +66,34 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) } } +static void tda8295_i2c_bridge(struct tuner *t, int close) +{ + struct tda8290_priv *priv = t->priv; + + unsigned char enable[2] = { 0x45, 0xc1 }; + unsigned char disable[2] = { 0x46, 0x00 }; + unsigned char buf[3] = { 0x45, 0x01, 0x00 }; + unsigned char *msg; + if (close) { + msg = enable; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); + /* let the bridge stabilize */ + msleep(20); + } else { + msg = disable; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); + + buf[2] = msg[1]; + buf[2] &= ~0x04; + tuner_i2c_xfer_send(&priv->i2c_props, buf, 3); + msleep(5); + + msg[1] |= 0x04; + tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); + } +} + /*---------------------------------------------------------------------*/ static void set_audio(struct tuner *t) @@ -233,6 +262,153 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) /*---------------------------------------------------------------------*/ +static void tda8295_power(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] = 0x01; + else + buf[1] = 0x03; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_set_easy_mode(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x01, 0x00 }; + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ + else + buf[1] = 0x00; /* reset active bit */ + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_set_video_std(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); + + tda8295_set_easy_mode(t, 1); + msleep(20); + tda8295_set_easy_mode(t, 0); +} + +/*---------------------------------------------------------------------*/ + +static void tda8295_agc1_out(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ + + tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + + if (enable) + buf[1] &= ~0x40; + else + buf[1] |= 0x40; + + tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); +} + +static void tda8295_agc2_out(struct tuner *t, int enable) +{ + struct tda8290_priv *priv = t->priv; + unsigned char set_gpio_cf[] = { 0x44, 0x00 }; + unsigned char set_gpio_val[] = { 0x46, 0x00 }; + + tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); + tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); + + set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ + + if (enable) { + set_gpio_cf[1] |= 0x01; /* config GPIO_0 as Open Drain Out */ + set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */ + } + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); +} + +static int tda8295_has_signal(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + + unsigned char hvpll_stat = 0x26; + unsigned char ret; + + tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); + return (ret & 0x01) ? 65535 : 0; +} + +/*---------------------------------------------------------------------*/ + +static void tda8295_set_freq(struct tuner *t, unsigned int freq) +{ + struct tda8290_priv *priv = t->priv; + u16 ifc; + + unsigned char blanking_mode[] = { 0x1d, 0x00 }; + + struct analog_parameters params = { + .frequency = freq, + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + + set_audio(t); + + ifc = priv->cfg.sgIF; /* FIXME */ + + tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); + + tda8295_power(t, 1); + tda8295_agc1_out(t, 1); + + tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); + + tda8295_set_video_std(t); + + blanking_mode[1] = 0x03; + tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); + msleep(20); + + tda8295_i2c_bridge(t, 1); + + if (t->fe.ops.tuner_ops.set_analog_params) + t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + + if (priv->cfg.agcf) + priv->cfg.agcf(&t->fe); + + if (tda8295_has_signal(t)) + tuner_dbg("tda8295 is locked\n"); + else + tuner_dbg("tda8295 not locked, no signal?\n"); + + tda8295_i2c_bridge(t, 0); +} + +/*---------------------------------------------------------------------*/ + static int tda8290_has_signal(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -264,6 +440,13 @@ static void tda8290_standby(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); } +static void tda8295_standby(struct tuner *t) +{ + tda8295_agc1_out(t, 0); /* Put AGC in tri-state */ + + tda8295_power(t, 0); +} + static void tda8290_init_if(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -279,6 +462,35 @@ static void tda8290_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } +static void tda8295_init_if(struct tuner *t) +{ + struct tda8290_priv *priv = t->priv; + + static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; + static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; + static unsigned char set_pll_reg6[] = { 0x3e, 0x63 }; + static unsigned char set_pll_reg0[] = { 0x38, 0x23 }; + static unsigned char set_pll_reg7[] = { 0x3f, 0x01 }; + static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; + static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; + + tda8295_power(t, 1); + + tda8295_set_easy_mode(t, 0); + tda8295_set_video_std(t); + + tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); + tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); + + tda8295_agc1_out(t, 0); + tda8295_agc2_out(t, 0); +} + static void tda8290_init_tuner(struct tuner *t) { struct tda8290_priv *priv = t->priv; @@ -298,7 +510,7 @@ static void tda8290_init_tuner(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8290_release(struct tuner *t) +static void tda829x_release(struct tuner *t) { if (t->fe.ops.tuner_ops.release) t->fe.ops.tuner_ops.release(&t->fe); @@ -312,7 +524,15 @@ static struct tuner_operations tda8290_tuner_ops = { .set_radio_freq = tda8290_set_freq, .has_signal = tda8290_has_signal, .standby = tda8290_standby, - .release = tda8290_release, + .release = tda829x_release, +}; + +static struct tuner_operations tda8295_tuner_ops = { + .set_tv_freq = tda8295_set_freq, + .set_radio_freq = tda8295_set_freq, + .has_signal = tda8295_has_signal, + .standby = tda8295_standby, + .release = tda829x_release, }; int tda8290_attach(struct tuner *t) @@ -403,6 +623,95 @@ int tda8290_attach(struct tuner *t) tda8290_init_if(t); return 0; } +EXPORT_SYMBOL_GPL(tda8290_attach); + +int tda8295_attach(struct tuner *t) +{ + struct tda8290_priv *priv = NULL; + u8 data; + int i, ret, tuners_found; + u32 tuner_addrs; + struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; + + priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + t->priv = priv; + + priv->i2c_props.addr = t->i2c.addr; + priv->i2c_props.adap = t->i2c.adapter; + + tda8295_i2c_bridge(t, 1); + /* probe for tuner chip */ + tuners_found = 0; + tuner_addrs = 0; + for (i = 0x60; i <= 0x63; i++) { + msg.addr = i; + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + if (ret == 1) { + tuners_found++; + tuner_addrs = (tuner_addrs << 8) + i; + } + } + /* if there is more than one tuner, we expect the right one is + behind the bridge and we choose the highest address that doesn't + give a response now + */ + tda8295_i2c_bridge(t, 0); + if (tuners_found > 1) + for (i = 0; i < tuners_found; i++) { + msg.addr = tuner_addrs & 0xff; + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + if (ret == 1) + tuner_addrs = tuner_addrs >> 8; + else + break; + } + if (tuner_addrs == 0) { + tuner_addrs = 0x60; + tuner_info("could not clearly identify tuner address, " + "defaulting to %x\n", tuner_addrs); + } else { + tuner_addrs = tuner_addrs & 0xff; + tuner_info("setting tuner address to %x\n", tuner_addrs); + } + priv->tda827x_addr = tuner_addrs; + msg.addr = tuner_addrs; + + tda8295_i2c_bridge(t, 1); + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + tda8295_i2c_bridge(t, 0); + if (ret != 1) + tuner_warn("TDA827x access failed!\n"); + if ((data & 0x3c) == 0) { + strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + tda18271_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap); + priv->tda827x_ver = 4; + } else { + strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); + + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + priv->tda827x_ver = 2; + } + priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ + tuner_info("type set to %s\n", t->i2c.name); + + memcpy(&t->ops, &tda8295_tuner_ops, sizeof(struct tuner_operations)); + + priv->cfg.tda827x_lpsel = 0; + t->mode = V4L2_TUNER_ANALOG_TV; + + tda8295_init_if(t); + return 0; +} +EXPORT_SYMBOL_GPL(tda8295_attach); int tda8290_probe(struct tuner *t) { @@ -434,12 +743,10 @@ int tda8290_probe(struct tuner *t) tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); return -1; } - EXPORT_SYMBOL_GPL(tda8290_probe); -EXPORT_SYMBOL_GPL(tda8290_attach); MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); -MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann"); +MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); MODULE_LICENSE("GPL"); /* diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index 9b63e62b3a0..dbbcb0f001e 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -24,6 +24,7 @@ extern int tda8290_probe(struct tuner *t); extern int tda8290_attach(struct tuner *t); +extern int tda8295_attach(struct tuner *t); #else static inline int tda8290_probe(struct tuner *t) { @@ -37,6 +38,13 @@ static inline int tda8290_attach(struct tuner *t) __FUNCTION__); return -EINVAL; } + +static inline int tda8295_attach(struct tuner *t) +{ + printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", + __FUNCTION__); + return -EINVAL; +} #endif #endif /* __TDA8290_H__ */ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 99558c708ae..6ae8cb205d8 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -278,6 +278,11 @@ static void set_type(struct i2c_client *c, unsigned int type, tda8290_attach(t); break; } + case TUNER_PHILIPS_TDA8295: + { + tda8295_attach(t); + break; + } case TUNER_TEA5767: if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { t->type = TUNER_ABSENT; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index ac363f01922..4a674c436cf 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -1475,6 +1475,9 @@ struct tunertype tuners[] = { .name = "Philips TEA5761 FM Radio", /* see tea5767.c for details */ }, + [TUNER_PHILIPS_TDA8295] = { /* Philips PAL|NTSC */ + .name = "tda8295+18271", + /* see tda8290.c for details */ }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 4b2c4034f5b..27bfe6d3a33 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -257,7 +257,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "LG TAPQ_H702F"}, { TUNER_ABSENT, "TCL M09WPP_4N_E"}, { TUNER_ABSENT, "MaxLinear MXL5005_v2"}, - { TUNER_ABSENT, "Philips 18271_8295"}, + { TUNER_PHILIPS_TDA8295, "Philips 18271_8295"}, }; static struct HAUPPAUGE_AUDIOIC diff --git a/include/media/tuner.h b/include/media/tuner.h index d49392d90e5..faacd2d50b7 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -124,6 +124,8 @@ extern int tuner_debug; #define TUNER_TDA9887 74 /* This tuner should be used only internally */ #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ +#define TUNER_PHILIPS_TDA8295 76 + /* tv card specific */ #define TDA9887_PRESENT (1<<0) #define TDA9887_PORT1_INACTIVE (1<<1) -- cgit v1.2.3-70-g09d2 From 1dde7a4fa2b197d298c3f1b97a7f78fd1c3a1bda Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 13:40:56 -0300 Subject: V4L/DVB (6436): tuner: move analog_tuner_ops into dvb_frontend_ops Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.h | 3 + drivers/media/video/tda8290.c | 8 +-- drivers/media/video/tda9887.c | 4 +- drivers/media/video/tuner-core.c | 91 ++++++++++++++++++------------- drivers/media/video/tuner-driver.h | 4 +- 5 files changed, 63 insertions(+), 47 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index c49fa049717..0dd0c672897 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -62,6 +62,8 @@ struct dvb_tuner_info { u32 bandwidth_step; }; +struct analog_tuner_ops; + struct analog_parameters { unsigned int frequency; unsigned int mode; @@ -146,6 +148,7 @@ struct dvb_frontend_ops { int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); struct dvb_tuner_ops tuner_ops; + struct analog_tuner_ops *analog_demod_ops; }; #define MAX_EVENT 8 diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index a38ed9db640..da5e5a8169f 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -519,7 +519,7 @@ static void tda829x_release(struct tuner *t) t->priv = NULL; } -static struct tuner_operations tda8290_tuner_ops = { +static struct analog_tuner_ops tda8290_tuner_ops = { .set_tv_freq = tda8290_set_freq, .set_radio_freq = tda8290_set_freq, .has_signal = tda8290_has_signal, @@ -527,7 +527,7 @@ static struct tuner_operations tda8290_tuner_ops = { .release = tda829x_release, }; -static struct tuner_operations tda8295_tuner_ops = { +static struct analog_tuner_ops tda8295_tuner_ops = { .set_tv_freq = tda8295_set_freq, .set_radio_freq = tda8295_set_freq, .has_signal = tda8295_has_signal, @@ -612,7 +612,7 @@ int tda8290_attach(struct tuner *t) if (t->fe.ops.tuner_ops.sleep) t->fe.ops.tuner_ops.sleep(&t->fe); - memcpy(&t->ops, &tda8290_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda8290_tuner_ops; tuner_info("type set to %s\n", t->i2c.name); @@ -703,7 +703,7 @@ int tda8295_attach(struct tuner *t) priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ tuner_info("type set to %s\n", t->i2c.name); - memcpy(&t->ops, &tda8295_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index be5387f11af..d9bfa812ffe 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -610,7 +610,7 @@ static void tda9887_release(struct tuner *t) t->priv = NULL; } -static struct tuner_operations tda9887_tuner_ops = { +static struct analog_tuner_ops tda9887_tuner_ops = { .set_tv_freq = tda9887_set_freq, .set_radio_freq = tda9887_set_freq, .standby = tda9887_standby, @@ -636,7 +636,7 @@ int tda9887_tuner_init(struct tuner *t) tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, t->i2c.driver->driver.name); - memcpy(&t->ops, &tda9887_tuner_ops, sizeof(struct tuner_operations)); + t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; return 0; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6ae8cb205d8..f31de98bbfa 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -122,16 +122,28 @@ static int fe_has_signal(struct tuner *t) return strength; } +static void tuner_status(struct tuner *t); + +static struct analog_tuner_ops tuner_core_ops = { + .set_tv_freq = fe_set_freq, + .set_radio_freq = fe_set_freq, + .standby = fe_standby, + .release = fe_release, + .has_signal = fe_has_signal, + .tuner_status = tuner_status +}; + /* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */ static void set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->ops.set_tv_freq) { + if ((NULL == ops) || (NULL == ops->set_tv_freq)) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -146,18 +158,19 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - t->ops.set_tv_freq(t, freq); + ops->set_tv_freq(t, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if (NULL == t->ops.set_radio_freq) { + if ((NULL == ops) || (NULL == ops->set_radio_freq)) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } @@ -173,7 +186,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) freq = radio_range[1] * 16000; } - t->ops.set_radio_freq(t, freq); + ops->set_radio_freq(t, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -235,6 +248,7 @@ static void set_type(struct i2c_client *c, unsigned int type, { struct tuner *t = i2c_get_clientdata(c); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; unsigned char buffer[4]; if (type == UNSET || type == TUNER_ABSENT) { @@ -262,8 +276,8 @@ static void set_type(struct i2c_client *c, unsigned int type, } /* discard private data, in case set_type() was previously called */ - if (t->ops.release) - t->ops.release(t); + if ((ops) && (ops->release)) + ops->release(t); else { kfree(t->priv); t->priv = NULL; @@ -339,15 +353,12 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } - if ((fe_tuner_ops->set_analog_params) && - ((NULL == t->ops.set_tv_freq) && (NULL == t->ops.set_radio_freq))) { + if (((NULL == ops) || + ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && + (fe_tuner_ops->set_analog_params)) { strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); - t->ops.set_tv_freq = fe_set_freq; - t->ops.set_radio_freq = fe_set_freq; - t->ops.standby = fe_standby; - t->ops.release = fe_release; - t->ops.has_signal = fe_has_signal; + t->fe.ops.analog_demod_ops = &tuner_core_ops; } tuner_info("type set to %s\n", t->i2c.name); @@ -524,6 +535,7 @@ static void tuner_status(struct tuner *t) { unsigned long freq, freq_fraction; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; const char *p; switch (t->mode) { @@ -553,11 +565,11 @@ static void tuner_status(struct tuner *t) if (tuner_status & TUNER_STATUS_STEREO) tuner_info("Stereo: yes\n"); } - if (t->ops.has_signal) { - tuner_info("Signal strength: %d\n", t->ops.has_signal(t)); + if ((ops) && (ops->has_signal)) { + tuner_info("Signal strength: %d\n", ops->has_signal(t)); } - if (t->ops.is_stereo) { - tuner_info("Stereo: %s\n", t->ops.is_stereo(t) ? "yes" : "no"); + if ((ops) && (ops->is_stereo)) { + tuner_info("Stereo: %s\n", ops->is_stereo(t) ? "yes" : "no"); } } @@ -584,7 +596,6 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; - t->ops.tuner_status = tuner_status; if (show_i2c) { unsigned char buffer[16]; @@ -701,6 +712,7 @@ static int tuner_probe(struct i2c_adapter *adap) static int tuner_detach(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; int err; err = i2c_detach_client(&t->i2c); @@ -710,8 +722,8 @@ static int tuner_detach(struct i2c_client *client) return err; } - if (t->ops.release) - t->ops.release(t); + if ((ops) && (ops->release)) + ops->release(t); else { kfree(t->priv); } @@ -728,6 +740,8 @@ static int tuner_detach(struct i2c_client *client) static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + if (mode == t->mode) return 0; @@ -735,8 +749,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; - if (t->ops.standby) - t->ops.standby(t); + if ((ops) && (ops->standby)) + ops->standby(t); return EINVAL; } return 0; @@ -759,6 +773,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tuner *t = i2c_get_clientdata(client); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (tuner_debug>1) v4l_i2c_print_ioctl(&(t->i2c),cmd); @@ -785,8 +800,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; t->mode = T_STANDBY; - if (t->ops.standby) - t->ops.standby(t); + if ((ops) && (ops->standby)) + ops->standby(t); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -854,8 +869,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) else vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { - if (t->ops.is_stereo) { - if (t->ops.is_stereo(t)) + if ((ops) && (ops->is_stereo)) { + if (ops->is_stereo(t)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -863,8 +878,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ~VIDEO_TUNER_STEREO_ON; } } - if (t->ops.has_signal) - vt->signal = t->ops.has_signal(t); + if ((ops) && (ops->has_signal)) + vt->signal = ops->has_signal(t); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -894,8 +909,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) fe_tuner_ops->get_status(&t->fe, &tuner_status); va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if (t->ops.is_stereo) - va->mode = t->ops.is_stereo(t) + } else if ((ops) && (ops->is_stereo)) + va->mode = ops->is_stereo(t) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } return 0; @@ -985,8 +1000,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; - if (t->ops.get_afc) - tuner->afc=t->ops.get_afc(t); + if ((ops) && (ops->get_afc)) + tuner->afc = ops->get_afc(t); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -1005,13 +1020,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } else { - if (t->ops.is_stereo) { - tuner->rxsubchans = t->ops.is_stereo(t) ? + if ((ops) && (ops->is_stereo)) { + tuner->rxsubchans = ops->is_stereo(t) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } } - if (t->ops.has_signal) - tuner->signal = t->ops.has_signal(t); + if ((ops) && (ops->has_signal)) + tuner->signal = ops->has_signal(t); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; tuner->audmode = t->audmode; @@ -1036,8 +1051,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case VIDIOC_LOG_STATUS: - if (t->ops.tuner_status) - t->ops.tuner_status(t); + if ((ops) && (ops->tuner_status)) + ops->tuner_status(t); break; } diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 28a10da76d1..f2a9c29f1f0 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -31,7 +31,7 @@ extern unsigned const int tuner_count; struct tuner; -struct tuner_operations { +struct analog_tuner_ops { void (*set_tv_freq)(struct tuner *t, unsigned int freq); void (*set_radio_freq)(struct tuner *t, unsigned int freq); int (*has_signal)(struct tuner *t); @@ -66,8 +66,6 @@ struct tuner { unsigned int config; int (*tuner_callback) (void *dev, int command,int arg); - - struct tuner_operations ops; }; /* ------------------------------------------------------------------------ */ -- cgit v1.2.3-70-g09d2 From 16f291684c50497cc92e83f01d354fae187d1f18 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 15:22:25 -0300 Subject: V4L/DVB (6438): tuner: move analog_demod_priv into struct dvb_frontend Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.h | 1 + drivers/media/video/tda8290.c | 40 +++++++++++++++---------------- drivers/media/video/tda9887.c | 14 +++++------ drivers/media/video/tuner-core.c | 8 +------ drivers/media/video/tuner-driver.h | 1 - 5 files changed, 29 insertions(+), 35 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 0dd0c672897..f93c5db3666 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -169,6 +169,7 @@ struct dvb_frontend { void* tuner_priv; void* frontend_priv; void* sec_priv; + void* analog_demod_priv; }; extern int dvb_register_frontend(struct dvb_adapter* dvb, diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index da5e5a8169f..e001c397ccf 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -50,7 +50,7 @@ struct tda8290_priv { static void tda8290_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -68,7 +68,7 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) static void tda8295_i2c_bridge(struct tuner *t, int close) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char enable[2] = { 0x45, 0xc1 }; unsigned char disable[2] = { 0x46, 0x00 }; @@ -98,7 +98,7 @@ static void tda8295_i2c_bridge(struct tuner *t, int close) static void set_audio(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; char* mode; priv->cfg.tda827x_lpsel = 0; @@ -145,7 +145,7 @@ static void set_audio(struct tuner *t) static void tda8290_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -264,7 +264,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) static void tda8295_power(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -280,7 +280,7 @@ static void tda8295_power(struct tuner *t, int enable) static void tda8295_set_easy_mode(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -296,7 +296,7 @@ static void tda8295_set_easy_mode(struct tuner *t, int enable) static void tda8295_set_video_std(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); @@ -310,7 +310,7 @@ static void tda8295_set_video_std(struct tuner *t) static void tda8295_agc1_out(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -326,7 +326,7 @@ static void tda8295_agc1_out(struct tuner *t, int enable) static void tda8295_agc2_out(struct tuner *t, int enable) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; @@ -347,7 +347,7 @@ static void tda8295_agc2_out(struct tuner *t, int enable) static int tda8295_has_signal(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char hvpll_stat = 0x26; unsigned char ret; @@ -361,7 +361,7 @@ static int tda8295_has_signal(struct tuner *t) static void tda8295_set_freq(struct tuner *t, unsigned int freq) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -411,7 +411,7 @@ static void tda8295_set_freq(struct tuner *t, unsigned int freq) static int tda8290_has_signal(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; @@ -425,7 +425,7 @@ static int tda8290_has_signal(struct tuner *t) static void tda8290_standby(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; @@ -449,7 +449,7 @@ static void tda8295_standby(struct tuner *t) static void tda8290_init_if(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; @@ -464,7 +464,7 @@ static void tda8290_init_if(struct tuner *t) static void tda8295_init_if(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; @@ -493,7 +493,7 @@ static void tda8295_init_if(struct tuner *t) static void tda8290_init_tuner(struct tuner *t) { - struct tda8290_priv *priv = t->priv; + struct tda8290_priv *priv = t->fe.analog_demod_priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -515,8 +515,8 @@ static void tda829x_release(struct tuner *t) if (t->fe.ops.tuner_ops.release) t->fe.ops.tuner_ops.release(&t->fe); - kfree(t->priv); - t->priv = NULL; + kfree(t->fe.analog_demod_priv); + t->fe.analog_demod_priv = NULL; } static struct analog_tuner_ops tda8290_tuner_ops = { @@ -546,7 +546,7 @@ int tda8290_attach(struct tuner *t) priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; @@ -636,7 +636,7 @@ int tda8295_attach(struct tuner *t) priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index d9bfa812ffe..68b22da7e25 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -512,7 +512,7 @@ static int tda9887_set_config(struct tuner *t, char *buf) static int tda9887_status(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; unsigned char buf[1]; int rc; @@ -525,7 +525,7 @@ static int tda9887_status(struct tuner *t) static void tda9887_configure(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; int rc; memset(priv->data,0,sizeof(priv->data)); @@ -572,13 +572,13 @@ static void tda9887_configure(struct tuner *t) static void tda9887_tuner_status(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); } static int tda9887_get_afc(struct tuner *t) { - struct tda9887_priv *priv = t->priv; + struct tda9887_priv *priv = t->fe.analog_demod_priv; static int AFC_BITS_2_kHz[] = { -12500, -37500, -62500, -97500, -112500, -137500, -162500, -187500, @@ -606,8 +606,8 @@ static void tda9887_set_freq(struct tuner *t, unsigned int freq) static void tda9887_release(struct tuner *t) { - kfree(t->priv); - t->priv = NULL; + kfree(t->fe.analog_demod_priv); + t->fe.analog_demod_priv = NULL; } static struct analog_tuner_ops tda9887_tuner_ops = { @@ -626,7 +626,7 @@ int tda9887_tuner_init(struct tuner *t) priv = kzalloc(sizeof(struct tda9887_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->priv = priv; + t->fe.analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 9de66769b62..9903b3f2530 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -280,10 +280,6 @@ static void set_type(struct i2c_client *c, unsigned int type, /* discard private data, in case set_type() was previously called */ if ((ops) && (ops->release)) ops->release(t); - else { - kfree(t->priv); - t->priv = NULL; - } switch (t->type) { case TUNER_MT2032: @@ -728,9 +724,7 @@ static int tuner_detach(struct i2c_client *client) if ((ops) && (ops->release)) ops->release(t); - else { - kfree(t->priv); - } + kfree(t); return 0; } diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index f2a9c29f1f0..fffacb378fd 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -57,7 +57,6 @@ struct tuner { v4l2_std_id std; int using_v4l2; - void *priv; struct dvb_frontend fe; -- cgit v1.2.3-70-g09d2 From 4e9154b8a77d0f0f8f06857162823905612a50d7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Oct 2007 19:39:50 -0300 Subject: V4L/DVB (6440): tuner: convert analog tuner demod sub-modules to dvb_frontend interface Convert tda9887 and tda8290/5 to dvb_frontend interface Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 164 ++++++++++++++++++++----------------- drivers/media/video/tda9887.c | 78 +++++++++++------- drivers/media/video/tuner-core.c | 79 ++++++++++-------- drivers/media/video/tuner-driver.h | 16 ++-- 4 files changed, 186 insertions(+), 151 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index e001c397ccf..288865c3c71 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -44,13 +44,15 @@ struct tda8290_priv { unsigned char tda827x_ver; struct tda827x_config cfg; + + struct tuner *t; }; /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct tuner *t, int close) +static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; @@ -66,9 +68,9 @@ static void tda8290_i2c_bridge(struct tuner *t, int close) } } -static void tda8295_i2c_bridge(struct tuner *t, int close) +static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x45, 0xc1 }; unsigned char disable[2] = { 0x46, 0x00 }; @@ -96,9 +98,10 @@ static void tda8295_i2c_bridge(struct tuner *t, int close) /*---------------------------------------------------------------------*/ -static void set_audio(struct tuner *t) +static void set_audio(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; char* mode; priv->cfg.tda827x_lpsel = 0; @@ -143,9 +146,11 @@ static void set_audio(struct tuner *t) tuner_dbg("setting tda8290 to system %s\n", mode); } -static void tda8290_set_freq(struct tuner *t, unsigned int freq) +static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; + unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; unsigned char expert_mode[] = { 0x01, 0x80 }; @@ -175,7 +180,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) .std = t->std }; - set_audio(t); + set_audio(fe); tuner_dbg("tda827xa config is 0x%02x\n", t->config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); @@ -193,10 +198,10 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2); tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); - if (t->fe.ops.tuner_ops.set_analog_params) - t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + if (fe->ops.tuner_ops.set_analog_params) + fe->ops.tuner_ops.set_analog_params(fe, ¶ms); for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); @@ -227,7 +232,7 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); if (priv->cfg.agcf) - priv->cfg.agcf(&t->fe); + priv->cfg.agcf(fe); msleep(100); tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); @@ -256,15 +261,15 @@ static void tda8290_set_freq(struct tuner *t, unsigned int freq) } } - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2); } /*---------------------------------------------------------------------*/ -static void tda8295_power(struct tuner *t, int enable) +static void tda8295_power(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -278,9 +283,9 @@ static void tda8295_power(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_set_easy_mode(struct tuner *t, int enable) +static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -294,23 +299,23 @@ static void tda8295_set_easy_mode(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_set_video_std(struct tuner *t) +static void tda8295_set_video_std(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x00, priv->tda8290_easy_mode }; tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); - tda8295_set_easy_mode(t, 1); + tda8295_set_easy_mode(fe, 1); msleep(20); - tda8295_set_easy_mode(t, 0); + tda8295_set_easy_mode(fe, 0); } /*---------------------------------------------------------------------*/ -static void tda8295_agc1_out(struct tuner *t, int enable) +static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); @@ -324,9 +329,9 @@ static void tda8295_agc1_out(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); } -static void tda8295_agc2_out(struct tuner *t, int enable) +static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; @@ -345,9 +350,9 @@ static void tda8295_agc2_out(struct tuner *t, int enable) tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); } -static int tda8295_has_signal(struct tuner *t) +static int tda8295_has_signal(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char hvpll_stat = 0x26; unsigned char ret; @@ -359,9 +364,10 @@ static int tda8295_has_signal(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8295_set_freq(struct tuner *t, unsigned int freq) +static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -373,45 +379,45 @@ static void tda8295_set_freq(struct tuner *t, unsigned int freq) .std = t->std }; - set_audio(t); + set_audio(fe); ifc = priv->cfg.sgIF; /* FIXME */ tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); - tda8295_power(t, 1); - tda8295_agc1_out(t, 1); + tda8295_power(fe, 1); + tda8295_agc1_out(fe, 1); tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); - tda8295_set_video_std(t); + tda8295_set_video_std(fe); blanking_mode[1] = 0x03; tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2); msleep(20); - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(fe, 1); - if (t->fe.ops.tuner_ops.set_analog_params) - t->fe.ops.tuner_ops.set_analog_params(&t->fe, ¶ms); + if (fe->ops.tuner_ops.set_analog_params) + fe->ops.tuner_ops.set_analog_params(fe, ¶ms); if (priv->cfg.agcf) - priv->cfg.agcf(&t->fe); + priv->cfg.agcf(fe); - if (tda8295_has_signal(t)) + if (tda8295_has_signal(fe)) tuner_dbg("tda8295 is locked\n"); else tuner_dbg("tda8295 not locked, no signal?\n"); - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(fe, 0); } /*---------------------------------------------------------------------*/ -static int tda8290_has_signal(struct tuner *t) +static int tda8290_has_signal(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; @@ -423,33 +429,35 @@ static int tda8290_has_signal(struct tuner *t) /*---------------------------------------------------------------------*/ -static void tda8290_standby(struct tuner *t) +static void tda8290_standby(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + unsigned char cb1[] = { 0x30, 0xD0 }; unsigned char tda8290_standby[] = { 0x00, 0x02 }; unsigned char tda8290_agc_tri[] = { 0x02, 0x20 }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); if (priv->tda827x_ver != 0) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2); tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2); } -static void tda8295_standby(struct tuner *t) +static void tda8295_standby(struct dvb_frontend *fe) { - tda8295_agc1_out(t, 0); /* Put AGC in tri-state */ + tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */ - tda8295_power(t, 0); + tda8295_power(fe, 0); } -static void tda8290_init_if(struct tuner *t) +static void tda8290_init_if(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; @@ -462,9 +470,9 @@ static void tda8290_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2); } -static void tda8295_init_if(struct tuner *t) +static void tda8295_init_if(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; static unsigned char set_adc_ctl[] = { 0x33, 0x14 }; static unsigned char set_adc_ctl2[] = { 0x34, 0x00 }; @@ -474,10 +482,10 @@ static void tda8295_init_if(struct tuner *t) static unsigned char set_pll_reg10[] = { 0x42, 0x61 }; static unsigned char set_gpio_reg0[] = { 0x44, 0x0b }; - tda8295_power(t, 1); + tda8295_power(fe, 1); - tda8295_set_easy_mode(t, 0); - tda8295_set_video_std(t); + tda8295_set_easy_mode(fe, 0); + tda8295_set_video_std(fe); tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2); @@ -487,13 +495,13 @@ static void tda8295_init_if(struct tuner *t) tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2); tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2); - tda8295_agc1_out(t, 0); - tda8295_agc2_out(t, 0); + tda8295_agc1_out(fe, 0); + tda8295_agc2_out(fe, 0); } -static void tda8290_init_tuner(struct tuner *t) +static void tda8290_init_tuner(struct dvb_frontend *fe) { - struct tda8290_priv *priv = t->fe.analog_demod_priv; + struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char tda8275_init[] = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf, 0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 }; unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b, @@ -503,20 +511,20 @@ static void tda8290_init_tuner(struct tuner *t) if (priv->tda827x_ver != 0) msg.buf = tda8275a_init; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(fe, 1); i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(fe, 0); } /*---------------------------------------------------------------------*/ -static void tda829x_release(struct tuner *t) +static void tda829x_release(struct dvb_frontend *fe) { - if (t->fe.ops.tuner_ops.release) - t->fe.ops.tuner_ops.release(&t->fe); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); - kfree(t->fe.analog_demod_priv); - t->fe.analog_demod_priv = NULL; + kfree(fe->analog_demod_priv); + fe->analog_demod_priv = NULL; } static struct analog_tuner_ops tda8290_tuner_ops = { @@ -552,8 +560,9 @@ int tda8290_attach(struct tuner *t) priv->i2c_props.adap = t->i2c.adapter; priv->cfg.config = &t->config; priv->cfg.tuner_callback = t->tuner_callback; + priv->t = t; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -569,7 +578,7 @@ int tda8290_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(t, 0); + tda8290_i2c_bridge(&t->fe, 0); if(tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -590,7 +599,7 @@ int tda8290_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(t, 1); + tda8290_i2c_bridge(&t->fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if( ret != 1) @@ -619,8 +628,8 @@ int tda8290_attach(struct tuner *t) priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; - tda8290_init_tuner(t); - tda8290_init_if(t); + tda8290_init_tuner(&t->fe); + tda8290_init_if(&t->fe); return 0; } EXPORT_SYMBOL_GPL(tda8290_attach); @@ -640,8 +649,9 @@ int tda8295_attach(struct tuner *t) priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->t = t; - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; @@ -657,7 +667,7 @@ int tda8295_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(&t->fe, 0); if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; @@ -678,9 +688,9 @@ int tda8295_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8295_i2c_bridge(t, 1); + tda8295_i2c_bridge(&t->fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8295_i2c_bridge(t, 0); + tda8295_i2c_bridge(&t->fe, 0); if (ret != 1) tuner_warn("TDA827x access failed!\n"); if ((data & 0x3c) == 0) { @@ -708,7 +718,7 @@ int tda8295_attach(struct tuner *t) priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; - tda8295_init_if(t); + tda8295_init_if(&t->fe); return 0; } EXPORT_SYMBOL_GPL(tda8295_attach); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 68b22da7e25..7663a557975 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -21,17 +21,19 @@ */ #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ + i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ + i2c_adapter_id(priv->t->i2c.adapter), priv->t->i2c.addr , ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; unsigned char data[4]; + + struct tuner *t; }; /* ---------------------------------------------------------------------- */ @@ -262,8 +264,10 @@ static struct tvnorm radio_mono = { /* ---------------------------------------------------------------------- */ -static void dump_read_message(struct tuner *t, unsigned char *buf) +static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf) { + struct tda9887_priv *priv = fe->analog_demod_priv; + static char *afc[16] = { "- 12.5 kHz", "- 37.5 kHz", @@ -290,8 +294,10 @@ static void dump_read_message(struct tuner *t, unsigned char *buf) tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } -static void dump_write_message(struct tuner *t, unsigned char *buf) +static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf) { + struct tda9887_priv *priv = fe->analog_demod_priv; + static char *sound[4] = { "AM/TV", "FM/radio", @@ -386,9 +392,12 @@ static void dump_write_message(struct tuner *t, unsigned char *buf) /* ---------------------------------------------------------------------- */ -static int tda9887_set_tvnorm(struct tuner *t, char *buf) +static int tda9887_set_tvnorm(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; struct tvnorm *norm = NULL; + char *buf = priv->data; int i; if (t->mode == V4L2_TUNER_RADIO) { @@ -426,8 +435,11 @@ module_param(port2, int, 0644); module_param(qss, int, 0644); module_param(adjust, int, 0644); -static int tda9887_set_insmod(struct tuner *t, char *buf) +static int tda9887_set_insmod(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + char *buf = priv->data; + if (UNSET != port1) { if (port1) buf[1] |= cOutputPort1Inactive; @@ -455,8 +467,12 @@ static int tda9887_set_insmod(struct tuner *t, char *buf) return 0; } -static int tda9887_set_config(struct tuner *t, char *buf) +static int tda9887_set_config(struct dvb_frontend *fe) { + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; + char *buf = priv->data; + if (t->tda9887_config & TDA9887_PORT1_ACTIVE) buf[1] &= ~cOutputPort1Inactive; if (t->tda9887_config & TDA9887_PORT1_INACTIVE) @@ -510,26 +526,27 @@ static int tda9887_set_config(struct tuner *t, char *buf) /* ---------------------------------------------------------------------- */ -static int tda9887_status(struct tuner *t) +static int tda9887_status(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; unsigned char buf[1]; int rc; memset(buf,0,sizeof(buf)); if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1))) tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); - dump_read_message(t, buf); + dump_read_message(fe, buf); return 0; } -static void tda9887_configure(struct tuner *t) +static void tda9887_configure(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; + struct tuner *t = priv->t; int rc; memset(priv->data,0,sizeof(priv->data)); - tda9887_set_tvnorm(t,priv->data); + tda9887_set_tvnorm(fe); /* A note on the port settings: These settings tend to depend on the specifics of the board. @@ -547,8 +564,8 @@ static void tda9887_configure(struct tuner *t) priv->data[1] |= cOutputPort1Inactive; priv->data[1] |= cOutputPort2Inactive; - tda9887_set_config(t,priv->data); - tda9887_set_insmod(t,priv->data); + tda9887_set_config(fe); + tda9887_set_insmod(fe); if (t->mode == T_STANDBY) { priv->data[1] |= cForcedMuteAudioON; @@ -557,28 +574,28 @@ static void tda9887_configure(struct tuner *t) tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1],priv->data[2],priv->data[3]); if (tuner_debug > 1) - dump_write_message(t, priv->data); + dump_write_message(fe, priv->data); if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (tuner_debug > 2) { msleep_interruptible(1000); - tda9887_status(t); + tda9887_status(fe); } } /* ---------------------------------------------------------------------- */ -static void tda9887_tuner_status(struct tuner *t) +static void tda9887_tuner_status(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", priv->data[1], priv->data[2], priv->data[3]); } -static int tda9887_get_afc(struct tuner *t) +static int tda9887_get_afc(struct dvb_frontend *fe) { - struct tda9887_priv *priv = t->fe.analog_demod_priv; + struct tda9887_priv *priv = fe->analog_demod_priv; static int AFC_BITS_2_kHz[] = { -12500, -37500, -62500, -97500, -112500, -137500, -162500, -187500, @@ -594,20 +611,20 @@ static int tda9887_get_afc(struct tuner *t) return afc; } -static void tda9887_standby(struct tuner *t) +static void tda9887_standby(struct dvb_frontend *fe) { - tda9887_configure(t); + tda9887_configure(fe); } -static void tda9887_set_freq(struct tuner *t, unsigned int freq) +static void tda9887_set_freq(struct dvb_frontend *fe, unsigned int freq) { - tda9887_configure(t); + tda9887_configure(fe); } -static void tda9887_release(struct tuner *t) +static void tda9887_release(struct dvb_frontend *fe) { - kfree(t->fe.analog_demod_priv); - t->fe.analog_demod_priv = NULL; + kfree(fe->analog_demod_priv); + fe->analog_demod_priv = NULL; } static struct analog_tuner_ops tda9887_tuner_ops = { @@ -630,6 +647,7 @@ int tda9887_tuner_init(struct tuner *t) priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->t = t; strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name)); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 9903b3f2530..805a2bd29e7 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -77,9 +77,10 @@ static struct i2c_client client_template; /* ---------------------------------------------------------------------- */ -static void fe_set_freq(struct tuner *t, unsigned int freq) +static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; + struct tuner *t = fe->analog_demod_priv; struct analog_parameters params = { .frequency = freq, @@ -92,39 +93,38 @@ static void fe_set_freq(struct tuner *t, unsigned int freq) tuner_warn("Tuner frontend module has no way to set freq\n"); return; } - fe_tuner_ops->set_analog_params(&t->fe, ¶ms); + fe_tuner_ops->set_analog_params(fe, ¶ms); } -static void fe_release(struct tuner *t) +static void fe_release(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - - if (fe_tuner_ops->release) - fe_tuner_ops->release(&t->fe); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); - t->fe.ops.analog_demod_ops = NULL; + fe->ops.analog_demod_ops = NULL; + /* DO NOT kfree(t->fe.analog_demod_priv) */ + fe->analog_demod_priv = NULL; } -static void fe_standby(struct tuner *t) +static void fe_standby(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; + struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; if (fe_tuner_ops->sleep) - fe_tuner_ops->sleep(&t->fe); + fe_tuner_ops->sleep(fe); } -static int fe_has_signal(struct tuner *t) +static int fe_has_signal(struct dvb_frontend *fe) { - struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; u16 strength = 0; - if (fe_tuner_ops->get_rf_strength) - fe_tuner_ops->get_rf_strength(&t->fe, &strength); + if (fe->ops.tuner_ops.get_rf_strength) + fe->ops.tuner_ops.get_rf_strength(fe, &strength); return strength; } -static void tuner_status(struct tuner *t); +static void tuner_status(struct dvb_frontend *fe); static struct analog_tuner_ops tuner_core_ops = { .set_tv_freq = fe_set_freq, @@ -160,7 +160,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - ops->set_tv_freq(t, freq); + ops->set_tv_freq(&t->fe, freq); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -188,7 +188,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) freq = radio_range[1] * 16000; } - ops->set_radio_freq(t, freq); + ops->set_radio_freq(&t->fe, freq); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -279,7 +279,7 @@ static void set_type(struct i2c_client *c, unsigned int type, /* discard private data, in case set_type() was previously called */ if ((ops) && (ops->release)) - ops->release(t); + ops->release(&t->fe); switch (t->type) { case TUNER_MT2032: @@ -359,6 +359,7 @@ static void set_type(struct i2c_client *c, unsigned int type, strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); t->fe.ops.analog_demod_ops = &tuner_core_ops; + t->fe.analog_demod_priv = t; } tuner_info("type set to %s\n", t->i2c.name); @@ -531,8 +532,9 @@ static int tuner_fixup_std(struct tuner *t) return 0; } -static void tuner_status(struct tuner *t) +static void tuner_status(struct dvb_frontend *fe) { + struct tuner *t = fe->analog_demod_priv; unsigned long freq, freq_fraction; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; @@ -566,10 +568,11 @@ static void tuner_status(struct tuner *t) tuner_info("Stereo: yes\n"); } if ((ops) && (ops->has_signal)) { - tuner_info("Signal strength: %d\n", ops->has_signal(t)); + tuner_info("Signal strength: %d\n", ops->has_signal(fe)); } if ((ops) && (ops->is_stereo)) { - tuner_info("Stereo: %s\n", ops->is_stereo(t) ? "yes" : "no"); + tuner_info("Stereo: %s\n", ops->is_stereo(fe) ? + "yes" : "no"); } } @@ -723,7 +726,7 @@ static int tuner_detach(struct i2c_client *client) } if ((ops) && (ops->release)) - ops->release(t); + ops->release(&t->fe); kfree(t); return 0; @@ -748,7 +751,7 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; if ((ops) && (ops->standby)) - ops->standby(t); + ops->standby(&t->fe); return EINVAL; } return 0; @@ -799,7 +802,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; t->mode = T_STANDBY; if ((ops) && (ops->standby)) - ops->standby(t); + ops->standby(&t->fe); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -868,7 +871,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { if ((ops) && (ops->is_stereo)) { - if (ops->is_stereo(t)) + if (ops->is_stereo(&t->fe)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -877,7 +880,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } } if ((ops) && (ops->has_signal)) - vt->signal = ops->has_signal(t); + vt->signal = ops->has_signal(&t->fe); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -908,7 +911,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } else if ((ops) && (ops->is_stereo)) - va->mode = ops->is_stereo(t) + va->mode = ops->is_stereo(&t->fe) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } return 0; @@ -999,7 +1002,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) tuner->type = t->mode; if ((ops) && (ops->get_afc)) - tuner->afc = ops->get_afc(t); + tuner->afc = ops->get_afc(&t->fe); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -1015,16 +1018,20 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) u32 tuner_status; fe_tuner_ops->get_status(&t->fe, &tuner_status); - tuner->rxsubchans = (tuner_status & TUNER_STATUS_STEREO) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + tuner->rxsubchans = + (tuner_status & TUNER_STATUS_STEREO) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; } else { if ((ops) && (ops->is_stereo)) { - tuner->rxsubchans = ops->is_stereo(t) ? - V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + tuner->rxsubchans = + ops->is_stereo(&t->fe) ? + V4L2_TUNER_SUB_STEREO : + V4L2_TUNER_SUB_MONO; } } if ((ops) && (ops->has_signal)) - tuner->signal = ops->has_signal(t); + tuner->signal = ops->has_signal(&t->fe); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; tuner->audmode = t->audmode; @@ -1050,7 +1057,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOC_LOG_STATUS: if ((ops) && (ops->tuner_status)) - ops->tuner_status(t); + ops->tuner_status(&t->fe); break; } diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index fffacb378fd..cc9c1c74117 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -32,14 +32,14 @@ extern unsigned const int tuner_count; struct tuner; struct analog_tuner_ops { - void (*set_tv_freq)(struct tuner *t, unsigned int freq); - void (*set_radio_freq)(struct tuner *t, unsigned int freq); - int (*has_signal)(struct tuner *t); - int (*is_stereo)(struct tuner *t); - int (*get_afc)(struct tuner *t); - void (*tuner_status)(struct tuner *t); - void (*standby)(struct tuner *t); - void (*release)(struct tuner *t); + void (*set_tv_freq)(struct dvb_frontend *fe, unsigned int freq); + void (*set_radio_freq)(struct dvb_frontend *fe, unsigned int freq); + int (*has_signal)(struct dvb_frontend *fe); + int (*is_stereo)(struct dvb_frontend *fe); + int (*get_afc)(struct dvb_frontend *fe); + void (*tuner_status)(struct dvb_frontend *fe); + void (*standby)(struct dvb_frontend *fe); + void (*release)(struct dvb_frontend *fe); }; struct tuner { -- cgit v1.2.3-70-g09d2 From 5c82f4497b46e9c3877618bc36661a4abbf9c646 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Oct 2007 01:10:39 -0300 Subject: V4L/DVB (6442): move std if setting from tda8290 to tda827x Signed-off-by: Michael Krufky Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda827x.c | 61 ++++++++++++++++++++++++++++++++--- drivers/media/dvb/frontends/tda827x.h | 3 -- drivers/media/video/tda8290.c | 20 +----------- 3 files changed, 57 insertions(+), 27 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda827x.c b/drivers/media/dvb/frontends/tda827x.c index 6de1aea02d5..8329d33b517 100644 --- a/drivers/media/dvb/frontends/tda827x.c +++ b/drivers/media/dvb/frontends/tda827x.c @@ -38,10 +38,57 @@ struct tda827x_priv { int i2c_addr; struct i2c_adapter *i2c_adap; struct tda827x_config *cfg; + + unsigned int sgIF; + unsigned char lpsel; + u32 frequency; u32 bandwidth; }; +static void tda827x_set_std(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + struct tda827x_priv *priv = fe->tuner_priv; + char *mode; + + priv->lpsel = 0; + if (params->std & V4L2_STD_MN) { + priv->sgIF = 92; + priv->lpsel = 1; + mode = "MN"; + } else if (params->std & V4L2_STD_B) { + priv->sgIF = 108; + mode = "B"; + } else if (params->std & V4L2_STD_GH) { + priv->sgIF = 124; + mode = "GH"; + } else if (params->std & V4L2_STD_PAL_I) { + priv->sgIF = 124; + mode = "I"; + } else if (params->std & V4L2_STD_DK) { + priv->sgIF = 124; + mode = "DK"; + } else if (params->std & V4L2_STD_SECAM_L) { + priv->sgIF = 124; + mode = "L"; + } else if (params->std & V4L2_STD_SECAM_LC) { + priv->sgIF = 20; + mode = "LC"; + } else { + priv->sgIF = 124; + mode = "xx"; + } + + if (params->mode == V4L2_TUNER_RADIO) + priv->sgIF = 88; /* if frequency is 5.5 MHz */ + + dprintk("setting tda827x to system %s\n", mode); +} + + +/* ------------------------------------------------------------------ */ + struct tda827x_data { u32 lomax; u8 spd; @@ -189,10 +236,12 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 }; unsigned int freq = params->frequency; + tda827x_set_std(fe, params); + if (params->mode == V4L2_TUNER_RADIO) freq = freq / 1000; - N = freq + priv->cfg->sgIF; + N = freq + priv->sgIF; i = 0; while (tda827x_table[i].lomax < N * 62500) { @@ -207,7 +256,7 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, tuner_reg[1] = (unsigned char)(N>>8); tuner_reg[2] = (unsigned char) N; tuner_reg[3] = 0x40; - tuner_reg[4] = 0x52 + (priv->cfg->tda827x_lpsel << 5); + tuner_reg[4] = 0x52 + (priv->lpsel << 5); tuner_reg[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) + (tda827x_table[i].bs << 3) + tda827x_table[i].bp; @@ -550,13 +599,15 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, .buf = tuner_reg, .len = sizeof(tuner_reg) }; unsigned int freq = params->frequency; + tda827x_set_std(fe, params); + tda827xa_lna_gain(fe, 1, params); msleep(10); if (params->mode == V4L2_TUNER_RADIO) freq = freq / 1000; - N = freq + priv->cfg->sgIF; + N = freq + priv->sgIF; i = 0; while (tda827xa_analog[i].lomax < N * 62500) { @@ -587,7 +638,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, tuner_reg[1] = 0xff; tuner_reg[2] = 0xe0; tuner_reg[3] = 0; - tuner_reg[4] = 0x99 + (priv->cfg->tda827x_lpsel << 1); + tuner_reg[4] = 0x99 + (priv->lpsel << 1); msg.len = 5; i2c_transfer(priv->i2c_adap, &msg, 1); @@ -627,7 +678,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, i2c_transfer(priv->i2c_adap, &msg, 1); tuner_reg[0] = 0xc0; - tuner_reg[1] = 0x19 + (priv->cfg->tda827x_lpsel << 1); + tuner_reg[1] = 0x19 + (priv->lpsel << 1); i2c_transfer(priv->i2c_adap, &msg, 1); priv->frequency = freq * 62500; diff --git a/drivers/media/dvb/frontends/tda827x.h b/drivers/media/dvb/frontends/tda827x.h index 06626f7af61..92eb65b4012 100644 --- a/drivers/media/dvb/frontends/tda827x.h +++ b/drivers/media/dvb/frontends/tda827x.h @@ -35,9 +35,6 @@ struct tda827x_config int (*sleep) (struct dvb_frontend *fe); /* interface to tda829x driver */ - unsigned char tda827x_lpsel; - unsigned int sgIF; - unsigned int *config; int (*tuner_callback) (void *dev, int command, int arg); diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 288865c3c71..1b19b93eabe 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -104,45 +104,32 @@ static void set_audio(struct dvb_frontend *fe) struct tuner *t = priv->t; char* mode; - priv->cfg.tda827x_lpsel = 0; if (t->std & V4L2_STD_MN) { - priv->cfg.sgIF = 92; priv->tda8290_easy_mode = 0x01; - priv->cfg.tda827x_lpsel = 1; mode = "MN"; } else if (t->std & V4L2_STD_B) { - priv->cfg.sgIF = 108; priv->tda8290_easy_mode = 0x02; mode = "B"; } else if (t->std & V4L2_STD_GH) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x04; mode = "GH"; } else if (t->std & V4L2_STD_PAL_I) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x08; mode = "I"; } else if (t->std & V4L2_STD_DK) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "DK"; } else if (t->std & V4L2_STD_SECAM_L) { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x20; mode = "L"; } else if (t->std & V4L2_STD_SECAM_LC) { - priv->cfg.sgIF = 20; priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { - priv->cfg.sgIF = 124; priv->tda8290_easy_mode = 0x10; mode = "xx"; } - if (t->mode == V4L2_TUNER_RADIO) - priv->cfg.sgIF = 88; /* if frequency is 5.5 MHz */ - tuner_dbg("setting tda8290 to system %s\n", mode); } @@ -368,7 +355,6 @@ static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) { struct tda8290_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; - u16 ifc; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -381,9 +367,7 @@ static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) set_audio(fe); - ifc = priv->cfg.sgIF; /* FIXME */ - - tuner_dbg("%s: ifc = %u, freq = %d\n", __FUNCTION__, ifc, freq); + tuner_dbg("%s: freq = %d\n", __FUNCTION__, freq); tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); @@ -625,7 +609,6 @@ int tda8290_attach(struct tuner *t) tuner_info("type set to %s\n", t->i2c.name); - priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; tda8290_init_tuner(&t->fe); @@ -715,7 +698,6 @@ int tda8295_attach(struct tuner *t) t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; - priv->cfg.tda827x_lpsel = 0; t->mode = V4L2_TUNER_ANALOG_TV; tda8295_init_if(&t->fe); -- cgit v1.2.3-70-g09d2 From a72dd305f99f6c6e4eff01478ae53fc80ce98fb1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 24 Oct 2007 09:30:17 -0300 Subject: V4L/DVB (6448): tda8290: fill i2c_gate_ctrl callback Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 1b19b93eabe..5975c548b8a 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -50,14 +50,15 @@ struct tda8290_priv { /*---------------------------------------------------------------------*/ -static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) +static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char enable[2] = { 0x21, 0xC0 }; unsigned char disable[2] = { 0x21, 0x00 }; unsigned char *msg; - if(close) { + + if (close) { msg = enable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); /* let the bridge stabilize */ @@ -66,9 +67,11 @@ static void tda8290_i2c_bridge(struct dvb_frontend *fe, int close) msg = disable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); } + + return 0; } -static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) +static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) { struct tda8290_priv *priv = fe->analog_demod_priv; @@ -76,6 +79,7 @@ static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) unsigned char disable[2] = { 0x46, 0x00 }; unsigned char buf[3] = { 0x45, 0x01, 0x00 }; unsigned char *msg; + if (close) { msg = enable; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); @@ -94,6 +98,8 @@ static void tda8295_i2c_bridge(struct dvb_frontend *fe, int close) msg[1] |= 0x04; tuner_i2c_xfer_send(&priv->i2c_props, msg, 2); } + + return 0; } /*---------------------------------------------------------------------*/ @@ -517,6 +523,7 @@ static struct analog_tuner_ops tda8290_tuner_ops = { .has_signal = tda8290_has_signal, .standby = tda8290_standby, .release = tda829x_release, + .i2c_gate_ctrl = tda8290_i2c_bridge, }; static struct analog_tuner_ops tda8295_tuner_ops = { @@ -525,6 +532,7 @@ static struct analog_tuner_ops tda8295_tuner_ops = { .has_signal = tda8295_has_signal, .standby = tda8295_standby, .release = tda829x_release, + .i2c_gate_ctrl = tda8295_i2c_bridge, }; int tda8290_attach(struct tuner *t) -- cgit v1.2.3-70-g09d2 From 8c125f2ceb3ec1ba01e96fffd8558ef163b40fe8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 27 Oct 2007 02:00:57 -0300 Subject: V4L/DVB (6468): tda8290: auto-detect tda8290 or tda8295 Consolidate tda8290_attach() and tda8295_attach() into a single function, tda829x_attach(), which will detect chip combinations tda8290 or tda8295 with tda8275, tda8275a or tda18271. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 257 +++++++++++++++++++-------------------- drivers/media/video/tda8290.h | 12 +- drivers/media/video/tuner-core.c | 6 +- 3 files changed, 127 insertions(+), 148 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 5975c548b8a..ed22be0f594 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -41,7 +41,13 @@ struct tda8290_priv { unsigned char tda8290_easy_mode; unsigned char tda827x_addr; - unsigned char tda827x_ver; + + unsigned char ver; +#define TDA8290 1 +#define TDA8295 2 +#define TDA8275 4 +#define TDA8275A 8 +#define TDA18271 16 struct tda827x_config cfg; @@ -136,7 +142,7 @@ static void set_audio(struct dvb_frontend *fe) mode = "xx"; } - tuner_dbg("setting tda8290 to system %s\n", mode); + tuner_dbg("setting tda829x to system %s\n", mode); } static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) @@ -429,7 +435,7 @@ static void tda8290_standby(struct dvb_frontend *fe) struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2}; tda8290_i2c_bridge(fe, 1); - if (priv->tda827x_ver != 0) + if (priv->ver & TDA8275A) cb1[1] = 0x90; i2c_transfer(priv->i2c_props.adap, &msg, 1); tda8290_i2c_bridge(fe, 0); @@ -498,7 +504,7 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) 0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b }; struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=tda8275_init, .len = 14}; - if (priv->tda827x_ver != 0) + if (priv->ver & TDA8275A) msg.buf = tda8275a_init; tda8290_i2c_bridge(fe, 1); @@ -517,48 +523,25 @@ static void tda829x_release(struct dvb_frontend *fe) fe->analog_demod_priv = NULL; } -static struct analog_tuner_ops tda8290_tuner_ops = { - .set_tv_freq = tda8290_set_freq, - .set_radio_freq = tda8290_set_freq, - .has_signal = tda8290_has_signal, - .standby = tda8290_standby, - .release = tda829x_release, - .i2c_gate_ctrl = tda8290_i2c_bridge, -}; - -static struct analog_tuner_ops tda8295_tuner_ops = { - .set_tv_freq = tda8295_set_freq, - .set_radio_freq = tda8295_set_freq, - .has_signal = tda8295_has_signal, - .standby = tda8295_standby, - .release = tda829x_release, - .i2c_gate_ctrl = tda8295_i2c_bridge, -}; - -int tda8290_attach(struct tuner *t) +static int tda829x_find_tuner(struct dvb_frontend *fe) { - struct tda8290_priv *priv = NULL; - u8 data; + struct tda8290_priv *priv = fe->analog_demod_priv; + struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; + struct tuner *t = priv->t; int i, ret, tuners_found; u32 tuner_addrs; - struct i2c_msg msg = {.flags=I2C_M_RD, .buf=&data, .len = 1}; + u8 data; + struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; - priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - t->fe.analog_demod_priv = priv; + if (NULL == ops) + return -EINVAL; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; - priv->cfg.config = &t->config; - priv->cfg.tuner_callback = t->tuner_callback; - priv->t = t; + ops->i2c_gate_ctrl(fe, 1); - tda8290_i2c_bridge(&t->fe, 1); /* probe for tuner chip */ tuners_found = 0; tuner_addrs = 0; - for (i=0x60; i<= 0x63; i++) { + for (i = 0x60; i <= 0x63; i++) { msg.addr = i; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret == 1) { @@ -570,20 +553,23 @@ int tda8290_attach(struct tuner *t) behind the bridge and we choose the highest address that doesn't give a response now */ - tda8290_i2c_bridge(&t->fe, 0); - if(tuners_found > 1) + + ops->i2c_gate_ctrl(fe, 0); + + if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { msg.addr = tuner_addrs & 0xff; ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if(ret == 1) + if (ret == 1) tuner_addrs = tuner_addrs >> 8; else break; } + if (tuner_addrs == 0) { - tuner_addrs = 0x61; - tuner_info("could not clearly identify tuner address, defaulting to %x\n", - tuner_addrs); + tuner_addrs = 0x60; + tuner_info("could not clearly identify tuner address, " + "defaulting to %x\n", tuner_addrs); } else { tuner_addrs = tuner_addrs & 0xff; tuner_info("setting tuner address to %x\n", tuner_addrs); @@ -591,127 +577,132 @@ int tda8290_attach(struct tuner *t) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - tda8290_i2c_bridge(&t->fe, 1); - + ops->i2c_gate_ctrl(fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if( ret != 1) - tuner_warn("TDA827x access failed!\n"); - if ((data & 0x3c) == 0) { - strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); - priv->tda827x_ver = 0; - } else { - strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); - priv->tda827x_ver = 2; + if (ret != 1) { + tuner_warn("tuner access failed!\n"); + return -EREMOTEIO; } - tda827x_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap, &priv->cfg); - /* FIXME: tda827x module doesn't probe the tuner until - * tda827x_initial_sleep is called - */ - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); + if (data == 0x83) { + priv->ver |= TDA18271; + tda18271_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap); + } else { + if ((data & 0x3c) == 0) + priv->ver |= TDA8275; + else + priv->ver |= TDA8275A; - t->fe.ops.analog_demod_ops = &tda8290_tuner_ops; + tda827x_attach(&t->fe, priv->tda827x_addr, + priv->i2c_props.adap, &priv->cfg); - tuner_info("type set to %s\n", t->i2c.name); + /* FIXME: tda827x module doesn't probe the tuner until + * tda827x_initial_sleep is called + */ + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + } + ops->i2c_gate_ctrl(fe, 0); - t->mode = V4L2_TUNER_ANALOG_TV; + switch (priv->ver) { + case TDA8290 | TDA8275: + strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA8275: + strlcpy(t->i2c.name, "tda8295+75", sizeof(t->i2c.name)); + break; + case TDA8290 | TDA8275A: + strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA8275A: + strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + break; + case TDA8290 | TDA18271: + strlcpy(t->i2c.name, "tda8290+18271", sizeof(t->i2c.name)); + break; + case TDA8295 | TDA18271: + strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + break; + default: + return -EINVAL; + } - tda8290_init_tuner(&t->fe); - tda8290_init_if(&t->fe); return 0; } -EXPORT_SYMBOL_GPL(tda8290_attach); -int tda8295_attach(struct tuner *t) +static struct analog_tuner_ops tda8290_tuner_ops = { + .set_tv_freq = tda8290_set_freq, + .set_radio_freq = tda8290_set_freq, + .has_signal = tda8290_has_signal, + .standby = tda8290_standby, + .release = tda829x_release, + .i2c_gate_ctrl = tda8290_i2c_bridge, +}; + +static struct analog_tuner_ops tda8295_tuner_ops = { + .set_tv_freq = tda8295_set_freq, + .set_radio_freq = tda8295_set_freq, + .has_signal = tda8295_has_signal, + .standby = tda8295_standby, + .release = tda829x_release, + .i2c_gate_ctrl = tda8295_i2c_bridge, +}; + +int tda829x_attach(struct tuner *t) { + struct dvb_frontend *fe = &t->fe; struct tda8290_priv *priv = NULL; - u8 data; - int i, ret, tuners_found; - u32 tuner_addrs; - struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; + + unsigned char tda8290_id[] = { 0x1f, 0x00 }; +#define TDA8290_ID 0x89 + unsigned char tda8295_id[] = { 0x2f, 0x00 }; +#define TDA8295_ID 0x8a priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - t->fe.analog_demod_priv = priv; + fe->analog_demod_priv = priv; priv->i2c_props.addr = t->i2c.addr; priv->i2c_props.adap = t->i2c.adapter; + priv->cfg.config = &t->config; + priv->cfg.tuner_callback = t->tuner_callback; priv->t = t; - tda8295_i2c_bridge(&t->fe, 1); - /* probe for tuner chip */ - tuners_found = 0; - tuner_addrs = 0; - for (i = 0x60; i <= 0x63; i++) { - msg.addr = i; - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if (ret == 1) { - tuners_found++; - tuner_addrs = (tuner_addrs << 8) + i; - } + /* detect tda8290 */ + tuner_i2c_xfer_send(&priv->i2c_props, &tda8290_id[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &tda8290_id[1], 1); + if (tda8290_id[1] == TDA8290_ID) { + priv->ver = TDA8290; + fe->ops.analog_demod_ops = &tda8290_tuner_ops; } - /* if there is more than one tuner, we expect the right one is - behind the bridge and we choose the highest address that doesn't - give a response now - */ - tda8295_i2c_bridge(&t->fe, 0); - if (tuners_found > 1) - for (i = 0; i < tuners_found; i++) { - msg.addr = tuner_addrs & 0xff; - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - if (ret == 1) - tuner_addrs = tuner_addrs >> 8; - else - break; - } - if (tuner_addrs == 0) { - tuner_addrs = 0x60; - tuner_info("could not clearly identify tuner address, " - "defaulting to %x\n", tuner_addrs); - } else { - tuner_addrs = tuner_addrs & 0xff; - tuner_info("setting tuner address to %x\n", tuner_addrs); + + /* detect tda8295 */ + tuner_i2c_xfer_send(&priv->i2c_props, &tda8295_id[0], 1); + tuner_i2c_xfer_recv(&priv->i2c_props, &tda8295_id[1], 1); + if (tda8295_id[1] == TDA8295_ID) { + priv->ver = TDA8295; + fe->ops.analog_demod_ops = &tda8295_tuner_ops; } - priv->tda827x_addr = tuner_addrs; - msg.addr = tuner_addrs; - tda8295_i2c_bridge(&t->fe, 1); - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); - tda8295_i2c_bridge(&t->fe, 0); - if (ret != 1) - tuner_warn("TDA827x access failed!\n"); - if ((data & 0x3c) == 0) { - strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); - tda18271_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap); - priv->tda827x_ver = 4; - } else { - strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); - tda827x_attach(&t->fe, priv->tda827x_addr, - priv->i2c_props.adap, &priv->cfg); + if (tda829x_find_tuner(fe) < 0) + return -EINVAL; - /* FIXME: tda827x module doesn't probe the tuner until - * tda827x_initial_sleep is called - */ - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); - priv->tda827x_ver = 2; - } - priv->tda827x_ver |= 1; /* signifies 8295 vs 8290 */ - tuner_info("type set to %s\n", t->i2c.name); + if (priv->ver & TDA8290) { + tda8290_init_tuner(fe); + tda8290_init_if(fe); + } else if (priv->ver & TDA8295) + tda8295_init_if(fe); - t->fe.ops.analog_demod_ops = &tda8295_tuner_ops; + tuner_info("type set to %s\n", t->i2c.name); t->mode = V4L2_TUNER_ANALOG_TV; - tda8295_init_if(&t->fe); return 0; } -EXPORT_SYMBOL_GPL(tda8295_attach); +EXPORT_SYMBOL_GPL(tda829x_attach); int tda8290_probe(struct tuner *t) { @@ -745,7 +736,7 @@ int tda8290_probe(struct tuner *t) } EXPORT_SYMBOL_GPL(tda8290_probe); -MODULE_DESCRIPTION("Philips TDA8290 + TDA8275 / TDA8275a tuner driver"); +MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index dbbcb0f001e..81517370b8d 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -23,8 +23,7 @@ #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) extern int tda8290_probe(struct tuner *t); -extern int tda8290_attach(struct tuner *t); -extern int tda8295_attach(struct tuner *t); +extern int tda829x_attach(struct tuner *t); #else static inline int tda8290_probe(struct tuner *t) { @@ -32,14 +31,7 @@ static inline int tda8290_probe(struct tuner *t) return -EINVAL; } -static inline int tda8290_attach(struct tuner *t) -{ - printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", - __FUNCTION__); - return -EINVAL; -} - -static inline int tda8295_attach(struct tuner *t) +static inline int tda829x_attach(struct tuner *t) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", __FUNCTION__); diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 88db8b33c86..6ab57ec3f5a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -295,13 +295,9 @@ static void set_type(struct i2c_client *c, unsigned int type, microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); break; case TUNER_PHILIPS_TDA8290: - { - tda8290_attach(t); - break; - } case TUNER_PHILIPS_TDA8295: { - tda8295_attach(t); + tda829x_attach(t); break; } case TUNER_TEA5767: -- cgit v1.2.3-70-g09d2 From 1cba97d71dca1a3c22b4d7f97893249817036215 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 14 Sep 2007 05:13:54 -0300 Subject: V4L/DVB (6471): tuner: i2c_client cannot be part of the tuner struct The bus-based I2C subsystem allocates the i2c_client struct. So if in order to be able to convert the tuner to the bus-based I2C API the embedded i2c_client struct must be removed from the tuner struct and replaced with a pointer. Signed-off-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 22 ++++++++-------- drivers/media/video/tda9887.c | 22 ++++++++-------- drivers/media/video/tuner-core.c | 51 ++++++++++++++++++++++---------------- drivers/media/video/tuner-driver.h | 14 +++++------ 4 files changed, 59 insertions(+), 50 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index ed22be0f594..c7705cbab2f 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -608,22 +608,22 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) switch (priv->ver) { case TDA8290 | TDA8275: - strlcpy(t->i2c.name, "tda8290+75", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+75", sizeof(t->i2c->name)); break; case TDA8295 | TDA8275: - strlcpy(t->i2c.name, "tda8295+75", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+75", sizeof(t->i2c->name)); break; case TDA8290 | TDA8275A: - strlcpy(t->i2c.name, "tda8290+75a", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+75a", sizeof(t->i2c->name)); break; case TDA8295 | TDA8275A: - strlcpy(t->i2c.name, "tda8295+75a", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+75a", sizeof(t->i2c->name)); break; case TDA8290 | TDA18271: - strlcpy(t->i2c.name, "tda8290+18271", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8290+18271", sizeof(t->i2c->name)); break; case TDA8295 | TDA18271: - strlcpy(t->i2c.name, "tda8295+18271", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda8295+18271", sizeof(t->i2c->name)); break; default: return -EINVAL; @@ -665,8 +665,8 @@ int tda829x_attach(struct tuner *t) return -ENOMEM; fe->analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; + priv->i2c_props.addr = t->i2c->addr; + priv->i2c_props.adap = t->i2c->adapter; priv->cfg.config = &t->config; priv->cfg.tuner_callback = t->tuner_callback; priv->t = t; @@ -696,7 +696,7 @@ int tda829x_attach(struct tuner *t) } else if (priv->ver & TDA8295) tda8295_init_if(fe); - tuner_info("type set to %s\n", t->i2c.name); + tuner_info("type set to %s\n", t->i2c->name); t->mode = V4L2_TUNER_ANALOG_TV; @@ -707,8 +707,8 @@ EXPORT_SYMBOL_GPL(tda829x_attach); int tda8290_probe(struct tuner *t) { struct tuner_i2c_props i2c_props = { - .adap = t->i2c.adapter, - .addr = t->i2c.addr + .adap = t->i2c->adapter, + .addr = t->i2c->addr }; unsigned char soft_reset[] = { 0x00, 0x00 }; diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 080bd308073..dfa2964d7ef 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -24,14 +24,14 @@ static int tda9887_debug; module_param_named(debug, tda9887_debug, int, 0644); #define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), \ - priv->t->i2c.addr, ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ + i2c_adapter_id(priv->t->i2c->adapter), \ + priv->t->i2c->addr, ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (tda9887_debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c.name, \ - i2c_adapter_id(priv->t->i2c.adapter), \ - priv->t->i2c.addr, ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, priv->t->i2c->name, \ + i2c_adapter_id(priv->t->i2c->adapter), \ + priv->t->i2c->addr, ##arg); } while (0) struct tda9887_priv { struct tuner_i2c_props i2c_props; @@ -651,14 +651,14 @@ int tda9887_attach(struct tuner *t) return -ENOMEM; t->fe.analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c.addr; - priv->i2c_props.adap = t->i2c.adapter; + priv->i2c_props.addr = t->i2c->addr; + priv->i2c_props.adap = t->i2c->adapter; priv->t = t; - strlcpy(t->i2c.name, "tda9887", sizeof(t->i2c.name)); + strlcpy(t->i2c->name, "tda9887", sizeof(t->i2c->name)); - tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, - t->i2c.driver->driver.name); + tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c->addr, + t->i2c->driver->driver.name); t->fe.ops.analog_demod_ops = &tda9887_tuner_ops; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index bff6e6a3e26..41ff4d2604a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -226,20 +226,20 @@ static void set_freq(struct i2c_client *c, unsigned long freq) static void tuner_i2c_address_check(struct tuner *t) { if ((t->type == UNSET || t->type == TUNER_ABSENT) || - ((t->i2c.addr < 0x64) || (t->i2c.addr > 0x6f))) + ((t->i2c->addr < 0x64) || (t->i2c->addr > 0x6f))) return; tuner_warn("====================== WARNING! ======================\n"); tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); tuner_warn("will soon be dropped. This message indicates that your\n"); tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", - t->i2c.name, t->i2c.addr); + t->i2c->name, t->i2c->addr); tuner_warn("To ensure continued support for your device, please\n"); tuner_warn("send a copy of this message, along with full dmesg\n"); tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", - t->i2c.adapter->name, t->i2c.addr, t->type, + t->i2c->adapter->name, t->i2c->addr, t->type, tuners[t->type].name); tuner_warn("====================== WARNING! ======================\n"); } @@ -250,7 +250,7 @@ static void attach_simple_tuner(struct tuner *t) .type = t->type, .tun = &tuners[t->type] }; - simple_tuner_attach(&t->fe, t->i2c.adapter, t->i2c.addr, &cfg); + simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); } static void set_type(struct i2c_client *c, unsigned int type, @@ -292,7 +292,7 @@ static void set_type(struct i2c_client *c, unsigned int type, switch (t->type) { case TUNER_MT2032: - microtune_attach(&t->fe, t->i2c.adapter, t->i2c.addr); + microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr); break; case TUNER_PHILIPS_TDA8290: { @@ -300,7 +300,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TEA5767: - if (tea5767_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { + if (tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) { t->type = TUNER_ABSENT; t->mode_mask = T_UNINITIALIZED; return; @@ -308,7 +308,7 @@ static void set_type(struct i2c_client *c, unsigned int type, t->mode_mask = T_RADIO; break; case TUNER_TEA5761: - if (tea5761_attach(&t->fe, t->i2c.adapter, t->i2c.addr) == NULL) { + if (tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr) == NULL) { t->type = TUNER_ABSENT; t->mode_mask = T_UNINITIALIZED; return; @@ -348,13 +348,14 @@ static void set_type(struct i2c_client *c, unsigned int type, if (((NULL == ops) || ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && (fe_tuner_ops->set_analog_params)) { - strlcpy(t->i2c.name, fe_tuner_ops->info.name, sizeof(t->i2c.name)); + strlcpy(t->i2c->name, fe_tuner_ops->info.name, + sizeof(t->i2c->name)); t->fe.ops.analog_demod_ops = &tuner_core_ops; t->fe.analog_demod_priv = t; } - tuner_info("type set to %s\n", t->i2c.name); + tuner_info("type set to %s\n", t->i2c->name); if (t->mode_mask == T_UNINITIALIZED) t->mode_mask = new_mode_mask; @@ -579,16 +580,23 @@ static unsigned default_mode_mask; */ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) { + struct i2c_client *client; struct tuner *t; - client_template.adapter = adap; - client_template.addr = addr; + client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (NULL == client) + return -ENOMEM; t = kzalloc(sizeof(struct tuner), GFP_KERNEL); - if (NULL == t) + if (NULL == t) { + kfree(client); return -ENOMEM; - memcpy(&t->i2c, &client_template, sizeof(struct i2c_client)); - i2c_set_clientdata(&t->i2c, t); + } + t->i2c = client; + client_template.adapter = adap; + client_template.addr = addr; + memcpy(client, &client_template, sizeof(struct i2c_client)); + i2c_set_clientdata(client, t); t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; @@ -598,7 +606,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) int i,rc; memset(buffer, 0, sizeof(buffer)); - rc = i2c_master_recv(&t->i2c, buffer, sizeof(buffer)); + rc = i2c_master_recv(client, buffer, sizeof(buffer)); tuner_info("I2C RECV = "); for (i=0;ii2c.adapter, t->i2c.addr) != EINVAL) { + if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { t->type = TUNER_TEA5761; t->mode_mask = T_RADIO; t->mode = T_STANDBY; @@ -639,7 +647,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) } break; case 0x60: - if (tea5767_autodetection(t->i2c.adapter, t->i2c.addr) != EINVAL) { + if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { t->type = TUNER_TEA5767; t->mode_mask = T_RADIO; t->mode = T_STANDBY; @@ -664,8 +672,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* Should be just before return */ register_client: tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); - i2c_attach_client (&t->i2c); - set_type (&t->i2c,t->type, t->mode_mask, t->config, t->tuner_callback); + i2c_attach_client (client); + set_type (client,t->type, t->mode_mask, t->config, t->tuner_callback); return 0; } @@ -711,7 +719,7 @@ static int tuner_detach(struct i2c_client *client) struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; int err; - err = i2c_detach_client(&t->i2c); + err = i2c_detach_client(t->i2c); if (err) { tuner_warn ("Client deregistration failed, client not detached.\n"); @@ -722,6 +730,7 @@ static int tuner_detach(struct i2c_client *client) ops->release(&t->fe); kfree(t); + kfree(client); return 0; } @@ -770,7 +779,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; if (tuner_debug>1) - v4l_i2c_print_ioctl(&(t->i2c),cmd); + v4l_i2c_print_ioctl(client,cmd); switch (cmd) { /* --- configuration --- */ diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 728cacd2168..0df136e58eb 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -45,7 +45,7 @@ struct analog_tuner_ops { struct tuner { /* device */ - struct i2c_client i2c; + struct i2c_client *i2c; unsigned int type; /* chip type */ @@ -71,16 +71,16 @@ struct tuner { /* ------------------------------------------------------------------------ */ #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ extern int tuner_debug; \ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \ - i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c->driver->driver.name, \ + i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #endif /* __TUNER_DRIVER_H__ */ -- cgit v1.2.3-70-g09d2 From f1f32849d65ab1eacfedbabb624876ac06c1af9f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 3 Nov 2007 22:14:54 -0300 Subject: V4L/DVB (6543): tda8290: enable probing of tda8295 Prevent the tda8295 from falsely being detected as a tda9887 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 64 ++++++++++++++++++++++++++++++---------- drivers/media/video/tda8290.h | 4 +-- drivers/media/video/tuner-core.c | 4 +-- 3 files changed, 53 insertions(+), 19 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index c7705cbab2f..dd239965465 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -632,6 +632,46 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) return 0; } +static int tda8290_probe(struct tuner_i2c_props *i2c_props) +{ +#define TDA8290_ID 0x89 + unsigned char tda8290_id[] = { 0x1f, 0x00 }; + + /* detect tda8290 */ + tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); + tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); + + if (tda8290_id[1] == TDA8290_ID) { + if (tuner_debug) + printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", + __FUNCTION__, i2c_adapter_id(i2c_props->adap), + i2c_props->addr); + return 0; + } + + return -1; +} + +static int tda8295_probe(struct tuner_i2c_props *i2c_props) +{ +#define TDA8295_ID 0x8a + unsigned char tda8295_id[] = { 0x2f, 0x00 }; + + /* detect tda8295 */ + tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); + tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); + + if (tda8295_id[1] == TDA8295_ID) { + if (tuner_debug) + printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", + __FUNCTION__, i2c_adapter_id(i2c_props->adap), + i2c_props->addr); + return 0; + } + + return -1; +} + static struct analog_tuner_ops tda8290_tuner_ops = { .set_tv_freq = tda8290_set_freq, .set_radio_freq = tda8290_set_freq, @@ -655,11 +695,6 @@ int tda829x_attach(struct tuner *t) struct dvb_frontend *fe = &t->fe; struct tda8290_priv *priv = NULL; - unsigned char tda8290_id[] = { 0x1f, 0x00 }; -#define TDA8290_ID 0x89 - unsigned char tda8295_id[] = { 0x2f, 0x00 }; -#define TDA8295_ID 0x8a - priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; @@ -671,18 +706,12 @@ int tda829x_attach(struct tuner *t) priv->cfg.tuner_callback = t->tuner_callback; priv->t = t; - /* detect tda8290 */ - tuner_i2c_xfer_send(&priv->i2c_props, &tda8290_id[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &tda8290_id[1], 1); - if (tda8290_id[1] == TDA8290_ID) { + if (tda8290_probe(&priv->i2c_props) == 0) { priv->ver = TDA8290; fe->ops.analog_demod_ops = &tda8290_tuner_ops; } - /* detect tda8295 */ - tuner_i2c_xfer_send(&priv->i2c_props, &tda8295_id[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &tda8295_id[1], 1); - if (tda8295_id[1] == TDA8295_ID) { + if (tda8295_probe(&priv->i2c_props) == 0) { priv->ver = TDA8295; fe->ops.analog_demod_ops = &tda8295_tuner_ops; } @@ -704,7 +733,7 @@ int tda829x_attach(struct tuner *t) } EXPORT_SYMBOL_GPL(tda829x_attach); -int tda8290_probe(struct tuner *t) +int tda829x_probe(struct tuner *t) { struct tuner_i2c_props i2c_props = { .adap = t->i2c->adapter, @@ -718,6 +747,11 @@ int tda8290_probe(struct tuner *t) unsigned char addr_dto_lsb = 0x07; unsigned char data; + if ((tda8290_probe(&i2c_props) == 0) || + (tda8295_probe(&i2c_props) == 0)) + return 0; + + /* fall back to old probing method */ tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); @@ -734,7 +768,7 @@ int tda8290_probe(struct tuner *t) tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); return -1; } -EXPORT_SYMBOL_GPL(tda8290_probe); +EXPORT_SYMBOL_GPL(tda829x_probe); MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver"); MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky"); diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index 81517370b8d..3a1f0452061 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -21,11 +21,11 @@ #include "tuner-driver.h" #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) -extern int tda8290_probe(struct tuner *t); +extern int tda829x_probe(struct tuner *t); extern int tda829x_attach(struct tuner *t); #else -static inline int tda8290_probe(struct tuner *t) +static inline int tda829x_probe(struct tuner *t) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return -EINVAL; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 17c873c869a..3ec50dbed74 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -649,8 +649,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) case 0x4b: /* If chip is not tda8290, don't register. since it can be tda9887*/ - if (tda8290_probe(t) == 0) { - tuner_dbg("chip at addr %x is a tda8290\n", addr); + if (tda829x_probe(t) == 0) { + tuner_dbg("tda829x detected\n"); } else { /* Default is being tda9887 */ t->type = TUNER_TDA9887; -- cgit v1.2.3-70-g09d2 From 1f3a4e328549cb85aa032c4ee5dfda7886754154 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 Nov 2007 10:51:28 -0300 Subject: V4L/DVB (6550): tda8290: return -ENODEV on probe failures Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index dd239965465..18e6a09642f 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -649,7 +649,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) return 0; } - return -1; + return -ENODEV; } static int tda8295_probe(struct tuner_i2c_props *i2c_props) @@ -669,7 +669,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) return 0; } - return -1; + return -ENODEV; } static struct analog_tuner_ops tda8290_tuner_ops = { @@ -766,7 +766,7 @@ int tda829x_probe(struct tuner *t) } } tuner_i2c_xfer_send(&i2c_props, restore_9886, 3); - return -1; + return -ENODEV; } EXPORT_SYMBOL_GPL(tda829x_probe); -- cgit v1.2.3-70-g09d2 From a818e1c8f7fcb42866a8630c508caddaa8edb331 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 Nov 2007 11:03:22 -0300 Subject: V4L/DVB (6551): tda8290: rule out tda988x before detecting tda8290/tda8295 To ensure prevention of detecting a tda9885/6/7 as a tda8290 or tda8295, we will rule out the tda988x before testing the tda8290 / tda8295 id registers. We read 8 bytes from the chip. If they are all equal, then it is not a tda829x, or some other error has occurred. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 18e6a09642f..f0191babe40 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -746,6 +746,22 @@ int tda829x_probe(struct tuner *t) unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; unsigned char addr_dto_lsb = 0x07; unsigned char data; +#define PROBE_BUFFER_SIZE 8 + unsigned char buf[PROBE_BUFFER_SIZE]; + int i; + + /* rule out tda9887, which would return the same byte repeatedly */ + tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); + tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); + for (i = 1; i < PROBE_BUFFER_SIZE; i++) { + if (buf[i] == buf[0]) + continue; + break; + } + + /* all bytes are equal, not a tda829x - probably a tda9887 */ + if (i == PROBE_BUFFER_SIZE) + return -ENODEV; if ((tda8290_probe(&i2c_props) == 0) || (tda8295_probe(&i2c_props) == 0)) -- cgit v1.2.3-70-g09d2 From 9dd659de9fbd1687c6175053c6453db5b932f152 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 4 Nov 2007 11:03:36 -0300 Subject: V4L/DVB (6556): tuner: convert to bus-based I2C API Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt20xx.c | 2 +- drivers/media/video/tda8290.c | 2 +- drivers/media/video/tea5761.c | 2 +- drivers/media/video/tea5767.c | 2 +- drivers/media/video/tuner-core.c | 99 ++++++++++++-------------------------- drivers/media/video/tuner-driver.h | 6 +-- drivers/media/video/tuner-i2c.h | 6 +-- drivers/media/video/tuner-simple.c | 2 +- drivers/media/video/tuner-xc2028.c | 2 +- 9 files changed, 44 insertions(+), 79 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index f49d1f4c40d..b630c26cfe8 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -14,7 +14,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "mt20xx " +#define PREFIX "mt20xx" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index f0191babe40..a849ded0000 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -31,7 +31,7 @@ static int tuner_debug; module_param_named(debug, tuner_debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tda8290 " +#define PREFIX "tda8290" /* ---------------------------------------------------------------------- */ diff --git a/drivers/media/video/tea5761.c b/drivers/media/video/tea5761.c index 2150222a386..5326eeceaac 100644 --- a/drivers/media/video/tea5761.c +++ b/drivers/media/video/tea5761.c @@ -18,7 +18,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5761 " +#define PREFIX "tea5761" struct tea5761_priv { struct tuner_i2c_props i2c_props; diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 2d2acbdd24a..2f5a99de185 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -20,7 +20,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tea5767 " +#define PREFIX "tea5767" /*****************************************************************************/ diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 48b2d46048a..1b0d28a0ca7 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "tuner-driver.h" #include "mt20xx.h" #include "tda8290.h" @@ -30,7 +31,7 @@ #define UNSET (-1U) -#define PREFIX "tuner " +#define PREFIX t->i2c->driver->driver.name /* standard i2c insmod options */ static unsigned short normal_i2c[] = { @@ -75,9 +76,6 @@ MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); MODULE_LICENSE("GPL"); -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ---------------------------------------------------------------------- */ static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) @@ -919,18 +917,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) static int tuner_suspend(struct i2c_client *c, pm_message_t state) { - struct tuner *t = i2c_get_clientdata (c); + struct tuner *t = i2c_get_clientdata(c); - tuner_dbg ("suspend\n"); + tuner_dbg("suspend\n"); /* FIXME: power down ??? */ return 0; } static int tuner_resume(struct i2c_client *c) { - struct tuner *t = i2c_get_clientdata (c); + struct tuner *t = i2c_get_clientdata(c); - tuner_dbg ("resume\n"); + tuner_dbg("resume\n"); if (V4L2_TUNER_RADIO == t->mode) { if (t->radio_freq) set_freq(c, t->radio_freq); @@ -946,7 +944,7 @@ static int tuner_resume(struct i2c_client *c) LIST_HEAD(tuner_list); /* Search for existing radio and/or TV tuners on the given I2C adapter. - Note that when this function is called from tuner_attach you can be + Note that when this function is called from tuner_probe you can be certain no other devices will be added/deleted at the same time, I2C core protects against that. */ static void tuner_lookup(struct i2c_adapter *adap, @@ -977,28 +975,19 @@ static void tuner_lookup(struct i2c_adapter *adap, } /* During client attach, set_type is called by adapter's attach_inform callback. - set_type must then be completed by tuner_attach. + set_type must then be completed by tuner_probe. */ -static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) +static int tuner_probe(struct i2c_client *client) { - struct i2c_client *client; struct tuner *t; struct tuner *radio; struct tuner *tv; - client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (NULL == client) - return -ENOMEM; - t = kzalloc(sizeof(struct tuner), GFP_KERNEL); - if (NULL == t) { - kfree(client); + if (NULL == t) return -ENOMEM; - } t->i2c = client; - client_template.adapter = adap; - client_template.addr = addr; - memcpy(client, &client_template, sizeof(struct i2c_client)); + strlcpy(client->name, "(tuner unset)", sizeof(client->name)); i2c_set_clientdata(client, t); t->type = UNSET; t->audmode = V4L2_TUNER_MODE_STEREO; @@ -1015,14 +1004,16 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) printk(KERN_CONT "%02x ", buffer[i]); printk("\n"); } - /* HACK: This test were added to avoid tuner to probe tda9840 and + /* HACK: This test was added to avoid tuner to probe tda9840 and tea6415c on the MXB card */ - if (adap->id == I2C_HW_SAA7146 && addr < 0x4a) + if (client->adapter->id == I2C_HW_SAA7146 && client->addr < 0x4a) { + kfree(t); return -ENODEV; + } /* autodetection code based on the i2c addr */ if (!no_autodetect) { - switch (addr) { + switch (client->addr) { case 0x10: if (tea5761_autodetection(t->i2c->adapter, t->i2c->addr) != EINVAL) { @@ -1092,7 +1083,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) /* Should be just before return */ register_client: - tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name); + tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1, + client->adapter->name); /* Sets a default mode */ if (t->mode_mask & T_ANALOG_TV) { @@ -1102,19 +1094,21 @@ register_client: } else { t->mode = T_DIGITAL_TV; } - - i2c_attach_client(client); set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); + list_add_tail(&t->list, &tuner_list); return 0; } -static int tuner_probe(struct i2c_adapter *adap) +static int tuner_legacy_probe(struct i2c_adapter *adap) { if (0 != addr) { normal_i2c[0] = addr; normal_i2c[1] = I2C_CLIENT_END; } + if ((adap->class & I2C_CLASS_TV_ANALOG) == 0) + return 0; + /* HACK: Ignore 0x6b and 0x6f on cx88 boards. * FusionHDTV5 RT Gold has an ir receiver at 0x6b * and an RTC at 0x6f which can get corrupted if probed. @@ -1136,64 +1130,35 @@ static int tuner_probe(struct i2c_adapter *adap) "too many options specified " "in i2c probe ignore list!\n"); } - - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, tuner_attach); - return 0; + return 1; } -static int tuner_detach(struct i2c_client *client) +static int tuner_remove(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; - int err; - - err = i2c_detach_client(t->i2c); - if (err) { - tuner_warn - ("Client deregistration failed, client not detached.\n"); - return err; - } if (ops && ops->release) ops->release(&t->fe); list_del(&t->list); kfree(t); - kfree(client); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .id = I2C_DRIVERID_TUNER, - .attach_adapter = tuner_probe, - .detach_client = tuner_detach, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "tuner", + .driverid = I2C_DRIVERID_TUNER, .command = tuner_command, + .probe = tuner_probe, + .remove = tuner_remove, .suspend = tuner_suspend, - .resume = tuner_resume, - .driver = { - .name = "tuner", - }, + .resume = tuner_resume, + .legacy_probe = tuner_legacy_probe, }; -static struct i2c_client client_template = { - .name = "(tuner unset)", - .driver = &driver, -}; - -static int __init tuner_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit tuner_cleanup_module(void) -{ - i2c_del_driver(&driver); -} -module_init(tuner_init_module); -module_exit(tuner_cleanup_module); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 3ff2943ecc1..d6e5afdaa82 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -72,15 +72,15 @@ struct tuner { /* ------------------------------------------------------------------------ */ #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \ + printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO PREFIX "%d-%04x: " fmt, \ + printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ extern int tuner_debug; \ if (tuner_debug) \ - printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); } while (0) #endif /* __TUNER_DRIVER_H__ */ diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index 159019ec337..cfba3d10906 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -48,14 +48,14 @@ static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, #ifndef __TUNER_DRIVER_H__ #define tuner_warn(fmt, arg...) do {\ - printk(KERN_WARNING PREFIX "%d-%04x: " fmt, \ + printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ - printk(KERN_INFO PREFIX "%d-%04x: " fmt, \ + printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ if ((debug)) \ - printk(KERN_DEBUG PREFIX "%d-%04x: " fmt, \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr , ##arg); } while (0) #endif /* __TUNER_DRIVER_H__ */ diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index eec13cb6cd6..c1db576696c 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -17,7 +17,7 @@ static int debug = 0; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -#define PREFIX "tuner-simple " +#define PREFIX "tuner-simple" static int offset = 0; module_param(offset, int, 0664); diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 473fa73b181..80d14020c78 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -22,7 +22,7 @@ #include #include "dvb_frontend.h" -#define PREFIX "xc2028 " +#define PREFIX "xc2028" static LIST_HEAD(xc2028_list); /* struct for storing firmware table */ -- cgit v1.2.3-70-g09d2 From bbe1e0ba527a18e1ddda2eabb9da369e5bcf556e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 5 Nov 2007 09:54:42 -0300 Subject: V4L/DVB (6563): tda8290: optimize for loop in tda829x_probe function Thanks to Trent Piepho for pointing this out. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index a849ded0000..c606f3c38cf 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -754,9 +754,8 @@ int tda829x_probe(struct tuner *t) tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); for (i = 1; i < PROBE_BUFFER_SIZE; i++) { - if (buf[i] == buf[0]) - continue; - break; + if (buf[i] != buf[0]) + break; } /* all bytes are equal, not a tda829x - probably a tda9887 */ -- cgit v1.2.3-70-g09d2 From 63c254805e38bad4c64b5f5b0e135a2a357fa0bf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 23 Nov 2007 15:08:11 -0300 Subject: V4L/DVB (6679): tda8290: force tuner init after attach Force tuner init after attach, then sleep until use. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index c606f3c38cf..09efb6a60db 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -597,13 +597,13 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) tda827x_attach(&t->fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); - - /* FIXME: tda827x module doesn't probe the tuner until - * tda827x_initial_sleep is called - */ - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); } + if (t->fe.ops.tuner_ops.init) + t->fe.ops.tuner_ops.init(&t->fe); + + if (t->fe.ops.tuner_ops.sleep) + t->fe.ops.tuner_ops.sleep(&t->fe); + ops->i2c_gate_ctrl(fe, 0); switch (priv->ver) { -- cgit v1.2.3-70-g09d2 From 6881647cce09931f3d787ab83b5250436427ceb9 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 8 Dec 2007 16:25:41 -0300 Subject: V4L/DVB (6782): tda8290: access frontend structure directly, where possible Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 09efb6a60db..d5517bcf6ff 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -587,7 +587,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) if (data == 0x83) { priv->ver |= TDA18271; - tda18271_attach(&t->fe, priv->tda827x_addr, + tda18271_attach(fe, priv->tda827x_addr, priv->i2c_props.adap); } else { if ((data & 0x3c) == 0) @@ -595,14 +595,14 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) else priv->ver |= TDA8275A; - tda827x_attach(&t->fe, priv->tda827x_addr, + tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg); } - if (t->fe.ops.tuner_ops.init) - t->fe.ops.tuner_ops.init(&t->fe); + if (fe->ops.tuner_ops.init) + fe->ops.tuner_ops.init(fe); - if (t->fe.ops.tuner_ops.sleep) - t->fe.ops.tuner_ops.sleep(&t->fe); + if (fe->ops.tuner_ops.sleep) + fe->ops.tuner_ops.sleep(fe); ops->i2c_gate_ctrl(fe, 0); -- cgit v1.2.3-70-g09d2 From c7919d520f4c9a064ae14bc4dd170c4c12ead2af Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 8 Dec 2007 17:06:30 -0300 Subject: V4L/DVB (6783): tuner: combine set_tv_freq and set_radio_freq into a single set_params method We can tell whether we are tuning television or radio by testing for struct analog_parameters *params->mode == V4L2_TUNER_RADIO There is no longer any need for separate set_tv_freq and set_radio_freq functions in the analog tuner demodulator modules. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 53 ++++++++++++++------------------------ drivers/media/video/tda9887.c | 6 ++--- drivers/media/video/tuner-core.c | 41 +++++++++++++++++------------ drivers/media/video/tuner-driver.h | 4 +-- 4 files changed, 49 insertions(+), 55 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index d5517bcf6ff..245b202560b 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -110,31 +110,32 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) /*---------------------------------------------------------------------*/ -static void set_audio(struct dvb_frontend *fe) +static void set_audio(struct dvb_frontend *fe, + struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; char* mode; - if (t->std & V4L2_STD_MN) { + if (params->std & V4L2_STD_MN) { priv->tda8290_easy_mode = 0x01; mode = "MN"; - } else if (t->std & V4L2_STD_B) { + } else if (params->std & V4L2_STD_B) { priv->tda8290_easy_mode = 0x02; mode = "B"; - } else if (t->std & V4L2_STD_GH) { + } else if (params->std & V4L2_STD_GH) { priv->tda8290_easy_mode = 0x04; mode = "GH"; - } else if (t->std & V4L2_STD_PAL_I) { + } else if (params->std & V4L2_STD_PAL_I) { priv->tda8290_easy_mode = 0x08; mode = "I"; - } else if (t->std & V4L2_STD_DK) { + } else if (params->std & V4L2_STD_DK) { priv->tda8290_easy_mode = 0x10; mode = "DK"; - } else if (t->std & V4L2_STD_SECAM_L) { + } else if (params->std & V4L2_STD_SECAM_L) { priv->tda8290_easy_mode = 0x20; mode = "L"; - } else if (t->std & V4L2_STD_SECAM_LC) { + } else if (params->std & V4L2_STD_SECAM_LC) { priv->tda8290_easy_mode = 0x40; mode = "LC"; } else { @@ -145,7 +146,8 @@ static void set_audio(struct dvb_frontend *fe) tuner_dbg("setting tda829x to system %s\n", mode); } -static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) +static void tda8290_set_params(struct dvb_frontend *fe, + struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; @@ -172,14 +174,7 @@ static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) pll_stat; int i; - struct analog_parameters params = { - .frequency = freq, - .mode = t->mode, - .audmode = t->audmode, - .std = t->std - }; - - set_audio(fe); + set_audio(fe, params); tuner_dbg("tda827xa config is 0x%02x\n", t->config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); @@ -200,7 +195,7 @@ static void tda8290_set_freq(struct dvb_frontend *fe, unsigned int freq) tda8290_i2c_bridge(fe, 1); if (fe->ops.tuner_ops.set_analog_params) - fe->ops.tuner_ops.set_analog_params(fe, ¶ms); + fe->ops.tuner_ops.set_analog_params(fe, params); for (i = 0; i < 3; i++) { tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); @@ -363,23 +358,17 @@ static int tda8295_has_signal(struct dvb_frontend *fe) /*---------------------------------------------------------------------*/ -static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) +static void tda8295_set_params(struct dvb_frontend *fe, + struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; struct tuner *t = priv->t; unsigned char blanking_mode[] = { 0x1d, 0x00 }; - struct analog_parameters params = { - .frequency = freq, - .mode = t->mode, - .audmode = t->audmode, - .std = t->std - }; - - set_audio(fe); + set_audio(fe, params); - tuner_dbg("%s: freq = %d\n", __FUNCTION__, freq); + tuner_dbg("%s: freq = %d\n", __FUNCTION__, params->frequency); tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); @@ -396,7 +385,7 @@ static void tda8295_set_freq(struct dvb_frontend *fe, unsigned int freq) tda8295_i2c_bridge(fe, 1); if (fe->ops.tuner_ops.set_analog_params) - fe->ops.tuner_ops.set_analog_params(fe, ¶ms); + fe->ops.tuner_ops.set_analog_params(fe, params); if (priv->cfg.agcf) priv->cfg.agcf(fe); @@ -673,8 +662,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) } static struct analog_tuner_ops tda8290_tuner_ops = { - .set_tv_freq = tda8290_set_freq, - .set_radio_freq = tda8290_set_freq, + .set_params = tda8290_set_params, .has_signal = tda8290_has_signal, .standby = tda8290_standby, .release = tda829x_release, @@ -682,8 +670,7 @@ static struct analog_tuner_ops tda8290_tuner_ops = { }; static struct analog_tuner_ops tda8295_tuner_ops = { - .set_tv_freq = tda8295_set_freq, - .set_radio_freq = tda8295_set_freq, + .set_params = tda8295_set_params, .has_signal = tda8295_has_signal, .standby = tda8295_standby, .release = tda829x_release, diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index dfa2964d7ef..d506d4bf825 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -622,7 +622,8 @@ static void tda9887_standby(struct dvb_frontend *fe) tda9887_configure(fe); } -static void tda9887_set_freq(struct dvb_frontend *fe, unsigned int freq) +static void tda9887_set_params(struct dvb_frontend *fe, + struct analog_parameters *params) { tda9887_configure(fe); } @@ -634,8 +635,7 @@ static void tda9887_release(struct dvb_frontend *fe) } static struct analog_tuner_ops tda9887_tuner_ops = { - .set_tv_freq = tda9887_set_freq, - .set_radio_freq = tda9887_set_freq, + .set_params = tda9887_set_params, .standby = tda9887_standby, .tuner_status = tda9887_tuner_status, .get_afc = tda9887_get_afc, diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e56a4194148..5f8bffc8209 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -78,23 +78,17 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ -static void fe_set_freq(struct dvb_frontend *fe, unsigned int freq) +static void fe_set_params(struct dvb_frontend *fe, + struct analog_parameters *params) { struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; struct tuner *t = fe->analog_demod_priv; - struct analog_parameters params = { - .frequency = freq, - .mode = t->mode, - .audmode = t->audmode, - .std = t->std - }; - if (NULL == fe_tuner_ops->set_analog_params) { tuner_warn("Tuner frontend module has no way to set freq\n"); return; } - fe_tuner_ops->set_analog_params(fe, ¶ms); + fe_tuner_ops->set_analog_params(fe, params); } static void fe_release(struct dvb_frontend *fe) @@ -136,8 +130,7 @@ static int fe_has_signal(struct dvb_frontend *fe) static void tuner_status(struct dvb_frontend *fe); static struct analog_tuner_ops tuner_core_ops = { - .set_tv_freq = fe_set_freq, - .set_radio_freq = fe_set_freq, + .set_params = fe_set_params, .standby = fe_standby, .release = fe_release, .has_signal = fe_has_signal, @@ -150,11 +143,17 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_parameters params = { + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if ((NULL == ops) || (NULL == ops->set_tv_freq)) { + if ((NULL == ops) || (NULL == ops->set_params)) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -169,7 +168,9 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) else freq = tv_range[1] * 16; } - ops->set_tv_freq(&t->fe, freq); + params.frequency = freq; + + ops->set_params(&t->fe, ¶ms); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) @@ -177,11 +178,17 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) struct tuner *t = i2c_get_clientdata(c); struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_parameters params = { + .mode = t->mode, + .audmode = t->audmode, + .std = t->std + }; + if (t->type == UNSET) { tuner_warn ("tuner type not set\n"); return; } - if ((NULL == ops) || (NULL == ops->set_radio_freq)) { + if ((NULL == ops) || (NULL == ops->set_params)) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } @@ -196,8 +203,9 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) else freq = radio_range[1] * 16000; } + params.frequency = freq; - ops->set_radio_freq(&t->fe, freq); + ops->set_params(&t->fe, ¶ms); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -359,8 +367,7 @@ static void set_type(struct i2c_client *c, unsigned int type, ops = t->fe.ops.analog_demod_ops; - if (((NULL == ops) || - ((NULL == ops->set_tv_freq) && (NULL == ops->set_radio_freq))) && + if (((NULL == ops) || (NULL == ops->set_params)) && (fe_tuner_ops->set_analog_params)) { strlcpy(t->i2c->name, fe_tuner_ops->info.name, sizeof(t->i2c->name)); diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index a4db32d97a1..91913ee08a0 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -32,8 +32,8 @@ extern unsigned const int tuner_count; struct tuner; struct analog_tuner_ops { - void (*set_tv_freq)(struct dvb_frontend *fe, unsigned int freq); - void (*set_radio_freq)(struct dvb_frontend *fe, unsigned int freq); + void (*set_params)(struct dvb_frontend *fe, + struct analog_parameters *params); int (*has_signal)(struct dvb_frontend *fe); int (*is_stereo)(struct dvb_frontend *fe); int (*get_afc)(struct dvb_frontend *fe); -- cgit v1.2.3-70-g09d2 From fa746aee336fedfe25e6945e5967399966948420 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 9 Dec 2007 05:16:10 -0300 Subject: V4L/DVB (6784): tda8290: prevent possible memory leak Always call tda829x_release if tda829x_attach fails for a reason other than failure to allocate memory for private structure. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 245b202560b..a39cb1f9e87 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -704,7 +704,7 @@ int tda829x_attach(struct tuner *t) } if (tda829x_find_tuner(fe) < 0) - return -EINVAL; + goto fail; if (priv->ver & TDA8290) { tda8290_init_tuner(fe); @@ -717,6 +717,11 @@ int tda829x_attach(struct tuner *t) t->mode = V4L2_TUNER_ANALOG_TV; return 0; + +fail: + tda829x_release(fe); + fe->ops.analog_demod_ops = NULL; + return -EINVAL; } EXPORT_SYMBOL_GPL(tda829x_attach); -- cgit v1.2.3-70-g09d2 From ab1660503ac3af7febfcf987648509b484d4feda Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 9 Dec 2007 02:26:48 -0300 Subject: V4L/DVB (6785): tda8290: remove dependency on struct tuner - remove dependency of tda8290 module on struct tuner - move tuner_foo printk macros from tuner-driver.h into tuner-core.c - clean up #includes of tuner-i2c.h / tuner-driver.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 103 ++++++++++++++++++------------------- drivers/media/video/tda8290.h | 24 ++++++--- drivers/media/video/tda9887.c | 1 + drivers/media/video/tuner-core.c | 43 ++++++++++++++-- drivers/media/video/tuner-driver.h | 27 ---------- drivers/media/video/tuner-i2c.h | 2 - include/media/tuner.h | 2 - 7 files changed, 109 insertions(+), 93 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index a39cb1f9e87..d0d13bc6125 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -23,12 +23,14 @@ #include #include #include +#include "tuner-driver.h" +#include "tuner-i2c.h" #include "tda8290.h" #include "tda827x.h" #include "tda18271.h" -static int tuner_debug; -module_param_named(debug, tuner_debug, int, 0644); +static int debug; +module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable verbose debug messages"); #define PREFIX "tda8290" @@ -50,8 +52,6 @@ struct tda8290_priv { #define TDA18271 16 struct tda827x_config cfg; - - struct tuner *t; }; /*---------------------------------------------------------------------*/ @@ -114,7 +114,6 @@ static void set_audio(struct dvb_frontend *fe, struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; char* mode; if (params->std & V4L2_STD_MN) { @@ -150,7 +149,6 @@ static void tda8290_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; unsigned char soft_reset[] = { 0x00, 0x00 }; unsigned char easy_mode[] = { 0x01, priv->tda8290_easy_mode }; @@ -176,7 +174,8 @@ static void tda8290_set_params(struct dvb_frontend *fe, set_audio(fe, params); - tuner_dbg("tda827xa config is 0x%02x\n", t->config); + if (priv->cfg.config) + tuner_dbg("tda827xa config is 0x%02x\n", *priv->cfg.config); tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2); tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2); tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2); @@ -362,7 +361,6 @@ static void tda8295_set_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct tda8290_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; unsigned char blanking_mode[] = { 0x1d, 0x00 }; @@ -442,13 +440,13 @@ static void tda8295_standby(struct dvb_frontend *fe) static void tda8290_init_if(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; - struct tuner *t = priv->t; unsigned char set_VS[] = { 0x30, 0x6F }; unsigned char set_GP00_CF[] = { 0x20, 0x01 }; unsigned char set_GP01_CF[] = { 0x20, 0x0B }; - if ((t->config == 1) || (t->config == 2)) + if ((priv->cfg.config) && + ((*priv->cfg.config == 1) || (*priv->cfg.config == 2))) tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2); else tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2); @@ -516,7 +514,6 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; - struct tuner *t = priv->t; int i, ret, tuners_found; u32 tuner_addrs; u8 data; @@ -595,29 +592,6 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) ops->i2c_gate_ctrl(fe, 0); - switch (priv->ver) { - case TDA8290 | TDA8275: - strlcpy(t->i2c->name, "tda8290+75", sizeof(t->i2c->name)); - break; - case TDA8295 | TDA8275: - strlcpy(t->i2c->name, "tda8295+75", sizeof(t->i2c->name)); - break; - case TDA8290 | TDA8275A: - strlcpy(t->i2c->name, "tda8290+75a", sizeof(t->i2c->name)); - break; - case TDA8295 | TDA8275A: - strlcpy(t->i2c->name, "tda8295+75a", sizeof(t->i2c->name)); - break; - case TDA8290 | TDA18271: - strlcpy(t->i2c->name, "tda8290+18271", sizeof(t->i2c->name)); - break; - case TDA8295 | TDA18271: - strlcpy(t->i2c->name, "tda8295+18271", sizeof(t->i2c->name)); - break; - default: - return -EINVAL; - } - return 0; } @@ -631,7 +605,7 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); if (tda8290_id[1] == TDA8290_ID) { - if (tuner_debug) + if (debug) printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", __FUNCTION__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); @@ -651,7 +625,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); if (tda8295_id[1] == TDA8295_ID) { - if (tuner_debug) + if (debug) printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", __FUNCTION__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); @@ -677,21 +651,24 @@ static struct analog_tuner_ops tda8295_tuner_ops = { .i2c_gate_ctrl = tda8295_i2c_bridge, }; -int tda829x_attach(struct tuner *t) +struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, u8 i2c_addr, + struct tda829x_config *cfg) { - struct dvb_frontend *fe = &t->fe; struct tda8290_priv *priv = NULL; + char *name; priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL); if (priv == NULL) - return -ENOMEM; + return NULL; fe->analog_demod_priv = priv; - priv->i2c_props.addr = t->i2c->addr; - priv->i2c_props.adap = t->i2c->adapter; - priv->cfg.config = &t->config; - priv->cfg.tuner_callback = t->tuner_callback; - priv->t = t; + priv->i2c_props.addr = i2c_addr; + priv->i2c_props.adap = i2c_adap; + if (cfg) { + priv->cfg.config = cfg->lna_cfg; + priv->cfg.tuner_callback = cfg->tuner_callback; + } if (tda8290_probe(&priv->i2c_props) == 0) { priv->ver = TDA8290; @@ -706,30 +683,50 @@ int tda829x_attach(struct tuner *t) if (tda829x_find_tuner(fe) < 0) goto fail; + switch (priv->ver) { + case TDA8290 | TDA8275: + name = "tda8290+75"; + break; + case TDA8295 | TDA8275: + name = "tda8295+75"; + break; + case TDA8290 | TDA8275A: + name = "tda8290+75a"; + break; + case TDA8295 | TDA8275A: + name = "tda8295+75a"; + break; + case TDA8290 | TDA18271: + name = "tda8290+18271"; + break; + case TDA8295 | TDA18271: + name = "tda8295+18271"; + break; + default: + goto fail; + } + tuner_info("type set to %s\n", name); + if (priv->ver & TDA8290) { tda8290_init_tuner(fe); tda8290_init_if(fe); } else if (priv->ver & TDA8295) tda8295_init_if(fe); - tuner_info("type set to %s\n", t->i2c->name); - - t->mode = V4L2_TUNER_ANALOG_TV; - - return 0; + return fe; fail: tda829x_release(fe); fe->ops.analog_demod_ops = NULL; - return -EINVAL; + return NULL; } EXPORT_SYMBOL_GPL(tda829x_attach); -int tda829x_probe(struct tuner *t) +int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) { struct tuner_i2c_props i2c_props = { - .adap = t->i2c->adapter, - .addr = t->i2c->addr + .adap = i2c_adap, + .addr = i2c_addr, }; unsigned char soft_reset[] = { 0x00, 0x00 }; diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index 3a1f0452061..4c547577e7c 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -18,24 +18,36 @@ #define __TDA8290_H__ #include -#include "tuner-driver.h" +#include "dvb_frontend.h" + +struct tda829x_config +{ + unsigned int *lna_cfg; + int (*tuner_callback) (void *dev, int command, int arg); +}; #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) -extern int tda829x_probe(struct tuner *t); +extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr); -extern int tda829x_attach(struct tuner *t); +extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct tda829x_config *cfg); #else -static inline int tda829x_probe(struct tuner *t) +static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return -EINVAL; } -static inline int tda829x_attach(struct tuner *t) +static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, + u8 i2c_addr, + struct tda829x_config *cfg) { printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n", __FUNCTION__); - return -EINVAL; + return NULL; } #endif diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index d506d4bf825..98d45c4912b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -9,6 +9,7 @@ #include #include #include +#include "tuner-i2c.h" #include "tda9887.h" diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 5f8bffc8209..0cc190761e2 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -52,7 +52,34 @@ static unsigned int no_autodetect = 0; static unsigned int show_i2c = 0; /* insmod options used at runtime => read/write */ -int tuner_debug = 0; +static int tuner_debug; + +#define tuner_warn(fmt, arg...) do { \ + printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ + i2c_adapter_id(t->i2c->adapter), \ + t->i2c->addr, ##arg); \ + } while (0) + +#define tuner_info(fmt, arg...) do { \ + printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ + i2c_adapter_id(t->i2c->adapter), \ + t->i2c->addr, ##arg); \ + } while (0) + +#define tuner_err(fmt, arg...) do { \ + printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ + i2c_adapter_id(t->i2c->adapter), \ + t->i2c->addr, ##arg); \ + } while (0) + +#define tuner_dbg(fmt, arg...) do { \ + if (tuner_debug) \ + printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ + i2c_adapter_id(t->i2c->adapter), \ + t->i2c->addr, ##arg); \ + } while (0) + +/* ------------------------------------------------------------------------ */ static unsigned int tv_range[2] = { 44, 958 }; static unsigned int radio_range[2] = { 65, 108 }; @@ -261,6 +288,15 @@ static void attach_simple_tuner(struct tuner *t) simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); } +static void attach_tda829x(struct tuner *t) +{ + struct tda829x_config cfg = { + .lna_cfg = &t->config, + .tuner_callback = t->tuner_callback, + }; + tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg); +} + static void set_type(struct i2c_client *c, unsigned int type, unsigned int new_mode_mask, unsigned int new_config, int (*tuner_callback) (void *dev, int command,int arg)) @@ -303,7 +339,7 @@ static void set_type(struct i2c_client *c, unsigned int type, break; case TUNER_PHILIPS_TDA8290: { - tda829x_attach(t); + attach_tda829x(t); break; } case TUNER_TEA5767: @@ -1045,7 +1081,8 @@ static int tuner_probe(struct i2c_client *client) case 0x4b: /* If chip is not tda8290, don't register. since it can be tda9887*/ - if (tda829x_probe(t) == 0) { + if (tda829x_probe(t->i2c->adapter, + t->i2c->addr) == 0) { tuner_dbg("tda829x detected\n"); } else { /* Default is being tda9887 */ diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index 91913ee08a0..a215161d024 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -24,13 +24,10 @@ #include #include -#include "tuner-i2c.h" #include "dvb_frontend.h" extern unsigned const int tuner_count; -struct tuner; - struct analog_tuner_ops { void (*set_params)(struct dvb_frontend *fe, struct analog_parameters *params); @@ -69,28 +66,4 @@ struct tuner { int (*tuner_callback) (void *dev, int command,int arg); }; -/* ------------------------------------------------------------------------ */ - -#define tuner_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(t->i2c->adapter), t->i2c->addr, ##arg); \ - } while (0) - -#define tuner_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); \ - } while (0) - -#define tuner_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); \ - } while (0) - -#define tuner_dbg(fmt, arg...) do { \ - extern int tuner_debug; \ - if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(t->i2c->adapter), t->i2c->addr , ##arg); \ - } while (0) - #endif /* __TUNER_DRIVER_H__ */ diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index d7cf72c3fd7..de52e8ffd34 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -59,7 +59,6 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, return (ret == 2) ? ilen : ret; } -#ifndef __TUNER_DRIVER_H__ #define tuner_warn(fmt, arg...) do { \ printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ i2c_adapter_id(priv->i2c_props.adap), \ @@ -84,6 +83,5 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, i2c_adapter_id(priv->i2c_props.adap), \ priv->i2c_props.addr , ##arg); \ } while (0) -#endif /* __TUNER_DRIVER_H__ */ #endif /* __TUNER_I2C_H__ */ diff --git a/include/media/tuner.h b/include/media/tuner.h index d49392d90e5..97be269afbe 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -24,8 +24,6 @@ #include -extern int tuner_debug; - #define ADDR_UNSET (255) #define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ -- cgit v1.2.3-70-g09d2 From a55db8cd7f8a107f3abcb4c803b1873b2be63663 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 9 Dec 2007 13:52:51 -0300 Subject: V4L/DVB (6786): tuner: add struct analog_demod_info to struct analog_tuner_ops Store the analog demodulator name in fe.ops.analog_demod_ops.info.name Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 6 ++++++ drivers/media/video/tda9887.c | 3 +++ drivers/media/video/tuner-core.c | 3 +++ drivers/media/video/tuner-driver.h | 7 +++++++ 4 files changed, 19 insertions(+) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index d0d13bc6125..403f96f998e 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -636,6 +636,9 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) } static struct analog_tuner_ops tda8290_tuner_ops = { + .info = { + .name = "TDA8290", + }, .set_params = tda8290_set_params, .has_signal = tda8290_has_signal, .standby = tda8290_standby, @@ -644,6 +647,9 @@ static struct analog_tuner_ops tda8290_tuner_ops = { }; static struct analog_tuner_ops tda8295_tuner_ops = { + .info = { + .name = "TDA8295", + }, .set_params = tda8295_set_params, .has_signal = tda8295_has_signal, .standby = tda8295_standby, diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 98d45c4912b..8a95f097ba2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -636,6 +636,9 @@ static void tda9887_release(struct dvb_frontend *fe) } static struct analog_tuner_ops tda9887_tuner_ops = { + .info = { + .name = "TDA9887", + }, .set_params = tda9887_set_params, .standby = tda9887_standby, .tuner_status = tda9887_tuner_status, diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 0cc190761e2..59e67c92575 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -410,6 +410,9 @@ static void set_type(struct i2c_client *c, unsigned int type, t->fe.ops.analog_demod_ops = &tuner_core_ops; t->fe.analog_demod_priv = t; + } else { + strlcpy(t->i2c->name, ops->info.name, + sizeof(t->i2c->name)); } tuner_dbg("type set to %s\n", t->i2c->name); diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h index a215161d024..c245f501a31 100644 --- a/drivers/media/video/tuner-driver.h +++ b/drivers/media/video/tuner-driver.h @@ -28,7 +28,14 @@ extern unsigned const int tuner_count; +struct analog_demod_info { + char name[128]; +}; + struct analog_tuner_ops { + + struct analog_demod_info info; + void (*set_params)(struct dvb_frontend *fe, struct analog_parameters *params); int (*has_signal)(struct dvb_frontend *fe); -- cgit v1.2.3-70-g09d2 From e435f95ce6468f0240f050e14c9eac93e2fe7e71 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 9 Dec 2007 22:23:30 -0300 Subject: V4L/DVB (6801): tda18271: pass i2c gate configuration into tda18271_attach() If we pass TDA18271_GATE_DIGITAL into tda18271_attach(), it will always try to use the digital demodulator's i2c gate. If we pass TDA18271_GATE_ANALOG into tda18271_attach(), it will always try to use the analog demodulator's i2c gate. If we pass TDA18271_GATE_AUTO into tda18271_attach(), it will try to use the analog demodulator's i2c gate when tuning in analog mode, and it will try to use the digital demodulator's i2c gate when tuning in digital mode. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 34 +++++++++++++++++++++++++++---- drivers/media/dvb/frontends/tda18271.h | 12 +++++++++-- drivers/media/video/tda8290.c | 3 ++- 3 files changed, 42 insertions(+), 7 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index dbf0f619a90..28c63fd4493 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -40,7 +40,9 @@ struct tda18271_priv { u8 i2c_addr; struct i2c_adapter *i2c_adap; unsigned char tda18271_regs[TDA18271_NUM_REGS]; + enum tda18271_mode mode; + enum tda18271_i2c_gate gate; u32 frequency; u32 bandwidth; @@ -50,17 +52,39 @@ static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct tda18271_priv *priv = fe->tuner_priv; struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; + enum tda18271_i2c_gate gate; int ret = 0; - switch (priv->mode) { - case TDA18271_ANALOG: + switch (priv->gate) { + case TDA18271_GATE_DIGITAL: + case TDA18271_GATE_ANALOG: + gate = priv->gate; + break; + case TDA18271_GATE_AUTO: + default: + switch (priv->mode) { + case TDA18271_DIGITAL: + gate = TDA18271_GATE_DIGITAL; + break; + case TDA18271_ANALOG: + default: + gate = TDA18271_GATE_ANALOG; + break; + } + } + + switch (gate) { + case TDA18271_GATE_ANALOG: if (ops && ops->i2c_gate_ctrl) ret = ops->i2c_gate_ctrl(fe, enable); break; - case TDA18271_DIGITAL: + case TDA18271_GATE_DIGITAL: if (fe->ops.i2c_gate_ctrl) ret = fe->ops.i2c_gate_ctrl(fe, enable); break; + default: + ret = -EINVAL; + break; } return ret; @@ -713,7 +737,8 @@ static struct dvb_tuner_ops tda18271_tuner_ops = { }; struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, - struct i2c_adapter *i2c) + struct i2c_adapter *i2c, + enum tda18271_i2c_gate gate) { struct tda18271_priv *priv = NULL; @@ -724,6 +749,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->i2c_addr = addr; priv->i2c_adap = i2c; + priv->gate = gate; memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, sizeof(struct dvb_tuner_ops)); diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index a8a19a7197f..d8400337263 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -24,13 +24,21 @@ #include #include "dvb_frontend.h" +enum tda18271_i2c_gate { + TDA18271_GATE_AUTO = 0, + TDA18271_GATE_ANALOG, + TDA18271_GATE_DIGITAL, +}; + #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); + struct i2c_adapter *i2c, + enum tda18271_i2c_gate gate); #else static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, - struct i2c_adapter *i2c) + struct i2c_adapter *i2c, + enum tda18271_i2c_gate gate); { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); return NULL; diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 403f96f998e..a451d9480c1 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -574,7 +574,8 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) if (data == 0x83) { priv->ver |= TDA18271; tda18271_attach(fe, priv->tda827x_addr, - priv->i2c_props.adap); + priv->i2c_props.adap, + TDA18271_GATE_ANALOG); } else { if ((data & 0x3c) == 0) priv->ver |= TDA8275; -- cgit v1.2.3-70-g09d2 From 9ad89f0104314786138d580ab2c1119e7e470f56 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 21 Dec 2007 03:00:59 -0300 Subject: V4L/DVB (6880): kill tuner-driver.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 1 - drivers/media/video/tda8290.c | 1 - drivers/media/video/tda9887.c | 1 - drivers/media/video/tuner-core.c | 1 - drivers/media/video/tuner-driver.h | 27 --------------------------- 5 files changed, 31 deletions(-) delete mode 100644 drivers/media/video/tuner-driver.h (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 28c63fd4493..406520f6310 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -20,7 +20,6 @@ #include #include -#include "tuner-driver.h" #include "tda18271.h" #include "tda18271-priv.h" diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index a451d9480c1..71d38ba37f2 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -23,7 +23,6 @@ #include #include #include -#include "tuner-driver.h" #include "tuner-i2c.h" #include "tda8290.h" #include "tda827x.h" diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 2abb76fba9a..1b017d52bfb 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -9,7 +9,6 @@ #include #include #include -#include "tuner-driver.h" #include "tuner-i2c.h" #include "tda9887.h" diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index f22c41bb97e..ad20af84809 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -20,7 +20,6 @@ #include #include #include -#include "tuner-driver.h" #include "mt20xx.h" #include "tda8290.h" #include "tea5761.h" diff --git a/drivers/media/video/tuner-driver.h b/drivers/media/video/tuner-driver.h deleted file mode 100644 index 79efecc9334..00000000000 --- a/drivers/media/video/tuner-driver.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - tuner-driver.h - interface for different tuners - - Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de) - minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef __TUNER_DRIVER_H__ -#define __TUNER_DRIVER_H__ - -#include "dvb_frontend.h" - -#endif /* __TUNER_DRIVER_H__ */ -- cgit v1.2.3-70-g09d2 From bc3e5c7fc20d3c09667067878fb7a55dd9fc041d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 21 Dec 2007 11:18:32 -0300 Subject: V4L/DVB (6881): include struct analog_demod_ops directly inside struct dvb_frontend Rather than using a pointer, include struct analog_demod_ops directly inside struct dvb_frontend. This will allow us to use dvb_attach in the future, along with removing the need to check the ops structure before having to check the pointer to the method being called. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.h | 4 +- drivers/media/dvb/frontends/tda18271-fe.c | 5 +- drivers/media/video/tda8290.c | 23 +++---- drivers/media/video/tda9887.c | 5 +- drivers/media/video/tuner-core.c | 99 +++++++++++++++---------------- 5 files changed, 66 insertions(+), 70 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 417802f83f7..aa4133f0bd1 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -105,7 +105,7 @@ struct analog_demod_info { char *name; }; -struct analog_tuner_ops { +struct analog_demod_ops { struct analog_demod_info info; @@ -168,7 +168,7 @@ struct dvb_frontend_ops { int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire); struct dvb_tuner_ops tuner_ops; - struct analog_tuner_ops *analog_demod_ops; + struct analog_demod_ops analog_ops; }; #define MAX_EVENT 8 diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 406520f6310..3c0f06e1f47 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -50,7 +50,6 @@ struct tda18271_priv { static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct tda18271_priv *priv = fe->tuner_priv; - struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; enum tda18271_i2c_gate gate; int ret = 0; @@ -74,8 +73,8 @@ static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) switch (gate) { case TDA18271_GATE_ANALOG: - if (ops && ops->i2c_gate_ctrl) - ret = ops->i2c_gate_ctrl(fe, enable); + if (fe->ops.analog_ops.i2c_gate_ctrl) + ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable); break; case TDA18271_GATE_DIGITAL: if (fe->ops.i2c_gate_ctrl) diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 71d38ba37f2..2e1d9b663a9 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -512,16 +512,16 @@ static void tda829x_release(struct dvb_frontend *fe) static int tda829x_find_tuner(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; - struct analog_tuner_ops *ops = fe->ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &fe->ops.analog_ops; int i, ret, tuners_found; u32 tuner_addrs; u8 data; struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; - if (NULL == ops) + if (NULL == analog_ops->i2c_gate_ctrl) return -EINVAL; - ops->i2c_gate_ctrl(fe, 1); + analog_ops->i2c_gate_ctrl(fe, 1); /* probe for tuner chip */ tuners_found = 0; @@ -539,7 +539,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) give a response now */ - ops->i2c_gate_ctrl(fe, 0); + analog_ops->i2c_gate_ctrl(fe, 0); if (tuners_found > 1) for (i = 0; i < tuners_found; i++) { @@ -562,7 +562,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) priv->tda827x_addr = tuner_addrs; msg.addr = tuner_addrs; - ops->i2c_gate_ctrl(fe, 1); + analog_ops->i2c_gate_ctrl(fe, 1); ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); if (ret != 1) { @@ -590,7 +590,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) if (fe->ops.tuner_ops.sleep) fe->ops.tuner_ops.sleep(fe); - ops->i2c_gate_ctrl(fe, 0); + analog_ops->i2c_gate_ctrl(fe, 0); return 0; } @@ -635,7 +635,7 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) return -ENODEV; } -static struct analog_tuner_ops tda8290_tuner_ops = { +static struct analog_demod_ops tda8290_ops = { .info = { .name = "TDA8290", }, @@ -646,7 +646,7 @@ static struct analog_tuner_ops tda8290_tuner_ops = { .i2c_gate_ctrl = tda8290_i2c_bridge, }; -static struct analog_tuner_ops tda8295_tuner_ops = { +static struct analog_demod_ops tda8295_ops = { .info = { .name = "TDA8295", }, @@ -678,12 +678,14 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, if (tda8290_probe(&priv->i2c_props) == 0) { priv->ver = TDA8290; - fe->ops.analog_demod_ops = &tda8290_tuner_ops; + memcpy(&fe->ops.analog_ops, &tda8290_ops, + sizeof(struct analog_demod_ops)); } if (tda8295_probe(&priv->i2c_props) == 0) { priv->ver = TDA8295; - fe->ops.analog_demod_ops = &tda8295_tuner_ops; + memcpy(&fe->ops.analog_ops, &tda8295_ops, + sizeof(struct analog_demod_ops)); } if (tda829x_find_tuner(fe) < 0) @@ -723,7 +725,6 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, fail: tda829x_release(fe); - fe->ops.analog_demod_ops = NULL; return NULL; } EXPORT_SYMBOL_GPL(tda829x_attach); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 1b017d52bfb..d3aabe2d146 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -648,7 +648,7 @@ static void tda9887_release(struct dvb_frontend *fe) fe->analog_demod_priv = NULL; } -static struct analog_tuner_ops tda9887_tuner_ops = { +static struct analog_demod_ops tda9887_ops = { .info = { .name = "TDA9887", }, @@ -677,7 +677,8 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, tuner_info("tda988[5/6/7] found\n"); - fe->ops.analog_demod_ops = &tda9887_tuner_ops; + memcpy(&fe->ops.analog_ops, &tda9887_ops, + sizeof(struct analog_demod_ops)); return fe; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index ad20af84809..f792871582f 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -143,8 +143,6 @@ static void fe_release(struct dvb_frontend *fe) if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); - fe->ops.analog_demod_ops = NULL; - /* DO NOT kfree(fe->analog_demod_priv) * * If we are in this function, analog_demod_priv contains a pointer @@ -189,7 +187,7 @@ static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg) static void tuner_status(struct dvb_frontend *fe); -static struct analog_tuner_ops tuner_core_ops = { +static struct analog_demod_ops tuner_core_ops = { .set_params = fe_set_params, .standby = fe_standby, .release = fe_release, @@ -202,7 +200,7 @@ static struct analog_tuner_ops tuner_core_ops = { static void set_tv_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct analog_parameters params = { .mode = t->mode, @@ -214,7 +212,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if ((NULL == ops) || (NULL == ops->set_params)) { + if (NULL == analog_ops->set_params) { tuner_warn ("Tuner has no way to set tv freq\n"); return; } @@ -231,13 +229,13 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) } params.frequency = freq; - ops->set_params(&t->fe, ¶ms); + analog_ops->set_params(&t->fe, ¶ms); } static void set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tuner *t = i2c_get_clientdata(c); - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; struct analog_parameters params = { .mode = t->mode, @@ -249,7 +247,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) tuner_warn ("tuner type not set\n"); return; } - if ((NULL == ops) || (NULL == ops->set_params)) { + if (analog_ops->set_params) { tuner_warn ("tuner has no way to set radio frequency\n"); return; } @@ -266,7 +264,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq) } params.frequency = freq; - ops->set_params(&t->fe, ¶ms); + analog_ops->set_params(&t->fe, ¶ms); } static void set_freq(struct i2c_client *c, unsigned long freq) @@ -337,7 +335,7 @@ static void set_type(struct i2c_client *c, unsigned int type, { struct tuner *t = i2c_get_clientdata(c); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; unsigned char buffer[4]; if (type == UNSET || type == TUNER_ABSENT) { @@ -364,8 +362,8 @@ static void set_type(struct i2c_client *c, unsigned int type, } /* discard private data, in case set_type() was previously called */ - if (ops && ops->release) - ops->release(&t->fe); + if (analog_ops->release) + analog_ops->release(&t->fe); switch (t->type) { case TUNER_MT2032: @@ -435,17 +433,16 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } - ops = t->fe.ops.analog_demod_ops; - - if (((NULL == ops) || (NULL == ops->set_params)) && + if ((NULL == analog_ops->set_params) && (fe_tuner_ops->set_analog_params)) { strlcpy(t->i2c->name, fe_tuner_ops->info.name, sizeof(t->i2c->name)); - t->fe.ops.analog_demod_ops = &tuner_core_ops; t->fe.analog_demod_priv = t; + memcpy(analog_ops, &tuner_core_ops, + sizeof(struct analog_demod_ops)); } else { - strlcpy(t->i2c->name, ops->info.name, + strlcpy(t->i2c->name, analog_ops->info.name, sizeof(t->i2c->name)); } @@ -624,7 +621,7 @@ static void tuner_status(struct dvb_frontend *fe) struct tuner *t = fe->analog_demod_priv; unsigned long freq, freq_fraction; struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; const char *p; switch (t->mode) { @@ -654,14 +651,12 @@ static void tuner_status(struct dvb_frontend *fe) if (tuner_status & TUNER_STATUS_STEREO) tuner_info("Stereo: yes\n"); } - if (ops) { - if (ops->has_signal) - tuner_info("Signal strength: %d\n", - ops->has_signal(fe)); - if (ops->is_stereo) - tuner_info("Stereo: %s\n", - ops->is_stereo(fe) ? "yes" : "no"); - } + if (analog_ops->has_signal) + tuner_info("Signal strength: %d\n", + analog_ops->has_signal(fe)); + if (analog_ops->is_stereo) + tuner_info("Stereo: %s\n", + analog_ops->is_stereo(fe) ? "yes" : "no"); } /* ---------------------------------------------------------------------- */ @@ -675,7 +670,7 @@ static void tuner_status(struct dvb_frontend *fe) static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; if (mode == t->mode) return 0; @@ -684,8 +679,8 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, if (check_mode(t, cmd) == EINVAL) { t->mode = T_STANDBY; - if (ops && ops->standby) - ops->standby(&t->fe); + if (analog_ops->standby) + analog_ops->standby(&t->fe); return EINVAL; } return 0; @@ -708,7 +703,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tuner *t = i2c_get_clientdata(client); struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; if (tuner_debug>1) v4l_i2c_print_ioctl(client,cmd); @@ -735,8 +730,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; t->mode = T_STANDBY; - if (ops && ops->standby) - ops->standby(&t->fe); + if (analog_ops->standby) + analog_ops->standby(&t->fe); break; #ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: @@ -804,8 +799,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) else vt->flags &= ~VIDEO_TUNER_STEREO_ON; } else { - if (ops && ops->is_stereo) { - if (ops->is_stereo(&t->fe)) + if (analog_ops->is_stereo) { + if (analog_ops->is_stereo(&t->fe)) vt->flags |= VIDEO_TUNER_STEREO_ON; else @@ -813,8 +808,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ~VIDEO_TUNER_STEREO_ON; } } - if (ops && ops->has_signal) - vt->signal = ops->has_signal(&t->fe); + if (analog_ops->has_signal) + vt->signal = + analog_ops->has_signal(&t->fe); vt->flags |= VIDEO_TUNER_LOW; /* Allow freqs at 62.5 Hz */ @@ -844,8 +840,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) fe_tuner_ops->get_status(&t->fe, &tuner_status); va->mode = (tuner_status & TUNER_STATUS_STEREO) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - } else if (ops && ops->is_stereo) - va->mode = ops->is_stereo(&t->fe) + } else if (analog_ops->is_stereo) + va->mode = analog_ops->is_stereo(&t->fe) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; } return 0; @@ -853,19 +849,18 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) #endif case TUNER_SET_CONFIG: { - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; struct v4l2_priv_tun_config *cfg = arg; if (t->type != cfg->tuner) break; - if ((NULL == ops) || (NULL == ops->set_config)) { + if (analog_ops->set_config) { tuner_warn("Tuner frontend module has no way to " "set config\n"); break; } - ops->set_config(&t->fe, cfg->priv); + analog_ops->set_config(&t->fe, cfg->priv); break; } /* --- v4l ioctls --- */ @@ -929,8 +924,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; - if (ops && ops->get_afc) - tuner->afc = ops->get_afc(&t->fe); + if (analog_ops->get_afc) + tuner->afc = analog_ops->get_afc(&t->fe); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -951,15 +946,15 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } else { - if (ops && ops->is_stereo) { + if (analog_ops->is_stereo) { tuner->rxsubchans = - ops->is_stereo(&t->fe) ? + analog_ops->is_stereo(&t->fe) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } } - if (ops && ops->has_signal) - tuner->signal = ops->has_signal(&t->fe); + if (analog_ops->has_signal) + tuner->signal = analog_ops->has_signal(&t->fe); tuner->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; tuner->audmode = t->audmode; @@ -984,8 +979,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } case VIDIOC_LOG_STATUS: - if (ops && ops->tuner_status) - ops->tuner_status(&t->fe); + if (analog_ops->tuner_status) + analog_ops->tuner_status(&t->fe); break; } @@ -1214,10 +1209,10 @@ static int tuner_legacy_probe(struct i2c_adapter *adap) static int tuner_remove(struct i2c_client *client) { struct tuner *t = i2c_get_clientdata(client); - struct analog_tuner_ops *ops = t->fe.ops.analog_demod_ops; + struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; - if (ops && ops->release) - ops->release(&t->fe); + if (analog_ops->release) + analog_ops->release(&t->fe); list_del(&t->list); kfree(t); -- cgit v1.2.3-70-g09d2 From c90762799c42df203fc2c9c1a2ac39f154f8faca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 24 Dec 2007 04:36:14 -0300 Subject: V4L/DVB (6908): tda8290: add the option not to probe for tuners passed into tda829x_config Prevent the tda8290 module from probing for tuners during tda829x_attach, by passing: .probe_tuner = TDA829X_DONT_PROBE, ...in struct tda829x_config Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 9 ++++++++- drivers/media/video/tda8290.h | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 2e1d9b663a9..bb62d5629af 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -688,10 +688,17 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, sizeof(struct analog_demod_ops)); } - if (tda829x_find_tuner(fe) < 0) + if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) && + (tda829x_find_tuner(fe) < 0)) goto fail; switch (priv->ver) { + case TDA8290: + name = "tda8290"; + break; + case TDA8295: + name = "tda8295"; + break; case TDA8290 | TDA8275: name = "tda8290+75"; break; diff --git a/drivers/media/video/tda8290.h b/drivers/media/video/tda8290.h index 7bce03183d0..dc8ef310b7b 100644 --- a/drivers/media/video/tda8290.h +++ b/drivers/media/video/tda8290.h @@ -23,6 +23,10 @@ struct tda829x_config { unsigned int *lna_cfg; int (*tuner_callback) (void *dev, int command, int arg); + + unsigned int probe_tuner:1; +#define TDA829X_PROBE_TUNER 0 +#define TDA829X_DONT_PROBE 1 }; #if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE)) -- cgit v1.2.3-70-g09d2 From 255b5113b4ed683898a24e381155c081f03411f7 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 1 Jan 2008 22:52:09 -0300 Subject: V4L/DVB (6960): tda18271: add support for NXP TDA18271HD/C2 Tested successfully with QAM256 digital cable. Analog television is limping, needs more work. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 885 +++++++++++++++++++++--- drivers/media/dvb/frontends/tda18271-priv.h | 72 +- drivers/media/dvb/frontends/tda18271-tables.c | 932 +++++++++++++++++++++++++- drivers/media/video/tda8290.c | 2 +- 4 files changed, 1779 insertions(+), 112 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 2c873ae6e8c..4b53baf12ef 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -71,7 +71,7 @@ static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) /*---------------------------------------------------------------------*/ -static void tda18271_dump_regs(struct dvb_frontend *fe) +static void tda18271_dump_regs(struct dvb_frontend *fe, int extended) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -93,6 +93,37 @@ static void tda18271_dump_regs(struct dvb_frontend *fe) tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]); tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]); tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]); + + /* only dump extended regs if DBG_ADV is set */ + if (!(tda18271_debug & DBG_ADV)) + return; + + /* W indicates write-only registers. + * Register dump for write-only registers shows last value written. */ + + tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]); + tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]); + tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]); + tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]); + tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]); + tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]); + tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]); + tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]); + tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]); + tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]); + tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]); + tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]); + tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]); + tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]); + tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]); + tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]); + tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]); + tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]); + tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]); + tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]); + tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]); + tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]); + tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]); } static void tda18271_read_regs(struct dvb_frontend *fe) @@ -119,7 +150,45 @@ static void tda18271_read_regs(struct dvb_frontend *fe) tda_err("ERROR: i2c_transfer returned: %d\n", ret); if (tda18271_debug & DBG_REG) - tda18271_dump_regs(fe); + tda18271_dump_regs(fe, 0); +} + +static void tda18271_read_extended(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + unsigned char regdump[TDA18271_NUM_REGS]; + unsigned char buf = 0x00; + int ret, i; + struct i2c_msg msg[] = { + { .addr = priv->i2c_addr, .flags = 0, + .buf = &buf, .len = 1 }, + { .addr = priv->i2c_addr, .flags = I2C_M_RD, + .buf = regdump, .len = TDA18271_NUM_REGS } + }; + + tda18271_i2c_gate_ctrl(fe, 1); + + /* read all registers */ + ret = i2c_transfer(priv->i2c_adap, msg, 2); + + tda18271_i2c_gate_ctrl(fe, 0); + + if (ret != 2) + tda_err("ERROR: i2c_transfer returned: %d\n", ret); + + for (i = 0; i <= TDA18271_NUM_REGS; i++) { + /* don't update write-only registers */ + if ((i != R_EB9) && + (i != R_EB16) && + (i != R_EB17) && + (i != R_EB19) && + (i != R_EB20)) + regs[i] = regdump[i]; + } + + if (tda18271_debug & DBG_REG) + tda18271_dump_regs(fe, 1); } static void tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) @@ -160,7 +229,15 @@ static int tda18271_init_regs(struct dvb_frontend *fe) i2c_adapter_id(priv->i2c_adap), priv->i2c_addr); /* initialize registers */ - regs[R_ID] = 0x83; + switch (priv->id) { + case TDA18271HDC1: + regs[R_ID] = 0x83; + break; + case TDA18271HDC2: + regs[R_ID] = 0x84; + break; + }; + regs[R_TM] = 0x08; regs[R_PL] = 0x80; regs[R_EP1] = 0xc6; @@ -176,7 +253,16 @@ static int tda18271_init_regs(struct dvb_frontend *fe) regs[R_MD1] = 0x00; regs[R_MD2] = 0x00; regs[R_MD3] = 0x00; - regs[R_EB1] = 0xff; + + switch (priv->id) { + case TDA18271HDC1: + regs[R_EB1] = 0xff; + break; + case TDA18271HDC2: + regs[R_EB1] = 0xfc; + break; + }; + regs[R_EB2] = 0x01; regs[R_EB3] = 0x84; regs[R_EB4] = 0x41; @@ -187,21 +273,49 @@ static int tda18271_init_regs(struct dvb_frontend *fe) regs[R_EB9] = 0x00; regs[R_EB10] = 0x00; regs[R_EB11] = 0x96; - regs[R_EB12] = 0x0f; + + switch (priv->id) { + case TDA18271HDC1: + regs[R_EB12] = 0x0f; + break; + case TDA18271HDC2: + regs[R_EB12] = 0x33; + break; + }; + regs[R_EB13] = 0xc1; regs[R_EB14] = 0x00; regs[R_EB15] = 0x8f; regs[R_EB16] = 0x00; regs[R_EB17] = 0x00; - regs[R_EB18] = 0x00; + + switch (priv->id) { + case TDA18271HDC1: + regs[R_EB18] = 0x00; + break; + case TDA18271HDC2: + regs[R_EB18] = 0x8c; + break; + }; + regs[R_EB19] = 0x00; regs[R_EB20] = 0x20; - regs[R_EB21] = 0x33; + + switch (priv->id) { + case TDA18271HDC1: + regs[R_EB21] = 0x33; + break; + case TDA18271HDC2: + regs[R_EB21] = 0xb3; + break; + }; + regs[R_EB22] = 0x48; regs[R_EB23] = 0xb0; tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); - /* setup AGC1 & AGC2 */ + + /* setup agc1 gain */ regs[R_EB17] = 0x00; tda18271_write_regs(fe, R_EB17, 1); regs[R_EB17] = 0x03; @@ -211,14 +325,17 @@ static int tda18271_init_regs(struct dvb_frontend *fe) regs[R_EB17] = 0x4c; tda18271_write_regs(fe, R_EB17, 1); - regs[R_EB20] = 0xa0; - tda18271_write_regs(fe, R_EB20, 1); - regs[R_EB20] = 0xa7; - tda18271_write_regs(fe, R_EB20, 1); - regs[R_EB20] = 0xe7; - tda18271_write_regs(fe, R_EB20, 1); - regs[R_EB20] = 0xec; - tda18271_write_regs(fe, R_EB20, 1); + /* setup agc2 gain */ + if ((priv->id) == TDA18271HDC1) { + regs[R_EB20] = 0xa0; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xa7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xe7; + tda18271_write_regs(fe, R_EB20, 1); + regs[R_EB20] = 0xec; + tda18271_write_regs(fe, R_EB20, 1); + } /* image rejection calibration */ @@ -235,103 +352,102 @@ static int tda18271_init_regs(struct dvb_frontend *fe) regs[R_MD2] = 0x08; regs[R_MD3] = 0x00; - tda18271_write_regs(fe, R_EP3, 11); + switch (priv->id) { + case TDA18271HDC1: + tda18271_write_regs(fe, R_EP3, 11); + break; + case TDA18271HDC2: + tda18271_write_regs(fe, R_EP3, 12); + break; + }; + + if ((priv->id) == TDA18271HDC2) { + /* main pll cp source on */ + regs[R_EB4] = 0x61; + tda18271_write_regs(fe, R_EB4, 1); + msleep(1); + + /* main pll cp source off */ + regs[R_EB4] = 0x41; + tda18271_write_regs(fe, R_EB4, 1); + } + msleep(5); /* pll locking */ - regs[R_EP1] = 0xc6; + /* launch detector */ tda18271_write_regs(fe, R_EP1, 1); msleep(5); /* wanted low measurement */ - regs[R_EP3] = 0x1f; - regs[R_EP4] = 0x66; regs[R_EP5] = 0x85; regs[R_CPD] = 0xcb; regs[R_CD1] = 0x66; regs[R_CD2] = 0x70; - regs[R_CD3] = 0x00; tda18271_write_regs(fe, R_EP3, 7); msleep(5); /* pll locking */ - regs[R_EP2] = 0xdf; + /* launch optimization algorithm */ tda18271_write_regs(fe, R_EP2, 1); msleep(30); /* image low optimization completion */ /* mid-band */ - regs[R_EP3] = 0x1f; - regs[R_EP4] = 0x66; regs[R_EP5] = 0x82; regs[R_CPD] = 0xa8; - regs[R_CD1] = 0x66; regs[R_CD2] = 0x00; - regs[R_CD3] = 0x00; regs[R_MPD] = 0xa9; regs[R_MD1] = 0x73; regs[R_MD2] = 0x1a; - regs[R_MD3] = 0x00; tda18271_write_regs(fe, R_EP3, 11); msleep(5); /* pll locking */ - regs[R_EP1] = 0xc6; tda18271_write_regs(fe, R_EP1, 1); msleep(5); /* wanted mid measurement */ - regs[R_EP3] = 0x1f; - regs[R_EP4] = 0x66; regs[R_EP5] = 0x86; regs[R_CPD] = 0xa8; regs[R_CD1] = 0x66; regs[R_CD2] = 0xa0; - regs[R_CD3] = 0x00; tda18271_write_regs(fe, R_EP3, 7); msleep(5); /* pll locking */ - regs[R_EP2] = 0xdf; + /* launch optimization algorithm */ tda18271_write_regs(fe, R_EP2, 1); msleep(30); /* image mid optimization completion */ /* high-band */ - regs[R_EP3] = 0x1f; - regs[R_EP4] = 0x66; regs[R_EP5] = 0x83; regs[R_CPD] = 0x98; regs[R_CD1] = 0x65; regs[R_CD2] = 0x00; - regs[R_CD3] = 0x00; regs[R_MPD] = 0x99; regs[R_MD1] = 0x71; regs[R_MD2] = 0xcd; - regs[R_MD3] = 0x00; tda18271_write_regs(fe, R_EP3, 11); msleep(5); /* pll locking */ - regs[R_EP1] = 0xc6; + /* launch detector */ tda18271_write_regs(fe, R_EP1, 1); msleep(5); /* wanted high measurement */ - regs[R_EP3] = 0x1f; - regs[R_EP4] = 0x66; regs[R_EP5] = 0x87; - regs[R_CPD] = 0x98; regs[R_CD1] = 0x65; regs[R_CD2] = 0x50; - regs[R_CD3] = 0x00; tda18271_write_regs(fe, R_EP3, 7); msleep(5); /* pll locking */ - regs[R_EP2] = 0xdf; - + /* launch optimization algorithm */ tda18271_write_regs(fe, R_EP2, 1); msleep(30); /* image high optimization completion */ + /* return to normal mode */ regs[R_EP4] = 0x64; tda18271_write_regs(fe, R_EP4, 1); - regs[R_EP1] = 0xc6; + /* synchronize */ tda18271_write_regs(fe, R_EP1, 1); return 0; @@ -359,7 +475,7 @@ static int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) u8 d, pd; u32 div; - int ret = tda18271_lookup_pll_map(MAIN_PLL, &freq, &pd, &d); + int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d); if (ret < 0) goto fail; @@ -391,7 +507,7 @@ static int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq) u8 d, pd; u32 div; - int ret = tda18271_lookup_pll_map(CAL_PLL, &freq, &pd, &d); + int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d); if (ret < 0) goto fail; @@ -413,7 +529,7 @@ static int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(BP_FILTER, freq, &val); + int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val); if (ret < 0) goto fail; @@ -430,7 +546,7 @@ static int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(RF_CAL_KMCO, freq, &val); + int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val); if (ret < 0) goto fail; @@ -447,7 +563,7 @@ static int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(RF_BAND, freq, &val); + int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val); if (ret < 0) goto fail; @@ -464,7 +580,7 @@ static int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(GAIN_TAPER, freq, &val); + int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val); if (ret < 0) goto fail; @@ -481,7 +597,7 @@ static int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(IR_MEASURE, freq, &val); + int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val); if (ret < 0) goto fail; @@ -498,7 +614,7 @@ static int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq) unsigned char *regs = priv->tda18271_regs; u8 val; - int ret = tda18271_lookup_map(RF_CAL, freq, &val); + int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val); if (ret < 0) goto fail; @@ -507,8 +623,581 @@ fail: return ret; } -static int tda18271_tune(struct dvb_frontend *fe, - u32 ifc, u32 freq, u32 bw, u8 std) +/* ------------------------------------------------------------------ */ + +static int tda18271_channel_configuration(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u32 N; + + /* update TV broadcast parameters */ + + /* set standard */ + regs[R_EP3] &= ~0x1f; /* clear std bits */ + regs[R_EP3] |= std; + + /* set cal mode to normal */ + regs[R_EP4] &= ~0x03; + + /* update IF output level & IF notch frequency */ + regs[R_EP4] &= ~0x1c; /* clear if level bits */ + + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_MPD] &= ~0x80; /* IF notch = 0 */ + break; + case TDA18271_DIGITAL: + regs[R_EP4] |= 0x04; /* IF level = 1 */ + regs[R_MPD] |= 0x80; /* IF notch = 1 */ + break; + } + regs[R_EP4] &= ~0x80; /* FM_RFn: turn this bit on only for fm radio */ + + /* update RF_TOP / IF_TOP */ + switch (priv->mode) { + case TDA18271_ANALOG: + regs[R_EB22] = 0x2c; + break; + case TDA18271_DIGITAL: + regs[R_EB22] = 0x37; + break; + } + tda18271_write_regs(fe, R_EB22, 1); + + /* --------------------------------------------------------------- */ + + /* disable Power Level Indicator */ + regs[R_EP1] |= 0x40; + + /* frequency dependent parameters */ + + tda18271_calc_ir_measure(fe, &freq); + + tda18271_calc_bp_filter(fe, &freq); + + tda18271_calc_rf_band(fe, &freq); + + tda18271_calc_gain_taper(fe, &freq); + + /* --------------------------------------------------------------- */ + + /* dual tuner and agc1 extra configuration */ + + /* main vco when Master, cal vco when slave */ + regs[R_EB1] |= 0x04; /* FIXME: assumes master */ + + /* agc1 always active */ + regs[R_EB1] &= ~0x02; + + /* agc1 has priority on agc2 */ + regs[R_EB1] &= ~0x01; + + tda18271_write_regs(fe, R_EB1, 1); + + /* --------------------------------------------------------------- */ + + N = freq + ifc; + + /* FIXME: assumes master */ + tda18271_calc_main_pll(fe, N); + tda18271_write_regs(fe, R_MPD, 4); + + tda18271_write_regs(fe, R_TM, 7); + + /* main pll charge pump source */ + regs[R_EB4] |= 0x20; + tda18271_write_regs(fe, R_EB4, 1); + + msleep(1); + + /* normal operation for the main pll */ + regs[R_EB4] &= ~0x20; + tda18271_write_regs(fe, R_EB4, 1); + + msleep(5); + + return 0; +} + +static int tda18271_read_thermometer(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + int tm; + + /* switch thermometer on */ + regs[R_TM] |= 0x10; + tda18271_write_regs(fe, R_TM, 1); + + /* read thermometer info */ + tda18271_read_regs(fe); + + if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) || + (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) { + + if ((regs[R_TM] & 0x20) == 0x20) + regs[R_TM] &= ~0x20; + else + regs[R_TM] |= 0x20; + + tda18271_write_regs(fe, R_TM, 1); + + msleep(10); /* temperature sensing */ + + /* read thermometer info */ + tda18271_read_regs(fe); + } + + tm = tda18271_lookup_thermometer(fe); + + /* switch thermometer off */ + regs[R_TM] &= ~0x10; + tda18271_write_regs(fe, R_TM, 1); + + /* set CAL mode to normal */ + regs[R_EP4] &= ~0x03; + tda18271_write_regs(fe, R_EP4, 1); + + return tm; +} + +static int tda18271_rf_tracking_filters_correction(struct dvb_frontend *fe, + u32 freq, int tm_rfcal) +{ + struct tda18271_priv *priv = fe->tuner_priv; + struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; + unsigned char *regs = priv->tda18271_regs; + int tm_current, rfcal_comp, approx, i; + u8 dc_over_dt, rf_tab; + + /* power up */ + regs[R_EP3] &= ~0xe0; /* sm = 0, sm_lt = 0, sm_xt = 0 */ + tda18271_write_regs(fe, R_EP3, 1); + + /* read die current temperature */ + tm_current = tda18271_read_thermometer(fe); + + /* frequency dependent parameters */ + + tda18271_calc_rf_cal(fe, &freq); + rf_tab = regs[R_EB14]; + + i = tda18271_lookup_rf_band(fe, &freq, NULL); + if (i < 0) + return -EINVAL; + + if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) { + approx = map[i].rf_a1 * + (freq / 1000 - map[i].rf1) + map[i].rf_b1 + rf_tab; + } else { + approx = map[i].rf_a2 * + (freq / 1000 - map[i].rf2) + map[i].rf_b2 + rf_tab; + } + + if (approx < 0) + approx = 0; + if (approx > 255) + approx = 255; + + tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt); + + /* calculate temperature compensation */ + rfcal_comp = dc_over_dt * (tm_current - tm_rfcal); + + regs[R_EB14] = approx + rfcal_comp; + tda18271_write_regs(fe, R_EB14, 1); + + return 0; +} + +static int tda18271_por(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + /* power up detector 1 */ + regs[R_EB12] &= ~0x20; + tda18271_write_regs(fe, R_EB12, 1); + + regs[R_EB18] &= ~0x80; /* turn agc1 loop on */ + regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ + tda18271_write_regs(fe, R_EB18, 1); + + regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */ + + /* POR mode */ + regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */ + regs[R_EP3] |= 0x80; /* sm = 1, sm_lt = 0, sm_xt = 0 */ + tda18271_write_regs(fe, R_EP3, 1); + + /* disable 1.5 MHz low pass filter */ + regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */ + regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */ + tda18271_write_regs(fe, R_EB21, 3); + + return 0; +} + +static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + u32 N; + + /* set CAL mode to normal */ + regs[R_EP4] &= ~0x03; + tda18271_write_regs(fe, R_EP4, 1); + + /* switch off agc1 */ + regs[R_EP3] |= 0x40; /* sm_lt = 1 */ + + regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */ + tda18271_write_regs(fe, R_EB18, 1); + + /* frequency dependent parameters */ + + tda18271_calc_bp_filter(fe, &freq); + tda18271_calc_gain_taper(fe, &freq); + tda18271_calc_rf_band(fe, &freq); + tda18271_calc_km(fe, &freq); + + tda18271_write_regs(fe, R_EP1, 3); + tda18271_write_regs(fe, R_EB13, 1); + + /* main pll charge pump source */ + regs[R_EB4] |= 0x20; + tda18271_write_regs(fe, R_EB4, 1); + + /* cal pll charge pump source */ + regs[R_EB7] |= 0x20; + tda18271_write_regs(fe, R_EB7, 1); + + /* force dcdc converter to 0 V */ + regs[R_EB14] = 0x00; + tda18271_write_regs(fe, R_EB14, 1); + + /* disable plls lock */ + regs[R_EB20] &= ~0x20; + tda18271_write_regs(fe, R_EB20, 1); + + /* set CAL mode to RF tracking filter calibration */ + regs[R_EP4] |= 0x03; + tda18271_write_regs(fe, R_EP4, 2); + + /* --------------------------------------------------------------- */ + + /* set the internal calibration signal */ + N = freq; + + tda18271_calc_main_pll(fe, N); + tda18271_write_regs(fe, R_MPD, 4); + + /* downconvert internal calibration */ + N += 1000000; + + tda18271_calc_main_pll(fe, N); + tda18271_write_regs(fe, R_MPD, 4); + + msleep(5); + + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EP1, 1); + + /* --------------------------------------------------------------- */ + + /* normal operation for the main pll */ + regs[R_EB4] &= ~0x20; + tda18271_write_regs(fe, R_EB4, 1); + + /* normal operation for the cal pll */ + regs[R_EB7] &= ~0x20; + tda18271_write_regs(fe, R_EB7, 1); + + msleep(5); /* plls locking */ + + /* launch the rf tracking filters calibration */ + regs[R_EB20] |= 0x20; + tda18271_write_regs(fe, R_EB20, 1); + + msleep(60); /* calibration */ + + /* --------------------------------------------------------------- */ + + /* set CAL mode to normal */ + regs[R_EP4] &= ~0x03; + + /* switch on agc1 */ + regs[R_EP3] &= ~0x40; /* sm_lt = 0 */ + + regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ + tda18271_write_regs(fe, R_EB18, 1); + + tda18271_write_regs(fe, R_EP3, 2); + + /* synchronization */ + tda18271_write_regs(fe, R_EP1, 1); + + /* get calibration result */ + tda18271_read_extended(fe); + + return regs[R_EB14]; +} + +static int tda18271_powerscan(struct dvb_frontend *fe, + u32 *freq_in, u32 *freq_out) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + int sgn, bcal, count, wait; + u8 cid_target; + u16 count_limit; + u32 freq; + + freq = *freq_in; + + tda18271_calc_rf_band(fe, &freq); + tda18271_calc_rf_cal(fe, &freq); + tda18271_calc_gain_taper(fe, &freq); + tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit); + + tda18271_write_regs(fe, R_EP2, 1); + tda18271_write_regs(fe, R_EB14, 1); + + /* downconvert frequency */ + freq += 1000000; + + tda18271_calc_main_pll(fe, freq); + tda18271_write_regs(fe, R_MPD, 4); + + msleep(5); /* pll locking */ + + /* detection mode */ + regs[R_EP4] &= ~0x03; + regs[R_EP4] |= 0x01; + tda18271_write_regs(fe, R_EP4, 1); + + /* launch power detection measurement */ + tda18271_write_regs(fe, R_EP2, 1); + + /* read power detection info, stored in EB10 */ + tda18271_read_extended(fe); + + /* algorithm initialization */ + sgn = 1; + *freq_out = *freq_in; + bcal = 0; + count = 0; + wait = false; + + while ((regs[R_EB10] & 0x3f) < cid_target) { + /* downconvert updated freq to 1 MHz */ + freq = *freq_in + (sgn * count) + 1000000; + + tda18271_calc_main_pll(fe, freq); + tda18271_write_regs(fe, R_MPD, 4); + + if (wait) { + msleep(5); /* pll locking */ + wait = false; + } else + udelay(100); /* pll locking */ + + /* launch power detection measurement */ + tda18271_write_regs(fe, R_EP2, 1); + + /* read power detection info, stored in EB10 */ + tda18271_read_extended(fe); + + count += 200; + + if (count < count_limit) + continue; + + if (sgn <= 0) + break; + + sgn = -1 * sgn; + count = 200; + wait = true; + } + + if ((regs[R_EB10] & 0x3f) >= cid_target) { + bcal = 1; + *freq_out = freq - 1000000; + } else + bcal = 0; + + tda_dbg("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n", + bcal, *freq_in, *freq_out, freq); + + return bcal; +} + +static int tda18271_powerscan_init(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + + /* set standard to digital */ + regs[R_EP3] &= ~0x1f; /* clear std bits */ + regs[R_EP3] |= 0x12; + + /* set cal mode to normal */ + regs[R_EP4] &= ~0x03; + + /* update IF output level & IF notch frequency */ + regs[R_EP4] &= ~0x1c; /* clear if level bits */ + + tda18271_write_regs(fe, R_EP3, 2); + + regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ + tda18271_write_regs(fe, R_EB18, 1); + + regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */ + + /* 1.5 MHz low pass filter */ + regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */ + regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */ + + tda18271_write_regs(fe, R_EB21, 3); + + return 0; +} + +static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) +{ + struct tda18271_priv *priv = fe->tuner_priv; + struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; + unsigned char *regs = priv->tda18271_regs; + int bcal, rf, i; +#define RF1 0 +#define RF2 1 +#define RF3 2 + u32 rf_default[3]; + u32 rf_freq[3]; + u8 prog_cal[3]; + u8 prog_tab[3]; + + i = tda18271_lookup_rf_band(fe, &freq, NULL); + + if (i < 0) + return i; + + rf_default[RF1] = 1000 * map[i].rf1_def; + rf_default[RF2] = 1000 * map[i].rf2_def; + rf_default[RF3] = 1000 * map[i].rf3_def; + + for (rf = RF1; rf <= RF3; rf++) { + if (0 == rf_default[rf]) + return 0; + tda_dbg("freq = %d, rf = %d\n", freq, rf); + + /* look for optimized calibration frequency */ + bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]); + + tda18271_calc_rf_cal(fe, &rf_freq[rf]); + prog_tab[rf] = regs[R_EB14]; + + if (1 == bcal) + prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]); + else + prog_cal[rf] = prog_tab[rf]; + + switch (rf) { + case RF1: + map[i].rf_a1 = 0; + map[i].rf_b1 = prog_cal[RF1] - prog_tab[RF1]; + map[i].rf1 = rf_freq[RF1] / 1000; + break; + case RF2: + map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - + prog_cal[RF1] + prog_tab[RF1]) / + ((rf_freq[RF2] - rf_freq[RF1]) / 1000); + map[i].rf2 = rf_freq[RF2] / 1000; + break; + case RF3: + map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - + prog_cal[RF2] + prog_tab[RF2]) / + ((rf_freq[RF3] - rf_freq[RF2]) / 1000); + map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; + map[i].rf3 = rf_freq[RF3] / 1000; + break; + default: + BUG(); + } + } + + return 0; +} + +static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe, + int *tm_rfcal) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned int i; + + tda_info("tda18271: performing RF tracking filter calibration\n"); + + /* wait for die temperature stabilization */ + msleep(200); + + tda18271_powerscan_init(fe); + + /* rf band calibration */ + for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) + tda18271_rf_tracking_filters_init(fe, 1000 * + priv->rf_cal_state[i].rfmax); + + *tm_rfcal = tda18271_read_thermometer(fe); + + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int tda18271_init_cal(struct dvb_frontend *fe, int *tm) +{ + struct tda18271_priv *priv = fe->tuner_priv; + + if (priv->cal_initialized) + return 0; + + /* initialization */ + tda18271_init(fe); + + tda18271_calc_rf_filter_curve(fe, tm); + + tda18271_por(fe); + + priv->cal_initialized = true; + + return 0; +} + +static int tda18271c2_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std) +{ + int tm = 0; + + tda_dbg("freq = %d, ifc = %d\n", freq, ifc); + + tda18271_init_cal(fe, &tm); + + tda18271_rf_tracking_filters_correction(fe, freq, tm); + + tda18271_channel_configuration(fe, ifc, freq, bw, std); + + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int tda18271c1_tune(struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; @@ -520,7 +1209,7 @@ static int tda18271_tune(struct dvb_frontend *fe, /* RF tracking filter calibration */ - /* calculate BP_Filter */ + /* calculate bp filter */ tda18271_calc_bp_filter(fe, &freq); tda18271_write_regs(fe, R_EP1, 1); @@ -537,10 +1226,10 @@ static int tda18271_tune(struct dvb_frontend *fe, regs[R_EB20] = 0xcc; tda18271_write_regs(fe, R_EB20, 1); - /* set CAL mode to RF tracking filter calibration */ + /* set cal mode to RF tracking filter calibration */ regs[R_EP4] |= 0x03; - /* calculate CAL PLL */ + /* calculate cal pll */ switch (priv->mode) { case TDA18271_ANALOG: @@ -553,7 +1242,7 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271_calc_cal_pll(fe, N); - /* calculate MAIN PLL */ + /* calculate main pll */ switch (priv->mode) { case TDA18271_ANALOG: @@ -569,14 +1258,14 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271_write_regs(fe, R_EP3, 11); msleep(5); /* RF tracking filter calibration initialization */ - /* search for K,M,CO for RF Calibration */ + /* search for K,M,CO for RF calibration */ tda18271_calc_km(fe, &freq); tda18271_write_regs(fe, R_EB13, 1); - /* search for RF_BAND */ + /* search for rf band */ tda18271_calc_rf_band(fe, &freq); - /* search for Gain_Taper */ + /* search for gain taper */ tda18271_calc_gain_taper(fe, &freq); tda18271_write_regs(fe, R_EP2, 1); @@ -660,10 +1349,13 @@ 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; u8 std; u32 bw, sgIF = 0; u32 freq = params->frequency; + BUG_ON(!priv->tune || !priv->std); + priv->mode = TDA18271_DIGITAL; /* see table 22 */ @@ -671,13 +1363,13 @@ static int tda18271_set_params(struct dvb_frontend *fe, switch (params->u.vsb.modulation) { case VSB_8: case VSB_16: - std = 0x1b; /* device-specific (spec says 0x1c) */ - sgIF = 5380000; + std = std_map->atsc_6.std_bits; + sgIF = std_map->atsc_6.if_freq; break; case QAM_64: case QAM_256: - std = 0x18; /* device-specific (spec says 0x1d) */ - sgIF = 4000000; + std = std_map->qam_6.std_bits; + sgIF = std_map->qam_6.if_freq; break; default: tda_warn("modulation not set!\n"); @@ -691,19 +1383,19 @@ static int tda18271_set_params(struct dvb_frontend *fe, } else if (fe->ops.info.type == FE_OFDM) { switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - std = 0x1b; /* device-specific (spec says 0x1c) */ bw = 6000000; - sgIF = 3300000; + std = std_map->dvbt_6.std_bits; + sgIF = std_map->dvbt_6.if_freq; break; case BANDWIDTH_7_MHZ: - std = 0x19; /* device-specific (spec says 0x1d) */ bw = 7000000; - sgIF = 3800000; + std = std_map->dvbt_7.std_bits; + sgIF = std_map->dvbt_7.if_freq; break; case BANDWIDTH_8_MHZ: - std = 0x1a; /* device-specific (spec says 0x1e) */ bw = 8000000; - sgIF = 4300000; + std = std_map->dvbt_8.std_bits; + sgIF = std_map->dvbt_8.if_freq; break; default: tda_warn("bandwidth not set!\n"); @@ -714,57 +1406,59 @@ static int tda18271_set_params(struct dvb_frontend *fe, return -EINVAL; } - return tda18271_tune(fe, sgIF, freq, bw, std); + return priv->tune(fe, sgIF, freq, bw, std); } 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; char *mode; u8 std; u32 sgIF, freq = params->frequency * 62500; + BUG_ON(!priv->tune || !priv->std); + priv->mode = TDA18271_ANALOG; - /* see table 22 */ if (params->std & V4L2_STD_MN) { - std = 0x0d; - sgIF = 5750000; + std = std_map->atv_mn.std_bits; + sgIF = std_map->atv_mn.if_freq; mode = "MN"; } else if (params->std & V4L2_STD_B) { - std = 0x0e; - sgIF = 6750000; + std = std_map->atv_b.std_bits; + sgIF = std_map->atv_b.if_freq; mode = "B"; } else if (params->std & V4L2_STD_GH) { - std = 0x0f; - sgIF = 7750000; + std = std_map->atv_gh.std_bits; + sgIF = std_map->atv_gh.if_freq; mode = "GH"; } else if (params->std & V4L2_STD_PAL_I) { - std = 0x0f; - sgIF = 7750000; + std = std_map->atv_i.std_bits; + sgIF = std_map->atv_i.if_freq; mode = "I"; } else if (params->std & V4L2_STD_DK) { - std = 0x0f; - sgIF = 7750000; + std = std_map->atv_dk.std_bits; + sgIF = std_map->atv_dk.if_freq; mode = "DK"; } else if (params->std & V4L2_STD_SECAM_L) { - std = 0x0f; - sgIF = 7750000; + std = std_map->atv_l.std_bits; + sgIF = std_map->atv_l.if_freq; mode = "L"; } else if (params->std & V4L2_STD_SECAM_LC) { - std = 0x0f; - sgIF = 1250000; + std = std_map->atv_lc.std_bits; + sgIF = std_map->atv_lc.if_freq; mode = "L'"; } else { - std = 0x0f; - sgIF = 7750000; + std = std_map->atv_i.std_bits; + sgIF = std_map->atv_i.if_freq; mode = "xx"; } tda_dbg("setting tda18271 to system %s\n", mode); - return tda18271_tune(fe, sgIF, freq, 0, std); + return priv->tune(fe, sgIF, freq, 0, std); } static int tda18271_release(struct dvb_frontend *fe) @@ -800,10 +1494,13 @@ static int tda18271_get_id(struct dvb_frontend *fe) switch (regs[R_ID] & 0x7f) { case 3: name = "TDA18271HD/C1"; + priv->id = TDA18271HDC1; + priv->tune = tda18271c1_tune; break; case 4: name = "TDA18271HD/C2"; - ret = -EPROTONOSUPPORT; + priv->id = TDA18271HDC2; + priv->tune = tda18271c2_tune; break; default: name = "Unknown device"; @@ -846,12 +1543,16 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, priv->i2c_addr = addr; priv->i2c_adap = i2c; priv->gate = gate; + priv->cal_initialized = false; fe->tuner_priv = priv; if (tda18271_get_id(fe) < 0) goto fail; + if (tda18271_assign_map_layout(fe) < 0) + goto fail; + memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, sizeof(struct dvb_tuner_ops)); @@ -866,7 +1567,7 @@ EXPORT_SYMBOL_GPL(tda18271_attach); MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver"); MODULE_AUTHOR("Michael Krufky "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.1"); +MODULE_VERSION("0.2"); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index 912b81e0c76..8552c6ae0d1 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -69,11 +69,54 @@ /*---------------------------------------------------------------------*/ +struct tda18271_rf_tracking_filter_cal { + u32 rfmax; + u8 rfband; + u32 rf1_def; + u32 rf2_def; + u32 rf3_def; + u32 rf1; + u32 rf2; + u32 rf3; + int rf_a1; + int rf_b1; + int rf_a2; + 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, }; +struct tda18271_map_layout; + +enum tda18271_ver { + TDA18271HDC1, + TDA18271HDC2, +}; + struct tda18271_priv { u8 i2c_addr; struct i2c_adapter *i2c_adap; @@ -81,6 +124,16 @@ struct tda18271_priv { enum tda18271_mode mode; enum tda18271_i2c_gate gate; + enum tda18271_ver id; + + unsigned int cal_initialized:1; + + struct tda18271_std_map *std; + struct tda18271_map_layout *maps; + struct tda18271_rf_tracking_filter_cal rf_cal_state[8]; + + int (*tune) (struct dvb_frontend *fe, + u32 ifc, u32 freq, u32 bw, u8 std); u32 frequency; u32 bandwidth; @@ -93,6 +146,7 @@ extern int tda18271_debug; #define DBG_INFO 1 #define DBG_MAP 2 #define DBG_REG 4 +#define DBG_ADV 8 #define tda_printk(kern, fmt, arg...) \ printk(kern "%s: " fmt, __FUNCTION__, ##arg) @@ -117,17 +171,31 @@ enum tda18271_map_type { /* tda18271_map */ RF_CAL, RF_CAL_KMCO, + RF_CAL_DC_OVER_DT, BP_FILTER, RF_BAND, GAIN_TAPER, IR_MEASURE, }; -extern int tda18271_lookup_pll_map(enum tda18271_map_type map_type, +extern int tda18271_lookup_pll_map(struct dvb_frontend *fe, + enum tda18271_map_type map_type, u32 *freq, u8 *post_div, u8 *div); -extern int tda18271_lookup_map(enum tda18271_map_type map_type, +extern int tda18271_lookup_map(struct dvb_frontend *fe, + enum tda18271_map_type map_type, u32 *freq, u8 *val); +extern int tda18271_lookup_thermometer(struct dvb_frontend *fe); + +extern int tda18271_lookup_rf_band(struct dvb_frontend *fe, + u32 *freq, u8 *rf_band); + +extern int tda18271_lookup_cid_target(struct dvb_frontend *fe, + u32 *freq, u8 *cid_target, + u16 *count_limit); + +extern int tda18271_assign_map_layout(struct dvb_frontend *fe); + #endif /* __TDA18271_PRIV_H__ */ /* diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index f8202c40b04..3042e5c873e 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -33,7 +33,7 @@ struct tda18271_map { /*---------------------------------------------------------------------*/ -static struct tda18271_pll_map tda18271_main_pll[] = { +static struct tda18271_pll_map tda18271c1_main_pll[] = { { .lomax = 32000, .pd = 0x5f, .d = 0xf0 }, { .lomax = 35000, .pd = 0x5e, .d = 0xe0 }, { .lomax = 37000, .pd = 0x5d, .d = 0xd0 }, @@ -77,7 +77,51 @@ static struct tda18271_pll_map tda18271_main_pll[] = { { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ }; -static struct tda18271_pll_map tda18271_cal_pll[] = { +static struct tda18271_pll_map tda18271c2_main_pll[] = { + { .lomax = 33125, .pd = 0x57, .d = 0xf0 }, + { .lomax = 35500, .pd = 0x56, .d = 0xe0 }, + { .lomax = 38188, .pd = 0x55, .d = 0xd0 }, + { .lomax = 41375, .pd = 0x54, .d = 0xc0 }, + { .lomax = 45125, .pd = 0x53, .d = 0xb0 }, + { .lomax = 49688, .pd = 0x52, .d = 0xa0 }, + { .lomax = 55188, .pd = 0x51, .d = 0x90 }, + { .lomax = 62125, .pd = 0x50, .d = 0x80 }, + { .lomax = 66250, .pd = 0x47, .d = 0x78 }, + { .lomax = 71000, .pd = 0x46, .d = 0x70 }, + { .lomax = 76375, .pd = 0x45, .d = 0x68 }, + { .lomax = 82750, .pd = 0x44, .d = 0x60 }, + { .lomax = 90250, .pd = 0x43, .d = 0x58 }, + { .lomax = 99375, .pd = 0x42, .d = 0x50 }, + { .lomax = 110375, .pd = 0x41, .d = 0x48 }, + { .lomax = 124250, .pd = 0x40, .d = 0x40 }, + { .lomax = 132500, .pd = 0x37, .d = 0x3c }, + { .lomax = 142000, .pd = 0x36, .d = 0x38 }, + { .lomax = 152750, .pd = 0x35, .d = 0x34 }, + { .lomax = 165500, .pd = 0x34, .d = 0x30 }, + { .lomax = 180500, .pd = 0x33, .d = 0x2c }, + { .lomax = 198750, .pd = 0x32, .d = 0x28 }, + { .lomax = 220750, .pd = 0x31, .d = 0x24 }, + { .lomax = 248500, .pd = 0x30, .d = 0x20 }, + { .lomax = 265000, .pd = 0x27, .d = 0x1e }, + { .lomax = 284000, .pd = 0x26, .d = 0x1c }, + { .lomax = 305500, .pd = 0x25, .d = 0x1a }, + { .lomax = 331000, .pd = 0x24, .d = 0x18 }, + { .lomax = 361000, .pd = 0x23, .d = 0x16 }, + { .lomax = 397500, .pd = 0x22, .d = 0x14 }, + { .lomax = 441500, .pd = 0x21, .d = 0x12 }, + { .lomax = 497000, .pd = 0x20, .d = 0x10 }, + { .lomax = 530000, .pd = 0x17, .d = 0x0f }, + { .lomax = 568000, .pd = 0x16, .d = 0x0e }, + { .lomax = 611000, .pd = 0x15, .d = 0x0d }, + { .lomax = 662000, .pd = 0x14, .d = 0x0c }, + { .lomax = 722000, .pd = 0x13, .d = 0x0b }, + { .lomax = 795000, .pd = 0x12, .d = 0x0a }, + { .lomax = 883000, .pd = 0x11, .d = 0x09 }, + { .lomax = 994000, .pd = 0x10, .d = 0x08 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + +static struct tda18271_pll_map tda18271c1_cal_pll[] = { { .lomax = 33000, .pd = 0xdd, .d = 0xd0 }, { .lomax = 36000, .pd = 0xdc, .d = 0xc0 }, { .lomax = 40000, .pd = 0xdb, .d = 0xb0 }, @@ -116,6 +160,44 @@ static struct tda18271_pll_map tda18271_cal_pll[] = { { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ }; +static struct tda18271_pll_map tda18271c2_cal_pll[] = { + { .lomax = 33813, .pd = 0xdd, .d = 0xd0 }, + { .lomax = 36625, .pd = 0xdc, .d = 0xc0 }, + { .lomax = 39938, .pd = 0xdb, .d = 0xb0 }, + { .lomax = 43938, .pd = 0xda, .d = 0xa0 }, + { .lomax = 48813, .pd = 0xd9, .d = 0x90 }, + { .lomax = 54938, .pd = 0xd8, .d = 0x80 }, + { .lomax = 62813, .pd = 0xd3, .d = 0x70 }, + { .lomax = 67625, .pd = 0xcd, .d = 0x68 }, + { .lomax = 73250, .pd = 0xcc, .d = 0x60 }, + { .lomax = 79875, .pd = 0xcb, .d = 0x58 }, + { .lomax = 87875, .pd = 0xca, .d = 0x50 }, + { .lomax = 97625, .pd = 0xc9, .d = 0x48 }, + { .lomax = 109875, .pd = 0xc8, .d = 0x40 }, + { .lomax = 125625, .pd = 0xc3, .d = 0x38 }, + { .lomax = 135250, .pd = 0xbd, .d = 0x34 }, + { .lomax = 146500, .pd = 0xbc, .d = 0x30 }, + { .lomax = 159750, .pd = 0xbb, .d = 0x2c }, + { .lomax = 175750, .pd = 0xba, .d = 0x28 }, + { .lomax = 195250, .pd = 0xb9, .d = 0x24 }, + { .lomax = 219750, .pd = 0xb8, .d = 0x20 }, + { .lomax = 251250, .pd = 0xb3, .d = 0x1c }, + { .lomax = 270500, .pd = 0xad, .d = 0x1a }, + { .lomax = 293000, .pd = 0xac, .d = 0x18 }, + { .lomax = 319500, .pd = 0xab, .d = 0x16 }, + { .lomax = 351500, .pd = 0xaa, .d = 0x14 }, + { .lomax = 390500, .pd = 0xa9, .d = 0x12 }, + { .lomax = 439500, .pd = 0xa8, .d = 0x10 }, + { .lomax = 502500, .pd = 0xa3, .d = 0x0e }, + { .lomax = 541000, .pd = 0x9d, .d = 0x0d }, + { .lomax = 586000, .pd = 0x9c, .d = 0x0c }, + { .lomax = 639000, .pd = 0x9b, .d = 0x0b }, + { .lomax = 703000, .pd = 0x9a, .d = 0x0a }, + { .lomax = 781000, .pd = 0x99, .d = 0x09 }, + { .lomax = 879000, .pd = 0x98, .d = 0x08 }, + { .lomax = 0, .pd = 0x00, .d = 0x00 }, /* end */ +}; + static struct tda18271_map tda18271_bp_filter[] = { { .rfmax = 62000, .val = 0x00 }, { .rfmax = 84000, .val = 0x01 }, @@ -127,7 +209,7 @@ static struct tda18271_map tda18271_bp_filter[] = { { .rfmax = 0, .val = 0x00 }, /* end */ }; -static struct tda18271_map tda18271_km[] = { +static struct tda18271_map tda18271c1_km[] = { { .rfmax = 61100, .val = 0x74 }, { .rfmax = 350000, .val = 0x40 }, { .rfmax = 720000, .val = 0x30 }, @@ -135,6 +217,15 @@ static struct tda18271_map tda18271_km[] = { { .rfmax = 0, .val = 0x00 }, /* end */ }; +static struct tda18271_map tda18271c2_km[] = { + { .rfmax = 47900, .val = 0x38 }, + { .rfmax = 61100, .val = 0x44 }, + { .rfmax = 350000, .val = 0x30 }, + { .rfmax = 720000, .val = 0x24 }, + { .rfmax = 865000, .val = 0x3c }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + static struct tda18271_map tda18271_rf_band[] = { { .rfmax = 47900, .val = 0x00 }, { .rfmax = 61100, .val = 0x01 }, @@ -236,7 +327,7 @@ static struct tda18271_map tda18271_gain_taper[] = { { .rfmax = 0, .val = 0x00 }, /* end */ }; -static struct tda18271_map tda18271_rf_cal[] = { +static struct tda18271_map tda18271c1_rf_cal[] = { { .rfmax = 41000, .val = 0x1e }, { .rfmax = 43000, .val = 0x30 }, { .rfmax = 45000, .val = 0x43 }, @@ -257,6 +348,446 @@ static struct tda18271_map tda18271_rf_cal[] = { { .rfmax = 0, .val = 0x00 }, /* end */ }; +static struct tda18271_map tda18271c2_rf_cal[] = { + { .rfmax = 41000, .val = 0x0f }, + { .rfmax = 43000, .val = 0x1c }, + { .rfmax = 45000, .val = 0x2f }, + { .rfmax = 46000, .val = 0x39 }, + { .rfmax = 47000, .val = 0x40 }, + { .rfmax = 47900, .val = 0x50 }, + { .rfmax = 49100, .val = 0x16 }, + { .rfmax = 50000, .val = 0x18 }, + { .rfmax = 51000, .val = 0x20 }, + { .rfmax = 53000, .val = 0x28 }, + { .rfmax = 55000, .val = 0x2b }, + { .rfmax = 56000, .val = 0x32 }, + { .rfmax = 57000, .val = 0x35 }, + { .rfmax = 58000, .val = 0x3e }, + { .rfmax = 59000, .val = 0x43 }, + { .rfmax = 60000, .val = 0x4e }, + { .rfmax = 61100, .val = 0x55 }, + { .rfmax = 63000, .val = 0x0f }, + { .rfmax = 64000, .val = 0x11 }, + { .rfmax = 65000, .val = 0x12 }, + { .rfmax = 66000, .val = 0x15 }, + { .rfmax = 67000, .val = 0x16 }, + { .rfmax = 68000, .val = 0x17 }, + { .rfmax = 70000, .val = 0x19 }, + { .rfmax = 71000, .val = 0x1c }, + { .rfmax = 72000, .val = 0x1d }, + { .rfmax = 73000, .val = 0x1f }, + { .rfmax = 74000, .val = 0x20 }, + { .rfmax = 75000, .val = 0x21 }, + { .rfmax = 76000, .val = 0x24 }, + { .rfmax = 77000, .val = 0x25 }, + { .rfmax = 78000, .val = 0x27 }, + { .rfmax = 80000, .val = 0x28 }, + { .rfmax = 81000, .val = 0x29 }, + { .rfmax = 82000, .val = 0x2d }, + { .rfmax = 83000, .val = 0x2e }, + { .rfmax = 84000, .val = 0x2f }, + { .rfmax = 85000, .val = 0x31 }, + { .rfmax = 86000, .val = 0x33 }, + { .rfmax = 87000, .val = 0x34 }, + { .rfmax = 88000, .val = 0x35 }, + { .rfmax = 89000, .val = 0x37 }, + { .rfmax = 90000, .val = 0x38 }, + { .rfmax = 91000, .val = 0x39 }, + { .rfmax = 93000, .val = 0x3c }, + { .rfmax = 94000, .val = 0x3e }, + { .rfmax = 95000, .val = 0x3f }, + { .rfmax = 96000, .val = 0x40 }, + { .rfmax = 97000, .val = 0x42 }, + { .rfmax = 99000, .val = 0x45 }, + { .rfmax = 100000, .val = 0x46 }, + { .rfmax = 102000, .val = 0x48 }, + { .rfmax = 103000, .val = 0x4a }, + { .rfmax = 105000, .val = 0x4d }, + { .rfmax = 106000, .val = 0x4e }, + { .rfmax = 107000, .val = 0x50 }, + { .rfmax = 108000, .val = 0x51 }, + { .rfmax = 110000, .val = 0x54 }, + { .rfmax = 111000, .val = 0x56 }, + { .rfmax = 112000, .val = 0x57 }, + { .rfmax = 113000, .val = 0x58 }, + { .rfmax = 114000, .val = 0x59 }, + { .rfmax = 115000, .val = 0x5c }, + { .rfmax = 116000, .val = 0x5d }, + { .rfmax = 117000, .val = 0x5f }, + { .rfmax = 119000, .val = 0x60 }, + { .rfmax = 120000, .val = 0x64 }, + { .rfmax = 121000, .val = 0x65 }, + { .rfmax = 122000, .val = 0x66 }, + { .rfmax = 123000, .val = 0x68 }, + { .rfmax = 124000, .val = 0x69 }, + { .rfmax = 125000, .val = 0x6c }, + { .rfmax = 126000, .val = 0x6d }, + { .rfmax = 127000, .val = 0x6e }, + { .rfmax = 128000, .val = 0x70 }, + { .rfmax = 129000, .val = 0x71 }, + { .rfmax = 130000, .val = 0x75 }, + { .rfmax = 131000, .val = 0x77 }, + { .rfmax = 132000, .val = 0x78 }, + { .rfmax = 133000, .val = 0x7b }, + { .rfmax = 134000, .val = 0x7e }, + { .rfmax = 135000, .val = 0x81 }, + { .rfmax = 136000, .val = 0x82 }, + { .rfmax = 137000, .val = 0x87 }, + { .rfmax = 138000, .val = 0x88 }, + { .rfmax = 139000, .val = 0x8d }, + { .rfmax = 140000, .val = 0x8e }, + { .rfmax = 141000, .val = 0x91 }, + { .rfmax = 142000, .val = 0x95 }, + { .rfmax = 143000, .val = 0x9a }, + { .rfmax = 144000, .val = 0x9d }, + { .rfmax = 145000, .val = 0xa1 }, + { .rfmax = 146000, .val = 0xa2 }, + { .rfmax = 147000, .val = 0xa4 }, + { .rfmax = 148000, .val = 0xa9 }, + { .rfmax = 149000, .val = 0xae }, + { .rfmax = 150000, .val = 0xb0 }, + { .rfmax = 151000, .val = 0xb1 }, + { .rfmax = 152000, .val = 0xb7 }, + { .rfmax = 153000, .val = 0xbd }, + { .rfmax = 154000, .val = 0x20 }, + { .rfmax = 155000, .val = 0x22 }, + { .rfmax = 156000, .val = 0x24 }, + { .rfmax = 157000, .val = 0x25 }, + { .rfmax = 158000, .val = 0x27 }, + { .rfmax = 159000, .val = 0x29 }, + { .rfmax = 160000, .val = 0x2c }, + { .rfmax = 161000, .val = 0x2d }, + { .rfmax = 163000, .val = 0x2e }, + { .rfmax = 164000, .val = 0x2f }, + { .rfmax = 165000, .val = 0x30 }, + { .rfmax = 166000, .val = 0x11 }, + { .rfmax = 167000, .val = 0x12 }, + { .rfmax = 168000, .val = 0x13 }, + { .rfmax = 169000, .val = 0x14 }, + { .rfmax = 170000, .val = 0x15 }, + { .rfmax = 172000, .val = 0x16 }, + { .rfmax = 173000, .val = 0x17 }, + { .rfmax = 174000, .val = 0x18 }, + { .rfmax = 175000, .val = 0x1a }, + { .rfmax = 176000, .val = 0x1b }, + { .rfmax = 178000, .val = 0x1d }, + { .rfmax = 179000, .val = 0x1e }, + { .rfmax = 180000, .val = 0x1f }, + { .rfmax = 181000, .val = 0x20 }, + { .rfmax = 182000, .val = 0x21 }, + { .rfmax = 183000, .val = 0x22 }, + { .rfmax = 184000, .val = 0x24 }, + { .rfmax = 185000, .val = 0x25 }, + { .rfmax = 186000, .val = 0x26 }, + { .rfmax = 187000, .val = 0x27 }, + { .rfmax = 188000, .val = 0x29 }, + { .rfmax = 189000, .val = 0x2a }, + { .rfmax = 190000, .val = 0x2c }, + { .rfmax = 191000, .val = 0x2d }, + { .rfmax = 192000, .val = 0x2e }, + { .rfmax = 193000, .val = 0x2f }, + { .rfmax = 194000, .val = 0x30 }, + { .rfmax = 195000, .val = 0x33 }, + { .rfmax = 196000, .val = 0x35 }, + { .rfmax = 198000, .val = 0x36 }, + { .rfmax = 200000, .val = 0x38 }, + { .rfmax = 201000, .val = 0x3c }, + { .rfmax = 202000, .val = 0x3d }, + { .rfmax = 203500, .val = 0x3e }, + { .rfmax = 206000, .val = 0x0e }, + { .rfmax = 208000, .val = 0x0f }, + { .rfmax = 212000, .val = 0x10 }, + { .rfmax = 216000, .val = 0x11 }, + { .rfmax = 217000, .val = 0x12 }, + { .rfmax = 218000, .val = 0x13 }, + { .rfmax = 220000, .val = 0x14 }, + { .rfmax = 222000, .val = 0x15 }, + { .rfmax = 225000, .val = 0x16 }, + { .rfmax = 228000, .val = 0x17 }, + { .rfmax = 231000, .val = 0x18 }, + { .rfmax = 234000, .val = 0x19 }, + { .rfmax = 235000, .val = 0x1a }, + { .rfmax = 236000, .val = 0x1b }, + { .rfmax = 237000, .val = 0x1c }, + { .rfmax = 240000, .val = 0x1d }, + { .rfmax = 242000, .val = 0x1f }, + { .rfmax = 247000, .val = 0x20 }, + { .rfmax = 249000, .val = 0x21 }, + { .rfmax = 252000, .val = 0x22 }, + { .rfmax = 253000, .val = 0x23 }, + { .rfmax = 254000, .val = 0x24 }, + { .rfmax = 256000, .val = 0x25 }, + { .rfmax = 259000, .val = 0x26 }, + { .rfmax = 262000, .val = 0x27 }, + { .rfmax = 264000, .val = 0x28 }, + { .rfmax = 267000, .val = 0x29 }, + { .rfmax = 269000, .val = 0x2a }, + { .rfmax = 271000, .val = 0x2b }, + { .rfmax = 273000, .val = 0x2c }, + { .rfmax = 275000, .val = 0x2d }, + { .rfmax = 277000, .val = 0x2e }, + { .rfmax = 279000, .val = 0x2f }, + { .rfmax = 282000, .val = 0x30 }, + { .rfmax = 284000, .val = 0x31 }, + { .rfmax = 286000, .val = 0x32 }, + { .rfmax = 287000, .val = 0x33 }, + { .rfmax = 290000, .val = 0x34 }, + { .rfmax = 293000, .val = 0x35 }, + { .rfmax = 295000, .val = 0x36 }, + { .rfmax = 297000, .val = 0x37 }, + { .rfmax = 300000, .val = 0x38 }, + { .rfmax = 303000, .val = 0x39 }, + { .rfmax = 305000, .val = 0x3a }, + { .rfmax = 306000, .val = 0x3b }, + { .rfmax = 307000, .val = 0x3c }, + { .rfmax = 310000, .val = 0x3d }, + { .rfmax = 312000, .val = 0x3e }, + { .rfmax = 315000, .val = 0x3f }, + { .rfmax = 318000, .val = 0x40 }, + { .rfmax = 320000, .val = 0x41 }, + { .rfmax = 323000, .val = 0x42 }, + { .rfmax = 324000, .val = 0x43 }, + { .rfmax = 325000, .val = 0x44 }, + { .rfmax = 327000, .val = 0x45 }, + { .rfmax = 331000, .val = 0x46 }, + { .rfmax = 334000, .val = 0x47 }, + { .rfmax = 337000, .val = 0x48 }, + { .rfmax = 339000, .val = 0x49 }, + { .rfmax = 340000, .val = 0x4a }, + { .rfmax = 341000, .val = 0x4b }, + { .rfmax = 343000, .val = 0x4c }, + { .rfmax = 345000, .val = 0x4d }, + { .rfmax = 349000, .val = 0x4e }, + { .rfmax = 352000, .val = 0x4f }, + { .rfmax = 353000, .val = 0x50 }, + { .rfmax = 355000, .val = 0x51 }, + { .rfmax = 357000, .val = 0x52 }, + { .rfmax = 359000, .val = 0x53 }, + { .rfmax = 361000, .val = 0x54 }, + { .rfmax = 362000, .val = 0x55 }, + { .rfmax = 364000, .val = 0x56 }, + { .rfmax = 368000, .val = 0x57 }, + { .rfmax = 370000, .val = 0x58 }, + { .rfmax = 372000, .val = 0x59 }, + { .rfmax = 375000, .val = 0x5a }, + { .rfmax = 376000, .val = 0x5b }, + { .rfmax = 377000, .val = 0x5c }, + { .rfmax = 379000, .val = 0x5d }, + { .rfmax = 382000, .val = 0x5e }, + { .rfmax = 384000, .val = 0x5f }, + { .rfmax = 385000, .val = 0x60 }, + { .rfmax = 386000, .val = 0x61 }, + { .rfmax = 388000, .val = 0x62 }, + { .rfmax = 390000, .val = 0x63 }, + { .rfmax = 393000, .val = 0x64 }, + { .rfmax = 394000, .val = 0x65 }, + { .rfmax = 396000, .val = 0x66 }, + { .rfmax = 397000, .val = 0x67 }, + { .rfmax = 398000, .val = 0x68 }, + { .rfmax = 400000, .val = 0x69 }, + { .rfmax = 402000, .val = 0x6a }, + { .rfmax = 403000, .val = 0x6b }, + { .rfmax = 407000, .val = 0x6c }, + { .rfmax = 408000, .val = 0x6d }, + { .rfmax = 409000, .val = 0x6e }, + { .rfmax = 410000, .val = 0x6f }, + { .rfmax = 411000, .val = 0x70 }, + { .rfmax = 412000, .val = 0x71 }, + { .rfmax = 413000, .val = 0x72 }, + { .rfmax = 414000, .val = 0x73 }, + { .rfmax = 417000, .val = 0x74 }, + { .rfmax = 418000, .val = 0x75 }, + { .rfmax = 420000, .val = 0x76 }, + { .rfmax = 422000, .val = 0x77 }, + { .rfmax = 423000, .val = 0x78 }, + { .rfmax = 424000, .val = 0x79 }, + { .rfmax = 427000, .val = 0x7a }, + { .rfmax = 428000, .val = 0x7b }, + { .rfmax = 429000, .val = 0x7d }, + { .rfmax = 432000, .val = 0x7f }, + { .rfmax = 434000, .val = 0x80 }, + { .rfmax = 435000, .val = 0x81 }, + { .rfmax = 436000, .val = 0x83 }, + { .rfmax = 437000, .val = 0x84 }, + { .rfmax = 438000, .val = 0x85 }, + { .rfmax = 439000, .val = 0x86 }, + { .rfmax = 440000, .val = 0x87 }, + { .rfmax = 441000, .val = 0x88 }, + { .rfmax = 442000, .val = 0x89 }, + { .rfmax = 445000, .val = 0x8a }, + { .rfmax = 446000, .val = 0x8b }, + { .rfmax = 447000, .val = 0x8c }, + { .rfmax = 448000, .val = 0x8e }, + { .rfmax = 449000, .val = 0x8f }, + { .rfmax = 450000, .val = 0x90 }, + { .rfmax = 452000, .val = 0x91 }, + { .rfmax = 453000, .val = 0x93 }, + { .rfmax = 454000, .val = 0x94 }, + { .rfmax = 456000, .val = 0x96 }, + { .rfmax = 457000, .val = 0x98 }, + { .rfmax = 461000, .val = 0x11 }, + { .rfmax = 468000, .val = 0x12 }, + { .rfmax = 472000, .val = 0x13 }, + { .rfmax = 473000, .val = 0x14 }, + { .rfmax = 474000, .val = 0x15 }, + { .rfmax = 481000, .val = 0x16 }, + { .rfmax = 486000, .val = 0x17 }, + { .rfmax = 491000, .val = 0x18 }, + { .rfmax = 498000, .val = 0x19 }, + { .rfmax = 499000, .val = 0x1a }, + { .rfmax = 501000, .val = 0x1b }, + { .rfmax = 506000, .val = 0x1c }, + { .rfmax = 511000, .val = 0x1d }, + { .rfmax = 516000, .val = 0x1e }, + { .rfmax = 520000, .val = 0x1f }, + { .rfmax = 521000, .val = 0x20 }, + { .rfmax = 525000, .val = 0x21 }, + { .rfmax = 529000, .val = 0x22 }, + { .rfmax = 533000, .val = 0x23 }, + { .rfmax = 539000, .val = 0x24 }, + { .rfmax = 541000, .val = 0x25 }, + { .rfmax = 547000, .val = 0x26 }, + { .rfmax = 549000, .val = 0x27 }, + { .rfmax = 551000, .val = 0x28 }, + { .rfmax = 556000, .val = 0x29 }, + { .rfmax = 561000, .val = 0x2a }, + { .rfmax = 563000, .val = 0x2b }, + { .rfmax = 565000, .val = 0x2c }, + { .rfmax = 569000, .val = 0x2d }, + { .rfmax = 571000, .val = 0x2e }, + { .rfmax = 577000, .val = 0x2f }, + { .rfmax = 580000, .val = 0x30 }, + { .rfmax = 582000, .val = 0x31 }, + { .rfmax = 584000, .val = 0x32 }, + { .rfmax = 588000, .val = 0x33 }, + { .rfmax = 591000, .val = 0x34 }, + { .rfmax = 596000, .val = 0x35 }, + { .rfmax = 598000, .val = 0x36 }, + { .rfmax = 603000, .val = 0x37 }, + { .rfmax = 604000, .val = 0x38 }, + { .rfmax = 606000, .val = 0x39 }, + { .rfmax = 612000, .val = 0x3a }, + { .rfmax = 615000, .val = 0x3b }, + { .rfmax = 617000, .val = 0x3c }, + { .rfmax = 621000, .val = 0x3d }, + { .rfmax = 622000, .val = 0x3e }, + { .rfmax = 625000, .val = 0x3f }, + { .rfmax = 632000, .val = 0x40 }, + { .rfmax = 633000, .val = 0x41 }, + { .rfmax = 634000, .val = 0x42 }, + { .rfmax = 642000, .val = 0x43 }, + { .rfmax = 643000, .val = 0x44 }, + { .rfmax = 647000, .val = 0x45 }, + { .rfmax = 650000, .val = 0x46 }, + { .rfmax = 652000, .val = 0x47 }, + { .rfmax = 657000, .val = 0x48 }, + { .rfmax = 661000, .val = 0x49 }, + { .rfmax = 662000, .val = 0x4a }, + { .rfmax = 665000, .val = 0x4b }, + { .rfmax = 667000, .val = 0x4c }, + { .rfmax = 670000, .val = 0x4d }, + { .rfmax = 673000, .val = 0x4e }, + { .rfmax = 676000, .val = 0x4f }, + { .rfmax = 677000, .val = 0x50 }, + { .rfmax = 681000, .val = 0x51 }, + { .rfmax = 683000, .val = 0x52 }, + { .rfmax = 686000, .val = 0x53 }, + { .rfmax = 688000, .val = 0x54 }, + { .rfmax = 689000, .val = 0x55 }, + { .rfmax = 691000, .val = 0x56 }, + { .rfmax = 695000, .val = 0x57 }, + { .rfmax = 698000, .val = 0x58 }, + { .rfmax = 703000, .val = 0x59 }, + { .rfmax = 704000, .val = 0x5a }, + { .rfmax = 705000, .val = 0x5b }, + { .rfmax = 707000, .val = 0x5c }, + { .rfmax = 710000, .val = 0x5d }, + { .rfmax = 712000, .val = 0x5e }, + { .rfmax = 717000, .val = 0x5f }, + { .rfmax = 718000, .val = 0x60 }, + { .rfmax = 721000, .val = 0x61 }, + { .rfmax = 722000, .val = 0x62 }, + { .rfmax = 723000, .val = 0x63 }, + { .rfmax = 725000, .val = 0x64 }, + { .rfmax = 727000, .val = 0x65 }, + { .rfmax = 730000, .val = 0x66 }, + { .rfmax = 732000, .val = 0x67 }, + { .rfmax = 735000, .val = 0x68 }, + { .rfmax = 740000, .val = 0x69 }, + { .rfmax = 741000, .val = 0x6a }, + { .rfmax = 742000, .val = 0x6b }, + { .rfmax = 743000, .val = 0x6c }, + { .rfmax = 745000, .val = 0x6d }, + { .rfmax = 747000, .val = 0x6e }, + { .rfmax = 748000, .val = 0x6f }, + { .rfmax = 750000, .val = 0x70 }, + { .rfmax = 752000, .val = 0x71 }, + { .rfmax = 754000, .val = 0x72 }, + { .rfmax = 757000, .val = 0x73 }, + { .rfmax = 758000, .val = 0x74 }, + { .rfmax = 760000, .val = 0x75 }, + { .rfmax = 763000, .val = 0x76 }, + { .rfmax = 764000, .val = 0x77 }, + { .rfmax = 766000, .val = 0x78 }, + { .rfmax = 767000, .val = 0x79 }, + { .rfmax = 768000, .val = 0x7a }, + { .rfmax = 773000, .val = 0x7b }, + { .rfmax = 774000, .val = 0x7c }, + { .rfmax = 776000, .val = 0x7d }, + { .rfmax = 777000, .val = 0x7e }, + { .rfmax = 778000, .val = 0x7f }, + { .rfmax = 779000, .val = 0x80 }, + { .rfmax = 781000, .val = 0x81 }, + { .rfmax = 783000, .val = 0x82 }, + { .rfmax = 784000, .val = 0x83 }, + { .rfmax = 785000, .val = 0x84 }, + { .rfmax = 786000, .val = 0x85 }, + { .rfmax = 793000, .val = 0x86 }, + { .rfmax = 794000, .val = 0x87 }, + { .rfmax = 795000, .val = 0x88 }, + { .rfmax = 797000, .val = 0x89 }, + { .rfmax = 799000, .val = 0x8a }, + { .rfmax = 801000, .val = 0x8b }, + { .rfmax = 802000, .val = 0x8c }, + { .rfmax = 803000, .val = 0x8d }, + { .rfmax = 804000, .val = 0x8e }, + { .rfmax = 810000, .val = 0x90 }, + { .rfmax = 811000, .val = 0x91 }, + { .rfmax = 812000, .val = 0x92 }, + { .rfmax = 814000, .val = 0x93 }, + { .rfmax = 816000, .val = 0x94 }, + { .rfmax = 817000, .val = 0x96 }, + { .rfmax = 818000, .val = 0x97 }, + { .rfmax = 820000, .val = 0x98 }, + { .rfmax = 821000, .val = 0x99 }, + { .rfmax = 822000, .val = 0x9a }, + { .rfmax = 828000, .val = 0x9b }, + { .rfmax = 829000, .val = 0x9d }, + { .rfmax = 830000, .val = 0x9f }, + { .rfmax = 831000, .val = 0xa0 }, + { .rfmax = 833000, .val = 0xa1 }, + { .rfmax = 835000, .val = 0xa2 }, + { .rfmax = 836000, .val = 0xa3 }, + { .rfmax = 837000, .val = 0xa4 }, + { .rfmax = 838000, .val = 0xa6 }, + { .rfmax = 840000, .val = 0xa8 }, + { .rfmax = 842000, .val = 0xa9 }, + { .rfmax = 845000, .val = 0xaa }, + { .rfmax = 846000, .val = 0xab }, + { .rfmax = 847000, .val = 0xad }, + { .rfmax = 848000, .val = 0xae }, + { .rfmax = 852000, .val = 0xaf }, + { .rfmax = 853000, .val = 0xb0 }, + { .rfmax = 858000, .val = 0xb1 }, + { .rfmax = 860000, .val = 0xb2 }, + { .rfmax = 861000, .val = 0xb3 }, + { .rfmax = 862000, .val = 0xb4 }, + { .rfmax = 863000, .val = 0xb6 }, + { .rfmax = 864000, .val = 0xb8 }, + { .rfmax = 865000, .val = 0xb9 }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + static struct tda18271_map tda18271_ir_measure[] = { { .rfmax = 30000, .val = 4 }, { .rfmax = 200000, .val = 5 }, @@ -265,23 +796,293 @@ static struct tda18271_map tda18271_ir_measure[] = { { .rfmax = 0, .val = 0 }, /* end */ }; +static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = { + { .rfmax = 47900, .val = 0x00 }, + { .rfmax = 55000, .val = 0x00 }, + { .rfmax = 61100, .val = 0x0a }, + { .rfmax = 64000, .val = 0x0a }, + { .rfmax = 82000, .val = 0x14 }, + { .rfmax = 84000, .val = 0x19 }, + { .rfmax = 119000, .val = 0x1c }, + { .rfmax = 124000, .val = 0x20 }, + { .rfmax = 129000, .val = 0x2a }, + { .rfmax = 134000, .val = 0x32 }, + { .rfmax = 139000, .val = 0x39 }, + { .rfmax = 144000, .val = 0x3e }, + { .rfmax = 149000, .val = 0x3f }, + { .rfmax = 152600, .val = 0x40 }, + { .rfmax = 154000, .val = 0x40 }, + { .rfmax = 164700, .val = 0x41 }, + { .rfmax = 203500, .val = 0x32 }, + { .rfmax = 353000, .val = 0x19 }, + { .rfmax = 356000, .val = 0x1a }, + { .rfmax = 359000, .val = 0x1b }, + { .rfmax = 363000, .val = 0x1c }, + { .rfmax = 366000, .val = 0x1d }, + { .rfmax = 369000, .val = 0x1e }, + { .rfmax = 373000, .val = 0x1f }, + { .rfmax = 376000, .val = 0x20 }, + { .rfmax = 379000, .val = 0x21 }, + { .rfmax = 383000, .val = 0x22 }, + { .rfmax = 386000, .val = 0x23 }, + { .rfmax = 389000, .val = 0x24 }, + { .rfmax = 393000, .val = 0x25 }, + { .rfmax = 396000, .val = 0x26 }, + { .rfmax = 399000, .val = 0x27 }, + { .rfmax = 402000, .val = 0x28 }, + { .rfmax = 404000, .val = 0x29 }, + { .rfmax = 407000, .val = 0x2a }, + { .rfmax = 409000, .val = 0x2b }, + { .rfmax = 412000, .val = 0x2c }, + { .rfmax = 414000, .val = 0x2d }, + { .rfmax = 417000, .val = 0x2e }, + { .rfmax = 419000, .val = 0x2f }, + { .rfmax = 422000, .val = 0x30 }, + { .rfmax = 424000, .val = 0x31 }, + { .rfmax = 427000, .val = 0x32 }, + { .rfmax = 429000, .val = 0x33 }, + { .rfmax = 432000, .val = 0x34 }, + { .rfmax = 434000, .val = 0x35 }, + { .rfmax = 437000, .val = 0x36 }, + { .rfmax = 439000, .val = 0x37 }, + { .rfmax = 442000, .val = 0x38 }, + { .rfmax = 444000, .val = 0x39 }, + { .rfmax = 447000, .val = 0x3a }, + { .rfmax = 449000, .val = 0x3b }, + { .rfmax = 457800, .val = 0x3c }, + { .rfmax = 465000, .val = 0x0f }, + { .rfmax = 477000, .val = 0x12 }, + { .rfmax = 483000, .val = 0x14 }, + { .rfmax = 502000, .val = 0x19 }, + { .rfmax = 508000, .val = 0x1b }, + { .rfmax = 519000, .val = 0x1c }, + { .rfmax = 522000, .val = 0x1d }, + { .rfmax = 524000, .val = 0x1e }, + { .rfmax = 534000, .val = 0x1f }, + { .rfmax = 549000, .val = 0x20 }, + { .rfmax = 554000, .val = 0x22 }, + { .rfmax = 584000, .val = 0x24 }, + { .rfmax = 589000, .val = 0x26 }, + { .rfmax = 658000, .val = 0x27 }, + { .rfmax = 664000, .val = 0x2c }, + { .rfmax = 669000, .val = 0x2d }, + { .rfmax = 699000, .val = 0x2e }, + { .rfmax = 704000, .val = 0x30 }, + { .rfmax = 709000, .val = 0x31 }, + { .rfmax = 714000, .val = 0x32 }, + { .rfmax = 724000, .val = 0x33 }, + { .rfmax = 729000, .val = 0x36 }, + { .rfmax = 739000, .val = 0x38 }, + { .rfmax = 744000, .val = 0x39 }, + { .rfmax = 749000, .val = 0x3b }, + { .rfmax = 754000, .val = 0x3c }, + { .rfmax = 759000, .val = 0x3d }, + { .rfmax = 764000, .val = 0x3e }, + { .rfmax = 769000, .val = 0x3f }, + { .rfmax = 774000, .val = 0x40 }, + { .rfmax = 779000, .val = 0x41 }, + { .rfmax = 784000, .val = 0x43 }, + { .rfmax = 789000, .val = 0x46 }, + { .rfmax = 794000, .val = 0x48 }, + { .rfmax = 799000, .val = 0x4b }, + { .rfmax = 804000, .val = 0x4f }, + { .rfmax = 809000, .val = 0x54 }, + { .rfmax = 814000, .val = 0x59 }, + { .rfmax = 819000, .val = 0x5d }, + { .rfmax = 824000, .val = 0x61 }, + { .rfmax = 829000, .val = 0x68 }, + { .rfmax = 834000, .val = 0x6e }, + { .rfmax = 839000, .val = 0x75 }, + { .rfmax = 844000, .val = 0x7e }, + { .rfmax = 849000, .val = 0x82 }, + { .rfmax = 854000, .val = 0x84 }, + { .rfmax = 859000, .val = 0x8f }, + { .rfmax = 865000, .val = 0x9a }, + { .rfmax = 0, .val = 0x00 }, /* end */ +}; + +/*---------------------------------------------------------------------*/ + +struct tda18271_thermo_map { + u8 d; + u8 r0; + u8 r1; +}; + +static struct tda18271_thermo_map tda18271_thermometer[] = { + { .d = 0x00, .r0 = 60, .r1 = 92 }, + { .d = 0x01, .r0 = 62, .r1 = 94 }, + { .d = 0x02, .r0 = 66, .r1 = 98 }, + { .d = 0x03, .r0 = 64, .r1 = 96 }, + { .d = 0x04, .r0 = 74, .r1 = 106 }, + { .d = 0x05, .r0 = 72, .r1 = 104 }, + { .d = 0x06, .r0 = 68, .r1 = 100 }, + { .d = 0x07, .r0 = 70, .r1 = 102 }, + { .d = 0x08, .r0 = 90, .r1 = 122 }, + { .d = 0x09, .r0 = 88, .r1 = 120 }, + { .d = 0x0a, .r0 = 84, .r1 = 116 }, + { .d = 0x0b, .r0 = 86, .r1 = 118 }, + { .d = 0x0c, .r0 = 76, .r1 = 108 }, + { .d = 0x0d, .r0 = 78, .r1 = 110 }, + { .d = 0x0e, .r0 = 82, .r1 = 114 }, + { .d = 0x0f, .r0 = 80, .r1 = 112 }, + { .d = 0x00, .r0 = 0, .r1 = 0 }, /* end */ +}; + +int tda18271_lookup_thermometer(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + unsigned char *regs = priv->tda18271_regs; + int val, i = 0; + + while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) { + if (tda18271_thermometer[i + 1].d == 0) + break; + i++; + } + + if ((regs[R_TM] & 0x20) == 0x20) + val = tda18271_thermometer[i].r1; + else + val = tda18271_thermometer[i].r0; + + tda_map("(%d) tm = %d\n", i, val); + + return val; +} + +/*---------------------------------------------------------------------*/ + +struct tda18271_cid_target_map { + u32 rfmax; + u8 target; + u16 limit; +}; + +static struct tda18271_cid_target_map tda18271_cid_target[] = { + { .rfmax = 46000, .target = 0x04, .limit = 1800 }, + { .rfmax = 52200, .target = 0x0a, .limit = 1500 }, + { .rfmax = 79100, .target = 0x01, .limit = 4000 }, + { .rfmax = 136800, .target = 0x18, .limit = 4000 }, + { .rfmax = 156700, .target = 0x18, .limit = 4000 }, + { .rfmax = 156700, .target = 0x18, .limit = 4000 }, + { .rfmax = 186250, .target = 0x0a, .limit = 4000 }, + { .rfmax = 230000, .target = 0x0a, .limit = 4000 }, + { .rfmax = 345000, .target = 0x18, .limit = 4000 }, + { .rfmax = 426000, .target = 0x0e, .limit = 4000 }, + { .rfmax = 489500, .target = 0x1e, .limit = 4000 }, + { .rfmax = 697500, .target = 0x32, .limit = 4000 }, + { .rfmax = 842000, .target = 0x3a, .limit = 4000 }, + { .rfmax = 0, .target = 0x00, .limit = 0 }, /* end */ +}; + +int tda18271_lookup_cid_target(struct dvb_frontend *fe, + u32 *freq, u8 *cid_target, u16 *count_limit) +{ + int i = 0; + + while ((tda18271_cid_target[i].rfmax * 1000) < *freq) { + if (tda18271_cid_target[i + 1].rfmax == 0) + break; + i++; + } + *cid_target = tda18271_cid_target[i].target; + *count_limit = tda18271_cid_target[i].limit; + + tda_map("(%d) cid_target = %02x, count_limit = %d\n", i, + tda18271_cid_target[i].target, tda18271_cid_target[i].limit); + + return 0; +} + +/*---------------------------------------------------------------------*/ + +static struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = { + { .rfmax = 47900, .rfband = 0x00, + .rf1_def = 46000, .rf2_def = 0, .rf3_def = 0 }, + { .rfmax = 61100, .rfband = 0x01, + .rf1_def = 52200, .rf2_def = 0, .rf3_def = 0 }, + { .rfmax = 152600, .rfband = 0x02, + .rf1_def = 70100, .rf2_def = 136800, .rf3_def = 0 }, + { .rfmax = 164700, .rfband = 0x03, + .rf1_def = 156700, .rf2_def = 0, .rf3_def = 0 }, + { .rfmax = 203500, .rfband = 0x04, + .rf1_def = 186250, .rf2_def = 0, .rf3_def = 0 }, + { .rfmax = 457800, .rfband = 0x05, + .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 }, + { .rfmax = 865000, .rfband = 0x06, + .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 }, + { .rfmax = 0, .rfband = 0x00, + .rf1_def = 0, .rf2_def = 0, .rf3_def = 0 }, /* end */ +}; + +int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band) +{ + struct tda18271_priv *priv = fe->tuner_priv; + struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; + int i = 0; + + while ((map[i].rfmax * 1000) < *freq) { + if (tda18271_debug & DBG_ADV) + tda_map("(%d) rfmax = %d < freq = %d, " + "rf1_def = %d, rf2_def = %d, rf3_def = %d, " + "rf1 = %d, rf2 = %d, rf3 = %d, " + "rf_a1 = %d, rf_a2 = %d, " + "rf_b1 = %d, rf_b2 = %d\n", + i, map[i].rfmax * 1000, *freq, + map[i].rf1_def, map[i].rf2_def, map[i].rf3_def, + map[i].rf1, map[i].rf2, map[i].rf3, + map[i].rf_a1, map[i].rf_a2, + map[i].rf_b1, map[i].rf_b2); + if (map[i].rfmax == 0) + return -EINVAL; + i++; + } + if (rf_band) + *rf_band = map[i].rfband; + + tda_map("(%d) rf_band = %02x\n", i, map[i].rfband); + + return i; +} + /*---------------------------------------------------------------------*/ -int tda18271_lookup_pll_map(enum tda18271_map_type map_type, +struct tda18271_map_layout { + struct tda18271_pll_map *main_pll; + struct tda18271_pll_map *cal_pll; + + struct tda18271_map *rf_cal; + struct tda18271_map *rf_cal_kmco; + struct tda18271_map *rf_cal_dc_over_dt; + + struct tda18271_map *bp_filter; + struct tda18271_map *rf_band; + struct tda18271_map *gain_taper; + struct tda18271_map *ir_measure; +}; + +/*---------------------------------------------------------------------*/ + +int tda18271_lookup_pll_map(struct dvb_frontend *fe, + enum tda18271_map_type map_type, u32 *freq, u8 *post_div, u8 *div) { + struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_pll_map *map = NULL; unsigned int i = 0; char *map_name; int ret = 0; + BUG_ON(!priv->maps); + switch (map_type) { case MAIN_PLL: - map = tda18271_main_pll; + map = priv->maps->main_pll; map_name = "main_pll"; break; case CAL_PLL: - map = tda18271_cal_pll; + map = priv->maps->cal_pll; map_name = "cal_pll"; break; default: @@ -308,44 +1109,53 @@ int tda18271_lookup_pll_map(enum tda18271_map_type map_type, *post_div = map[i].pd; *div = map[i].d; - tda_map("%s: post div = 0x%02x, div = 0x%02x\n", - map_name, *post_div, *div); + tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n", + i, map_name, *post_div, *div); fail: return ret; } -int tda18271_lookup_map(enum tda18271_map_type map_type, u32 *freq, u8 *val) +int tda18271_lookup_map(struct dvb_frontend *fe, + enum tda18271_map_type map_type, + u32 *freq, u8 *val) { + struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_map *map = NULL; unsigned int i = 0; char *map_name; int ret = 0; + BUG_ON(!priv->maps); + switch (map_type) { case BP_FILTER: - map = tda18271_bp_filter; + map = priv->maps->bp_filter; map_name = "bp_filter"; break; case RF_CAL_KMCO: - map = tda18271_km; + map = priv->maps->rf_cal_kmco; map_name = "km"; break; case RF_BAND: - map = tda18271_rf_band; + map = priv->maps->rf_band; map_name = "rf_band"; break; case GAIN_TAPER: - map = tda18271_gain_taper; + map = priv->maps->gain_taper; map_name = "gain_taper"; break; case RF_CAL: - map = tda18271_rf_cal; + map = priv->maps->rf_cal; map_name = "rf_cal"; break; case IR_MEASURE: - map = tda18271_ir_measure; + map = priv->maps->ir_measure; map_name = "ir_measure"; break; + case RF_CAL_DC_OVER_DT: + map = priv->maps->rf_cal_dc_over_dt; + map_name = "rf_cal_dc_over_dt"; + break; default: /* we should never get here */ map_name = "undefined"; @@ -369,11 +1179,99 @@ int tda18271_lookup_map(enum tda18271_map_type map_type, u32 *freq, u8 *val) } *val = map[i].val; - tda_map("%s: 0x%02x\n", map_name, *val); + tda_map("(%d) %s: 0x%02x\n", i, map_name, *val); fail: return ret; } +/*---------------------------------------------------------------------*/ + +static struct tda18271_std_map tda18271c1_std_map = { + .atv_b = { .if_freq = 6750000, .std_bits = 0x0e }, + .atv_dk = { .if_freq = 7750000, .std_bits = 0x0f }, + .atv_gh = { .if_freq = 7750000, .std_bits = 0x0f }, + .atv_i = { .if_freq = 7750000, .std_bits = 0x0f }, + .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 }, + .qam_8 = { .if_freq = 5000000, .std_bits = 0x1f }, +}; + +static struct tda18271_std_map tda18271c2_std_map = { + .atv_b = { .if_freq = 6000000, .std_bits = 0x0d }, + .atv_dk = { .if_freq = 6900000, .std_bits = 0x0e }, + .atv_gh = { .if_freq = 7100000, .std_bits = 0x0e }, + .atv_i = { .if_freq = 7250000, .std_bits = 0x0e }, + .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 }, + .dvbt_6 = { .if_freq = 3300000, .std_bits = 0x1c }, + .dvbt_7 = { .if_freq = 3500000, .std_bits = 0x1c }, + .dvbt_8 = { .if_freq = 4000000, .std_bits = 0x1d }, + .qam_6 = { .if_freq = 4000000, .std_bits = 0x1d }, + .qam_8 = { .if_freq = 5000000, .std_bits = 0x1f }, +}; + +/*---------------------------------------------------------------------*/ + +static struct tda18271_map_layout tda18271c1_map_layout = { + .main_pll = tda18271c1_main_pll, + .cal_pll = tda18271c1_cal_pll, + + .rf_cal = tda18271c1_rf_cal, + .rf_cal_kmco = tda18271c1_km, + + .bp_filter = tda18271_bp_filter, + .rf_band = tda18271_rf_band, + .gain_taper = tda18271_gain_taper, + .ir_measure = tda18271_ir_measure, +}; + +static struct tda18271_map_layout tda18271c2_map_layout = { + .main_pll = tda18271c2_main_pll, + .cal_pll = tda18271c2_cal_pll, + + .rf_cal = tda18271c2_rf_cal, + .rf_cal_kmco = tda18271c2_km, + + .rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt, + + .bp_filter = tda18271_bp_filter, + .rf_band = tda18271_rf_band, + .gain_taper = tda18271_gain_taper, + .ir_measure = tda18271_ir_measure, +}; + +int tda18271_assign_map_layout(struct dvb_frontend *fe) +{ + struct tda18271_priv *priv = fe->tuner_priv; + int ret = 0; + + switch (priv->id) { + case TDA18271HDC1: + priv->maps = &tda18271c1_map_layout; + priv->std = &tda18271c1_std_map; + break; + case TDA18271HDC2: + priv->maps = &tda18271c2_map_layout; + priv->std = &tda18271c2_std_map; + break; + default: + ret = -EINVAL; + break; + } + memcpy(priv->rf_cal_state, &tda18271_rf_band_template, + sizeof(tda18271_rf_band_template)); + + return ret; +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index bb62d5629af..54d261a2f25 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -570,7 +570,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) return -EREMOTEIO; } - if (data == 0x83) { + if ((data == 0x83) || (data == 0x84)) { priv->ver |= TDA18271; tda18271_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, -- cgit v1.2.3-70-g09d2 From f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 2 Jan 2008 03:01:54 -0300 Subject: 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 82 +++++++++++++++++++++++++-- drivers/media/dvb/frontends/tda18271-priv.h | 23 +------- drivers/media/dvb/frontends/tda18271-tables.c | 18 +++--- drivers/media/dvb/frontends/tda18271.h | 30 +++++++++- drivers/media/video/cx23885/cx23885-dvb.c | 12 +++- drivers/media/video/tda8290.c | 6 +- 6 files changed, 131 insertions(+), 40 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index 537d520de22..b17ab4ace08 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -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; diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index deb375ea253..6e04258ca6f 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -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, diff --git a/drivers/media/dvb/frontends/tda18271-tables.c b/drivers/media/dvb/frontends/tda18271-tables.c index 46f1d4ddda3..2f8ea72bcab 100644 --- a/drivers/media/dvb/frontends/tda18271-tables.c +++ b/drivers/media/dvb/frontends/tda18271-tables.c @@ -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; diff --git a/drivers/media/dvb/frontends/tda18271.h b/drivers/media/dvb/frontends/tda18271.h index f5356810331..36a3a548a6f 100644 --- a/drivers/media/dvb/frontends/tda18271.h +++ b/drivers/media/dvb/frontends/tda18271.h @@ -24,21 +24,47 @@ #include #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; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 81dd47f6f65..948a7fb7ed0 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -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: diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 54d261a2f25..eab530708a4 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -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; -- cgit v1.2.3-70-g09d2 From a4f263b587573f47cc6bc7ad85e5f650169d48f6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 6 Jan 2008 15:52:56 -0300 Subject: V4L/DVB (6986): tda18271: share state between analog and digital tuner instances Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda18271-fe.c | 93 ++++++++++++++++++++++------- drivers/media/dvb/frontends/tda18271-priv.h | 3 + drivers/media/video/tda8290.c | 9 ++- 3 files changed, 81 insertions(+), 24 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index e860f4c009c..aa93e155062 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c @@ -27,6 +27,9 @@ module_param_named(debug, tda18271_debug, int, 0644); MODULE_PARM_DESC(debug, "set debug level " "(info=1, map=2, reg=4, adv=8 (or-able))"); +static LIST_HEAD(tda18271_list); +static DEFINE_MUTEX(tda18271_list_mutex); + /*---------------------------------------------------------------------*/ static int tda18271_ir_cal_init(struct dvb_frontend *fe) @@ -936,8 +939,24 @@ fail: static int tda18271_release(struct dvb_frontend *fe) { - kfree(fe->tuner_priv); + struct tda18271_priv *priv = fe->tuner_priv; + + mutex_lock(&tda18271_list_mutex); + + priv->count--; + + if (!priv->count) { + tda_dbg("destroying instance @ %d-%04x\n", + i2c_adapter_id(priv->i2c_adap), + priv->i2c_addr); + list_del(&priv->tda18271_list); + + kfree(priv); + } + mutex_unlock(&tda18271_list_mutex); + fe->tuner_priv = NULL; + return 0; } @@ -1071,43 +1090,73 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, struct tda18271_config *cfg) { struct tda18271_priv *priv = NULL; + int state_found = 0; + + mutex_lock(&tda18271_list_mutex); + + list_for_each_entry(priv, &tda18271_list, tda18271_list) { + if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) && + (priv->i2c_addr == addr)) { + tda_dbg("attaching existing tuner @ %d-%04x\n", + i2c_adapter_id(priv->i2c_adap), + priv->i2c_addr); + priv->count++; + fe->tuner_priv = priv; + state_found = 1; + /* allow dvb driver to override i2c gate setting */ + if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) + priv->gate = cfg->gate; + break; + } + } + if (state_found == 0) { + tda_dbg("creating new tuner instance @ %d-%04x\n", + i2c_adapter_id(i2c), addr); + + priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); + if (priv == NULL) { + mutex_unlock(&tda18271_list_mutex); + return NULL; + } - priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; + priv->i2c_addr = addr; + priv->i2c_adap = i2c; + priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; + priv->cal_initialized = false; + mutex_init(&priv->lock); + priv->count++; - priv->i2c_addr = addr; - priv->i2c_adap = i2c; - priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; - priv->cal_initialized = false; - mutex_init(&priv->lock); + fe->tuner_priv = priv; - fe->tuner_priv = priv; + list_add_tail(&priv->tda18271_list, &tda18271_list); - if (tda18271_get_id(fe) < 0) - goto fail; + if (tda18271_get_id(fe) < 0) + goto fail; - if (tda18271_assign_map_layout(fe) < 0) - goto fail; + if (tda18271_assign_map_layout(fe) < 0) + goto fail; - memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, - sizeof(struct dvb_tuner_ops)); + mutex_lock(&priv->lock); + tda18271_init_regs(fe); + mutex_unlock(&priv->lock); + } /* 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); - - mutex_lock(&priv->lock); + mutex_unlock(&tda18271_list_mutex); - tda18271_init_regs(fe); + memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, + sizeof(struct dvb_tuner_ops)); - mutex_unlock(&priv->lock); + if (tda18271_debug & DBG_MAP) + tda18271_dump_std_map(fe); return fe; fail: + mutex_unlock(&tda18271_list_mutex); + tda18271_release(fe); return NULL; } diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index af89cfab006..5c04d63ae84 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h @@ -102,10 +102,13 @@ struct tda18271_priv { struct i2c_adapter *i2c_adap; unsigned char tda18271_regs[TDA18271_NUM_REGS]; + struct list_head tda18271_list; + enum tda18271_mode mode; enum tda18271_i2c_gate gate; enum tda18271_ver id; + unsigned int count; unsigned int tm_rfcal; unsigned int cal_initialized:1; diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index eab530708a4..4ac7c043889 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -502,8 +502,13 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) static void tda829x_release(struct dvb_frontend *fe) { - if (fe->ops.tuner_ops.release) - fe->ops.tuner_ops.release(fe); + struct tda8290_priv *priv = fe->analog_demod_priv; + + /* dont try to release the tuner + * if we didn't attach it from this module */ + if ((priv->ver > TDA8290) && (priv->ver > TDA8295)) + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); kfree(fe->analog_demod_priv); fe->analog_demod_priv = NULL; -- cgit v1.2.3-70-g09d2 From 006ed1ecf2c62659e5dd902350a7eb209b8a5257 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 9 Jan 2008 10:44:27 -0300 Subject: V4L/DVB (6989): tda18271: clean up chip id logic in tda829x_release This test is easier to read. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 4ac7c043889..3e593a3d903 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -504,9 +504,9 @@ static void tda829x_release(struct dvb_frontend *fe) { struct tda8290_priv *priv = fe->analog_demod_priv; - /* dont try to release the tuner - * if we didn't attach it from this module */ - if ((priv->ver > TDA8290) && (priv->ver > TDA8295)) + /* only try to release the tuner if we've + * attached it from within this module */ + if (priv->ver & (TDA18271 | TDA8275 | TDA8275A)) if (fe->ops.tuner_ops.release) fe->ops.tuner_ops.release(fe); -- cgit v1.2.3-70-g09d2 From 0f2ce9834246519e483e89dbc7225fe1fcbd30a8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 21 Jan 2008 10:55:37 -0300 Subject: V4L/DVB (7055): make tuner names consistent with standard cases Change TDA9887 to tda9887. TDA8290 shall reflect the actual hardware present in its name, ie: tda8295+18271 tda8290+8275a Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda8290.c | 8 ++------ drivers/media/video/tda9887.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/media/video/tda8290.c') diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 3e593a3d903..55bc89a6f06 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -645,9 +645,6 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) } static struct analog_demod_ops tda8290_ops = { - .info = { - .name = "TDA8290", - }, .set_params = tda8290_set_params, .has_signal = tda8290_has_signal, .standby = tda8290_standby, @@ -656,9 +653,6 @@ static struct analog_demod_ops tda8290_ops = { }; static struct analog_demod_ops tda8295_ops = { - .info = { - .name = "TDA8295", - }, .set_params = tda8295_set_params, .has_signal = tda8295_has_signal, .standby = tda8295_standby, @@ -731,6 +725,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, } tuner_info("type set to %s\n", name); + fe->ops.analog_ops.info.name = name; + if (priv->ver & TDA8290) { tda8290_init_tuner(fe); tda8290_init_if(fe); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index d3aabe2d146..106c93b8203 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -650,7 +650,7 @@ static void tda9887_release(struct dvb_frontend *fe) static struct analog_demod_ops tda9887_ops = { .info = { - .name = "TDA9887", + .name = "tda9887", }, .set_params = tda9887_set_params, .standby = tda9887_standby, -- cgit v1.2.3-70-g09d2