Commit d6586193 authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds

[PATCH] dvb: nxt2002: add ATSC support, misc fixes

- [DVB] mt352: exported a mt352_read_reg-function, implemented a single byte
        write_register function (needed for dibusb)
- [DVB] nxt2002: patch by Taylor Jacob to add support for ATSC/VSB frontends
        and the B2C2/BBTI Air2PC-ATSC card
- [DVB] stv0297: fix tuning problems and compile time warnings, patch by Markus Breitenberger
- [DVB] fix spelling errors in various frontend drivers
Signed-off-by: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4f4f9689
...@@ -58,16 +58,26 @@ do { \ ...@@ -58,16 +58,26 @@ do { \
if (debug) printk(KERN_DEBUG "mt352: " args); \ if (debug) printk(KERN_DEBUG "mt352: " args); \
} while (0) } while (0)
int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
{ {
struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv; struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
u8 buf[2] = { reg, val };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0,
.buf = ibuf, .len = ilen }; .buf = buf, .len = 2 };
int err = i2c_transfer(state->i2c, &msg, 1); int err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1) { if (err != 1) {
dprintk("mt352_write() failed (err = %d)!\n", err); dprintk("mt352_write() to reg %x failed (err = %d)!\n", reg, err);
return err; return err;
} }
return 0;
}
int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
{
int err,i;
for (i=0; i < ilen-1; i++)
if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1])))
return err;
return 0; return 0;
} }
...@@ -92,9 +102,10 @@ static u8 mt352_read_register(struct mt352_state* state, u8 reg) ...@@ -92,9 +102,10 @@ static u8 mt352_read_register(struct mt352_state* state, u8 reg)
return b1[0]; return b1[0];
} }
u8 mt352_read(struct dvb_frontend *fe, u8 reg)
{
return mt352_read_register(fe->demodulator_priv,reg);
}
...@@ -556,3 +567,4 @@ MODULE_LICENSE("GPL"); ...@@ -556,3 +567,4 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mt352_attach); EXPORT_SYMBOL(mt352_attach);
EXPORT_SYMBOL(mt352_write); EXPORT_SYMBOL(mt352_write);
EXPORT_SYMBOL(mt352_read);
...@@ -54,5 +54,6 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, ...@@ -54,5 +54,6 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct i2c_adapter* i2c); struct i2c_adapter* i2c);
extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen); extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
extern u8 mt352_read(struct dvb_frontend *fe, u8 reg);
#endif // MT352_H #endif // MT352_H
This diff is collapsed.
/*
Driver for the Nxt2002 demodulator
*/
#ifndef NXT2002_H
#define NXT2002_H
#include <linux/dvb/frontend.h>
#include <linux/firmware.h>
struct nxt2002_config
{
/* the demodulator's i2c address */
u8 demod_address;
/* request firmware for device */
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
struct i2c_adapter* i2c);
#endif // NXT2002_H
...@@ -38,10 +38,7 @@ struct stv0297_state { ...@@ -38,10 +38,7 @@ struct stv0297_state {
struct dvb_frontend frontend; struct dvb_frontend frontend;
int freq_off;
unsigned long base_freq; unsigned long base_freq;
u8 pwm; u8 pwm;
}; };
...@@ -162,8 +159,10 @@ static int stv0297_readreg (struct stv0297_state* state, u8 reg) ...@@ -162,8 +159,10 @@ static int stv0297_readreg (struct stv0297_state* state, u8 reg)
int ret; int ret;
u8 b0[] = { reg }; u8 b0[] = { reg };
u8 b1[] = { 0 }; u8 b1[] = { 0 };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len =
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; 1},
{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
};
// this device needs a STOP between the register and data // this device needs a STOP between the register and data
if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
...@@ -193,8 +192,10 @@ static int stv0297_writereg_mask (struct stv0297_state* state, u8 reg, u8 mask, ...@@ -193,8 +192,10 @@ static int stv0297_writereg_mask (struct stv0297_state* state, u8 reg, u8 mask,
static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len) static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len)
{ {
int ret; int ret;
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 }, struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf =
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } }; &reg1,.len = 1},
{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
};
// this device needs a STOP between the register and data // this device needs a STOP between the register and data
if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) { if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
...@@ -209,6 +210,21 @@ static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len ...@@ -209,6 +210,21 @@ static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len
return 0; return 0;
} }
static u32 stv0297_get_symbolrate(struct stv0297_state *state)
{
u64 tmp;
tmp = stv0297_readreg(state, 0x55);
tmp |= stv0297_readreg(state, 0x56) << 8;
tmp |= stv0297_readreg(state, 0x57) << 16;
tmp |= stv0297_readreg(state, 0x58) << 24;
tmp *= STV0297_CLOCK_KHZ;
tmp >>= 32;
return (u32) tmp;
}
static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate) static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate)
{ {
long tmp; long tmp;
...@@ -259,39 +275,40 @@ static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset) ...@@ -259,39 +275,40 @@ static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset)
stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f); stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f);
} }
/*
static long stv0297_get_carrieroffset(struct stv0297_state* state) static long stv0297_get_carrieroffset(struct stv0297_state* state)
{ {
s32 raw; s64 tmp;
long tmp;
stv0297_writereg(state,0x6B, 0x00); stv0297_writereg(state,0x6B, 0x00);
raw = stv0297_readreg(state,0x66); tmp = stv0297_readreg(state, 0x66);
raw |= (stv0297_readreg(state,0x67) << 8); tmp |= (stv0297_readreg(state, 0x67) << 8);
raw |= (stv0297_readreg(state,0x68) << 16); tmp |= (stv0297_readreg(state, 0x68) << 16);
raw |= (stv0297_readreg(state,0x69) & 0x0F) << 24; tmp |= (stv0297_readreg(state, 0x69) & 0x0F) << 24;
tmp = raw; tmp *= stv0297_get_symbolrate(state);
tmp /= 26844L; tmp >>= 28;
return tmp; return (s32) tmp;
} }
*/
static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq) static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq)
{ {
/* s32 tmp;
s64 tmp;
if (freq > 10000) freq -= STV0297_CLOCK_KHZ; if (freq > 10000)
freq -= STV0297_CLOCK_KHZ;
tmp = freq << 16; tmp = (STV0297_CLOCK_KHZ * 1000) / (1 << 16);
do_div(tmp, STV0297_CLOCK_KHZ); tmp = (freq * 1000) / tmp;
if (tmp > 0xffff) tmp = 0xffff; // check this calculation if (tmp > 0xffff)
tmp = 0xffff;
stv0297_writereg_mask(state, 0x25, 0x80, 0x80); stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
stv0297_writereg(state, 0x21, tmp >> 8); stv0297_writereg(state, 0x21, tmp >> 8);
stv0297_writereg(state, 0x20, tmp); stv0297_writereg(state, 0x20, tmp);
*/
} }
static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation) static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation)
...@@ -413,6 +430,15 @@ static int stv0297_init (struct dvb_frontend* fe) ...@@ -413,6 +430,15 @@ static int stv0297_init (struct dvb_frontend* fe)
return 0; return 0;
} }
static int stv0297_sleep(struct dvb_frontend *fe)
{
struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
stv0297_writereg_mask(state, 0x80, 1, 1);
return 0;
}
static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status) static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status)
{ {
struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv; struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
...@@ -484,6 +510,7 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -484,6 +510,7 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
int carrieroffset; int carrieroffset;
unsigned long starttime; unsigned long starttime;
unsigned long timeout; unsigned long timeout;
fe_spectral_inversion_t inversion;
switch(p->u.qam.modulation) { switch(p->u.qam.modulation) {
case QAM_16: case QAM_16:
...@@ -508,8 +535,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -508,8 +535,11 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
} }
// determine inversion dependant parameters // determine inversion dependant parameters
inversion = p->inversion;
if (state->config->invert)
inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
carrieroffset = -330; carrieroffset = -330;
switch(p->inversion) { switch (inversion) {
case INVERSION_OFF: case INVERSION_OFF:
break; break;
...@@ -522,13 +552,14 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -522,13 +552,14 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return -EINVAL; return -EINVAL;
} }
stv0297_init(fe);
state->config->pll_set(fe, p); state->config->pll_set(fe, p);
/* clear software interrupts */ /* clear software interrupts */
stv0297_writereg(state, 0x82, 0x0); stv0297_writereg(state, 0x82, 0x0);
/* set initial demodulation frequency */ /* set initial demodulation frequency */
stv0297_set_initialdemodfreq(state, state->freq_off + 7250); stv0297_set_initialdemodfreq(state, 7250);
/* setup AGC */ /* setup AGC */
stv0297_writereg_mask(state, 0x43, 0x10, 0x00); stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
...@@ -588,7 +619,7 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -588,7 +619,7 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_set_symbolrate(state, p->u.qam.symbol_rate/1000); stv0297_set_symbolrate(state, p->u.qam.symbol_rate/1000);
stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000); stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
stv0297_set_carrieroffset(state, carrieroffset); stv0297_set_carrieroffset(state, carrieroffset);
stv0297_set_inversion(state, p->inversion); stv0297_set_inversion(state, inversion);
/* kick off lock */ /* kick off lock */
stv0297_writereg_mask(state, 0x88, 0x08, 0x08); stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
...@@ -664,7 +695,6 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -664,7 +695,6 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
/* success!! */ /* success!! */
stv0297_writereg_mask(state, 0x5a, 0x40, 0x00); stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
state->freq_off = stv0297_get_carrieroffset(state);
state->base_freq = p->frequency; state->base_freq = p->frequency;
return 0; return 0;
...@@ -681,10 +711,12 @@ static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par ...@@ -681,10 +711,12 @@ static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
reg_00 = stv0297_readreg(state, 0x00); reg_00 = stv0297_readreg(state, 0x00);
reg_83 = stv0297_readreg(state, 0x83); reg_83 = stv0297_readreg(state, 0x83);
p->frequency = state->base_freq + state->freq_off; p->frequency = state->base_freq;
p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF; p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
p->u.qam.symbol_rate = 0; if (state->config->invert)
p->u.qam.fec_inner = 0; p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
p->u.qam.symbol_rate = stv0297_get_symbolrate(state) * 1000;
p->u.qam.fec_inner = FEC_NONE;
switch((reg_00 >> 4) & 0x7) { switch((reg_00 >> 4) & 0x7) {
case 0: case 0:
...@@ -729,7 +761,6 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, ...@@ -729,7 +761,6 @@ struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
state->config = config; state->config = config;
state->i2c = i2c; state->i2c = i2c;
memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
state->freq_off = 0;
state->base_freq = 0; state->base_freq = 0;
state->pwm = pwm; state->pwm = pwm;
...@@ -764,6 +795,7 @@ static struct dvb_frontend_ops stv0297_ops = { ...@@ -764,6 +795,7 @@ static struct dvb_frontend_ops stv0297_ops = {
.release = stv0297_release, .release = stv0297_release,
.init = stv0297_init, .init = stv0297_init,
.sleep = stv0297_sleep,
.set_frontend = stv0297_set_frontend, .set_frontend = stv0297_set_frontend,
.get_frontend = stv0297_get_frontend, .get_frontend = stv0297_get_frontend,
......
...@@ -29,6 +29,9 @@ struct stv0297_config ...@@ -29,6 +29,9 @@ struct stv0297_config
/* the demodulator's i2c address */ /* the demodulator's i2c address */
u8 demod_address; u8 demod_address;
/* does the "inversion" need inverted? */
u8 invert:1;
/* PLL maintenance */ /* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe); int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de> Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
Copyright (C) 2004 Markus Schulz <msc@antzsystem.de> Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
Suppport for TDA10021 Support for TDA10021
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de> Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
Copyright (C) 2004 Markus Schulz <msc@antzsystem.de> Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
Suppport for TDA10021 Support for TDA10021
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
......
...@@ -27,10 +27,10 @@ ...@@ -27,10 +27,10 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/irq.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment