Commit eb97de0b authored by Michael Hunold's avatar Michael Hunold Committed by Linus Torvalds

[PATCH] dvb: av7110 driver update

- av7110: fixed av7110_before_after_tune()/av7110_fe_lock_fix(): firmware >=
  261d: wait for empty message queue, firmware <= 261c: wait 50ms

- av7110: add __user and __iomem annotations, remove some unnecessary cast
  (patch by C.Y.M)

- av7110: __av7110_send_fw_cmd(): added some sanity checks suggested by
  Werner Fin

- av7110: added support for full-featured DVB-C cards: 13c2:0000 Siemens
  DVB-C (full-length card) VES1820/Philips CD1516 and 13c2:0003 Haupauge DVB-C
  2.1 VES1820/ALPS TDBE2

- av7110: follow saa7146 changes, remove superflous casts, and other misc. 
  minor cleanups

- av7110: Fixed race condition between driver and av7110 while accessing the
  COMMAND register in DPRAM.  See
  http://www.linuxtv.org/mailinglists/vdr/2004/01-2004/msg00331.html

- budget: various cleanups by Adrian bunk 
Signed-off-by: default avatarMichael Hunold <hunold@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0e8a0d01
This diff is collapsed.
......@@ -34,6 +34,11 @@
#include <media/saa7146_vv.h>
#define ANALOG_TUNER_VES1820 1
#define ANALOG_TUNER_STV0297 2
#define ANALOG_TUNER_VBI 0x100
extern int av7110_debug;
#define dprintk(level,args...) \
......@@ -82,7 +87,7 @@ struct av7110 {
char *card_name;
/* support for analog module of dvb-c */
int has_analog_tuner;
int analog_tuner_flags;
int current_input;
u32 current_freq;
......@@ -122,8 +127,8 @@ struct av7110 {
spinlock_t debilock;
struct semaphore dcomlock;
int debitype;
int debilen;
volatile int debitype;
volatile int debilen;
/* Recording and playback flags */
......@@ -235,6 +240,7 @@ struct av7110 {
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
......
......@@ -110,16 +110,16 @@ void av7110_reset_arm(struct av7110 *av7110)
saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
IER_DISABLE(av7110->dev, (MASK_19 | MASK_03));
saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03));
SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
msleep(30); /* the firmware needs some time to initialize */
ARM_ResetMailBox(av7110);
saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03));
IER_ENABLE(av7110->dev, MASK_03);
SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
SAA7146_IER_ENABLE(av7110->dev, MASK_03);
av7110->arm_ready = 1;
dprintk(1, "reset ARM\n");
......@@ -223,8 +223,8 @@ int av7110_bootarm(struct av7110 *av7110)
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03));
SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
/* enable DEBI */
saa7146_write(av7110->dev, MC1, 0x08800880);
......@@ -280,8 +280,8 @@ int av7110_bootarm(struct av7110 *av7110)
//ARM_ClearIrq(av7110);
ARM_ResetMailBox(av7110);
saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03));
IER_ENABLE(av7110->dev, MASK_03);
SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
SAA7146_IER_ENABLE(av7110->dev, MASK_03);
av7110->arm_errors = 0;
av7110->arm_ready = 1;
......@@ -293,13 +293,44 @@ int av7110_bootarm(struct av7110 *av7110)
* DEBI command polling
****************************************************************************/
int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
{
unsigned long start;
u32 stat;
if (FW_VERSION(av7110->arm_app) <= 0x261c) {
/* not supported by old firmware */
msleep(50);
return 0;
}
/* new firmware */
start = jiffies;
for (;;) {
if (down_interruptible(&av7110->dcomlock))
return -ERESTARTSYS;
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
up(&av7110->dcomlock);
if ((stat & flags) == 0) {
break;
}
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
__FUNCTION__, stat & flags);
return -1;
}
msleep(1);
}
return 0;
}
int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
{
int i;
unsigned long start;
#ifdef COM_DEBUG
char *type = NULL;
u16 flags[2] = {0, 0};
u32 stat;
#endif
// dprintk(4, "%p\n", av7110);
......@@ -330,14 +361,45 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
}
#endif
switch ((buf[0] >> 8) & 0xff) {
case COMTYPE_PIDFILTER:
case COMTYPE_ENCODER:
case COMTYPE_REC_PLAY:
case COMTYPE_MPEGDECODER:
type = "MSG";
flags[0] = GPMQOver;
flags[1] = GPMQFull;
break;
case COMTYPE_OSD:
type = "OSD";
flags[0] = OSDQOver;
flags[1] = OSDQFull;
break;
default:
break;
}
if (type != NULL) {
/* non-immediate COMMAND type */
start = jiffies;
while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) {
msleep(1);
if (time_after(jiffies, start + ARM_WAIT_OSD)) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for !OSDQFull\n", __FUNCTION__);
for (;;) {
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & flags[0]) {
printk(KERN_ERR "%s: %s QUEUE overflow\n",
__FUNCTION__, type);
return -1;
}
if ((stat & flags[1]) == 0)
break;
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
__FUNCTION__, type);
return -1;
}
msleep(1);
}
}
for (i = 2; i < length; i++)
wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
......@@ -972,7 +1034,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
goto out;
} else {
int i, len = dc->x0-dc->color+1;
u8 __user *colors = dc->data;
u8 __user *colors = (u8 *)dc->data;
u8 r, g, b, blend;
for (i = 0; i<len; i++) {
......
......@@ -65,6 +65,9 @@ enum av7110_video_output_mode
#define HPQOver 0x0008
#define OSDQFull 0x0010 /* OSD Queue Full */
#define OSDQOver 0x0020
#define GPMQBusy 0x0040 /* Queue not empty, FW >= 261d */
#define HPQBusy 0x0080
#define OSDQBusy 0x0100
/* hw section filter flags */
#define SECTION_EIT 0x01
......@@ -368,6 +371,7 @@ extern int av7110_firmversion(struct av7110 *av7110);
#define FW_4M_SDRAM(arm_app) ((arm_app) & 0x40000000)
#define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF)
extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags);
extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...);
extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
......
......@@ -92,10 +92,8 @@ static struct v4l2_input inputs[2] = {
}
};
/* for Siemens DVB-C analog module: (taken from ves1820.c) */
static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data)
static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
{
u8 addr = 0x09;
u8 buf[] = { 0x00, reg, data };
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
......@@ -106,6 +104,17 @@ static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data)
return 0;
}
static int stv0297_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
{
u8 buf [] = { reg, data };
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 2 };
if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
return -1;
return 0;
}
static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
{
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
......@@ -117,12 +126,7 @@ static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
return 0;
}
/**
* set up the downconverter frequency divisor for a
* reference clock comparision frequency of 62.5 kHz.
*/
static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq)
static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
{
u32 div;
u8 config;
......@@ -151,6 +155,34 @@ static int tuner_set_tv_freq(struct saa7146_dev *dev, u32 freq)
return tuner_write(dev, 0x61, buf);
}
static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
{
u32 div;
u8 data[4];
div = (freq + 38900000 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0xce;
if (freq < 45000000)
return -EINVAL;
else if (freq < 137000000)
data[3] = 0x01;
else if (freq < 403000000)
data[3] = 0x02;
else if (freq < 860000000)
data[3] = 0x04;
else
return -EINVAL;
stv0297_writereg(dev, 0x1C, 0x87, 0x78);
stv0297_writereg(dev, 0x1C, 0x86, 0xc8);
return tuner_write(dev, 0x63, data);
}
static struct saa7146_standard analog_standard[];
static struct saa7146_standard dvb_standard[];
......@@ -168,7 +200,6 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
struct saa7146_vv *vv = dev->vv_data;
struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
u16 adswitch;
u8 band = 0;
int source, sync, err;
dprintk(4, "%p\n", av7110);
......@@ -184,7 +215,6 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
if (0 != av7110->current_input) {
adswitch = 1;
band = 0x60; /* analog band */
source = SAA7146_HPS_SOURCE_PORT_B;
sync = SAA7146_HPS_SYNC_PORT_B;
memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
......@@ -195,9 +225,16 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
}
} else {
adswitch = 0;
band = 0x20; /* digital band */
source = SAA7146_HPS_SOURCE_PORT_A;
sync = SAA7146_HPS_SYNC_PORT_A;
memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
......@@ -208,15 +245,20 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
}
}
/* hmm, this does not do anything!? */
if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
dprintk(1, "ADSwitch error\n");
if (ves1820_writereg(dev, 0x0f, band))
dprintk(1, "setting band in demodulator failed.\n");
saa7146_set_hps_source_and_sync(dev, source, sync);
if (vv->ov_suspend != NULL) {
......@@ -242,7 +284,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
if (!av7110->has_analog_tuner || t->index != 0)
if (!av7110->analog_tuner_flags || t->index != 0)
return -EINVAL;
memset(t, 0, sizeof(*t));
......@@ -285,7 +327,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
u16 fm_matrix, src;
dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
if (!av7110->has_analog_tuner || av7110->current_input != 1)
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
switch (t->audmode) {
......@@ -322,7 +364,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
if (!av7110->has_analog_tuner || av7110->current_input != 1)
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
memset(f, 0, sizeof(*f));
......@@ -336,7 +378,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
if (!av7110->has_analog_tuner || av7110->current_input != 1)
if (!av7110->analog_tuner_flags || av7110->current_input != 1)
return -EINVAL;
if (V4L2_TUNER_ANALOG_TV != f->type)
......@@ -346,7 +388,11 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
/* tune in desired frequency */
tuner_set_tv_freq(dev, f->frequency);
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
ves1820_set_tv_freq(dev, f->frequency);
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
stv0297_set_tv_freq(dev, f->frequency);
}
av7110->current_freq = f->frequency;
msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
......@@ -361,7 +407,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
if (av7110->has_analog_tuner ) {
if (av7110->analog_tuner_flags) {
if (i->index < 0 || i->index >= 2)
return -EINVAL;
} else {
......@@ -386,7 +432,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
if (!av7110->has_analog_tuner )
if (!av7110->analog_tuner_flags)
return 0;
if (input < 0 || input >= 2)
......@@ -528,7 +574,27 @@ int av7110_init_analog_module(struct av7110 *av7110)
INFO(("saa7113 not accessible.\n"));
} else {
u8 *i = saa7113_init_regs;
av7110->has_analog_tuner = 1;
if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
/* Fujitsu/Siemens DVB-Cable */
av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
/* Hauppauge/TT DVB-C premium */
av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
/* Hauppauge/TT DVB-C premium */
av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
}
/* setup for DVB by default */
if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
dprintk(1, "setting band in demodulator failed.\n");
} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
}
/* init the saa7113 */
while (*i != 0xff) {
if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
......@@ -579,7 +645,7 @@ int av7110_init_v4l(struct av7110 *av7110)
/* special case DVB-C: these cards have an analog tuner
plus need some special handling, so we have separate
saa7146_ext_vv data for these... */
if (av7110->has_analog_tuner)
if (av7110->analog_tuner_flags)
ret = saa7146_vv_init(dev, &av7110_vv_data_c);
else
ret = saa7146_vv_init(dev, &av7110_vv_data_st);
......@@ -594,12 +660,12 @@ int av7110_init_v4l(struct av7110 *av7110)
saa7146_vv_release(dev);
return -ENODEV;
}
if (av7110->has_analog_tuner) {
if (av7110->analog_tuner_flags) {
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
ERR(("cannot register vbi v4l2 device. skipping.\n"));
} else
/* we use this to remember that this dvb-c card can do vbi */
av7110->has_analog_tuner = 2;
} else {
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
}
}
return 0;
}
......@@ -607,7 +673,7 @@ int av7110_init_v4l(struct av7110 *av7110)
int av7110_exit_v4l(struct av7110 *av7110)
{
saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
if (2 == av7110->has_analog_tuner)
if (av7110->analog_tuner_flags & ANALOG_TUNER_VBI)
saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
return 0;
}
......
......@@ -563,23 +563,13 @@ static int philips_tu1216_pll_init(struct dvb_frontend *fe)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len =
sizeof(tu1216_init) };
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
// setup PLL configuration
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
// disable the mc44BC374c (do not check for errors)
tuner_msg.addr = 0x65;
tuner_msg.buf = disable_mc44BC374c;
tuner_msg.len = sizeof(disable_mc44BC374c);
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) {
i2c_transfer(&budget->i2c_adap, &tuner_msg, 1);
}
return 0;
}
......@@ -593,7 +583,7 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
u8 band, cp, filter;
// determine charge pump
tuner_frequency = params->frequency + 36130000;
tuner_frequency = params->frequency + 36166000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
......@@ -620,7 +610,7 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
// determine band
if (params->frequency < 49000000)
return -EINVAL;
else if (params->frequency < 159000000)
else if (params->frequency < 161000000)
band = 1;
else if (params->frequency < 444000000)
band = 2;
......@@ -632,17 +622,14 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
// setup PLL filter
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
tda1004x_write_byte(fe, 0x0C, 0);
filter = 0;
break;
case BANDWIDTH_7_MHZ:
tda1004x_write_byte(fe, 0x0C, 0);
filter = 0;
break;
case BANDWIDTH_8_MHZ:
tda1004x_write_byte(fe, 0x0C, 0xFF);
filter = 1;
break;
......@@ -651,11 +638,11 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
}
// calculate divisor
// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
tuner_buf[1] = tuner_frequency & 0xff;
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
......@@ -679,6 +666,7 @@ struct tda1004x_config philips_tu1216_config = {
.demod_address = 0x8,
.invert = 1,
.invert_oclk = 1,
.pll_init = philips_tu1216_pll_init,
.pll_set = philips_tu1216_pll_set,
.request_firmware = philips_tu1216_request_firmware,
......
......@@ -844,6 +844,7 @@ static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8,
.invert = 0,
.invert_oclk = 0,
.pll_init = philips_tdm1316l_pll_init,
.pll_set = philips_tdm1316l_pll_set,
.request_firmware = philips_tdm1316l_request_firmware,
......
......@@ -56,7 +56,7 @@ static int stop_ts_capture(struct budget *budget)
return budget->feeding;
saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
IER_DISABLE(budget->dev, MASK_10);
SAA7146_IER_DISABLE(budget->dev, MASK_10);
return 0;
}
......@@ -124,7 +124,7 @@ static int start_ts_capture (struct budget *budget)
saa7146_write(dev, MC2, (MASK_04 | MASK_20));
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on
IER_ENABLE(budget->dev, MASK_10); // VPE
SAA7146_IER_ENABLE(budget->dev, MASK_10); // VPE
return ++budget->feeding;
}
......
......@@ -3,6 +3,8 @@ config DVB_TTUSB_BUDGET
depends on DVB_CORE && USB
select DVB_CX22700
select DVB_TDA1004X
select DVB_TDA8083
select DVB_STV0299
help
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
......
......@@ -26,6 +26,8 @@
#include "dvb_net.h"
#include "cx22700.h"
#include "tda1004x.h"
#include "stv0299.h"
#include "tda8083.h"
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
......@@ -489,7 +491,6 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
}
#endif
#if 0
static int ttusb_update_lnb(struct ttusb *ttusb)
{
u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
......@@ -524,7 +525,6 @@ static int ttusb_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
return ttusb_update_lnb(ttusb);
}
#endif
#endif
#if 0
......@@ -1177,7 +1177,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
return 0;
......@@ -1194,24 +1195,187 @@ static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8,
.invert = 1,
.invert_oclk = 0,
.pll_init = philips_tdm1316l_pll_init,
.pll_set = philips_tdm1316l_pll_set,
.request_firmware = philips_tdm1316l_request_firmware,
};
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
0x02, 0x00,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
0x06, 0x40, /* DAC not used, set to high impendance mode */
0x07, 0x00, /* DAC LSB */
0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
0x09, 0x00, /* FIFO */
0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
0x10, 0x3f, // AGC2 0x3d
0x11, 0x84,
0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
0x15, 0xc9, // lock detector threshold
0x16, 0x00,
0x17, 0x00,
0x18, 0x00,
0x19, 0x00,
0x1a, 0x00,
0x1f, 0x50,
0x20, 0x00,
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
0x29, 0x1e, // 1/2 threshold
0x2a, 0x14, // 2/3 threshold
0x2b, 0x0f, // 3/4 threshold
0x2c, 0x09, // 5/6 threshold
0x2d, 0x05, // 7/8 threshold
0x2e, 0x01,
0x31, 0x1f, // test all FECs
0x32, 0x19, // viterbi and synchro search
0x33, 0xfc, // rs control
0x34, 0x93, // error control
0x0f, 0x52,
0xff, 0xff
};
static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
if (srate < 1500000) {
aclk = 0xb7;
bclk = 0x47;
} else if (srate < 3000000) {
aclk = 0xb7;
bclk = 0x4b;
} else if (srate < 7000000) {
aclk = 0xb7;
bclk = 0x4f;
} else if (srate < 14000000) {
aclk = 0xb7;
bclk = 0x53;
} else if (srate < 30000000) {
aclk = 0xb6;
bclk = 0x53;
} else if (srate < 45000000) {
aclk = 0xb4;
bclk = 0x51;
}
stv0299_writereg(fe, 0x13, aclk);
stv0299_writereg(fe, 0x14, bclk);
stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
return 0;
}
static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
div = (params->frequency + (125 - 1)) / 125; // round correctly
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0xC4;
if (params->frequency > 1530000)
buf[3] = 0xc0;
if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct stv0299_config alps_bsru6_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
.invert = 1,
.enhanced_tuning = 0,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
.pll_set = alps_bsru6_pll_set,
};
static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
div = params->frequency / 125;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x8e;
buf[3] = 0x00;
if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
.demod_address = 0x68,
.pll_set = ttusb_novas_grundig_29504_491_pll_set,
};
static void frontend_init(struct ttusb* ttusb)
{
switch(ttusb->dev->descriptor.idProduct) {
case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059)
// try the ALPS BSRU6 first
ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) {
ttusb->fe->ops->set_voltage = ttusb_set_voltage;
break;
}
// Grundig 29504-491
ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) {
ttusb->fe->ops->set_voltage = ttusb_set_voltage;
break;
}
break;
case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
// try the ALPS TDMB7 first
ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) break;
if (ttusb->fe != NULL)
break;
// Philips td1316
ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) break;
if (ttusb->fe != NULL)
break;
break;
}
......@@ -1382,7 +1546,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
}
static struct usb_device_id ttusb_table[] = {
/* {USB_DEVICE(0xb48, 0x1003)},UNDEFINED HARDWARE - mail linuxtv.org list */
{USB_DEVICE(0xb48, 0x1003)},
/* {USB_DEVICE(0xb48, 0x1004)},UNDEFINED HARDWARE - mail linuxtv.org list*/ /* to be confirmed ???? */
{USB_DEVICE(0xb48, 0x1005)},
{}
......
......@@ -62,7 +62,7 @@ typedef enum fe_caps {
FE_CAN_HIERARCHY_AUTO = 0x100000,
FE_CAN_8VSB = 0x200000,
FE_CAN_16VSB = 0x400000,
FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending
FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically
FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output
} fe_caps_t;
......
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