From: "Michael Büsch" <m@bues.ch>
To: Antti Palosaari <crope@iki.fi>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>, linux-media@vger.kernel.org
Subject: Re: [GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 => TerraTec Cinergy T Stick [0ccd:0093]
Date: Sat, 31 Mar 2012 18:49:07 +0200 [thread overview]
Message-ID: <20120331184907.4eed0481@milhouse> (raw)
In-Reply-To: <4F77320F.8050009@iki.fi>
[-- Attachment #1.1: Type: text/plain, Size: 1158 bytes --]
On Sat, 31 Mar 2012 19:34:23 +0300
Antti Palosaari <crope@iki.fi> wrote:
> On 31.03.2012 19:29, Michael Büsch wrote:
> > On Sat, 31 Mar 2012 17:28:38 +0300
> > Antti Palosaari<crope@iki.fi> wrote:
> >
> >> Googling the filename reveals many links, here is one:
> >> http://xgazza.altervista.org/Linux/DVB/dvb-usb-af9035-01.fw
> >
> > Hm, on tuner register access I get these errors:
> >
> > [ 9259.080907] af9035_ctrl_msg: command=03 failed fw error=2
> > [ 9259.080922] i2c i2c-8: I2C write reg failed, reg: 07, val: 0f
> >
> > Is it possible that this firmware is incompatible with my stick?
> > The firmware that I successfully used with the other af9035 driver seems to
> > be incompatible with your driver, though. It crashes it somewhere
> > on firmware download in one of the USB transfer's memcpy.
>
> Most likely it is incompatible. It is surely one of the earliest
> firmwares. I will try to make that new fw downloaded ASAP, likely
> tomorrow morning it is done.
Ok, thanks a lot.
Attached are my current fc0011 patches. Just for reference.
--
Greetings, Michael.
PGP encryption is encouraged / 908D8B0E
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: fc0011-tuner.patch --]
[-- Type: text/x-patch, Size: 16820 bytes --]
Index: linux/drivers/media/common/tuners/Kconfig
===================================================================
--- linux.orig/drivers/media/common/tuners/Kconfig 2012-03-31 00:32:25.000000000 +0200
+++ linux/drivers/media/common/tuners/Kconfig 2012-03-31 13:03:07.279334714 +0200
@@ -204,6 +204,13 @@
help
NXP TDA18218 silicon tuner driver.
+config MEDIA_TUNER_FC0011
+ tristate "Fitipower FC0011 silicon tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMISE
+ help
+ Fitipower FC0011 silicon tuner driver.
+
config MEDIA_TUNER_TDA18212
tristate "NXP TDA18212 silicon tuner"
depends on VIDEO_MEDIA && I2C
Index: linux/drivers/media/common/tuners/Makefile
===================================================================
--- linux.orig/drivers/media/common/tuners/Makefile 2012-03-31 00:32:25.000000000 +0200
+++ linux/drivers/media/common/tuners/Makefile 2012-03-31 13:03:42.444806267 +0200
@@ -29,6 +29,7 @@
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o
+obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o
ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
Index: linux/drivers/media/common/tuners/fc0011.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux/drivers/media/common/tuners/fc0011.c 2012-03-31 14:30:24.122314647 +0200
@@ -0,0 +1,489 @@
+/*
+ * Fitipower FC0011 tuner driver
+ *
+ * Copyright (C) 2012 Michael Buesch <m@bues.ch>
+ *
+ * Derived from FC0012 tuner driver:
+ * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
+ *
+ * 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 "fc0011.h"
+
+
+/* Tuner registers */
+enum {
+ FC11_REG_0,
+ FC11_REG_FA, /* FA */
+ FC11_REG_FP, /* FP */
+ FC11_REG_XINHI, /* XIN high 8 bit */
+ FC11_REG_XINLO, /* XIN low 8 bit */
+ FC11_REG_VCO, /* VCO */
+ FC11_REG_VCOSEL, /* VCO select */
+ FC11_REG_7, /* Unknown tune reg 7 */
+ FC11_REG_8, /* Unknown tune reg 8 */
+ FC11_REG_9,
+ FC11_REG_10, /* Unknown tune reg 10 */
+ FC11_REG_11, /* Unknown tune reg 11 */
+ FC11_REG_12,
+ FC11_REG_RCCAL, /* RC calibrate */
+ FC11_REG_VCOCAL, /* VCO calibrate */
+ FC11_REG_15,
+ FC11_REG_16, /* Unknown tune reg 16 */
+ FC11_REG_17,
+
+ FC11_NR_REGS, /* Number of registers */
+};
+
+enum FC11_REG_VCOSEL_bits {
+ FC11_VCOSEL_2 = 0x08, /* VCO select 2 */
+ FC11_VCOSEL_1 = 0x10, /* VCO select 1 */
+ FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */
+ FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */
+ FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */
+};
+
+enum FC11_REG_RCCAL_bits {
+ FC11_RCCAL_FORCE = 0x10, /* force */
+};
+
+enum FC11_REG_VCOCAL_bits {
+ FC11_VCOCAL_RUN = 0, /* VCO calibration run */
+ FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */
+ FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */
+ FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */
+};
+
+
+struct fc0011_priv {
+ struct i2c_adapter *i2c;
+ u8 addr;
+
+ u32 frequency;
+ u32 bandwidth;
+};
+
+
+static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val)
+{
+ u8 buf[2] = { reg, val };
+ struct i2c_msg msg = { .addr = priv->addr,
+ .flags = 0, .buf = buf, .len = 2 };
+
+ msleep(1);
+ if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+ dev_err(&priv->i2c->dev,
+ "I2C write reg failed, reg: %02x, val: %02x\n",
+ reg, val);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val)
+{
+ struct i2c_msg msg[2] = {
+ { .addr = priv->addr,
+ .flags = 0, .buf = ®, .len = 1 },
+ { .addr = priv->addr,
+ .flags = I2C_M_RD, .buf = val, .len = 1 },
+ };
+
+ if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+ dev_err(&priv->i2c->dev,
+ "I2C read failed, reg: %02x\n", reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int fc0011_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+
+ return 0;
+}
+
+static int fc0011_init(struct dvb_frontend *fe)
+{
+ struct fc0011_priv *priv = fe->tuner_priv;
+ int err;
+
+ if (WARN_ON(!fe->callback))
+ return -EINVAL;
+ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+ FC0011_FE_CALLBACK_POWER, 0);
+ if (err) {
+ dev_err(&priv->i2c->dev, "power-on callback failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int fc0011_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct fc0011_priv *priv = fe->tuner_priv;
+ int err;
+ unsigned int i;
+ u32 freq = p->frequency / 1000;
+ u32 bandwidth = p->bandwidth_hz / 1000;
+ u32 fvco, xin, xdiv, xdivr;
+ u16 frac;
+ u8 fa, fp, vco_sel, vco_cal;
+ u8 regs[FC11_NR_REGS] = { };
+
+ regs[FC11_REG_7] = 0x0F;
+ regs[FC11_REG_8] = 0x3E;
+ regs[FC11_REG_10] = 0xB8;
+ regs[FC11_REG_11] = 0x80;
+ regs[FC11_REG_RCCAL] = 0x04;
+ err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
+ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
+ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
+ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
+ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
+ if (err)
+ return -EIO;
+
+ /* Set VCO freq and VCO div */
+ if (freq < 54000) {
+ fvco = freq * 64;
+ regs[FC11_REG_VCO] = 0x82;
+ } else if (freq < 108000) {
+ fvco = freq * 32;
+ regs[FC11_REG_VCO] = 0x42;
+ } else if (freq < 216000) {
+ fvco = freq * 16;
+ regs[FC11_REG_VCO] = 0x22;
+ } else if (freq < 432000) {
+ fvco = freq * 8;
+ regs[FC11_REG_VCO] = 0x12;
+ } else {
+ fvco = freq * 4;
+ regs[FC11_REG_VCO] = 0x0A;
+ }
+
+ /* Calc XIN. The PLL reference frequency is 18 MHz. */
+ xdiv = fvco / 18000;
+ frac = fvco - xdiv * 18000;
+ frac = (frac << 15) / 18000;
+ if (frac >= 16384)
+ frac += 32786;
+ if (!frac)
+ xin = 0;
+ else if (frac < 511)
+ xin = 512;
+ else if (frac < 65026)
+ xin = frac;
+ else
+ xin = 65024;
+ regs[FC11_REG_XINHI] = xin >> 8;
+ regs[FC11_REG_XINLO] = xin;
+
+ /* Calc FP and FA */
+ xdivr = xdiv;
+ if (fvco - xdiv * 18000 >= 9000)
+ xdivr += 1; /* round */
+ fp = xdivr / 8;
+ fa = xdivr - fp * 8;
+ if (fa < 2) {
+ fp -= 1;
+ fa += 8;
+ }
+ if (fp > 0x1F) {
+ fp &= 0x1F;
+ fa &= 0xF;
+ }
+ if (fa >= fp) {
+ dev_warn(&priv->i2c->dev,
+ "fa %02X >= fp %02X, but trying to continue\n",
+ (unsigned int)(u8)fa, (unsigned int)(u8)fp);
+ }
+ regs[FC11_REG_FA] = fa;
+ regs[FC11_REG_FP] = fp;
+
+ /* Select bandwidth */
+ switch (bandwidth) {
+ case 8000:
+ break;
+ case 7000:
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
+ break;
+ default:
+ case 6000:
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M;
+ break;
+ }
+
+ /* Pre VCO select */
+ if (fvco < 2320000) {
+ vco_sel = 0;
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ } else if (fvco < 3080000) {
+ vco_sel = 1;
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
+ } else {
+ vco_sel = 2;
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
+ }
+
+ /* Fix for low freqs */
+ if (freq < 45000) {
+ regs[FC11_REG_FA] = 0x6;
+ regs[FC11_REG_FP] = 0x11;
+ }
+
+ /* Clock out fix */
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT;
+
+ /* Write the cached registers */
+ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) {
+ err = fc0011_writereg(priv, i, regs[i]);
+ if (err)
+ return err;
+ }
+
+ /* VCO calibration */
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET);
+ if (err)
+ return err;
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
+ if (err)
+ return err;
+ /* Read calib val */
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
+ if (err)
+ return err;
+ msleep(10);
+ err = fc0011_readreg(priv, FC11_REG_VCOCAL, &vco_cal);
+ if (err)
+ return err;
+ if (!(vco_cal & FC11_VCOCAL_OK)) {
+ /* Reset the tuner and try again */
+ err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+ FC0011_FE_CALLBACK_RESET, 0);
+ if (err) {
+ dev_err(&priv->i2c->dev, "Failed to reset tuner\n");
+ return err;
+ }
+ /* Reinit tuner config */
+ err = 0;
+ for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++)
+ err |= fc0011_writereg(priv, i, regs[i]);
+ err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
+ err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
+ err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
+ err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
+ err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
+ if (err)
+ return -EIO;
+ /* VCO calibration */
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET);
+ if (err)
+ return err;
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
+ if (err)
+ return err;
+ /* Read calib val */
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
+ if (err)
+ return err;
+ msleep(10);
+ err = fc0011_readreg(priv, FC11_REG_VCOCAL, &vco_cal);
+ if (err)
+ return err;
+ }
+ if (!(vco_cal & FC11_VCOCAL_OK)) {
+ dev_err(&priv->i2c->dev, "Failed to read VCO calibration value\n");
+ return -EIO;
+ }
+ vco_cal &= FC11_VCOCAL_VALUEMASK;
+
+ switch (vco_sel) {
+ case 0:
+ if (vco_cal < 8) {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RESET);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RUN);
+ if (err)
+ return -EIO;
+ } else {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ if (err)
+ return err;
+ }
+ break;
+ case 1:
+ if (vco_cal < 5) {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RESET);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RUN);
+ if (err)
+ return -EIO;
+ } else if (vco_cal <= 48) {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ if (err)
+ return err;
+ } else {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RESET);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RUN);
+ if (err)
+ return -EIO;
+ }
+ break;
+ case 2:
+ if (vco_cal > 53) {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RESET);
+ err |= fc0011_writereg(priv, FC11_REG_VCOCAL,
+ FC11_VCOCAL_RUN);
+ if (err)
+ return -EIO;
+ } else {
+ regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
+ regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
+ err = fc0011_writereg(priv, FC11_REG_VCOSEL,
+ regs[FC11_REG_VCOSEL]);
+ if (err)
+ return err;
+ }
+ break;
+ }
+ err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
+ if (err)
+ return err;
+ msleep(10);
+ err = fc0011_readreg(priv, FC11_REG_VCOCAL, &vco_cal);
+ if (err)
+ return err;
+ msleep(10);
+
+ err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]);
+ if (err)
+ return err;
+ regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE;
+ err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
+ if (err)
+ return err;
+ err = fc0011_writereg(priv, FC11_REG_16, 0xB);
+ if (err)
+ return err;
+
+ priv->frequency = p->frequency;
+ priv->bandwidth = p->bandwidth_hz;
+
+ return 0;
+}
+
+static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct fc0011_priv *priv = fe->tuner_priv;
+
+ *frequency = priv->frequency;
+
+ return 0;
+}
+
+static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ *frequency = 0;
+
+ return 0;
+}
+
+static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct fc0011_priv *priv = fe->tuner_priv;
+
+ *bandwidth = priv->bandwidth;
+
+ return 0;
+}
+
+static const struct dvb_tuner_ops fc0011_tuner_ops = {
+ .info = {
+ .name = "Fitipower FC0011",
+
+ .frequency_min = 45000000,
+ .frequency_max = 1000000000,
+ },
+
+ .release = fc0011_release,
+ .init = fc0011_init,
+
+ .set_params = fc0011_set_params,
+
+ .get_frequency = fc0011_get_frequency,
+ .get_if_frequency = fc0011_get_if_frequency,
+ .get_bandwidth = fc0011_get_bandwidth,
+};
+
+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct fc0011_config *config)
+{
+ struct fc0011_priv *priv;
+
+ priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL);
+ if (!priv)
+ return NULL;
+
+ priv->i2c = i2c;
+ priv->addr = config->i2c_address;
+
+ fe->tuner_priv = priv;
+ fe->ops.tuner_ops = fc0011_tuner_ops;
+
+ dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n");
+
+ return fe;
+}
+EXPORT_SYMBOL(fc0011_attach);
+
+MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
+MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
+MODULE_LICENSE("GPL");
Index: linux/drivers/media/common/tuners/fc0011.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux/drivers/media/common/tuners/fc0011.h 2012-03-31 14:27:31.822958249 +0200
@@ -0,0 +1,41 @@
+#ifndef LINUX_FC0011_H_
+#define LINUX_FC0011_H_
+
+#include "dvb_frontend.h"
+
+
+/** struct fc0011_config - fc0011 hardware config
+ *
+ * @i2c_address: I2C bus address.
+ */
+struct fc0011_config {
+ u8 i2c_address;
+};
+
+/** enum fc0011_fe_callback_commands - Frontend callbacks
+ *
+ * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware.
+ * @FC0011_FE_CALLBACK_RESET: Request a tuner reset.
+ */
+enum fc0011_fe_callback_commands {
+ FC0011_FE_CALLBACK_POWER,
+ FC0011_FE_CALLBACK_RESET,
+};
+
+#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\
+ defined(CONFIG_MEDIA_TUNER_FC0011_MODULE)
+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct fc0011_config *config);
+#else
+static inline
+struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ const struct fc0011_config *config)
+{
+ dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n");
+ return NULL;
+}
+#endif
+
+#endif /* LINUX_FC0011_H_ */
Index: linux/MAINTAINERS
===================================================================
--- linux.orig/MAINTAINERS 2012-03-31 00:32:24.000000000 +0200
+++ linux/MAINTAINERS 2012-03-31 13:03:07.291336671 +0200
@@ -2694,6 +2694,13 @@
F: Documentation/hwmon/f71805f
F: drivers/hwmon/f71805f.c
+FC0011 TUNER DRIVER
+M: Michael Buesch <m@bues.ch>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: drivers/media/common/tuners/fc0011.h
+F: drivers/media/common/tuners/fc0011.c
+
FANOTIFY
M: Eric Paris <eparis@redhat.com>
S: Maintained
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: af9035-add-usbid.patch --]
[-- Type: text/x-patch, Size: 1127 bytes --]
Index: linux/drivers/media/dvb/dvb-usb/af9035.c
===================================================================
--- linux.orig/drivers/media/dvb/dvb-usb/af9035.c 2012-03-31 15:25:06.611122203 +0200
+++ linux/drivers/media/dvb/dvb-usb/af9035.c 2012-03-31 18:44:14.557214890 +0200
@@ -634,11 +634,17 @@
enum af9035_id_entry {
AF9035_0CCD_0093,
+ AF9035_15A4_1001,
+ AF9035_15A4_9035,
};
static struct usb_device_id af9035_id[] = {
[AF9035_0CCD_0093] = {
USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)},
+ [AF9035_15A4_1001] = {
+ USB_DEVICE(0x15A4, 0x1001)},
+ [AF9035_15A4_9035] = {
+ USB_DEVICE(0x15A4, 0x9035)},
{},
};
@@ -681,14 +687,20 @@
.i2c_algo = &af9035_i2c_algo,
- .num_device_descs = 1,
+ .num_device_descs = 2,
.devices = {
{
.name = "TerraTec Cinergy T Stick",
.cold_ids = {
&af9035_id[AF9035_0CCD_0093],
},
- },
+ }, {
+ .name = "Afatech Technologies DVB-T stick",
+ .cold_ids = {
+ &af9035_id[AF9035_15A4_1001],
+ &af9035_id[AF9035_15A4_9035],
+ },
+ }
}
},
};
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: af9035-add-fc0011-tuner.patch --]
[-- Type: text/x-patch, Size: 5663 bytes --]
Index: linux/drivers/media/dvb/dvb-usb/af9035.c
===================================================================
--- linux.orig/drivers/media/dvb/dvb-usb/af9035.c 2012-03-31 18:44:28.265457286 +0200
+++ linux/drivers/media/dvb/dvb-usb/af9035.c 2012-03-31 18:44:38.241633686 +0200
@@ -19,9 +19,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#define DEBUG 1
+
#include "af9035.h"
#include "af9033.h"
#include "tua9001.h"
+#include "fc0011.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static DEFINE_MUTEX(af9035_usb_mutex);
@@ -486,6 +489,7 @@
switch (tmp) {
case AF9033_TUNER_TUA9001:
+ case AF9033_TUNER_FC0011:
af9035_af9033_config[i].spec_inv = 1;
break;
default:
@@ -531,6 +535,83 @@
return ret;
}
+static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
+ int cmd, int arg)
+{
+ int err;
+
+ switch (cmd) {
+ case FC0011_FE_CALLBACK_POWER:
+ /* Tuner enable */
+ err = af9035_wr_reg_mask(d, 0xd8eb, 1, 1);
+ if (err)
+ return err;
+ err = af9035_wr_reg_mask(d, 0xd8ec, 1, 1);
+ if (err)
+ return err;
+ err = af9035_wr_reg_mask(d, 0xd8ed, 1, 1);
+ if (err)
+ return err;
+ /* LED */
+ err = af9035_wr_reg_mask(d, 0xd8d0, 1, 1);
+ if (err)
+ return err;
+ err = af9035_wr_reg_mask(d, 0xd8d1, 1, 1);
+ if (err)
+ return err;
+ msleep(10);
+ break;
+ case FC0011_FE_CALLBACK_RESET:
+ err = af9035_wr_reg(d, 0xd8e9, 1);
+ if (err)
+ return err;
+ err = af9035_wr_reg(d, 0xd8e8, 1);
+ if (err)
+ return err;
+ err = af9035_wr_reg(d, 0xd8e7, 1);
+ if (err)
+ return err;
+ msleep(10);
+ err = af9035_wr_reg(d, 0xd8e7, 0);
+ if (err)
+ return err;
+ msleep(10);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
+{
+ switch (af9035_af9033_config[0].tuner) {
+ case AF9033_TUNER_FC0011:
+ return af9035_fc0011_tuner_callback(d, cmd, arg);
+ default:
+ break;
+ }
+
+ return -ENODEV;
+}
+
+static int af9035_frontend_callback(void *adapter_priv, int component,
+ int cmd, int arg)
+{
+ struct i2c_adapter *adap = adapter_priv;
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+
+ switch (component) {
+ case DVB_FRONTEND_COMPONENT_TUNER:
+ return af9035_tuner_callback(d, cmd, arg);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
{
int ret;
@@ -554,6 +635,7 @@
ret = -ENODEV;
goto err;
}
+ adap->fe_adap[0].fe->callback = af9035_frontend_callback;
return 0;
@@ -567,6 +649,10 @@
.i2c_addr = 0x60,
};
+static const struct fc0011_config af9035_fc0011_config = {
+ .i2c_address = 0xC0,
+};
+
static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
{
int ret;
@@ -615,6 +701,10 @@
fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, &af9035_tua9001_config);
break;
+ case AF9033_TUNER_FC0011:
+ fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe,
+ &adap->dev->i2c_adap, &af9035_fc0011_config);
+ break;
default:
fe = NULL;
}
Index: linux/drivers/media/dvb/frontends/af9033.c
===================================================================
--- linux.orig/drivers/media/dvb/frontends/af9033.c 2012-03-31 18:43:26.392363037 +0200
+++ linux/drivers/media/dvb/frontends/af9033.c 2012-03-31 18:44:38.241633686 +0200
@@ -297,6 +297,10 @@
len = ARRAY_SIZE(tuner_init_tua9001);
init = tuner_init_tua9001;
break;
+ case AF9033_TUNER_FC0011:
+ len = ARRAY_SIZE(tuner_init_fc0011);
+ init = tuner_init_fc0011;
+ break;
default:
pr_debug("%s: unsupported tuner ID=%d\n", __func__,
state->cfg.tuner);
Index: linux/drivers/media/dvb/frontends/af9033_priv.h
===================================================================
--- linux.orig/drivers/media/dvb/frontends/af9033_priv.h 2012-03-31 18:43:26.392363037 +0200
+++ linux/drivers/media/dvb/frontends/af9033_priv.h 2012-03-31 18:44:38.241633686 +0200
@@ -238,5 +238,66 @@
{ 0x80f1e6, 0x00 },
};
+/* Fitipower fc0011 tuner init
+ AF9033_TUNER_FC0011 = 0x28 */
+static const struct reg_val tuner_init_fc0011[] = {
+ { 0x800046, AF9033_TUNER_FC0011 },
+ { 0x800057, 0x00 },
+ { 0x800058, 0x01 },
+ { 0x80005f, 0x00 },
+ { 0x800060, 0x00 },
+ { 0x800068, 0xa5 },
+ { 0x80006e, 0x01 },
+ { 0x800071, 0x0A },
+ { 0x800072, 0x02 },
+ { 0x800074, 0x01 },
+ { 0x800079, 0x01 },
+ { 0x800093, 0x00 },
+ { 0x800094, 0x00 },
+ { 0x800095, 0x00 },
+ { 0x800096, 0x00 },
+ { 0x80009b, 0x2D },
+ { 0x80009c, 0x60 },
+ { 0x80009d, 0x23 },
+ { 0x8000a4, 0x50 },
+ { 0x8000ad, 0x50 },
+ { 0x8000b3, 0x01 },
+ { 0x8000b7, 0x88 },
+ { 0x8000b8, 0xa6 },
+ { 0x8000c3, 0x01 },
+ { 0x8000c4, 0x01 },
+ { 0x8000c7, 0x69 },
+ { 0x80F007, 0x00 },
+ { 0x80F00A, 0x1B },
+ { 0x80F00B, 0x1B },
+ { 0x80F00C, 0x1B },
+ { 0x80F00D, 0x1B },
+ { 0x80F00E, 0xFF },
+ { 0x80F00F, 0x01 },
+ { 0x80F010, 0x00 },
+ { 0x80F011, 0x02 },
+ { 0x80F012, 0xFF },
+ { 0x80F013, 0x01 },
+ { 0x80F014, 0x00 },
+ { 0x80F015, 0x02 },
+ { 0x80F01B, 0xEF },
+ { 0x80F01C, 0x01 },
+ { 0x80F01D, 0x0f },
+ { 0x80F01E, 0x02 },
+ { 0x80F01F, 0x6E },
+ { 0x80F020, 0x00 },
+ { 0x80F025, 0xDE },
+ { 0x80F026, 0x00 },
+ { 0x80F027, 0x0A },
+ { 0x80F028, 0x03 },
+ { 0x80F029, 0x6E },
+ { 0x80F02A, 0x00 },
+ { 0x80F047, 0x00 },
+ { 0x80F054, 0x00 },
+ { 0x80F055, 0x00 },
+ { 0x80F077, 0x01 },
+ { 0x80F1E6, 0x00 },
+};
+
#endif /* AF9033_PRIV_H */
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
next prev parent reply other threads:[~2012-03-31 16:49 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-30 12:33 [GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 => TerraTec Cinergy T Stick [0ccd:0093] Antti Palosaari
2012-03-30 21:45 ` Michael Büsch
2012-03-30 22:00 ` Antti Palosaari
2012-03-30 22:14 ` Michael Büsch
2012-03-31 14:04 ` Michael Büsch
2012-03-31 14:28 ` Antti Palosaari
2012-03-31 16:29 ` Michael Büsch
2012-03-31 16:34 ` Antti Palosaari
2012-03-31 16:48 ` Antti Palosaari
2012-03-31 16:52 ` Michael Büsch
2012-04-01 4:51 ` Antti Palosaari
2012-04-01 8:33 ` Michael Büsch
2012-04-01 12:19 ` Michael Büsch
2012-04-01 12:29 ` Antti Palosaari
2012-04-01 13:11 ` Michael Büsch
2012-04-01 13:19 ` Antti Palosaari
2012-04-01 14:42 ` Hans-Frieder Vogt
2012-04-01 14:56 ` Michael Büsch
2012-04-01 16:24 ` Hans-Frieder Vogt
2012-04-01 16:36 ` Michael Büsch
2012-04-01 16:15 ` Michael Büsch
2012-04-01 16:20 ` Antti Palosaari
2012-04-01 16:32 ` Michael Büsch
2012-04-01 16:39 ` Antti Palosaari
2012-04-01 16:44 ` Michael Büsch
2012-04-01 9:56 ` Gianluca Gennari
2012-04-01 10:27 ` Hans-Frieder Vogt
2012-04-01 12:31 ` Antti Palosaari
2012-04-01 14:31 ` Hans-Frieder Vogt
2012-04-01 15:00 ` Antti Palosaari
2012-04-01 15:04 ` Hans-Frieder Vogt
2012-04-01 12:53 ` Antti Palosaari
2012-04-01 17:15 ` [PATCH][GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 support for AverTV A867R (mxl5007t tuner) Hans-Frieder Vogt
2012-04-01 17:24 ` Antti Palosaari
2012-04-01 18:11 ` [PATCH][GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 i2c read fix Hans-Frieder Vogt
2012-04-01 18:16 ` Antti Palosaari
2012-04-01 21:07 ` [PATCH][GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 support for AverTV A867R (mxl5007t), version 2 Hans-Frieder Vogt
2012-04-01 21:19 ` [PATCH] AF9033 read_ber and read_ucblocks implementation Hans-Frieder Vogt
2012-04-01 21:56 ` Antti Palosaari
2012-04-01 22:11 ` Antti Palosaari
2012-04-01 21:32 ` [PATCH][GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 support for AverTV A867R (mxl5007t), version 2 Antti Palosaari
2012-04-02 17:02 ` Hans-Frieder Vogt
2012-03-31 16:49 ` Michael Büsch [this message]
2012-04-06 11:11 ` [GIT PULL FOR 3.5] AF9035/AF9033/TUA9001 => TerraTec Cinergy T Stick [0ccd:0093] Antti Palosaari
2012-05-07 18:44 ` [GIT PULL FOR 3.5] AF9035/AF9033 Antti Palosaari
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120331184907.4eed0481@milhouse \
--to=m@bues.ch \
--cc=crope@iki.fi \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox