diff options
Diffstat (limited to 'drivers/media/common')
-rw-r--r-- | drivers/media/common/saa7146_fops.c | 2 | ||||
-rw-r--r-- | drivers/media/common/saa7146_i2c.c | 1 | ||||
-rw-r--r-- | drivers/media/common/saa7146_vbi.c | 2 | ||||
-rw-r--r-- | drivers/media/common/saa7146_video.c | 2 | ||||
-rw-r--r-- | drivers/media/common/tuners/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/common/tuners/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18218.c | 334 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18218.h | 45 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18218_priv.h | 106 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18271-common.c | 61 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18271-fe.c | 16 | ||||
-rw-r--r-- | drivers/media/common/tuners/tda18271.h | 5 | ||||
-rw-r--r-- | drivers/media/common/tuners/xc5000.c | 2 | ||||
-rw-r--r-- | drivers/media/common/tuners/xc5000.h | 4 |
14 files changed, 544 insertions, 44 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 4da2a54cb8bd..e3fedc60fe77 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -56,7 +56,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, BUG_ON(in_interrupt()); - videobuf_waiton(&buf->vb,0,0); + videobuf_waiton(q, &buf->vb, 0, 0); videobuf_dma_unmap(q->dev, dma); videobuf_dma_free(dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 48cb154c7a46..3d88542612ea 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -414,7 +414,6 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c i2c_adapter->dev.parent = &dev->pci->dev; i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo_data = NULL; - i2c_adapter->id = I2C_HW_SAA7146; i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; i2c_adapter->retries = SAA7146_I2C_RETRIES; } diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 8224c301d050..2d4533ab22b7 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), - file); + file, NULL); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index a212a91a30f0..741c5732b430 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1386,7 +1386,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7146_buf), - file); + file, NULL); return 0; } diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index b3ed5daaacf2..2385e6cca635 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -179,4 +179,11 @@ config MEDIA_TUNER_MAX2165 help A driver for the silicon tuner MAX2165 from Maxim. +config MEDIA_TUNER_TDA18218 + tristate "NXP TDA18218 silicon tuner" + depends on VIDEO_MEDIA && I2C + default m if MEDIA_TUNER_CUSTOMISE + help + NXP TDA18218 silicon tuner driver. + endif # MEDIA_TUNER_CUSTOMISE diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index a5438523f30d..96da03d349ca 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o +obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c new file mode 100644 index 000000000000..8da1fdeddaa7 --- /dev/null +++ b/drivers/media/common/tuners/tda18218.c @@ -0,0 +1,334 @@ +/* + * NXP TDA18218HN silicon tuner driver + * + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> + * + * 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 "tda18218.h" +#include "tda18218_priv.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +/* write multiple registers */ +static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) +{ + int ret; + u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg->i2c_address, + .flags = 0, + .buf = buf, + } + }; + + msg_len_max = priv->cfg->i2c_wr_max - 1; + quotient = len / msg_len_max; + remainder = len % msg_len_max; + msg_len = msg_len_max; + for (i = 0; (i <= quotient && remainder); i++) { + if (i == quotient) /* set len of the last msg */ + msg_len = remainder; + + msg[0].len = msg_len + 1; + buf[0] = reg + i * msg_len_max; + memcpy(&buf[1], &val[i * msg_len_max], msg_len); + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret != 1) + break; + } + + if (ret == 1) { + ret = 0; + } else { + warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + +/* read multiple registers */ +static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) +{ + int ret; + u8 buf[reg+len]; /* we must start read always from reg 0x00 */ + struct i2c_msg msg[2] = { + { + .addr = priv->cfg->i2c_address, + .flags = 0, + .len = 1, + .buf = "\x00", + }, { + .addr = priv->cfg->i2c_address, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret == 2) { + memcpy(val, &buf[reg], len); + ret = 0; + } else { + warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + +/* write single register */ +static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val) +{ + return tda18218_wr_regs(priv, reg, &val, 1); +} + +/* read single register */ + +static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val) +{ + return tda18218_rd_regs(priv, reg, val, 1); +} + +static int tda18218_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct tda18218_priv *priv = fe->tuner_priv; + int ret; + u8 buf[3], i, BP_Filter, LP_Fc; + u32 LO_Frac; + /* TODO: find out correct AGC algorithm */ + u8 agc[][2] = { + { R20_AGC11, 0x60 }, + { R23_AGC21, 0x02 }, + { R20_AGC11, 0xa0 }, + { R23_AGC21, 0x09 }, + { R20_AGC11, 0xe0 }, + { R23_AGC21, 0x0c }, + { R20_AGC11, 0x40 }, + { R23_AGC21, 0x01 }, + { R20_AGC11, 0x80 }, + { R23_AGC21, 0x08 }, + { R20_AGC11, 0xc0 }, + { R23_AGC21, 0x0b }, + { R24_AGC22, 0x1c }, + { R24_AGC22, 0x0c }, + }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ + + /* low-pass filter cut-off frequency */ + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + LP_Fc = 0; + LO_Frac = params->frequency + 4000000; + break; + case BANDWIDTH_7_MHZ: + LP_Fc = 1; + LO_Frac = params->frequency + 3500000; + break; + case BANDWIDTH_8_MHZ: + default: + LP_Fc = 2; + LO_Frac = params->frequency + 4000000; + break; + } + + /* band-pass filter */ + if (LO_Frac < 188000000) + BP_Filter = 3; + else if (LO_Frac < 253000000) + BP_Filter = 4; + else if (LO_Frac < 343000000) + BP_Filter = 5; + else + BP_Filter = 6; + + buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */ + buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */ + buf[2] = priv->regs[R1C_AGC2B]; + ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3); + if (ret) + goto error; + + buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */ + buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */ + buf[2] = (LO_Frac / 1000) << 4 | + (priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */ + ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3); + if (ret) + goto error; + + buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */ + ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1); + if (ret) + goto error; + + buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */ + ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1); + if (ret) + goto error; + + /* trigger AGC */ + for (i = 0; i < ARRAY_SIZE(agc); i++) { + ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]); + if (ret) + goto error; + } + +error: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ + + if (ret) + dbg("%s: failed ret:%d", __func__, ret); + + return ret; +} + +static int tda18218_sleep(struct dvb_frontend *fe) +{ + struct tda18218_priv *priv = fe->tuner_priv; + int ret; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ + + /* standby */ + ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0)); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ + + if (ret) + dbg("%s: failed ret:%d", __func__, ret); + + return ret; +} + +static int tda18218_init(struct dvb_frontend *fe) +{ + struct tda18218_priv *priv = fe->tuner_priv; + int ret; + + /* TODO: calibrations */ + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ + + ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ + + if (ret) + dbg("%s: failed ret:%d", __func__, ret); + + return ret; +} + +static int tda18218_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static const struct dvb_tuner_ops tda18218_tuner_ops = { + .info = { + .name = "NXP TDA18218", + + .frequency_min = 174000000, + .frequency_max = 864000000, + .frequency_step = 1000, + }, + + .release = tda18218_release, + .init = tda18218_init, + .sleep = tda18218_sleep, + + .set_params = tda18218_set_params, +}; + +struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tda18218_config *cfg) +{ + struct tda18218_priv *priv = NULL; + u8 val; + int ret; + /* chip default registers values */ + static u8 def_regs[] = { + 0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40, + 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00, + 0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01, + 0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9, + 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6 + }; + + priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->cfg = cfg; + priv->i2c = i2c; + fe->tuner_priv = priv; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ + + /* check if the tuner is there */ + ret = tda18218_rd_reg(priv, R00_ID, &val); + dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); + if (ret || val != def_regs[R00_ID]) { + kfree(priv); + return NULL; + } + + info("NXP TDA18218HN successfully identified."); + + memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops, + sizeof(struct dvb_tuner_ops)); + memcpy(priv->regs, def_regs, sizeof(def_regs)); + + /* loop-through enabled chip default register values */ + if (priv->cfg->loop_through) { + priv->regs[R17_PD1] = 0xb0; + priv->regs[R18_PD2] = 0x59; + } + + /* standby */ + ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0)); + if (ret) + dbg("%s: failed ret:%d", __func__, ret); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ + + return fe; +} +EXPORT_SYMBOL(tda18218_attach); + +MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver"); +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/tda18218.h b/drivers/media/common/tuners/tda18218.h new file mode 100644 index 000000000000..b4180d180029 --- /dev/null +++ b/drivers/media/common/tuners/tda18218.h @@ -0,0 +1,45 @@ +/* + * NXP TDA18218HN silicon tuner driver + * + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> + * + * 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 TDA18218_H +#define TDA18218_H + +#include "dvb_frontend.h" + +struct tda18218_config { + u8 i2c_address; + u8 i2c_wr_max; + u8 loop_through:1; +}; + +#if defined(CONFIG_MEDIA_TUNER_TDA18218) || \ + (defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE)) +extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tda18218_config *cfg); +#else +static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tda18218_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/common/tuners/tda18218_priv.h new file mode 100644 index 000000000000..904e5365c78c --- /dev/null +++ b/drivers/media/common/tuners/tda18218_priv.h @@ -0,0 +1,106 @@ +/* + * NXP TDA18218HN silicon tuner driver + * + * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> + * + * 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 TDA18218_PRIV_H +#define TDA18218_PRIV_H + +#define LOG_PREFIX "tda18218" + +#undef dbg +#define dbg(f, arg...) \ + if (debug) \ + printk(KERN_DEBUG LOG_PREFIX": " f "\n" , ## arg) +#undef err +#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) +#undef info +#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) +#undef warn +#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) + +#define R00_ID 0x00 /* ID byte */ +#define R01_R1 0x01 /* Read byte 1 */ +#define R02_R2 0x02 /* Read byte 2 */ +#define R03_R3 0x03 /* Read byte 3 */ +#define R04_R4 0x04 /* Read byte 4 */ +#define R05_R5 0x05 /* Read byte 5 */ +#define R06_R6 0x06 /* Read byte 6 */ +#define R07_MD1 0x07 /* Main divider byte 1 */ +#define R08_PSM1 0x08 /* PSM byte 1 */ +#define R09_MD2 0x09 /* Main divider byte 2 */ +#define R0A_MD3 0x0a /* Main divider byte 1 */ +#define R0B_MD4 0x0b /* Main divider byte 4 */ +#define R0C_MD5 0x0c /* Main divider byte 5 */ +#define R0D_MD6 0x0d /* Main divider byte 6 */ +#define R0E_MD7 0x0e /* Main divider byte 7 */ +#define R0F_MD8 0x0f /* Main divider byte 8 */ +#define R10_CD1 0x10 /* Call divider byte 1 */ +#define R11_CD2 0x11 /* Call divider byte 2 */ +#define R12_CD3 0x12 /* Call divider byte 3 */ +#define R13_CD4 0x13 /* Call divider byte 4 */ +#define R14_CD5 0x14 /* Call divider byte 5 */ +#define R15_CD6 0x15 /* Call divider byte 6 */ +#define R16_CD7 0x16 /* Call divider byte 7 */ +#define R17_PD1 0x17 /* Power-down byte 1 */ +#define R18_PD2 0x18 /* Power-down byte 2 */ +#define R19_XTOUT 0x19 /* XTOUT byte */ +#define R1A_IF1 0x1a /* IF byte 1 */ +#define R1B_IF2 0x1b /* IF byte 2 */ +#define R1C_AGC2B 0x1c /* AGC2b byte */ +#define R1D_PSM2 0x1d /* PSM byte 2 */ +#define R1E_PSM3 0x1e /* PSM byte 3 */ +#define R1F_PSM4 0x1f /* PSM byte 4 */ +#define R20_AGC11 0x20 /* AGC1 byte 1 */ +#define R21_AGC12 0x21 /* AGC1 byte 2 */ +#define R22_AGC13 0x22 /* AGC1 byte 3 */ +#define R23_AGC21 0x23 /* AGC2 byte 1 */ +#define R24_AGC22 0x24 /* AGC2 byte 2 */ +#define R25_AAGC 0x25 /* Analog AGC byte */ +#define R26_RC 0x26 /* RC byte */ +#define R27_RSSI 0x27 /* RSSI byte */ +#define R28_IRCAL1 0x28 /* IR CAL byte 1 */ +#define R29_IRCAL2 0x29 /* IR CAL byte 2 */ +#define R2A_IRCAL3 0x2a /* IR CAL byte 3 */ +#define R2B_IRCAL4 0x2b /* IR CAL byte 4 */ +#define R2C_RFCAL1 0x2c /* RF CAL byte 1 */ +#define R2D_RFCAL2 0x2d /* RF CAL byte 2 */ +#define R2E_RFCAL3 0x2e /* RF CAL byte 3 */ +#define R2F_RFCAL4 0x2f /* RF CAL byte 4 */ +#define R30_RFCAL5 0x30 /* RF CAL byte 5 */ +#define R31_RFCAL6 0x31 /* RF CAL byte 6 */ +#define R32_RFCAL7 0x32 /* RF CAL byte 7 */ +#define R33_RFCAL8 0x33 /* RF CAL byte 8 */ +#define R34_RFCAL9 0x34 /* RF CAL byte 9 */ +#define R35_RFCAL10 0x35 /* RF CAL byte 10 */ +#define R36_RFCALRAM1 0x36 /* RF CAL RAM byte 1 */ +#define R37_RFCALRAM2 0x37 /* RF CAL RAM byte 2 */ +#define R38_MARGIN 0x38 /* Margin byte */ +#define R39_FMAX1 0x39 /* Fmax byte 1 */ +#define R3A_FMAX2 0x3a /* Fmax byte 2 */ + +#define TDA18218_NUM_REGS 59 + +struct tda18218_priv { + struct tda18218_config *cfg; + struct i2c_adapter *i2c; + + u8 regs[TDA18218_NUM_REGS]; +}; + +#endif diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index e1f678281a58..5466d47db899 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -193,25 +193,51 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) unsigned char *regs = priv->tda18271_regs; unsigned char buf[TDA18271_NUM_REGS + 1]; struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, - .buf = buf, .len = len + 1 }; - int i, ret; + .buf = buf }; + int i, ret = 1, max; BUG_ON((len == 0) || (idx + len > sizeof(buf))); - buf[0] = idx; - for (i = 1; i <= len; i++) - buf[i] = regs[idx - 1 + i]; + + switch (priv->small_i2c) { + case TDA18271_03_BYTE_CHUNK_INIT: + max = 3; + break; + case TDA18271_08_BYTE_CHUNK_INIT: + max = 8; + break; + case TDA18271_16_BYTE_CHUNK_INIT: + max = 16; + break; + case TDA18271_39_BYTE_CHUNK_INIT: + default: + max = 39; + } tda18271_i2c_gate_ctrl(fe, 1); + while (len) { + if (max > len) + max = len; + + buf[0] = idx; + for (i = 1; i <= max; i++) + buf[i] = regs[idx - 1 + i]; - /* write registers */ - ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + msg.len = max + 1; + /* write registers */ + ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); + if (ret != 1) + break; + + idx += max; + len -= max; + } tda18271_i2c_gate_ctrl(fe, 0); if (ret != 1) tda_err("ERROR: idx = 0x%x, len = %d, " - "i2c_transfer returned: %d\n", idx, len, ret); + "i2c_transfer returned: %d\n", idx, max, ret); return (ret == 1 ? 0 : ret); } @@ -326,24 +352,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) regs[R_EB22] = 0x48; regs[R_EB23] = 0xb0; - switch (priv->small_i2c) { - case TDA18271_08_BYTE_CHUNK_INIT: - tda18271_write_regs(fe, 0x00, 0x08); - tda18271_write_regs(fe, 0x08, 0x08); - tda18271_write_regs(fe, 0x10, 0x08); - tda18271_write_regs(fe, 0x18, 0x08); - tda18271_write_regs(fe, 0x20, 0x07); - break; - case TDA18271_16_BYTE_CHUNK_INIT: - tda18271_write_regs(fe, 0x00, 0x10); - tda18271_write_regs(fe, 0x10, 0x10); - tda18271_write_regs(fe, 0x20, 0x07); - break; - case TDA18271_39_BYTE_CHUNK_INIT: - default: - tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); - break; - } + tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); /* setup agc1 gain */ regs[R_EB17] = 0x00; diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 7955e49a3440..9ad4454a148d 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1156,7 +1156,6 @@ static int tda18271_get_id(struct dvb_frontend *fe) struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; char *name; - int ret = 0; mutex_lock(&priv->lock); tda18271_read_regs(fe); @@ -1172,17 +1171,16 @@ static int tda18271_get_id(struct dvb_frontend *fe) priv->id = TDA18271HDC2; break; default: - name = "Unknown device"; - ret = -EINVAL; - break; + tda_info("Unknown device (%i) detected @ %d-%04x, device not supported.\n", + regs[R_ID], i2c_adapter_id(priv->i2c_props.adap), + priv->i2c_props.addr); + return -EINVAL; } - tda_info("%s detected @ %d-%04x%s\n", name, - i2c_adapter_id(priv->i2c_props.adap), - priv->i2c_props.addr, - (0 == ret) ? "" : ", device not supported."); + tda_info("%s detected @ %d-%04x\n", name, + i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr); - return ret; + return 0; } static int tda18271_setup_configuration(struct dvb_frontend *fe, diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h index d7fcc36dc6e6..3abb221f3d07 100644 --- a/drivers/media/common/tuners/tda18271.h +++ b/drivers/media/common/tuners/tda18271.h @@ -80,8 +80,9 @@ enum tda18271_output_options { enum tda18271_small_i2c { TDA18271_39_BYTE_CHUNK_INIT = 0, - TDA18271_16_BYTE_CHUNK_INIT = 1, - TDA18271_08_BYTE_CHUNK_INIT = 2, + TDA18271_16_BYTE_CHUNK_INIT = 16, + TDA18271_08_BYTE_CHUNK_INIT = 8, + TDA18271_03_BYTE_CHUNK_INIT = 3, }; struct tda18271_config { diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index d2b2c12a5561..76ac5cd84af7 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -1042,7 +1042,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg) + const struct xc5000_config *cfg) { struct xc5000_priv *priv = NULL; int instance; diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index e6d7236c9ea1..3756e73649be 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -53,11 +53,11 @@ struct xc5000_config { (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg); + const struct xc5000_config *cfg); #else static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg) + const struct xc5000_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; |