diff options
Diffstat (limited to 'linux/drivers/media/dvb/frontends')
-rw-r--r-- | linux/drivers/media/dvb/frontends/Kconfig | 7 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/cx22700.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/dib7000p.c | 35 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/stb6100.c | 5 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda10021.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/tda8261.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/ves1820.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/zl10039.c | 308 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/zl10039.h | 40 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/zl10353.c | 14 |
11 files changed, 411 insertions, 11 deletions
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 1f43f9af8..d7c4837fa 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -81,6 +81,13 @@ config DVB_ZL10036 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_ZL10039 + tristate "Zarlink ZL10039 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index fa65868d7..3523767e7 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_ZL10036) += zl10036.o +obj-$(CONFIG_DVB_ZL10039) += zl10039.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c index fbd838eca..5fbc0fc37 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.c +++ b/linux/drivers/media/dvb/frontends/cx22700.c @@ -155,7 +155,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet p->hierarchy_information > HIERARCHY_4) return -EINVAL; - if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) + if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ) return -EINVAL; if (p->bandwidth == BANDWIDTH_7_MHZ) diff --git a/linux/drivers/media/dvb/frontends/dib7000p.c b/linux/drivers/media/dvb/frontends/dib7000p.c index ebb7594e3..57bee771c 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.c +++ b/linux/drivers/media/dvb/frontends/dib7000p.c @@ -11,6 +11,7 @@ #include <linux/i2c.h> #include "compat.h" +#include "dvb_math.h" #include "dvb_frontend.h" #include "dib7000p.h" @@ -909,7 +910,7 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 255, 255, 255, 255, 255, 255}; u32 xtal = state->cfg.bw->xtal_hz / 1000; - int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; + int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz; int k; int coef_re[8],coef_im[8]; int bw_khz = bw; @@ -1243,7 +1244,37 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) { - *snr = 0x0000; + struct dib7000p_state *state = fe->demodulator_priv; + u16 val; + s32 signal_mant, signal_exp, noise_mant, noise_exp; + u32 result = 0; + + val = dib7000p_read_word(state, 479); + noise_mant = (val >> 4) & 0xff; + noise_exp = ((val & 0xf) << 2); + val = dib7000p_read_word(state, 480); + noise_exp += ((val >> 14) & 0x3); + if ((noise_exp & 0x20) != 0) + noise_exp -= 0x40; + + signal_mant = (val >> 6) & 0xFF; + signal_exp = (val & 0x3F); + if ((signal_exp & 0x20) != 0) + signal_exp -= 0x40; + + if (signal_mant != 0) + result = intlog10(2) * 10 * signal_exp + 10 * + intlog10(signal_mant); + else + result = intlog10(2) * 10 * signal_exp - 100; + + if (noise_mant != 0) + result -= intlog10(2) * 10 * noise_exp + 10 * + intlog10(noise_mant); + else + result -= intlog10(2) * 10 * noise_exp - 100; + + *snr = result / ((1 << 24) / 10); return 0; } diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 2b1af36b8..2de9e0c01 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/string.h> +#include "compat.h" #include "dvb_frontend.h" #include "stb6100.h" @@ -374,7 +375,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ nint = fvco / (state->reference << psd2); /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ - nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference; + nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2)) + << (9 - psd2), + state->reference); dprintk(verbose, FE_DEBUG, 1, "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", frequency, srate, (unsigned int)g, (unsigned int)odiv, diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index 242636e59..f410fd5e2 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -29,6 +29,7 @@ #include <linux/string.h> #include <linux/slab.h> +#include "compat.h" #include "dvb_frontend.h" #include "tda1002x.h" @@ -176,7 +177,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate tmp = ((symbolrate << 4) % FIN) << 8; ratio = (ratio << 8) + tmp / FIN; tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN); BDR = ratio; BDRI = (((XIN << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/frontends/tda8261.c b/linux/drivers/media/dvb/frontends/tda8261.c index b6d177799..320c3c36d 100644 --- a/linux/drivers/media/dvb/frontends/tda8261.c +++ b/linux/drivers/media/dvb/frontends/tda8261.c @@ -136,9 +136,9 @@ static int tda8261_set_state(struct dvb_frontend *fe, if (frequency < 1450000) buf[3] = 0x00; - if (frequency < 2000000) + else if (frequency < 2000000) buf[3] = 0x40; - if (frequency < 2150000) + else if (frequency < 2150000) buf[3] = 0x80; /* Set params */ diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 6e78e4865..afd7f09ac 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <asm/div64.h> +#include "compat.h" #include "dvb_frontend.h" #include "ves1820.h" @@ -165,7 +166,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) tmp = ((symbolrate << 4) % fin) << 8; ratio = (ratio << 8) + tmp / fin; tmp = (tmp % fin) << 8; - ratio = (ratio << 8) + (tmp + fin / 2) / fin; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin); BDR = ratio; BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/frontends/zl10039.c b/linux/drivers/media/dvb/frontends/zl10039.c new file mode 100644 index 000000000..11b29cb88 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.c @@ -0,0 +1,308 @@ +/* + * Driver for Zarlink ZL10039 DVB-S tuner + * + * Copyright 2007 Jan D. Louw <jd.louw@mweb.co.za> + * + * 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 <linux/module.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/dvb/frontend.h> + +#include "dvb_frontend.h" +#include "zl10039.h" + +static int debug; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG args); \ + } while (0) + +enum zl10039_model_id { + ID_ZL10039 = 1 +}; + +struct zl10039_state { + struct i2c_adapter *i2c; + u8 i2c_addr; + u8 id; +}; + +enum zl10039_reg_addr { + PLL0 = 0, + PLL1, + PLL2, + PLL3, + RFFE, + BASE0, + BASE1, + BASE2, + LO0, + LO1, + LO2, + LO3, + LO4, + LO5, + LO6, + GENERAL +}; + +static int zl10039_read(const struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *buf, + const size_t count) +{ + u8 regbuf[] = { reg }; + struct i2c_msg msg[] = { + {/* Write register address */ + .addr = state->i2c_addr, + .flags = 0, + .buf = regbuf, + .len = 1, + }, {/* Read count bytes */ + .addr = state->i2c_addr, + .flags = I2C_M_RD, + .buf = buf, + .len = count, + }, + }; + + dprintk("%s\n", __func__); + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + dprintk("%s: i2c read error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static int zl10039_write(struct zl10039_state *state, + const enum zl10039_reg_addr reg, const u8 *src, + const size_t count) +{ + u8 buf[count + 1]; + struct i2c_msg msg = { + .addr = state->i2c_addr, + .flags = 0, + .buf = buf, + .len = count + 1, + }; + + dprintk("%s\n", __func__); + /* Write register address and data in one go */ + buf[0] = reg; + memcpy(&buf[1], src, count); + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + dprintk("%s: i2c write error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static inline int zl10039_readreg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *val) +{ + return zl10039_read(state, reg, val, 1); +} + +static inline int zl10039_writereg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, + const u8 val) +{ + return zl10039_write(state, reg, &val, 1); +} + +static int zl10039_init(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* Reset logic */ + ret = zl10039_writereg(state, GENERAL, 0x40); + if (ret < 0) { + dprintk("Note: i2c write error normal when resetting the " + "tuner\n"); + } + /* Wake up */ + ret = zl10039_writereg(state, GENERAL, 0x01); + if (ret < 0) { + dprintk("Tuner power up failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_sleep(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = zl10039_writereg(state, GENERAL, 0x80); + if (ret < 0) { + dprintk("Tuner sleep failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct zl10039_state *state = fe->tuner_priv; + u8 buf[6]; + u8 bf; + u32 fbw; + u32 div; + int ret; + + dprintk("%s\n", __func__); + dprintk("Set frequency = %d, symbol rate = %d\n", + params->frequency, params->u.qpsk.symbol_rate); + + /* Assumed 10.111 MHz crystal oscillator */ + /* Cancelled num/den 80 to prevent overflow */ + div = (params->frequency * 1000) / 126387; + fbw = (params->u.qpsk.symbol_rate * 27) / 32000; + /* Cancelled num/den 10 to prevent overflow */ + bf = ((fbw * 5088) / 1011100) - 1; + + /*PLL divider*/ + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + /*Reference divider*/ + /* Select reference ratio of 80 */ + buf[2] = 0x1D; + /*PLL test modes*/ + buf[3] = 0x40; + /*RF Control register*/ + buf[4] = 0x6E; /* Bypass enable */ + /*Baseband filter cutoff */ + buf[5] = bf; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* BR = 10, Enable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x0A); + if (ret < 0) + goto error; + /* Write new config values */ + ret = zl10039_write(state, PLL0, buf, sizeof(buf)); + if (ret < 0) + goto error; + /* BR = 10, Disable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x6A); + if (ret < 0) + goto error; + + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return 0; +error: + dprintk("Error setting tuner\n"); + return ret; +} + +static int zl10039_release(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + + dprintk("%s\n", __func__); + kfree(state); + fe->tuner_priv = NULL; + return 0; +} + +static struct dvb_tuner_ops zl10039_ops = { + .release = zl10039_release, + .init = zl10039_init, + .sleep = zl10039_sleep, + .set_params = zl10039_set_params, +}; + +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, struct i2c_adapter *i2c) +{ + struct zl10039_state *state = NULL; + + dprintk("%s\n", __func__); + state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->i2c = i2c; + state->i2c_addr = i2c_addr; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* check if this is a valid tuner */ + if (zl10039_readreg(state, GENERAL, &state->id) < 0) { + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + goto error; + } + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + state->id = state->id & 0x0f; + switch (state->id) { + case ID_ZL10039: + strcpy(fe->ops.tuner_ops.info.name, + "Zarlink ZL10039 DVB-S tuner"); + break; + default: + dprintk("Chip ID=%x does not match a known type\n", state->id); + break; + goto error; + } + + memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = state; + dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr); + return fe; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(zl10039_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver"); +MODULE_AUTHOR("Jan D. Louw <jd.louw@mweb.co.za>"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/zl10039.h b/linux/drivers/media/dvb/frontends/zl10039.h new file mode 100644 index 000000000..5eee7ea16 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.h @@ -0,0 +1,40 @@ +/* + Driver for Zarlink ZL10039 DVB-S tuner + + Copyright (C) 2007 Jan D. Louw <jd.louw@mweb.co.za> + + 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 ZL10039_H +#define ZL10039_H + +#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \ + && defined(MODULE)) +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_ZL10039 */ + +#endif /* ZL10039_H */ diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index a69e9602c..37a050efd 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -39,6 +39,8 @@ struct zl10353_state { struct zl10353_config config; enum fe_bandwidth bandwidth; + u32 ucblocks; + u32 frequency; }; static int debug; @@ -204,6 +206,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, u16 tps = 0; struct dvb_ofdm_parameters *op = ¶m->u.ofdm; + state->frequency = param->frequency; + zl10353_single_write(fe, RESET, 0x80); udelay(200); zl10353_single_write(fe, 0xEA, 0x01); @@ -469,7 +473,7 @@ static int zl10353_get_parameters(struct dvb_frontend *fe, break; } - param->frequency = 0; + param->frequency = state->frequency; op->bandwidth = state->bandwidth; param->inversion = INVERSION_AUTO; @@ -549,9 +553,13 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct zl10353_state *state = fe->demodulator_priv; + u32 ubl = 0; + + ubl = zl10353_read_register(state, RS_UBC_1) << 8 | + zl10353_read_register(state, RS_UBC_0); - *ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 | - zl10353_read_register(state, RS_UBC_0); + state->ucblocks += ubl; + *ucblocks = state->ucblocks; return 0; } |