summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/frontends/ves1820.c
diff options
context:
space:
mode:
authorMichael Hunold <devnull@localhost>2004-08-09 11:11:59 +0000
committerMichael Hunold <devnull@localhost>2004-08-09 11:11:59 +0000
commitaa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0 (patch)
treef69a3066d76ac2afa40a6d85fec0887d683abbd0 /linux/drivers/media/dvb/frontends/ves1820.c
parentf0e186adfa45c6d6fc266051e392c11510afe154 (diff)
downloadmediapointer-dvb-s2-aa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0.tar.gz
mediapointer-dvb-s2-aa5175a2e68ec4ecf4b63ff5ec12cdfeb7fa8dd0.tar.bz2
- convert to kernel i2c
- whitespace and coding style cleanup - temporarily removed the possibility to set the initial pwm value via module parameters
Diffstat (limited to 'linux/drivers/media/dvb/frontends/ves1820.c')
-rw-r--r--linux/drivers/media/dvb/frontends/ves1820.c660
1 files changed, 341 insertions, 319 deletions
diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c
index 3008d985d..7bf168e85 100644
--- a/linux/drivers/media/dvb/frontends/ves1820.c
+++ b/linux/drivers/media/dvb/frontends/ves1820.c
@@ -32,60 +32,30 @@
#include "dvb_functions.h"
#include "dvb_i2c.h"
-#if 0
-#define dprintk(x...) printk(x)
-#else
-#define dprintk(x...)
-#endif
+/* I2C_DRIVERID_VES1820 is already defined in i2c-id.h */
+static int debug = 0;
+#define dprintk if (debug) printk
-#define MAX_UNITS 4
-static int pwm[MAX_UNITS] = { -1, -1, -1, -1 };
static int verbose;
-/**
- * since we need only a few bits to store internal state we don't allocate
- * extra memory but use frontend->data as bitfield
- */
+struct ves1820_state {
+ int pwm;
+ u8 reg0;
+ int tuner;
+ u8 demod_addr;
+ struct i2c_adapter *i2c;
+ struct dvb_adapter *dvb;
+};
-#define SET_PWM(data,pwm) do { \
- long d = (long)data; \
- d &= ~0xff; \
- d |= pwm; \
- data = (void *)d; \
-} while (0)
-
-#define SET_REG0(data,reg0) do { \
- long d = (long)data; \
- d &= ~(0xff << 8); \
- d |= reg0 << 8; \
- data = (void *)d; \
-} while (0)
-
-#define SET_TUNER(data,type) do { \
- long d = (long)data; \
- d &= ~(0xff << 16); \
- d |= type << 16; \
- data = (void *)d; \
-} while (0)
-
-#define SET_DEMOD_ADDR(data,type) do { \
- long d = (long)data; \
- d &= ~(0xff << 24); \
- d |= type << 24; \
- data = (void *)d; \
-} while (0)
-
-#define GET_PWM(data) ((u8) ((long) data & 0xff))
-#define GET_REG0(data) ((u8) (((long) data >> 8) & 0xff))
-#define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff))
-#define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff))
+/* possible ves1820 adresses */
+static u8 addr[] = { 0x61, 0x62 };
#if defined(CONFIG_DBOX2)
#define XIN 69600000UL
#define DISABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0)
#define ENABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0)
#define HAS_INVERSION(reg0) (reg0 & 0x20)
-#else /* PCI cards */
+#else /* PCI cards */
#define XIN 57840000UL
#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0)
#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0)
@@ -94,30 +64,29 @@ static int verbose;
#define FIN (XIN >> 4)
-
-
static struct dvb_frontend_info ves1820_info = {
.name = "VES1820 based DVB-C frontend",
.type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 51000000,
.frequency_max = 858000000,
- .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
- .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
+ .symbol_rate_min = (XIN / 2) / 64, /* SACLK/64 == (XIN/2)/64 */
+ .symbol_rate_max = (XIN / 2) / 4, /* SACLK/4 */
#if 0
- .frequency_tolerance = ???,
- .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
+ .frequency_tolerance = ? ? ?,
+ .symbol_rate_tolerance = ? ? ?, /* ppm *//* == 8% (spec p. 5) */
.notifier_delay = ?,
#endif
- .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
- FE_CAN_QAM_128 | FE_CAN_QAM_256 |
- FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO,
+ .caps = FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 |
+ FE_CAN_QAM_256 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_INVERSION_AUTO,
};
-
-
-static u8 ves1820_inittab [] =
-{
+static u8 ves1820_inittab[] = {
0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A,
0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20,
0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -127,79 +96,70 @@ static u8 ves1820_inittab [] =
0x00, 0x00, 0x00, 0x00, 0x40
};
-
-static int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data)
+static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
{
- u8 addr = GET_DEMOD_ADDR(fe->data);
- u8 buf[] = { 0x00, reg, data };
- struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
- struct dvb_i2c_bus *i2c = fe->i2c;
- int ret;
+ u8 buf[] = { 0x00, reg, data };
+ struct i2c_msg msg = {.addr = state->demod_addr,.flags = 0,.buf = buf,.len = 3 };
+ int ret;
- ret = i2c->xfer (i2c, &msg, 1);
+ ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
- printk("DVB: VES1820(%d): %s, writereg error "
- "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- fe->i2c->adapter->num, __FUNCTION__, reg, data, ret);
+ printk("ves1820: %s(): writereg error (reg == 0x%02x,"
+ "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
dvb_delay(10);
return (ret != 1) ? -EREMOTEIO : 0;
}
-
-static u8 ves1820_readreg (struct dvb_frontend *fe, u8 reg)
+static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
{
- u8 b0 [] = { 0x00, reg };
- u8 b1 [] = { 0 };
- u8 addr = GET_DEMOD_ADDR(fe->data);
- struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 },
- { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
- struct dvb_i2c_bus *i2c = fe->i2c;
+ u8 b0[] = { 0x00, reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ {.addr = state->demod_addr,.flags = 0,.buf = b0,.len = 2},
+ {.addr = state->demod_addr,.flags = I2C_M_RD,.buf = b1,.len = 1}
+ };
int ret;
- ret = i2c->xfer (i2c, msg, 2);
+ ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
- printk("DVB: VES1820(%d): %s: readreg error (ret == %i)\n",
- fe->i2c->adapter->num, __FUNCTION__, ret);
+ printk("ves1820: %s(): readreg error (reg == 0x%02x,"
+ "ret == %i)\n", __FUNCTION__, reg, ret);
return b1[0];
}
-
-static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4])
+static int tuner_write(struct ves1820_state *state, u8 addr, u8 data[4])
{
- int ret;
- struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
+ int ret;
+ struct i2c_msg msg = {.addr = addr,.flags = 0,.buf = data,.len = 4 };
- ret = i2c->xfer (i2c, &msg, 1);
+ ret = i2c_transfer(state->i2c, &msg, 1);
- if (ret != 1)
- printk("DVB: VES1820(%d): %s: i/o error (ret == %i)\n",
- i2c->adapter->num, __FUNCTION__, ret);
+ if (ret != 1)
+ printk("ves1820: %s(): i/o error (ret == %i)\n", __FUNCTION__, ret);
- return (ret != 1) ? -EREMOTEIO : 0;
+ return (ret != 1) ? -EREMOTEIO : 0;
}
-
/**
* set up the downconverter frequency divisor for a
* reference clock comparision frequency of 62.5 kHz.
*/
-static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq)
+static int tuner_set_tv_freq(struct ves1820_state *state, u32 freq)
{
- u32 div, ifreq;
- static u8 addr [] = { 0x61, 0x62 };
- static u8 byte3 [] = { 0x8e, 0x85 };
- int tuner_type = GET_TUNER(fe->data);
- u8 buf [4];
+ u32 div, ifreq;
+ static u8 byte3[] = { 0x8e, 0x85 };
+ int tuner_type = state->tuner;
+ u8 buf[4];
- if (tuner_type == 0xff) /* PLL not reachable over i2c ... */
+ if (tuner_type == 0xff) /* PLL not reachable over i2c ... */
return 0;
- if (strstr (fe->i2c->adapter->name, "Technotrend") ||
- strstr (fe->i2c->adapter->name, "TT-Budget"))
+ if (strstr(state->i2c->name, "Technotrend")
+ || strstr(state->i2c->name, "TT-Budget"))
ifreq = 35937500;
else
ifreq = 36125000;
@@ -212,147 +172,147 @@ static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq)
if (tuner_type == 1) {
buf[2] |= (div >> 10) & 0x60;
- buf[3] = (freq < 174000000 ? 0x88 :
- freq < 470000000 ? 0x84 : 0x81);
+ buf[3] = (freq < 174000000 ? 0x88 : freq < 470000000 ? 0x84 : 0x81);
} else {
- buf[3] = (freq < 174000000 ? 0xa1 :
- freq < 454000000 ? 0x92 : 0x34);
+ buf[3] = (freq < 174000000 ? 0xa1 : freq < 454000000 ? 0x92 : 0x34);
}
- return tuner_write (fe->i2c, addr[tuner_type], buf);
+ return tuner_write(state, addr[tuner_type], buf);
}
-
-static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0,
- fe_spectral_inversion_t inversion)
+static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion)
{
- reg0 |= GET_REG0(fe->data) & 0x62;
+ reg0 |= state->reg0 & 0x62;
if (INVERSION_ON == inversion)
ENABLE_INVERSION(reg0);
else if (INVERSION_OFF == inversion)
DISABLE_INVERSION(reg0);
- ves1820_writereg (fe, 0x00, reg0 & 0xfe);
- ves1820_writereg (fe, 0x00, reg0 | 0x01);
+ ves1820_writereg(state, 0x00, reg0 & 0xfe);
+ ves1820_writereg(state, 0x00, reg0 | 0x01);
/**
* check lock and toggle inversion bit if required...
*/
- if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) {
+ if (INVERSION_AUTO == inversion && !(ves1820_readreg(state, 0x11) & 0x08)) {
mdelay(50);
- if (!(ves1820_readreg (fe, 0x11) & 0x08)) {
+ if (!(ves1820_readreg(state, 0x11) & 0x08)) {
reg0 ^= 0x20;
- ves1820_writereg (fe, 0x00, reg0 & 0xfe);
- ves1820_writereg (fe, 0x00, reg0 | 0x01);
+ ves1820_writereg(state, 0x00, reg0 & 0xfe);
+ ves1820_writereg(state, 0x00, reg0 | 0x01);
}
}
- SET_REG0(fe->data, reg0);
+ state->reg0 = reg0;
return 0;
}
-
-static int ves1820_init (struct dvb_frontend *fe)
+static int ves1820_init(struct ves1820_state *state)
{
int i;
- dprintk("DVB: VES1820(%d): init chip\n", fe->i2c->adapter->num);
-
- ves1820_writereg (fe, 0, 0);
+ ves1820_writereg(state, 0, 0);
#if defined(CONFIG_DBOX2)
ves1820_inittab[2] &= ~0x08;
#endif
- for (i=0; i<53; i++)
- ves1820_writereg (fe, i, ves1820_inittab[i]);
+ for (i = 0; i < 53; i++)
+ ves1820_writereg(state, i, ves1820_inittab[i]);
- ves1820_writereg (fe, 0x34, GET_PWM(fe->data));
+ ves1820_writereg(state, 0x34, state->pwm);
return 0;
}
-
-static int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate)
+static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
{
- s32 BDR;
- s32 BDRI;
- s16 SFIL=0;
- u16 NDEC = 0;
- u32 tmp, ratio;
+ s32 BDR;
+ s32 BDRI;
+ s16 SFIL = 0;
+ u16 NDEC = 0;
+ u32 tmp, ratio;
- if (symbolrate > XIN/2)
- symbolrate = XIN/2;
+ if (symbolrate > XIN / 2)
+ symbolrate = XIN / 2;
if (symbolrate < 500000)
- symbolrate = 500000;
-
- if (symbolrate < XIN/16) NDEC = 1;
- if (symbolrate < XIN/32) NDEC = 2;
- if (symbolrate < XIN/64) NDEC = 3;
+ symbolrate = 500000;
+
+ if (symbolrate < XIN / 16)
+ NDEC = 1;
+ if (symbolrate < XIN / 32)
+ NDEC = 2;
+ if (symbolrate < XIN / 64)
+ NDEC = 3;
+
+ if (symbolrate < (u32) (XIN / 12.3))
+ SFIL = 1;
+ if (symbolrate < (u32) (XIN / 16))
+ SFIL = 0;
+ if (symbolrate < (u32) (XIN / 24.6))
+ SFIL = 1;
+ if (symbolrate < (u32) (XIN / 32))
+ SFIL = 0;
+ if (symbolrate < (u32) (XIN / 49.2))
+ SFIL = 1;
+ if (symbolrate < (u32) (XIN / 64))
+ SFIL = 0;
+ if (symbolrate < (u32) (XIN / 98.4))
+ SFIL = 1;
+
+ symbolrate <<= NDEC;
+ ratio = (symbolrate << 4) / FIN;
+ tmp = ((symbolrate << 4) % FIN) << 8;
+ ratio = (ratio << 8) + tmp / FIN;
+ tmp = (tmp % FIN) << 8;
+ ratio = (ratio << 8) + (tmp + FIN / 2) / FIN;
+
+ BDR = ratio;
+ BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
+
+ if (BDRI > 0xFF)
+ BDRI = 0xFF;
+
+ SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
+
+ NDEC = (NDEC << 6) | ves1820_inittab[0x03];
+
+ ves1820_writereg(state, 0x03, NDEC);
+ ves1820_writereg(state, 0x0a, BDR & 0xff);
+ ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff);
+ ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f);
+
+ ves1820_writereg(state, 0x0d, BDRI);
+ ves1820_writereg(state, 0x0e, SFIL);
- if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
- if (symbolrate < (u32)(XIN/16)) SFIL = 0;
- if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
- if (symbolrate < (u32)(XIN/32)) SFIL = 0;
- if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
- if (symbolrate < (u32)(XIN/64)) SFIL = 0;
- if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;
-
- symbolrate <<= NDEC;
- ratio = (symbolrate << 4) / FIN;
- tmp = ((symbolrate << 4) % FIN) << 8;
- ratio = (ratio << 8) + tmp / FIN;
- tmp = (tmp % FIN) << 8;
- ratio = (ratio << 8) + (tmp + FIN/2) / FIN;
-
- BDR = ratio;
- BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
-
- if (BDRI > 0xFF)
- BDRI = 0xFF;
-
- SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
-
- NDEC = (NDEC << 6) | ves1820_inittab[0x03];
-
- ves1820_writereg (fe, 0x03, NDEC);
- ves1820_writereg (fe, 0x0a, BDR&0xff);
- ves1820_writereg (fe, 0x0b, (BDR>> 8)&0xff);
- ves1820_writereg (fe, 0x0c, (BDR>>16)&0x3f);
-
- ves1820_writereg (fe, 0x0d, BDRI);
- ves1820_writereg (fe, 0x0e, SFIL);
-
- return 0;
+ return 0;
}
-
-static int ves1820_set_parameters (struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int ves1820_set_parameters(struct ves1820_state *state, struct dvb_frontend_parameters *p)
{
- static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
- static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 };
- static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 };
- static const u8 reg0x08 [] = { 162, 116, 67, 52, 35 };
- static const u8 reg0x09 [] = { 145, 150, 106, 126, 107 };
+ static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
+ static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
+ static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
+ static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
+ static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
int real_qam = p->u.qam.modulation - QAM_16;
if (real_qam < 0 || real_qam > 4)
return -EINVAL;
- tuner_set_tv_freq (fe, p->frequency);
- ves1820_set_symbolrate (fe, p->u.qam.symbol_rate);
- ves1820_writereg (fe, 0x34, GET_PWM(fe->data));
+ tuner_set_tv_freq(state, p->frequency);
+ ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
+ ves1820_writereg(state, 0x34, state->pwm);
- ves1820_writereg (fe, 0x01, reg0x01[real_qam]);
- ves1820_writereg (fe, 0x05, reg0x05[real_qam]);
- ves1820_writereg (fe, 0x08, reg0x08[real_qam]);
- ves1820_writereg (fe, 0x09, reg0x09[real_qam]);
+ ves1820_writereg(state, 0x01, reg0x01[real_qam]);
+ ves1820_writereg(state, 0x05, reg0x05[real_qam]);
+ ves1820_writereg(state, 0x08, reg0x08[real_qam]);
+ ves1820_writereg(state, 0x09, reg0x09[real_qam]);
- ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion);
+ ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
/* yes, this speeds things up: userspace reports lock in about 8 ms
instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */
@@ -361,133 +321,127 @@ static int ves1820_set_parameters (struct dvb_frontend *fe,
return 0;
}
-
-
-static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
+static int ves1820_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
- switch (cmd) {
+ struct ves1820_state *state = (struct ves1820_state *) fe->data;
+
+ switch (cmd) {
case FE_GET_INFO:
- memcpy (arg, &ves1820_info, sizeof(struct dvb_frontend_info));
+ memcpy(arg, &ves1820_info, sizeof(struct dvb_frontend_info));
break;
- case FE_READ_STATUS:
- {
- fe_status_t *status = (fe_status_t *) arg;
- int sync;
+ case FE_READ_STATUS:
+ {
+ fe_status_t *status = (fe_status_t *) arg;
+ int sync;
- *status = 0;
+ *status = 0;
- sync = ves1820_readreg (fe, 0x11);
+ sync = ves1820_readreg(state, 0x11);
- if (sync & 1)
- *status |= FE_HAS_SIGNAL;
+ if (sync & 1)
+ *status |= FE_HAS_SIGNAL;
- if (sync & 2)
- *status |= FE_HAS_CARRIER;
+ if (sync & 2)
+ *status |= FE_HAS_CARRIER;
- if (sync & 2) /* XXX FIXME! */
- *status |= FE_HAS_VITERBI;
+ if (sync & 2) /* XXX FIXME! */
+ *status |= FE_HAS_VITERBI;
- if (sync & 4)
- *status |= FE_HAS_SYNC;
+ if (sync & 4)
+ *status |= FE_HAS_SYNC;
- if (sync & 8)
- *status |= FE_HAS_LOCK;
+ if (sync & 8)
+ *status |= FE_HAS_LOCK;
- break;
- }
+ break;
+ }
case FE_READ_BER:
- {
- u32 ber = ves1820_readreg(fe, 0x14) |
- (ves1820_readreg(fe, 0x15) << 8) |
- ((ves1820_readreg(fe, 0x16) & 0x0f) << 16);
- *((u32*) arg) = 10 * ber;
- break;
- }
+ {
+ u32 ber = ves1820_readreg(state, 0x14) |
+ (ves1820_readreg(state, 0x15) << 8) |
+ ((ves1820_readreg(state, 0x16) & 0x0f) << 16);
+ *((u32 *) arg) = 10 * ber;
+ break;
+ }
case FE_READ_SIGNAL_STRENGTH:
- {
- u8 gain = ves1820_readreg(fe, 0x17);
- *((u16*) arg) = (gain << 8) | gain;
- break;
- }
+ {
+ u8 gain = ves1820_readreg(state, 0x17);
+ *((u16 *) arg) = (gain << 8) | gain;
+ break;
+ }
case FE_READ_SNR:
- {
- u8 quality = ~ves1820_readreg(fe, 0x18);
- *((u16*) arg) = (quality << 8) | quality;
- break;
- }
+ {
+ u8 quality = ~ves1820_readreg(state, 0x18);
+ *((u16 *) arg) = (quality << 8) | quality;
+ break;
+ }
case FE_READ_UNCORRECTED_BLOCKS:
- *((u32*) arg) = ves1820_readreg (fe, 0x13) & 0x7f;
- if (*((u32*) arg) == 0x7f)
- *((u32*) arg) = 0xffffffff;
+ *((u32 *) arg) = ves1820_readreg(state, 0x13) & 0x7f;
+ if (*((u32 *) arg) == 0x7f)
+ *((u32 *) arg) = 0xffffffff;
/* reset uncorrected block counter */
- ves1820_writereg (fe, 0x10, ves1820_inittab[0x10] & 0xdf);
- ves1820_writereg (fe, 0x10, ves1820_inittab[0x10]);
+ ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
+ ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
break;
- case FE_SET_FRONTEND:
- return ves1820_set_parameters (fe, arg);
+ case FE_SET_FRONTEND:
+ return ves1820_set_parameters(state, arg);
case FE_GET_FRONTEND:
- {
- struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *)arg;
- u8 reg0 = GET_REG0(fe->data);
- int sync;
- s8 afc = 0;
-
- sync = ves1820_readreg(fe, 0x11);
- afc = ves1820_readreg(fe, 0x19);
- if (verbose) {
- /* AFC only valid when carrier has been recovered */
- printk(sync & 2 ? "DVB: VES1820(%d): AFC (%d) %dHz\n" :
- "DVB: VES1820(%d): [AFC (%d) %dHz]\n",
- fe->i2c->adapter->num, afc,
- -((s32)p->u.qam.symbol_rate * afc) >> 10);
+ {
+ struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *) arg;
+ int sync;
+ s8 afc = 0;
+
+ sync = ves1820_readreg(state, 0x11);
+ afc = ves1820_readreg(state, 0x19);
+ if (verbose) {
+ /* AFC only valid when carrier has been recovered */
+ printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
+ "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10);
+ }
+
+ p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF;
+ p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+
+ p->u.qam.fec_inner = FEC_NONE;
+
+ p->frequency = ((p->frequency + 31250) / 62500) * 62500;
+ if (sync & 2)
+ p->frequency -= ((s32) p->u.qam.symbol_rate * afc) >> 10;
+ break;
}
-
- p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF;
- p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16;
-
- p->u.qam.fec_inner = FEC_NONE;
-
- p->frequency = ((p->frequency + 31250) / 62500) * 62500;
- if (sync & 2)
- p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
- break;
- }
case FE_SLEEP:
- ves1820_writereg (fe, 0x1b, 0x02); /* pdown ADC */
- ves1820_writereg (fe, 0x00, 0x80); /* standby */
+ ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */
+ ves1820_writereg(state, 0x00, 0x80); /* standby */
break;
- case FE_INIT:
- return ves1820_init (fe);
+ case FE_INIT:
+ return ves1820_init(state);
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
+ }
- return 0;
+ return 0;
}
-
-static long probe_tuner (struct dvb_i2c_bus *i2c)
+static long probe_tuner(struct i2c_adapter *i2c)
{
- static const struct i2c_msg msg1 =
- { .addr = 0x61, .flags = 0, .buf = NULL, .len = 0 };
- static const struct i2c_msg msg2 =
- { .addr = 0x62, .flags = 0, .buf = NULL, .len = 0 };
+ struct i2c_msg msg1 = {.addr = 0x61,.flags = 0,.buf = NULL,.len = 0 };
+ struct i2c_msg msg2 = {.addr = 0x62,.flags = 0,.buf = NULL,.len = 0 };
int type;
- if (i2c->xfer(i2c, &msg1, 1) == 1) {
+ if (i2c_transfer(i2c, &msg1, 1) == 1) {
type = 0;
- printk ("DVB: VES1820(%d): setup for tuner spXXXX\n", i2c->adapter->num);
- } else if (i2c->xfer(i2c, &msg2, 1) == 1) {
+ printk("ves1820: setup for tuner spXXXX\n");
+ } else if (i2c_transfer(i2c, &msg2, 1) == 1) {
type = 1;
- printk ("DVB: VES1820(%d): setup for tuner sp5659c\n", i2c->adapter->num);
+ printk("ves1820: setup for tuner sp5659c\n");
} else {
type = -1;
}
@@ -495,96 +449,164 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
return type;
}
-
-static u8 read_pwm (struct dvb_i2c_bus *i2c)
+static u8 read_pwm(struct i2c_adapter *i2c)
{
u8 b = 0xff;
u8 pwm;
- struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 },
- { .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } };
+ struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
+ {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
+ };
- if ((i2c->xfer(i2c, msg, 2) != 2) || (pwm == 0xff))
+ if ((i2c_transfer(i2c, msg, 2) != 2) || (pwm == 0xff))
pwm = 0x48;
- printk("DVB: VES1820(%d): pwm=0x%02x\n", i2c->adapter->num, pwm);
+ printk("ves1820: pwm=0x%02x\n", pwm);
return pwm;
}
-
-static long probe_demod_addr (struct dvb_i2c_bus *i2c)
+static long probe_demod_addr(struct i2c_adapter *i2c)
{
- u8 b [] = { 0x00, 0x1a };
+ u8 b[] = { 0x00, 0x1a };
u8 id;
- struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b, .len = 2 },
- { .addr = 0x08, .flags = I2C_M_RD, .buf = &id, .len = 1 } };
+ struct i2c_msg msg[] = { {.addr = 0x08,.flags = 0,.buf = b,.len = 2},
+ {.addr = 0x08,.flags = I2C_M_RD,.buf = &id,.len = 1}
+ };
- if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70)
+ if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70)
return msg[0].addr;
msg[0].addr = msg[1].addr = 0x09;
- if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70)
+ if (i2c_transfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70)
return msg[0].addr;
return -1;
}
+static struct i2c_client client_template;
-static int ves1820_attach (struct dvb_i2c_bus *i2c, void **data)
+static int attach_adapter(struct i2c_adapter *adapter)
{
- void *priv = NULL;
+ struct i2c_client *client;
+ struct ves1820_state *state;
long demod_addr;
- long tuner_type;
+ int tuner_type;
+ int ret;
- if ((demod_addr = probe_demod_addr(i2c)) < 0)
+ demod_addr = probe_demod_addr(adapter);
+ if (demod_addr < 0)
return -ENODEV;
- tuner_type = probe_tuner(i2c);
+ tuner_type = probe_tuner(adapter);
+ if (tuner_type < 0) {
+ printk("ves1820: demod found, but unknown tuner type.\n");
+ return -ENODEV;
+ }
- if ((i2c->adapter->num < MAX_UNITS) && pwm[i2c->adapter->num] != -1) {
- printk("DVB: VES1820(%d): pwm=0x%02x (user specified)\n",
- i2c->adapter->num, pwm[i2c->adapter->num]);
- SET_PWM(priv, pwm[i2c->adapter->num]);
+ if ((state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL)) == NULL) {
+ return -ENOMEM;
}
- else
- SET_PWM(priv, read_pwm(i2c));
- SET_REG0(priv, ves1820_inittab[0]);
- SET_TUNER(priv, tuner_type);
- SET_DEMOD_ADDR(priv, demod_addr);
- return dvb_register_frontend (ves1820_ioctl, i2c, priv, &ves1820_info);
-}
+ if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+ kfree(state);
+ return -ENOMEM;
+ }
+ state->i2c = adapter;
+ state->tuner = tuner_type;
+ state->pwm = read_pwm(adapter);
+ state->reg0 = ves1820_inittab[0];
+ state->demod_addr = demod_addr;
-static void ves1820_detach (struct dvb_i2c_bus *i2c, void *data)
-{
- dvb_unregister_frontend (ves1820_ioctl, i2c);
+ /* todo: honour user pwm setting somehow */
+
+ memcpy(client, &client_template, sizeof(struct i2c_client));
+ client->adapter = adapter;
+ client->addr = addr[tuner_type];
+
+ i2c_set_clientdata(client, (void *) state);
+
+ ret = i2c_attach_client(client);
+ if (ret) {
+ kfree(client);
+ kfree(state);
+ return -EFAULT;
+ }
+
+ BUG_ON(!state->dvb);
+
+ ret = dvb_register_frontend_new(ves1820_ioctl, state->dvb, state, &ves1820_info, THIS_MODULE);
+ if (ret) {
+ i2c_detach_client(client);
+ kfree(client);
+ kfree(state);
+ return -EFAULT;
+ }
+
+ return 0;
}
+static int detach_client(struct i2c_client *client)
+{
+ struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client);
+ dvb_unregister_frontend_new(ves1820_ioctl, state->dvb);
+ i2c_detach_client(client);
+ BUG_ON(state->dvb);
+ kfree(client);
+ kfree(state);
+ return 0;
+}
-static int __init init_ves1820 (void)
+static int command(struct i2c_client *client, unsigned int cmd, void *arg)
{
- int i;
- for (i = 0; i < MAX_UNITS; i++)
- if (pwm[i] < -1 || pwm[i] > 255)
- return -EINVAL;
- return dvb_register_i2c_device (THIS_MODULE,
- ves1820_attach, ves1820_detach);
+ struct ves1820_state *state = (struct ves1820_state *) i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case FE_REGISTER:{
+ state->dvb = (struct dvb_adapter *) arg;
+ break;
+ }
+ case FE_UNREGISTER:{
+ state->dvb = NULL;
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
}
+static struct i2c_driver driver = {
+ .owner = THIS_MODULE,
+ .name = "ves1820",
+ .id = I2C_DRIVERID_VES1820,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = attach_adapter,
+ .detach_client = detach_client,
+ .command = command,
+};
+
+static struct i2c_client client_template = {
+ I2C_DEVNAME("ves1820"),
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
+};
-static void __exit exit_ves1820 (void)
+static int __init init_ves1820(void)
{
- dvb_unregister_i2c_device (ves1820_attach);
+ return i2c_add_driver(&driver);
}
+static void __exit exit_ves1820(void)
+{
+ if (i2c_del_driver(&driver))
+ printk("ves1820: driver deregistration failed\n");
+}
module_init(init_ves1820);
module_exit(exit_ves1820);
-MODULE_PARM(pwm, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM_DESC(pwm, "override PWM value stored in EEPROM (tuner calibration)");
MODULE_PARM(verbose, "i");
MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");