[PATCH 09/11] mxl301rf: namespace cleanup & remodelling

From: ÐÑÐÐ ÐÐÐÐÐÑÐ, AreMa Inc
Date: Sun Oct 05 2014 - 05:01:36 EST


- minimize exports
- use client->dev.platform_data to point frontend
- use real address for I2C
- no freq limits in FE, it is non sense. move here...
- try to treat invalid frequency as channel number

Signed-off-by: ÐÑÐÐ ÐÐÐÐÐÑÐ, AreMa Inc <knightrider@xxxxxx>
---
drivers/media/tuners/mxl301rf.c | 550 +++++++++++++++++++++-------------------
1 file changed, 291 insertions(+), 259 deletions(-)

diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c
index 1575a5d..b1ed978 100644
--- a/drivers/media/tuners/mxl301rf.c
+++ b/drivers/media/tuners/mxl301rf.c
@@ -1,12 +1,12 @@
/*
- * MaxLinear MxL301RF OFDM tuner driver
+ * Sharp VA4M6JC2103 - Earthsoft PT3 ISDB-T tuner MaxLinear CMOS Hybrid TV MxL301RF
*
- * Copyright (C) 2014 Akihiro Tsukada <tskd08@xxxxxxxxx>
- *
- * 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 version 2.
+ * Copyright (C) 2014 Budi Rachmanto, AreMa Inc. <info@xxxxxx>
*
+ * 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
@@ -14,116 +14,24 @@
* GNU General Public License for more details.
*/

-/*
- * NOTICE:
- * This driver is incomplete and lacks init/config of the chips,
- * as the necessary info is not disclosed.
- * Other features like get_if_frequency() are missing as well.
- * It assumes that users of this driver (such as a PCI bridge of
- * DTV receiver cards) properly init and configure the chip
- * via I2C *before* calling this driver's init() function.
- *
- * Currently, PT3 driver is the only one that uses this driver,
- * and contains init/config code in its firmware.
- * Thus some part of the code might be dependent on PT3 specific config.
- */
-
-#include <linux/kernel.h>
+#include "dvb_frontend.h"
#include "mxl301rf.h"

-struct mxl301rf_state {
- struct mxl301rf_config cfg;
- struct i2c_client *i2c;
+struct mxl301rf {
+ struct dvb_frontend *fe;
+ u8 addr_tuner, idx;
+ u32 freq;
+ int (*read)(struct dvb_frontend *fe, u8 *buf, int buflen);
};

-static struct mxl301rf_state *cfg_to_state(struct mxl301rf_config *c)
-{
- return container_of(c, struct mxl301rf_state, cfg);
-}
-
-static int raw_write(struct mxl301rf_state *state, const u8 *buf, int len)
-{
- int ret;
-
- ret = i2c_master_send(state->i2c, buf, len);
- if (ret >= 0 && ret < len)
- ret = -EIO;
- return (ret == len) ? 0 : ret;
-}
-
-static int reg_write(struct mxl301rf_state *state, u8 reg, u8 val)
-{
- u8 buf[2] = { reg, val };
-
- return raw_write(state, buf, 2);
-}
-
-static int reg_read(struct mxl301rf_state *state, u8 reg, u8 *val)
-{
- u8 wbuf[2] = { 0xfb, reg };
- int ret;
-
- ret = raw_write(state, wbuf, sizeof(wbuf));
- if (ret == 0)
- ret = i2c_master_recv(state->i2c, val, 1);
- if (ret >= 0 && ret < 1)
- ret = -EIO;
- return (ret == 1) ? 0 : ret;
-}
-
-/* tuner_ops */
-
-/* get RSSI and update propery cache, set to *out in % */
-static int mxl301rf_get_rf_strength(struct dvb_frontend *fe, u16 *out)
-{
- struct mxl301rf_state *state;
- int ret;
- u8 rf_in1, rf_in2, rf_off1, rf_off2;
- u16 rf_in, rf_off;
- s64 level;
- struct dtv_fe_stats *rssi;
-
- rssi = &fe->dtv_property_cache.strength;
- rssi->len = 1;
- rssi->stat[0].scale = FE_SCALE_NOT_AVAILABLE;
- *out = 0;
-
- state = fe->tuner_priv;
- ret = reg_write(state, 0x14, 0x01);
- if (ret < 0)
- return ret;
- usleep_range(1000, 2000);
-
- ret = reg_read(state, 0x18, &rf_in1);
- if (ret == 0)
- ret = reg_read(state, 0x19, &rf_in2);
- if (ret == 0)
- ret = reg_read(state, 0xd6, &rf_off1);
- if (ret == 0)
- ret = reg_read(state, 0xd7, &rf_off2);
- if (ret != 0)
- return ret;
-
- rf_in = (rf_in2 & 0x07) << 8 | rf_in1;
- rf_off = (rf_off2 & 0x0f) << 5 | (rf_off1 >> 3);
- level = rf_in - rf_off - (113 << 3); /* x8 dBm */
- level = level * 1000 / 8;
- rssi->stat[0].svalue = level;
- rssi->stat[0].scale = FE_SCALE_DECIBEL;
- /* *out = (level - min) * 100 / (max - min) */
- *out = (rf_in - rf_off + (1 << 9) - 1) * 100 / ((5 << 9) - 2);
- return 0;
-}
-
-/* spur shift parameters */
-struct shf {
- u32 freq; /* Channel center frequency */
- u32 ofst_th; /* Offset frequency threshold */
- u8 shf_val; /* Spur shift value */
- u8 shf_dir; /* Spur shift direction */
+struct shf_dvbt {
+ u32 freq, /* Channel center frequency @ kHz */
+ freq_th; /* Offset frequency threshold @ kHz */
+ u8 shf_val, /* Spur shift value */
+ shf_dir; /* Spur shift direction */
};

-static const struct shf shf_tab[] = {
+static const struct shf_dvbt shf_dvbt_tab[] = {
{ 64500, 500, 0x92, 0x07 },
{ 191500, 300, 0xe2, 0x07 },
{ 205500, 500, 0x2c, 0x04 },
@@ -143,207 +51,331 @@ static const struct shf shf_tab[] = {
{ 153143, 500, 0x01, 0x07 }
};

-struct reg_val {
- u8 reg;
- u8 val;
-} __attribute__ ((__packed__));
-
-static const struct reg_val set_idac[] = {
- { 0x0d, 0x00 },
- { 0x0c, 0x67 },
- { 0x6f, 0x89 },
- { 0x70, 0x0c },
- { 0x6f, 0x8a },
- { 0x70, 0x0e },
- { 0x6f, 0x8b },
- { 0x70, 0x1c },
+static const u32 mxl301rf_rf_tab[112] = {
+ 0x058d3f49, 0x05e8ccc9, 0x06445a49, 0x069fe7c9, 0x06fb7549,
+ 0x075702c9, 0x07b29049, 0x080e1dc9, 0x0869ab49, 0x08c538c9,
+ 0x0920c649, 0x097c53c9, 0x09f665c9, 0x0a51f349, 0x0aad80c9,
+ 0x0b090e49, 0x0b649bc9, 0x0ba1a4c9, 0x0bfd3249, 0x0c58bfc9,
+ 0x0cb44d49, 0x0d0fdac9, 0x0d6b6849, 0x0dc6f5c9, 0x0e228349,
+ 0x0e7e10c9, 0x0ed99e49, 0x0f352bc9, 0x0f90b949, 0x0fec46c9,
+ 0x1047d449, 0x10a361c9, 0x10feef49, 0x115a7cc9, 0x11b60a49,
+ 0x121197c9, 0x126d2549, 0x12c8b2c9, 0x13244049, 0x137fcdc9,
+ 0x13db5b49, 0x1436e8c9, 0x14927649, 0x14ee03c9, 0x15499149,
+ 0x15a51ec9, 0x1600ac49, 0x165c39c9, 0x16b7c749, 0x171354c9,
+ 0x176ee249, 0x17ca6fc9, 0x1825fd49, 0x18818ac9, 0x18dd1849,
+ 0x1938a5c9, 0x19943349, 0x19efc0c9, 0x1a4b4e49, 0x1aa6dbc9,
+ 0x1b026949, 0x1b5df6c9, 0x1bb98449, 0x1c339649, 0x1c8f23c9,
+ 0x1ceab149, 0x1d463ec9, 0x1da1cc49, 0x1dfd59c9, 0x1e58e749,
+ 0x1eb474c9, 0x1f100249, 0x1f6b8fc9, 0x1fc71d49, 0x2022aac9,
+ 0x207e3849, 0x20d9c5c9, 0x21355349, 0x2190e0c9, 0x21ec6e49,
+ 0x2247fbc9, 0x22a38949, 0x22ff16c9, 0x235aa449, 0x23b631c9,
+ 0x2411bf49, 0x246d4cc9, 0x24c8da49, 0x252467c9, 0x257ff549,
+ 0x25db82c9, 0x26371049, 0x26929dc9, 0x26ee2b49, 0x2749b8c9,
+ 0x27a54649, 0x2800d3c9, 0x285c6149, 0x28b7eec9, 0x29137c49,
+ 0x296f09c9, 0x29ca9749, 0x2a2624c9, 0x2a81b249, 0x2add3fc9,
+ 0x2b38cd49, 0x2b945ac9, 0x2befe849, 0x2c4b75c9, 0x2ca70349,
+ 0x2d0290c9, 0x2d5e1e49,
};
+#define MXL301RF_NHK (mxl301rf_rf_tab[77]) /* æææéåä Nippon HÅsÅ KyÅkai, Japan Broadcasting Corporation */

-static int mxl301rf_set_params(struct dvb_frontend *fe)
+int mxl301rf_freq(int freq)
{
- struct reg_val tune0[] = {
- { 0x13, 0x00 }, /* abort tuning */
- { 0x3b, 0xc0 },
- { 0x3b, 0x80 },
- { 0x10, 0x95 }, /* BW */
- { 0x1a, 0x05 },
- { 0x61, 0x00 }, /* spur shift value (placeholder) */
- { 0x62, 0xa0 } /* spur shift direction (placeholder) */
- };
+ if (freq >= 90000000)
+ return freq; /* real_freq Hz */
+ if (freq > 255)
+ return MXL301RF_NHK;
+ if (freq > 127)
+ return mxl301rf_rf_tab[freq - 128]; /* freqno (IO#) */
+ if (freq > 63) { /* CATV */
+ freq -= 64;
+ if (freq > 22)
+ return mxl301rf_rf_tab[freq - 1]; /* C23-C62 */
+ if (freq > 12)
+ return mxl301rf_rf_tab[freq - 10]; /* C13-C22 */
+ return MXL301RF_NHK;
+ }
+ if (freq > 62)
+ return MXL301RF_NHK;
+ if (freq > 12)
+ return mxl301rf_rf_tab[freq + 50]; /* 13-62 */
+ if (freq > 3)
+ return mxl301rf_rf_tab[freq + 9]; /* 4-12 */
+ if (freq)
+ return mxl301rf_rf_tab[freq - 1]; /* 1-3 */
+ return MXL301RF_NHK;
+}

- struct reg_val tune1[] = {
- { 0x11, 0x40 }, /* RF frequency L (placeholder) */
- { 0x12, 0x0e }, /* RF frequency H (placeholder) */
- { 0x13, 0x01 } /* start tune */
+void mxl301rf_rftune(struct dvb_frontend *fe, u8 *data, u32 *size, u32 freq)
+{
+ u8 rf_data[] = {
+ 0x13, 0x00, /* abort tune */
+ 0x3b, 0xc0,
+ 0x3b, 0x80,
+ 0x10, 0x95, /* BW */
+ 0x1a, 0x05,
+ 0x61, 0x00,
+ 0x62, 0xa0,
+ 0x11, 0x40, /* 2 bytes to store RF freq. */
+ 0x12, 0x0e, /* 2 bytes to store RF freq. */
+ 0x13, 0x01 /* start tune */
};
-
- struct mxl301rf_state *state;
- u32 freq;
- u16 f;
- u32 tmp, div;
- int i, ret;
-
- state = fe->tuner_priv;
- freq = fe->dtv_property_cache.frequency;
-
- /* spur shift function (for analog) */
- for (i = 0; i < ARRAY_SIZE(shf_tab); i++) {
- if (freq >= (shf_tab[i].freq - shf_tab[i].ofst_th) * 1000 &&
- freq <= (shf_tab[i].freq + shf_tab[i].ofst_th) * 1000) {
- tune0[5].val = shf_tab[i].shf_val;
- tune0[6].val = 0xa0 | shf_tab[i].shf_dir;
- break;
- }
- }
- ret = raw_write(state, (u8 *) tune0, sizeof(tune0));
- if (ret < 0)
- goto failed;
- usleep_range(3000, 4000);
-
- /* convert freq to 10.6 fixed point float [MHz] */
- f = freq / 1000000;
- tmp = freq % 1000000;
- div = 1000000;
+ u32 i, dig_rf_freq, tmp,
+ kHz = 1000,
+ MHz = 1000000,
+ frac_divider = 1000000;
+
+ freq = mxl301rf_freq(freq);
+ dig_rf_freq = freq / MHz;
+ tmp = freq % MHz;
for (i = 0; i < 6; i++) {
- f <<= 1;
- div >>= 1;
- if (tmp > div) {
- tmp -= div;
- f |= 1;
+ dig_rf_freq <<= 1;
+ frac_divider /= 2;
+ if (tmp > frac_divider) {
+ tmp -= frac_divider;
+ dig_rf_freq++;
}
}
if (tmp > 7812)
- f++;
- tune1[0].val = f & 0xff;
- tune1[1].val = f >> 8;
- ret = raw_write(state, (u8 *) tune1, sizeof(tune1));
- if (ret < 0)
- goto failed;
- msleep(31);
-
- ret = reg_write(state, 0x1a, 0x0d);
- if (ret < 0)
- goto failed;
- ret = raw_write(state, (u8 *) set_idac, sizeof(set_idac));
- if (ret < 0)
- goto failed;
- return 0;
+ dig_rf_freq++;
+ rf_data[2 * 7 + 1] = (u8)(dig_rf_freq);
+ rf_data[2 * 8 + 1] = (u8)(dig_rf_freq >> 8);
+
+ for (i = 0; i < ARRAY_SIZE(shf_dvbt_tab); i++) {
+ if ((freq >= (shf_dvbt_tab[i].freq - shf_dvbt_tab[i].freq_th) * kHz) &&
+ (freq <= (shf_dvbt_tab[i].freq + shf_dvbt_tab[i].freq_th) * kHz)) {
+ rf_data[2 * 5 + 1] = shf_dvbt_tab[i].shf_val;
+ rf_data[2 * 6 + 1] = 0xa0 | shf_dvbt_tab[i].shf_dir;
+ break;
+ }
+ }
+ memcpy(data, rf_data, sizeof(rf_data));
+ *size = sizeof(rf_data);

-failed:
- dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
- __func__, fe->dvb->num, fe->id);
- return ret;
+ dev_dbg(fe->dvb->device, "mx_rftune freq=%d\n", freq);
}

-static const struct reg_val standby_data[] = {
- { 0x01, 0x00 },
- { 0x13, 0x00 }
-};
-
-static int mxl301rf_sleep(struct dvb_frontend *fe)
+/* write via demodulator */
+int mxl301rf_fe_write_data(struct dvb_frontend *fe, u8 addr_data, const u8 *data, int len)
{
- struct mxl301rf_state *state;
- int ret;
+ u8 buf[len + 1];

- state = fe->tuner_priv;
- ret = raw_write(state, (u8 *)standby_data, sizeof(standby_data));
- if (ret < 0)
- dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
- __func__, fe->dvb->num, fe->id);
- return ret;
+ buf[0] = addr_data;
+ memcpy(buf + 1, data, len);
+ return fe->ops.write(fe, buf, len + 1);
}

+#define MXL301RF_FE_PASSTHROUGH 0xfe

-/* init sequence is not public.
- * the parent must have init'ed the device.
- * just wake up here.
- */
-static int mxl301rf_init(struct dvb_frontend *fe)
+int mxl301rf_fe_write_tuner(struct dvb_frontend *fe, const u8 *data, int len)
{
- struct mxl301rf_state *state;
+ u8 buf[len + 2];
+
+ buf[0] = MXL301RF_FE_PASSTHROUGH;
+ buf[1] = ((struct mxl301rf *)fe->tuner_priv)->addr_tuner << 1;
+ memcpy(buf + 2, data, len);
+ return fe->ops.write(fe, buf, len + 2);
+}
+
+/* read via demodulator */
+void mxl301rf_fe_read(struct dvb_frontend *fe, u8 addr, u8 *data)
+{
+ struct mxl301rf *mx = fe->tuner_priv;
+ const u8 wbuf[2] = {0xfb, addr};
int ret;

- state = fe->tuner_priv;
+ mxl301rf_fe_write_tuner(fe, wbuf, sizeof(wbuf));
+ ret = mx->read(fe, &mx->addr_tuner, 1);
+ if (ret >= 0)
+ *data = ret;
+}

- ret = reg_write(state, 0x01, 0x01);
- if (ret < 0) {
- dev_warn(&state->i2c->dev, "(%s) failed. [adap%d-fe%d]\n",
- __func__, fe->dvb->num, fe->id);
- return ret;
- }
- return 0;
+void mxl301rf_idac_setting(struct dvb_frontend *fe)
+{
+ const u8 idac[] = {
+ 0x0d, 0x00,
+ 0x0c, 0x67,
+ 0x6f, 0x89,
+ 0x70, 0x0c,
+ 0x6f, 0x8a,
+ 0x70, 0x0e,
+ 0x6f, 0x8b,
+ 0x70, 0x10+12,
+ };
+ mxl301rf_fe_write_tuner(fe, idac, sizeof(idac));
}

-/* I2C driver functions */
+void mxl301rf_set_register(struct dvb_frontend *fe, u8 addr, u8 value)
+{
+ const u8 data[2] = {addr, value};

-static const struct dvb_tuner_ops mxl301rf_ops = {
- .info = {
- .name = "MaxLinear MxL301RF",
+ mxl301rf_fe_write_tuner(fe, data, sizeof(data));
+}

- .frequency_min = 93000000,
- .frequency_max = 803142857,
- },
+int mxl301rf_write_imsrst(struct dvb_frontend *fe)
+{
+ u8 data = 0x01 << 6;

- .init = mxl301rf_init,
- .sleep = mxl301rf_sleep,
+ return mxl301rf_fe_write_data(fe, 0x01, &data, 1);
+}

- .set_params = mxl301rf_set_params,
- .get_rf_strength = mxl301rf_get_rf_strength,
+enum mxl301rf_agc {
+ MXL301RF_AGC_AUTO,
+ MXL301RF_AGC_MANUAL,
};

+int mxl301rf_set_agc(struct dvb_frontend *fe, enum mxl301rf_agc agc)
+{
+ u8 data = (agc == MXL301RF_AGC_AUTO) ? 0x40 : 0x00;
+ int err = mxl301rf_fe_write_data(fe, 0x25, &data, 1);
+
+ if (err)
+ return err;
+ data = 0x4c | ((agc == MXL301RF_AGC_AUTO) ? 0x00 : 0x01);
+ return mxl301rf_fe_write_data(fe, 0x23, &data, 1) ||
+ mxl301rf_write_imsrst(fe);
+}

-static int mxl301rf_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+int mxl301rf_sleep(struct dvb_frontend *fe)
{
- struct mxl301rf_state *state;
- struct mxl301rf_config *cfg;
- struct dvb_frontend *fe;
+ u8 buf = (1 << 7) | (1 << 4);
+ const u8 data[4] = {0x01, 0x00, 0x13, 0x00};
+ int err = mxl301rf_set_agc(fe, MXL301RF_AGC_MANUAL);
+
+ if (err)
+ return err;
+ mxl301rf_fe_write_tuner(fe, data, sizeof(data));
+ return mxl301rf_fe_write_data(fe, 0x03, &buf, 1);
+}

- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
+bool mxl301rf_rfsynth_locked(struct dvb_frontend *fe)
+{
+ u8 data;

- state->i2c = client;
- cfg = client->dev.platform_data;
+ mxl301rf_fe_read(fe, 0x16, &data);
+ return (data & 0x0c) == 0x0c;
+}

- memcpy(&state->cfg, cfg, sizeof(state->cfg));
- fe = cfg->fe;
- fe->tuner_priv = state;
- memcpy(&fe->ops.tuner_ops, &mxl301rf_ops, sizeof(mxl301rf_ops));
+bool mxl301rf_refsynth_locked(struct dvb_frontend *fe)
+{
+ u8 data;

- i2c_set_clientdata(client, &state->cfg);
- dev_info(&client->dev, "MaxLinear MxL301RF attached.\n");
+ mxl301rf_fe_read(fe, 0x16, &data);
+ return (data & 0x03) == 0x03;
+}
+
+bool mxl301rf_locked(struct dvb_frontend *fe)
+{
+ bool locked1 = false, locked2 = false;
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+ while (time_before(jiffies, timeout)) {
+ locked1 = mxl301rf_rfsynth_locked(fe);
+ locked2 = mxl301rf_refsynth_locked(fe);
+ if (locked1 && locked2)
+ break;
+ msleep_interruptible(1);
+ }
+ dev_dbg(fe->dvb->device, "#%d %s lock1=%d lock2=%d\n", ((struct mxl301rf *)fe->tuner_priv)->idx, __func__, locked1, locked2);
+ return locked1 && locked2 ? !mxl301rf_set_agc(fe, MXL301RF_AGC_AUTO) : false;
+}
+
+int mxl301rf_tuner_rftune(struct dvb_frontend *fe, u32 freq)
+{
+ struct mxl301rf *mx = fe->tuner_priv;
+ u8 data[100];
+ u32 size = 0;
+ int err = mxl301rf_set_agc(fe, MXL301RF_AGC_MANUAL);
+
+ if (err)
+ return err;
+ mx->freq = freq;
+ mxl301rf_rftune(fe, data, &size, freq);
+ if (size != 20) {
+ dev_dbg(fe->dvb->device, "fail mx_rftune size = %d\n", size);
+ return -EINVAL;
+ }
+ mxl301rf_fe_write_tuner(fe, data, 14);
+ msleep_interruptible(1);
+ mxl301rf_fe_write_tuner(fe, data + 14, 6);
+ msleep_interruptible(1);
+ mxl301rf_set_register(fe, 0x1a, 0x0d);
+ mxl301rf_idac_setting(fe);
+ return mxl301rf_locked(fe) ? 0 : -ETIMEDOUT;
+}
+
+int mxl301rf_wakeup(struct dvb_frontend *fe)
+{
+ struct mxl301rf *mx = fe->tuner_priv;
+ int err;
+ u8 buf = (1 << 7) | (0 << 4);
+ const u8 data[2] = {0x01, 0x01};
+
+ err = mxl301rf_fe_write_data(fe, 0x03, &buf, 1);
+ if (err)
+ return err;
+ mxl301rf_fe_write_tuner(fe, data, sizeof(data));
+ mxl301rf_tuner_rftune(fe, mx->freq);
return 0;
}

-static int mxl301rf_remove(struct i2c_client *client)
+static struct dvb_tuner_ops mxl301rf_ops = {
+ .info = {
+ .frequency_min = 1, /* freq under 90 MHz is handled as channel */
+ .frequency_max = 770000000, /* Hz */
+ .frequency_step = 142857,
+ },
+ .set_frequency = mxl301rf_tuner_rftune,
+ .sleep = mxl301rf_sleep,
+ .init = mxl301rf_wakeup,
+};
+
+int mxl301rf_remove(struct i2c_client *client)
{
- struct mxl301rf_state *state;
+ struct dvb_frontend *fe = i2c_get_clientdata(client);

- state = cfg_to_state(i2c_get_clientdata(client));
- state->cfg.fe->tuner_priv = NULL;
- kfree(state);
+ dev_dbg(&client->dev, "%s\n", __func__);
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
return 0;
}

+int mxl301rf_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ u8 d[] = { 0x10, 0x01 };
+ struct dvb_frontend *fe = client->dev.platform_data;
+ struct mxl301rf *mx = kzalloc(sizeof(struct mxl301rf), GFP_KERNEL);

-static const struct i2c_device_id mxl301rf_id[] = {
- {"mxl301rf", 0},
- {}
+ if (!mx)
+ return -ENOMEM;
+ fe->tuner_priv = mx;
+ mx->fe = fe;
+ mx->idx = (client->addr & 1) | 2;
+ mx->addr_tuner = client->addr;
+ mx->read = fe->ops.tuner_ops.calc_regs;
+ memcpy(&fe->ops.tuner_ops, &mxl301rf_ops, sizeof(struct dvb_tuner_ops));
+ i2c_set_clientdata(client, fe);
+ return mxl301rf_fe_write_data(fe, 0x1c, d, 1) ||
+ mxl301rf_fe_write_data(fe, 0x1d, d+1, 1);
+}
+
+static struct i2c_device_id mxl301rf_id_table[] = {
+ { MXL301RF_DRVNAME, 0 },
+ { },
};
-MODULE_DEVICE_TABLE(i2c, mxl301rf_id);
+MODULE_DEVICE_TABLE(i2c, mxl301rf_id_table);

static struct i2c_driver mxl301rf_driver = {
.driver = {
- .name = "mxl301rf",
+ .owner = THIS_MODULE,
+ .name = mxl301rf_id_table->name,
},
.probe = mxl301rf_probe,
.remove = mxl301rf_remove,
- .id_table = mxl301rf_id,
+ .id_table = mxl301rf_id_table,
};
-
module_i2c_driver(mxl301rf_driver);

-MODULE_DESCRIPTION("MaxLinear MXL301RF tuner");
-MODULE_AUTHOR("Akihiro TSUKADA");
+MODULE_AUTHOR("Budi Rachmanto, AreMa Inc. <knightrider(@)are.ma>");
+MODULE_DESCRIPTION("Earthsoft PT3 MxL301RF MaxLinear CMOS Hybrid TV ISDB-T tuner driver");
MODULE_LICENSE("GPL");
+
--
1.8.4.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/