[PATCH] v4l: bug fixes for tuner, cx88 and tea5767
- In CX88 code, some cards needs to have audio reprogramed after changing video channel; - Tuner autodetection code seems not to work on some cards. Now, no_autodetect insmod option allows disabling autodetection code; - Minor fixes in tea5767 to reduce integer trunc; - There are some new Pixelview Ultra Pro cards that doesn't use TEA5767 for radio. As autodetection is capable of checking for tea, radio tuners and addresses removed. - CX88 version number incremented. Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
1eb29128c6
Коммит
c5287ba132
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: cx88-cards.c,v 1.85 2005/07/04 19:35:05 mkrufky Exp $
|
* $Id: cx88-cards.c,v 1.86 2005/07/14 03:06:43 mchehab Exp $
|
||||||
*
|
*
|
||||||
* device driver for Conexant 2388x based TV cards
|
* device driver for Conexant 2388x based TV cards
|
||||||
* card-specific stuff.
|
* card-specific stuff.
|
||||||
|
@ -682,9 +682,9 @@ struct cx88_board cx88_boards[] = {
|
||||||
.name = "PixelView PlayTV Ultra Pro (Stereo)",
|
.name = "PixelView PlayTV Ultra Pro (Stereo)",
|
||||||
/* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
|
/* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
|
||||||
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
|
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
|
||||||
.radio_type = TUNER_TEA5767,
|
.radio_type = UNSET,
|
||||||
.tuner_addr = 0xc2>>1,
|
.tuner_addr = ADDR_UNSET,
|
||||||
.radio_addr = 0xc0>>1,
|
.radio_addr = ADDR_UNSET,
|
||||||
.input = {{
|
.input = {{
|
||||||
.type = CX88_VMUX_TELEVISION,
|
.type = CX88_VMUX_TELEVISION,
|
||||||
.vmux = 0,
|
.vmux = 0,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: cx88-dvb.c,v 1.41 2005/07/04 19:35:05 mkrufky Exp $
|
* $Id: cx88-dvb.c,v 1.42 2005/07/12 15:44:55 mkrufky Exp $
|
||||||
*
|
*
|
||||||
* device driver for Conexant 2388x based TV cards
|
* device driver for Conexant 2388x based TV cards
|
||||||
* MPEG Transport Stream (DVB) routines
|
* MPEG Transport Stream (DVB) routines
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: cx88-video.c,v 1.79 2005/07/07 14:17:47 mchehab Exp $
|
* $Id: cx88-video.c,v 1.80 2005/07/13 08:49:08 mchehab Exp $
|
||||||
*
|
*
|
||||||
* device driver for Conexant 2388x based TV cards
|
* device driver for Conexant 2388x based TV cards
|
||||||
* video4linux video interface
|
* video4linux video interface
|
||||||
|
@ -1346,6 +1346,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
|
||||||
dev->freq = f->frequency;
|
dev->freq = f->frequency;
|
||||||
cx88_newstation(core);
|
cx88_newstation(core);
|
||||||
cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
|
cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
|
||||||
|
|
||||||
|
/* When changing channels it is required to reset TVAUDIO */
|
||||||
|
msleep (10);
|
||||||
|
cx88_set_tvaudio(core);
|
||||||
|
|
||||||
up(&dev->lock);
|
up(&dev->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: cx88.h,v 1.68 2005/07/07 14:17:47 mchehab Exp $
|
* $Id: cx88.h,v 1.69 2005/07/13 17:25:25 mchehab Exp $
|
||||||
*
|
*
|
||||||
* v4l2 device driver for cx2388x based TV cards
|
* v4l2 device driver for cx2388x based TV cards
|
||||||
*
|
*
|
||||||
|
@ -35,8 +35,8 @@
|
||||||
#include "btcx-risc.h"
|
#include "btcx-risc.h"
|
||||||
#include "cx88-reg.h"
|
#include "cx88-reg.h"
|
||||||
|
|
||||||
#include <linux/version.h>
|
#include <linux/utsname.h>
|
||||||
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,4)
|
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
|
||||||
|
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
# define TRUE (1==1)
|
# define TRUE (1==1)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
|
* For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
|
||||||
* I2C address is allways 0xC0.
|
* I2C address is allways 0xC0.
|
||||||
*
|
*
|
||||||
* $Id: tea5767.c,v 1.18 2005/07/07 03:02:55 mchehab Exp $
|
* $Id: tea5767.c,v 1.21 2005/07/14 03:06:43 mchehab Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
|
* Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
|
||||||
* This code is placed under the terms of the GNU General Public License
|
* This code is placed under the terms of the GNU General Public License
|
||||||
|
@ -153,17 +153,17 @@ static void tea5767_status_dump(unsigned char *buffer)
|
||||||
|
|
||||||
switch (TEA5767_HIGH_LO_32768) {
|
switch (TEA5767_HIGH_LO_32768) {
|
||||||
case TEA5767_HIGH_LO_13MHz:
|
case TEA5767_HIGH_LO_13MHz:
|
||||||
frq = 1000 * (div * 50 - 700 - 225) / 4; /* Freq in KHz */
|
frq = (div * 50000 - 700000 - 225000) / 4; /* Freq in KHz */
|
||||||
break;
|
break;
|
||||||
case TEA5767_LOW_LO_13MHz:
|
case TEA5767_LOW_LO_13MHz:
|
||||||
frq = 1000 * (div * 50 + 700 + 225) / 4; /* Freq in KHz */
|
frq = (div * 50000 + 700000 + 225000) / 4; /* Freq in KHz */
|
||||||
break;
|
break;
|
||||||
case TEA5767_LOW_LO_32768:
|
case TEA5767_LOW_LO_32768:
|
||||||
frq = 1000 * (div * 32768 / 1000 + 700 + 225) / 4; /* Freq in KHz */
|
frq = (div * 32768 + 700000 + 225000) / 4; /* Freq in KHz */
|
||||||
break;
|
break;
|
||||||
case TEA5767_HIGH_LO_32768:
|
case TEA5767_HIGH_LO_32768:
|
||||||
default:
|
default:
|
||||||
frq = 1000 * (div * 32768 / 1000 - 700 - 225) / 4; /* Freq in KHz */
|
frq = (div * 32768 - 700000 - 225000) / 4; /* Freq in KHz */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buffer[0] = (div >> 8) & 0x3f;
|
buffer[0] = (div >> 8) & 0x3f;
|
||||||
|
@ -196,7 +196,7 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
|
||||||
unsigned div;
|
unsigned div;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
tuner_dbg (PREFIX "radio freq counter %d\n", frq);
|
tuner_dbg (PREFIX "radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
|
||||||
|
|
||||||
/* Rounds freq to next decimal value - for 62.5 KHz step */
|
/* Rounds freq to next decimal value - for 62.5 KHz step */
|
||||||
/* frq = 20*(frq/16)+radio_frq[frq%16]; */
|
/* frq = 20*(frq/16)+radio_frq[frq%16]; */
|
||||||
|
@ -224,19 +224,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
|
||||||
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
|
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
|
||||||
buffer[2] |= TEA5767_HIGH_LO_INJECT;
|
buffer[2] |= TEA5767_HIGH_LO_INJECT;
|
||||||
buffer[4] |= TEA5767_PLLREF_ENABLE;
|
buffer[4] |= TEA5767_PLLREF_ENABLE;
|
||||||
div = (frq * 4 / 16 + 700 + 225 + 25) / 50;
|
div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000;
|
||||||
break;
|
break;
|
||||||
case TEA5767_LOW_LO_13MHz:
|
case TEA5767_LOW_LO_13MHz:
|
||||||
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
|
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
|
||||||
|
|
||||||
buffer[4] |= TEA5767_PLLREF_ENABLE;
|
buffer[4] |= TEA5767_PLLREF_ENABLE;
|
||||||
div = (frq * 4 / 16 - 700 - 225 + 25) / 50;
|
div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000;
|
||||||
break;
|
break;
|
||||||
case TEA5767_LOW_LO_32768:
|
case TEA5767_LOW_LO_32768:
|
||||||
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
|
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
|
||||||
buffer[3] |= TEA5767_XTAL_32768;
|
buffer[3] |= TEA5767_XTAL_32768;
|
||||||
/* const 700=4000*175 Khz - to adjust freq to right value */
|
/* const 700=4000*175 Khz - to adjust freq to right value */
|
||||||
div = (1000 * (frq * 4 / 16 - 700 - 225) + 16384) >> 15;
|
div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15;
|
||||||
break;
|
break;
|
||||||
case TEA5767_HIGH_LO_32768:
|
case TEA5767_HIGH_LO_32768:
|
||||||
default:
|
default:
|
||||||
|
@ -244,17 +244,21 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
|
||||||
|
|
||||||
buffer[2] |= TEA5767_HIGH_LO_INJECT;
|
buffer[2] |= TEA5767_HIGH_LO_INJECT;
|
||||||
buffer[3] |= TEA5767_XTAL_32768;
|
buffer[3] |= TEA5767_XTAL_32768;
|
||||||
div = (1000 * (frq * 4 / 16 + 700 + 225) + 16384) >> 15;
|
div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buffer[0] = (div >> 8) & 0x3f;
|
buffer[0] = (div >> 8) & 0x3f;
|
||||||
buffer[1] = div & 0xff;
|
buffer[1] = div & 0xff;
|
||||||
|
|
||||||
if (tuner_debug)
|
|
||||||
tea5767_status_dump(buffer);
|
|
||||||
|
|
||||||
if (5 != (rc = i2c_master_send(c, buffer, 5)))
|
if (5 != (rc = i2c_master_send(c, buffer, 5)))
|
||||||
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
|
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
|
||||||
|
|
||||||
|
if (tuner_debug) {
|
||||||
|
if (5 != (rc = i2c_master_recv(c, buffer, 5)))
|
||||||
|
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
|
||||||
|
else
|
||||||
|
tea5767_status_dump(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tea5767_signal(struct i2c_client *c)
|
static int tea5767_signal(struct i2c_client *c)
|
||||||
|
@ -294,7 +298,7 @@ int tea5767_autodetection(struct i2c_client *c)
|
||||||
struct tuner *t = i2c_get_clientdata(c);
|
struct tuner *t = i2c_get_clientdata(c);
|
||||||
|
|
||||||
if (5 != (rc = i2c_master_recv(c, buffer, 5))) {
|
if (5 != (rc = i2c_master_recv(c, buffer, 5))) {
|
||||||
tuner_warn("it is not a TEA5767. Received %i chars.\n", rc);
|
tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,11 +314,11 @@ int tea5767_autodetection(struct i2c_client *c)
|
||||||
* bit 0 : internally set to 0
|
* bit 0 : internally set to 0
|
||||||
* Byte 5: bit 7:0 : == 0
|
* Byte 5: bit 7:0 : == 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
|
if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
|
||||||
tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
|
tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuner_warn("TEA5767 detected.\n");
|
tuner_warn("TEA5767 detected.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: tuner-core.c,v 1.55 2005/07/08 13:20:33 mchehab Exp $
|
* $Id: tuner-core.c,v 1.58 2005/07/14 03:06:43 mchehab Exp $
|
||||||
*
|
*
|
||||||
* i2c tv tuner chip device driver
|
* i2c tv tuner chip device driver
|
||||||
* core core, i.e. kernel interfaces, registering and so on
|
* core core, i.e. kernel interfaces, registering and so on
|
||||||
|
@ -39,6 +39,9 @@ I2C_CLIENT_INSMOD;
|
||||||
static unsigned int addr = 0;
|
static unsigned int addr = 0;
|
||||||
module_param(addr, int, 0444);
|
module_param(addr, int, 0444);
|
||||||
|
|
||||||
|
static unsigned int no_autodetect = 0;
|
||||||
|
module_param(no_autodetect, int, 0444);
|
||||||
|
|
||||||
/* insmod options used at runtime => read/write */
|
/* insmod options used at runtime => read/write */
|
||||||
unsigned int tuner_debug = 0;
|
unsigned int tuner_debug = 0;
|
||||||
module_param(tuner_debug, int, 0644);
|
module_param(tuner_debug, int, 0644);
|
||||||
|
@ -318,17 +321,19 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
|
||||||
tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
|
tuner_info("chip found @ 0x%x (%s)\n", addr << 1, adap->name);
|
||||||
|
|
||||||
/* TEA5767 autodetection code - only for addr = 0xc0 */
|
/* TEA5767 autodetection code - only for addr = 0xc0 */
|
||||||
if (addr == 0x60) {
|
if (!no_autodetect) {
|
||||||
if (tea5767_autodetection(&t->i2c) != EINVAL) {
|
if (addr == 0x60) {
|
||||||
t->type = TUNER_TEA5767;
|
if (tea5767_autodetection(&t->i2c) != EINVAL) {
|
||||||
t->mode_mask = T_RADIO;
|
t->type = TUNER_TEA5767;
|
||||||
t->mode = T_STANDBY;
|
t->mode_mask = T_RADIO;
|
||||||
t->freq = 87.5 * 16; /* Sets freq to FM range */
|
t->mode = T_STANDBY;
|
||||||
default_mode_mask &= ~T_RADIO;
|
t->freq = 87.5 * 16; /* Sets freq to FM range */
|
||||||
|
default_mode_mask &= ~T_RADIO;
|
||||||
|
|
||||||
i2c_attach_client (&t->i2c);
|
i2c_attach_client (&t->i2c);
|
||||||
set_type(&t->i2c,t->type, t->mode_mask);
|
set_type(&t->i2c,t->type, t->mode_mask);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,7 +636,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
tuner_dbg("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
|
tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp=0x%02x,nr=%d,sz=%d)\n",
|
||||||
|
cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd),
|
||||||
|
_IOC_NR(cmd), _IOC_SIZE(cmd));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче