diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 4d4d0bb5920a..62a65efdf8d6 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -64,6 +64,7 @@ struct dvb_pll_desc { void (*set)(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params); u8 *initdata; + u8 *initdata2; u8 *sleepdata; int count; struct { @@ -321,26 +322,73 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { static void opera1_bw(struct dvb_frontend *fe, u8 *buf, const struct dvb_frontend_parameters *params) { - if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) - buf[2] |= 0x08; + struct dvb_pll_priv *priv = fe->tuner_priv; + u32 b_w = (params->u.qpsk.symbol_rate * 27) / 32000; + struct i2c_msg msg = { + .addr = priv->pll_i2c_address, + .flags = 0, + .buf = buf, + .len = 4 + }; + int result; + u8 lpf; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + result = i2c_transfer(priv->i2c, &msg, 1); + if (result != 1) + printk(KERN_ERR "%s: i2c_transfer failed:%d", + __func__, result); + + if (b_w <= 10000) + lpf = 0xc; + else if (b_w <= 12000) + lpf = 0x2; + else if (b_w <= 14000) + lpf = 0xa; + else if (b_w <= 16000) + lpf = 0x6; + else if (b_w <= 18000) + lpf = 0xe; + else if (b_w <= 20000) + lpf = 0x1; + else if (b_w <= 22000) + lpf = 0x9; + else if (b_w <= 24000) + lpf = 0x5; + else if (b_w <= 26000) + lpf = 0xd; + else if (b_w <= 28000) + lpf = 0x3; + else + lpf = 0xb; + buf[2] ^= 0x1c; /* Flip bits 3-5 */ + /* Set lpf */ + buf[2] |= ((lpf >> 2) & 0x3) << 3; + buf[3] |= (lpf & 0x3) << 2; + + return; } static struct dvb_pll_desc dvb_pll_opera1 = { .name = "Opera Tuner", .min = 900000, .max = 2250000, + .initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 }, + .initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 }, .iffreq= 0, .set = opera1_bw, .count = 8, .entries = { - { 1064000, 500, 0xe5, 0xc6 }, - { 1169000, 500, 0xe5, 0xe6 }, - { 1299000, 500, 0xe5, 0x24 }, - { 1444000, 500, 0xe5, 0x44 }, - { 1606000, 500, 0xe5, 0x64 }, - { 1777000, 500, 0xe5, 0x84 }, - { 1941000, 500, 0xe5, 0xa4 }, - { 2250000, 500, 0xe5, 0xc4 }, + { 1064000, 500, 0xf9, 0xc2 }, + { 1169000, 500, 0xf9, 0xe2 }, + { 1299000, 500, 0xf9, 0x20 }, + { 1444000, 500, 0xf9, 0x40 }, + { 1606000, 500, 0xf9, 0x60 }, + { 1777000, 500, 0xf9, 0x80 }, + { 1941000, 500, 0xf9, 0xa0 }, + { 2250000, 500, 0xf9, 0xc0 }, } }; @@ -648,8 +696,17 @@ static int dvb_pll_init(struct dvb_frontend *fe) int result; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + result = i2c_transfer(priv->i2c, &msg, 1); + if (result != 1) return result; + if (priv->pll_desc->initdata2) { + msg.buf = priv->pll_desc->initdata2 + 1; + msg.len = priv->pll_desc->initdata2[0]; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + result = i2c_transfer(priv->i2c, &msg, 1); + if (result != 1) + return result; } return 0; }