From patchwork Tue Jun 7 00:05:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jose Alberto Reguero X-Patchwork-Id: 854972 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p570DtrU020883 for ; Tue, 7 Jun 2011 00:13:55 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755269Ab1FGANm (ORCPT ); Mon, 6 Jun 2011 20:13:42 -0400 Received: from impaqm2.telefonica.net ([213.4.138.18]:29239 "EHLO telefonica.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754041Ab1FGANl (ORCPT ); Mon, 6 Jun 2011 20:13:41 -0400 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Tue, 07 Jun 2011 00:13:56 +0000 (UTC) X-Greylist: delayed 469 seconds by postgrey-1.27 at vger.kernel.org; Mon, 06 Jun 2011 20:13:40 EDT Received: from IMPmailhost2.adm.correo ([10.20.102.39]) by IMPaqm2.telefonica.net with bizsmtp id snyJ1g00x0r0BT63Mo5FJY; Tue, 07 Jun 2011 02:05:15 +0200 Received: from jar7.dominio ([2.137.107.204]) by IMPmailhost2.adm.correo with BIZ IMP id so5E1g0044QdmXW1io5EFR; Tue, 07 Jun 2011 02:05:15 +0200 X-Brightmail-Tracker: AAAAAA== X-original-sender: jareguero@telefonica.net From: Jose Alberto Reguero To: linux-media@vger.kernel.org Subject: [PATCH] add support for the dvb-t part of CT-3650 Date: Tue, 7 Jun 2011 02:05:07 +0200 User-Agent: KMail/1.13.7 (Linux/2.6.35.13-91.fc14.x86_64; KDE/4.6.3; x86_64; ; ) MIME-Version: 1.0 Message-Id: <201106070205.08118.jareguero@telefonica.net> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org This patch add suport for the dvb-t part of CT-3650. Jose Alberto Signed-off-by: Jose Alberto Reguero diff -urN linux/drivers/media/common/tuners/tda827x.c linux.new/drivers/media/common/tuners/tda827x.c --- linux/drivers/media/common/tuners/tda827x.c 2010-07-03 23:22:08.000000000 +0200 +++ linux.new/drivers/media/common/tuners/tda827x.c 2011-06-06 14:45:02.912154000 +0200 @@ -135,14 +135,29 @@ static int tuner_transfer(struct dvb_frontend *fe, struct i2c_msg *msg, - const int size) + int size) { int rc; struct tda827x_priv *priv = fe->tuner_priv; + struct i2c_msg msgr[2]; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - rc = i2c_transfer(priv->i2c_adap, msg, size); + if (priv->cfg->i2cr && (msg->flags == I2C_M_RD)) { + msgr[0].addr = msg->addr; + msgr[0].flags = 0; + msgr[0].len = msg->len - 1; + msgr[0].buf = msg->buf; + msgr[1].addr = msg->addr; + msgr[1].flags = I2C_M_RD; + msgr[1].len = 1; + msgr[1].buf = msg->buf; + size = 2; + rc = i2c_transfer(priv->i2c_adap, msgr, size); + msg->buf[msg->len - 1] = msgr[1].buf[0]; + } else { + rc = i2c_transfer(priv->i2c_adap, msg, size); + } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); diff -urN linux/drivers/media/common/tuners/tda827x.h linux.new/drivers/media/common/tuners/tda827x.h --- linux/drivers/media/common/tuners/tda827x.h 2010-07-03 23:22:08.000000000 +0200 +++ linux.new/drivers/media/common/tuners/tda827x.h 2011-05-21 22:48:31.484340005 +0200 @@ -38,6 +38,8 @@ int switch_addr; void (*agcf)(struct dvb_frontend *fe); + + u8 i2cr; }; diff -urN linux/drivers/media/dvb/dvb-usb/ttusb2.c linux.new/drivers/media/dvb/dvb-usb/ttusb2.c --- linux/drivers/media/dvb/dvb-usb/ttusb2.c 2011-01-10 16:24:45.000000000 +0100 +++ linux.new/drivers/media/dvb/dvb-usb/ttusb2.c 2011-06-06 14:35:37.906154000 +0200 @@ -30,6 +30,7 @@ #include "tda826x.h" #include "tda10086.h" #include "tda1002x.h" +#include "tda10048.h" #include "tda827x.h" #include "lnbp21.h" @@ -44,6 +45,8 @@ struct ttusb2_state { u8 id; u16 last_rc_key; + struct dvb_frontend *fe; + u8 initialized; }; static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, @@ -155,7 +158,6 @@ return 0; } - /* Callbacks for DVB USB */ static int ttusb2_identify_state (struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, @@ -167,11 +169,58 @@ static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) { + struct ttusb2_state *state; u8 b = onoff; - ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); - return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); + if (onoff) { + state = (struct ttusb2_state *)d->priv; + if (!state->initialized) { + ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); + ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); + state->initialized = 1; + } + } + return 0; +} + +//get access to tuner +static int lock_tuner(struct tda10048_state *state) +{ + u8 buf[2] = { 0x0f, 0xc0 }; + struct i2c_msg msg = {.addr=0x0c, .flags=0, .buf=buf, .len=2}; + + if(i2c_transfer(state->i2c, &msg, 1) != 1) + { + printk("tda10048: lock tuner fails\n"); + return -EREMOTEIO; + } + return 0; } +//release access from tuner +static int unlock_tuner(struct tda10048_state *state) +{ + u8 buf[2] = { 0x0f, 0x40 }; + struct i2c_msg msg_post={.addr=0x0c, .flags=0, .buf=buf, .len=2}; + + if(i2c_transfer(state->i2c, &msg_post, 1) != 1) + { + printk("tda10048: unlock tuner fails\n"); + return -EREMOTEIO; + } + return 0; +} + +static int tda10023_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct tda10048_state *state = fe->demodulator_priv; + + if (enable) { + lock_tuner(state); + } else { + unlock_tuner(state); + } + return 0; +} static struct tda10086_config tda10086_config = { .demod_address = 0x0e, @@ -190,6 +239,23 @@ .deltaf = 0xa511, }; +static struct tda10048_config tda10048_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_PARALLEL_OUTPUT, + .inversion = TDA10048_INVERSION_ON, + .dtv6_if_freq_khz = TDA10048_IF_4000, + .dtv7_if_freq_khz = TDA10048_IF_4500, + .dtv8_if_freq_khz = TDA10048_IF_5000, + .clk_freq_khz = TDA10048_CLK_16000, + .no_firmware = 1, + .i2c_gate = tda10023_i2c_gate_ctrl, +}; + +static struct tda827x_config tda827x_config = { + .i2cr = 1, + .config = 0, +}; + static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap) { if (usb_set_interface(adap->dev->udev,0,3) < 0) @@ -205,18 +271,30 @@ static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap) { + struct ttusb2_state *state; if (usb_set_interface(adap->dev->udev, 0, 3) < 0) err("set interface to alts=3 failed"); if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) { deb_info("TDA10023 attach failed\n"); return -ENODEV; } + adap->fe->id = 1; + state = (struct ttusb2_state *)adap->dev->priv; + if ((state->fe = dvb_attach(tda10048_attach, &tda10048_config, &adap->dev->i2c_adap)) == NULL) { + deb_info("TDA10048 attach failed\n"); + return -ENODEV; + } + dvb_register_frontend(&adap->dvb_adap, state->fe); + if (dvb_attach(tda827x_attach, state->fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) { + printk(KERN_ERR "%s: No tda827x found!\n", __func__); + return -ENODEV; + } return 0; } static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap) { - if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) { + if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) { printk(KERN_ERR "%s: No tda827x found!\n", __func__); return -ENODEV; } @@ -242,6 +320,19 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400; static struct dvb_usb_device_properties ttusb2_properties_ct3650; +static void ttusb2_usb_disconnect (struct usb_interface *intf) +{ + struct dvb_usb_device *d = usb_get_intfdata (intf); + struct ttusb2_state * state; + + state = (struct ttusb2_state *)d->priv; + if (state->fe) { + dvb_unregister_frontend(state->fe); + dvb_frontend_detach(state->fe); + } + dvb_usb_device_exit (intf); +} + static int ttusb2_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -422,7 +513,7 @@ static struct usb_driver ttusb2_driver = { .name = "dvb_usb_ttusb2", .probe = ttusb2_probe, - .disconnect = dvb_usb_device_exit, + .disconnect = ttusb2_usb_disconnect, .id_table = ttusb2_table, }; diff -urN linux/drivers/media/dvb/frontends/tda10048.c linux.new/drivers/media/dvb/frontends/tda10048.c --- linux/drivers/media/dvb/frontends/tda10048.c 2010-10-25 01:34:58.000000000 +0200 +++ linux.new/drivers/media/dvb/frontends/tda10048.c 2011-06-04 13:04:47.759000004 +0200 @@ -136,26 +136,6 @@ printk(KERN_DEBUG "tda10048: " fmt, ## arg);\ } while (0) -struct tda10048_state { - - struct i2c_adapter *i2c; - - /* We'll cache and update the attach config settings */ - struct tda10048_config config; - struct dvb_frontend frontend; - - int fwloaded; - - u32 freq_if_hz; - u32 xtal_hz; - u32 pll_mfactor; - u32 pll_nfactor; - u32 pll_pfactor; - u32 sample_freq; - - enum fe_bandwidth bandwidth; -}; - static struct init_tab { u8 reg; u16 data; @@ -214,6 +194,8 @@ { TDA10048_CLK_16000, TDA10048_IF_3800, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_4000, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_4300, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_4500, 10, 3, 0 }, + { TDA10048_CLK_16000, TDA10048_IF_5000, 10, 3, 0 }, { TDA10048_CLK_16000, TDA10048_IF_36130, 10, 3, 0 }, }; @@ -710,12 +692,16 @@ if (config->disable_gate_access) return 0; - if (enable) - return tda10048_writereg(state, TDA10048_CONF_C4_1, - tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); - else - return tda10048_writereg(state, TDA10048_CONF_C4_1, - tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd); + if (config->i2c_gate) { + return config->i2c_gate(fe, enable); + } else { + if (enable) + return tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02); + else + return tda10048_writereg(state, TDA10048_CONF_C4_1, + tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd); + } } static int tda10048_output_mode(struct dvb_frontend *fe, int serial) @@ -785,7 +771,7 @@ for (i = 0; i < ARRAY_SIZE(init_tab); i++) tda10048_writereg(state, init_tab[i].reg, init_tab[i].data); - if (state->fwloaded == 0) + if ((state->fwloaded == 0) && (!config->no_firmware)) ret = tda10048_firmware_upload(fe); /* Set either serial or parallel */ diff -urN linux/drivers/media/dvb/frontends/tda10048.h linux.new/drivers/media/dvb/frontends/tda10048.h --- linux/drivers/media/dvb/frontends/tda10048.h 2010-07-03 23:22:08.000000000 +0200 +++ linux.new/drivers/media/dvb/frontends/tda10048.h 2011-06-04 13:04:39.721000004 +0200 @@ -51,6 +51,7 @@ #define TDA10048_IF_4300 4300 #define TDA10048_IF_4500 4500 #define TDA10048_IF_4750 4750 +#define TDA10048_IF_5000 5000 #define TDA10048_IF_36130 36130 u16 dtv6_if_freq_khz; u16 dtv7_if_freq_khz; @@ -62,6 +63,30 @@ /* Disable I2C gate access */ u8 disable_gate_access; + + u8 no_firmware; + + int (*i2c_gate) (struct dvb_frontend *fe, int enable); +}; + +struct tda10048_state { + + struct i2c_adapter *i2c; + + /* We'll cache and update the attach config settings */ + struct tda10048_config config; + struct dvb_frontend frontend; + + int fwloaded; + + u32 freq_if_hz; + u32 xtal_hz; + u32 pll_mfactor; + u32 pll_nfactor; + u32 pll_pfactor; + u32 sample_freq; + + enum fe_bandwidth bandwidth; }; #if defined(CONFIG_DVB_TDA10048) || \