* [patch] v4l: cx88 driver update
@ 2005-03-08 11:00 Gerd Knorr
0 siblings, 0 replies; 2+ messages in thread
From: Gerd Knorr @ 2005-03-08 11:00 UTC (permalink / raw)
To: Andrew Morton, Linux Kernel Mailing List
Hi,
Finally the big cx88 driver update which makes the cx88-dvb
driver compile and work for some cards. A number of changes
accumulated over time ...
* various new tv cards added / fixed.
* added support for infrared remote controls.
* some fixes in the blackbird (mpeg encoder) driver,
starts working now.
* configurarion for analog hauppauge cards now uses
the tveeprom module.
* kconfig fixups.
* powermanagement fixups.
* lot of tweaks for tv audio (make NICAM decoding work).
* lot of changes in the dvb driver, still not working
for all cards though as some more changes in the dvb
subsystem are needed.
Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
---
drivers/media/video/Kconfig | 10
drivers/media/video/cx88/Makefile | 3
drivers/media/video/cx88/cx88-blackbird.c | 27 -
drivers/media/video/cx88/cx88-cards.c | 393 ++++++++++---------
drivers/media/video/cx88/cx88-core.c | 42 +-
drivers/media/video/cx88/cx88-dvb.c | 185 +++++---
drivers/media/video/cx88/cx88-i2c.c | 3
drivers/media/video/cx88/cx88-input.c | 396 +++++++++++++++++++
drivers/media/video/cx88/cx88-mpeg.c | 44 +-
drivers/media/video/cx88/cx88-tvaudio.c | 455 +++++++++++++++-------
drivers/media/video/cx88/cx88-vbi.c | 5
drivers/media/video/cx88/cx88-video.c | 34 -
drivers/media/video/cx88/cx88.h | 38 +
13 files changed, 1189 insertions(+), 446 deletions(-)
Index: linux-2.6.11/drivers/media/video/cx88/cx88-cards.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-cards.c 2005-03-07 10:14:56.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-cards.c 2005-03-08 10:33:15.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-cards.c,v 1.47 2004/11/03 09:04:50 kraxel Exp $
+ * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -26,14 +26,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
-# define WITH_DVB 1
-#endif
-
#include "cx88.h"
-#ifdef WITH_DVB
-#include "cx22702.h"
-#endif
/* ------------------------------------------------------------------ */
/* board config info */
@@ -59,6 +52,7 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_HAUPPAUGE] = {
.name = "Hauppauge WinTV 34xxx models",
.tuner_type = UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -91,7 +85,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PIXELVIEW] = {
.name = "PixelView",
- .tuner_type = UNSET,
+ .tuner_type = 5,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -126,7 +120,7 @@ struct cx88_board cx88_boards[] = {
.gpio0 = 0x03fe,
}},
},
- [CX88_BOARD_WINFAST2000XP] = {
+ [CX88_BOARD_WINFAST2000XP_EXPERT] = {
.name = "Leadtek Winfast 2000XP Expert",
.tuner_type = 44,
.tda9887_conf = TDA9887_PRESENT,
@@ -217,26 +211,55 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- }},
+ .gpio0 = 0x0035e700,
+ .gpio1 = 0x00003004,
+ .gpio2 = 0x0035e700,
+ .gpio3 = 0x02000000,
+ },{
+
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0035c700,
+ .gpio1 = 0x00003004,
+ .gpio2 = 0x0035c700,
+ .gpio3 = 0x02000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0035c700,
+ .gpio1 = 0x0035c700,
+ .gpio2 = 0x02000000,
+ .gpio3 = 0x02000000,
+ }},
.radio = {
- .type = CX88_RADIO,
- },
+ .type = CX88_RADIO,
+ .gpio0 = 0x0035d700,
+ .gpio1 = 0x00007004,
+ .gpio2 = 0x0035d700,
+ .gpio3 = 0x02000000,
+ },
},
[CX88_BOARD_LEADTEK_PVR2000] = {
+ // gpio values for PAL version from regspy by DScaler
.name = "Leadtek PVR 2000",
.tuner_type = 38,
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ .gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x0000bde6,
}},
.radio = {
.type = CX88_RADIO,
+ .gpio0 = 0x0000bd62,
},
.blackbird = 1,
},
@@ -320,14 +343,15 @@ struct cx88_board cx88_boards[] = {
.name = "KWorld/VStream XPert DVB-T",
.tuner_type = TUNER_ABSENT,
.input = {{
- .type = CX88_VMUX_DVB,
- .vmux = 0,
- },{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
}},
.dvb = 1,
},
@@ -452,6 +476,131 @@ struct cx88_board cx88_boards[] = {
}},
.dvb = 1,
},
+ [CX88_BOARD_DNTV_LIVE_DVB_T] = {
+ .name = "digitalnow DNTV Live! DVB-T",
+ .tuner_type = TUNER_ABSENT,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x00000700,
+ .gpio2 = 0x00000101,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x00000700,
+ .gpio2 = 0x00000101,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_PCHDTV_HD3000] = {
+ .name = "pcHDTV HD3000 HDTV",
+ .tuner_type = TUNER_THOMSON_DTT7610,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x00008484,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .vmux = 2,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
+ // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
+ // GPIO values obtained from regspy, courtesy Sean Covel
+ .name = "Hauppauge WinTV 28xxx (Roslyn) models",
+ .tuner_type = UNSET,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xed12, // internal decoder
+ .gpio2 = 0x00ff,
+ },{
+ .type = CX88_VMUX_DEBUG,
+ .vmux = 0,
+ .gpio0 = 0xff01, // mono from tuner chip
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xff02,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xed92,
+ .gpio2 = 0x00ff,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xed96,
+ .gpio2 = 0x00ff,
+ },
+ .blackbird = 1,
+ },
+ [CX88_BOARD_DIGITALLOGIC_MEC] = {
+ /* params copied over from Leadtek PVR 2000 */
+ .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
+ /* not sure yet about the tuner type */
+ .tuner_type = 38,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0000bde6,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0000bde6,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0000bde6,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0000bd62,
+ },
+ .blackbird = 1,
+ },
+ [CX88_BOARD_IODATA_GVBCTV7E] = {
+ .name = "IODATA GV/BCTV7E",
+ .tuner_type = TUNER_PHILIPS_FQ1286,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 1,
+ .gpio1 = 0x0000e03f,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 2,
+ .gpio1 = 0x0000e07f,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 3,
+ .gpio1 = 0x0000e07f,
+ }}
+ },
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -482,11 +631,11 @@ struct cx88_subid cx88_subids[] = {
},{
.subvendor = 0x107d,
.subdevice = 0x6611,
- .card = CX88_BOARD_WINFAST2000XP,
+ .card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6613, /* NTSC */
- .card = CX88_BOARD_WINFAST2000XP,
+ .card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6620,
@@ -543,6 +692,30 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x18AC,
.subdevice = 0xDB10,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ },{
+ .subvendor = 0x1554,
+ .subdevice = 0x4811,
+ .card = CX88_BOARD_PIXELVIEW,
+ },{
+ .subvendor = 0x7063,
+ .subdevice = 0x3000, /* HD-3000 card */
+ .card = CX88_BOARD_PCHDTV_HD3000,
+ },{
+ .subvendor = 0x17DE,
+ .subdevice = 0xA8A6,
+ .card = CX88_BOARD_DNTV_LIVE_DVB_T,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x2801,
+ .card = CX88_BOARD_HAUPPAUGE_ROSLYN,
+ },{
+ .subvendor = 0x14F1,
+ .subdevice = 0x0342,
+ .card = CX88_BOARD_DIGITALLOGIC_MEC,
+ },{
+ .subvendor = 0x10fc,
+ .subdevice = 0xd035,
+ .card = CX88_BOARD_IODATA_GVBCTV7E,
}
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -552,7 +725,7 @@ const unsigned int cx88_idcount = ARRAY_
static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
- /* This is just for the Winfast 2000 XP board ATM; I don't have data on
+ /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
* any others.
*
* Byte 0 is 1 on the NTSC board.
@@ -569,108 +742,27 @@ static void __devinit leadtek_eeprom(str
core->has_radio = 1;
core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
- printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: "
+ printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
"tuner=%d, eeprom[0]=0x%02x\n",
core->name, core->tuner_type, eeprom_data[0]);
}
/* ----------------------------------------------------------------------- */
-/* some hauppauge specific stuff */
-
-static struct {
- int id;
- char *name;
-} hauppauge_tuner[] __devinitdata = {
- { TUNER_ABSENT, "" },
- { TUNER_ABSENT, "External" },
- { TUNER_ABSENT, "Unspecified" },
- { TUNER_PHILIPS_PAL, "Philips FI1216" },
- { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
- { TUNER_PHILIPS_NTSC, "Philips FI1236" },
- { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
- { TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
- { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
- { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
- { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
- { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
- { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
- { TUNER_TEMIC_NTSC, "Temic 4032FY5" },
- { TUNER_TEMIC_PAL, "Temic 4002FH5" },
- { TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
- { TUNER_PHILIPS_PAL, "Philips FR1216 MK2" },
- { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
- { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
- { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
- { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
- { TUNER_PHILIPS_PAL, "Philips FM1216" },
- { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
- { TUNER_PHILIPS_NTSC, "Philips FM1236" },
- { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
- { TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
- { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
- { TUNER_ABSENT, "Samsung TCPN9082D" },
- { TUNER_ABSENT, "Samsung TCPM9092P" },
- { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
- { TUNER_ABSENT, "Samsung TCPN9085D" },
- { TUNER_ABSENT, "Samsung TCPB9085P" },
- { TUNER_ABSENT, "Samsung TCPL9091P" },
- { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
- { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" },
- { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
- { TUNER_PHILIPS_NTSC, "Philips TD1536" },
- { TUNER_PHILIPS_NTSC, "Philips TD1536D" },
- { TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */
- { TUNER_ABSENT, "Philips FI1256MP" },
- { TUNER_ABSENT, "Samsung TCPQ9091P" },
- { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
- { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
- { TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
- { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
- { TUNER_ABSENT, "Philips TD1536D_FH_44"},
- { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"},
- { TUNER_LG_PAL_FM, "LG TPI8PSB01D"},
- { TUNER_LG_PAL, "LG TPI8PSB11D"},
- { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
- { TUNER_LG_PAL_I, "LG TAPC-I701D"}
-};
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
- unsigned int blk2,tuner,radio,model;
-
- if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) {
- printk(KERN_WARNING "%s: Hauppauge eeprom: invalid\n",
- core->name);
- return;
- }
-
- /* Block 2 starts after len+3 bytes header */
- blk2 = eeprom_data[1] + 3;
-
- /* decode + use some config infos */
- model = eeprom_data[12] << 8 | eeprom_data[11];
- tuner = eeprom_data[9];
- radio = eeprom_data[blk2-1] & 0x01;
-
- if (tuner < ARRAY_SIZE(hauppauge_tuner))
- core->tuner_type = hauppauge_tuner[tuner].id;
- if (radio)
- core->has_radio = 1;
+ struct tveeprom tv;
- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, "
- "tuner=%s (%d), radio=%s\n",
- core->name, model, (tuner < ARRAY_SIZE(hauppauge_tuner)
- ? hauppauge_tuner[tuner].name : "?"),
- core->tuner_type, radio ? "yes" : "no");
+ tveeprom_hauppauge_analog(&tv, eeprom_data);
+ core->tuner_type = tv.tuner_type;
+ core->has_radio = tv.has_radio;
}
-#ifdef WITH_DVB
static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
{
int model;
int tuner;
- char *tname;
/* Make sure we support the board model */
model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c];
@@ -689,26 +781,18 @@ static int hauppauge_eeprom_dvb(struct c
/* Make sure we support the tuner */
tuner = ee[0x2d];
switch(tuner) {
- case 0x4B:
- tname = "Thomson DTT 7595";
- core->pll_type = PLLTYPE_DTT7595;
- break;
- case 0x4C:
- tname = "Thomson DTT 7592";
- core->pll_type = PLLTYPE_DTT7592;
+ case 0x4B: /* dtt 7595 */
+ case 0x4C: /* dtt 7592 */
break;
default:
printk("%s: error: unknown hauppauge tuner 0x%02x\n",
core->name, tuner);
return -ENODEV;
}
- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%s (%d)\n",
- core->name, model, tname, tuner);
-
- core->pll_addr = 0x61;
- core->demod_addr = 0x43;
+ printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%d\n",
+ core->name, model, tuner);
+ return 0;
}
-#endif
/* ----------------------------------------------------------------------- */
/* some GDI (was: Modular Technology) specific stuff */
@@ -763,36 +847,6 @@ static void gdi_eeprom(struct cx88_core
/* ----------------------------------------------------------------------- */
-static int
-i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len)
-{
- unsigned char buf;
- int err;
-
- c->addr = 0xa0 >> 1;
- buf = 0;
- if (1 != (err = i2c_master_send(c,&buf,1))) {
- printk(KERN_INFO "cx88: Huh, no eeprom present (err=%d)?\n",
- err);
- return -1;
- }
- if (len != (err = i2c_master_recv(c,eedata,len))) {
- printk(KERN_WARNING "cx88: i2c eeprom read error (err=%d)\n",
- err);
- return -1;
- }
-#if 0
- for (i = 0; i < len; i++) {
- if (0 == (i % 16))
- printk(KERN_INFO "cx88 ee: %02x:",i);
- printk(" %02x",eedata[i]);
- if (15 == (i % 16))
- printk("\n");
- }
-#endif
- return 0;
-}
-
void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
{
int i;
@@ -823,41 +877,46 @@ void cx88_card_setup(struct cx88_core *c
{
static u8 eeprom[128];
+ if (0 == core->i2c_rc) {
+ core->i2c_client.addr = 0xa0 >> 1;
+ tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
+ }
+
switch (core->board) {
case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_ROSLYN:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- hauppauge_eeprom(core,eeprom+8);
+ hauppauge_eeprom(core,eeprom+8);
break;
case CX88_BOARD_GDI:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- gdi_eeprom(core,eeprom);
+ gdi_eeprom(core,eeprom);
break;
- case CX88_BOARD_WINFAST2000XP:
+ case CX88_BOARD_WINFAST2000XP_EXPERT:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- leadtek_eeprom(core,eeprom);
+ leadtek_eeprom(core,eeprom);
+ break;
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ if (0 == core->i2c_rc)
+ hauppauge_eeprom_dvb(core,eeprom);
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- /* Tuner reset is hooked to the tuner out of reset */
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ /* GPIO0:0 is hooked to mt352 reset pin */
cx_set(MO_GP0_IO, 0x00000101);
cx_clear(MO_GP0_IO, 0x00000001);
msleep(1);
cx_set(MO_GP0_IO, 0x00000101);
break;
-#ifdef WITH_DVB
- case CX88_BOARD_HAUPPAUGE_DVB_T1:
- if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- hauppauge_eeprom_dvb(core,eeprom);
- break;
- case CX88_BOARD_CONEXANT_DVB_T1:
- core->pll_type = PLLTYPE_DTT7579;
- core->pll_addr = 0x60;
- core->demod_addr = 0x43;
+ case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ cx_set(MO_GP0_IO, 0x00000707);
+ cx_set(MO_GP2_IO, 0x00000101);
+ cx_clear(MO_GP2_IO, 0x00000001);
+ msleep(1);
+ cx_clear(MO_GP0_IO, 0x00000007);
+ cx_set(MO_GP2_IO, 0x00000101);
break;
-#endif
}
if (cx88_boards[core->board].radio.type == CX88_RADIO)
core->has_radio = 1;
Index: linux-2.6.11/drivers/media/video/cx88/cx88-core.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-core.c 2005-03-07 10:13:16.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-core.c 2005-03-08 10:33:15.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-core.c,v 1.15 2004/10/25 11:26:36 kraxel Exp $
+ * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -62,6 +63,10 @@ static unsigned int nicam = 0;
module_param(nicam,int,0644);
MODULE_PARM_DESC(nicam,"tv audio is nicam");
+static unsigned int nocomb = 0;
+module_param(nocomb,int,0644);
+MODULE_PARM_DESC(nocomb,"disable comb filter");
+
#define dprintk(level,fmt, arg...) if (core_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
@@ -462,6 +467,7 @@ int cx88_risc_decode(u32 risc)
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
+#if 0 /* currently unused, but useful for debugging */
void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc)
{
@@ -479,6 +485,7 @@ void cx88_risc_disasm(struct cx88_core *
break;
}
}
+#endif
void cx88_sram_channel_dump(struct cx88_core *core,
struct sram_channel *ch)
@@ -579,10 +586,19 @@ void cx88_print_irqbits(char *name, char
/* ------------------------------------------------------------------ */
-void cx88_irq(struct cx88_core *core, u32 status, u32 mask)
+int cx88_core_irq(struct cx88_core *core, u32 status)
{
- cx88_print_irqbits(core->name, "irq pci",
- cx88_pci_irqs, status, mask);
+ int handled = 0;
+
+ if (status & (1<<18)) {
+ cx88_ir_irq(core);
+ handled++;
+ }
+ if (!handled)
+ cx88_print_irqbits(core->name, "irq pci",
+ cx88_pci_irqs, status,
+ core->pci_irqmask);
+ return handled;
}
void cx88_wakeup(struct cx88_core *core,
@@ -800,6 +816,8 @@ int cx88_set_scale(struct cx88_core *cor
value |= (1 << 0); // 3-tap interpolation
if (width < 193)
value |= (1 << 1); // 5-tap interpolation
+ if (nocomb)
+ value |= (3 << 5); // disable comb filter
cx_write(MO_FILTER_EVEN, value);
cx_write(MO_FILTER_ODD, value);
@@ -887,8 +905,8 @@ static int set_tvaudio(struct cx88_core
cx88_set_tvaudio(core);
// cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
- cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */
- cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */
+ cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
+ cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
return 0;
}
@@ -969,6 +987,9 @@ int cx88_set_tvnorm(struct cx88_core *co
cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
norm_vbipack(norm)));
+ // this is needed as well to set all tvnorm parameter
+ cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
+
// audio
set_tvaudio(core);
@@ -1105,9 +1126,10 @@ struct cx88_core* cx88_core_get(struct p
goto fail_unlock;
memset(core,0,sizeof(*core));
+ atomic_inc(&core->refcount);
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
- atomic_inc(&core->refcount);
+ core->pci_irqmask = 0x00fc00;
core->nr = cx88_devcount++;
sprintf(core->name,"cx88[%d]",core->nr);
@@ -1150,6 +1172,7 @@ struct cx88_core* cx88_core_get(struct p
cx88_reset(core);
cx88_i2c_init(core,pci);
cx88_card_setup(core);
+ cx88_ir_init(core,pci);
up(&devlist);
return core;
@@ -1170,6 +1193,7 @@ void cx88_core_put(struct cx88_core *cor
return;
down(&devlist);
+ cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
@@ -1187,7 +1211,7 @@ EXPORT_SYMBOL(cx88_vid_irqs);
EXPORT_SYMBOL(cx88_mpeg_irqs);
EXPORT_SYMBOL(cx88_print_irqbits);
-EXPORT_SYMBOL(cx88_irq);
+EXPORT_SYMBOL(cx88_core_irq);
EXPORT_SYMBOL(cx88_wakeup);
EXPORT_SYMBOL(cx88_reset);
EXPORT_SYMBOL(cx88_shutdown);
@@ -1197,8 +1221,6 @@ EXPORT_SYMBOL(cx88_risc_databuffer);
EXPORT_SYMBOL(cx88_risc_stopper);
EXPORT_SYMBOL(cx88_free_buffer);
-EXPORT_SYMBOL(cx88_risc_disasm);
-
EXPORT_SYMBOL(cx88_sram_channels);
EXPORT_SYMBOL(cx88_sram_channel_setup);
EXPORT_SYMBOL(cx88_sram_channel_dump);
Index: linux-2.6.11/drivers/media/video/cx88/cx88-blackbird.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-blackbird.c 2005-03-08 10:33:15.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-blackbird.c 2005-03-08 10:33:20.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-blackbird.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
@@ -207,10 +208,6 @@ static int register_write(struct cx88_co
cx_read(P1_RADDR0);
return wait_ready_gpio0_bit1(core,1);
-#if 0
- udelay(1000); /* without this, things don't go right (subsequent memory_write()'s don't get through */
- /* ? would this be safe here? set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); */
-#endif
}
@@ -283,7 +280,7 @@ static int blackbird_api_cmd(struct cx88
timeout = jiffies + msecs_to_jiffies(10);
for (;;) {
memory_read(dev->core, dev->mailbox, &flag);
- if (0 == (flag & 4))
+ if (0 != (flag & 4))
break;
if (time_after(jiffies,timeout)) {
dprintk(0, "ERROR: API Mailbox timeout\n");
@@ -324,7 +321,7 @@ static int blackbird_find_mailbox(struct
signaturecnt = 0;
if (4 == signaturecnt) {
dprintk(1, "Mailbox signature found\n");
- return i;
+ return i+1;
}
}
dprintk(0, "Mailbox signature values not found!\n");
@@ -427,7 +424,8 @@ static void blackbird_codec_settings(str
blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
/* assign frame size */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
+ dev->height, dev->width);
/* assign aspect ratio */
blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
@@ -629,8 +627,8 @@ static int mpeg_do_ioctl(struct inode *i
memset(f,0,sizeof(*f));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- f->fmt.pix.width = 720;
- f->fmt.pix.height = 576;
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
}
@@ -694,6 +692,10 @@ static int mpeg_open(struct inode *inode
file->private_data = fh;
fh->dev = dev;
+ /* FIXME: locking against other video device */
+ cx88_set_scale(dev->core, dev->width, dev->height,
+ V4L2_FIELD_INTERLACED);
+
videobuf_queue_init(&fh->mpegq, &blackbird_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -715,6 +717,7 @@ static int mpeg_release(struct inode *in
if (fh->mpegq.reading)
videobuf_read_stop(&fh->mpegq);
+ videobuf_mmap_free(&fh->mpegq);
file->private_data = NULL;
kfree(fh);
return 0;
@@ -821,6 +824,8 @@ static int __devinit blackbird_probe(str
memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
+ dev->width = 720;
+ dev->height = 480;
err = cx8802_init_common(dev);
if (0 != err)
@@ -852,6 +857,8 @@ static void __devexit blackbird_remove(s
/* common */
cx8802_fini_common(dev);
+ cx88_core_put(dev->core,dev->pci);
+ kfree(dev);
}
static struct pci_device_id cx8802_pci_tbl[] = {
Index: linux-2.6.11/drivers/media/video/Kconfig
===================================================================
--- linux-2.6.11.orig/drivers/media/video/Kconfig 2005-03-07 10:15:21.000000000 +0100
+++ linux-2.6.11/drivers/media/video/Kconfig 2005-03-08 10:33:15.000000000 +0100
@@ -305,11 +305,14 @@ config VIDEO_HEXIUM_GEMINI
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
- depends on VIDEO_DEV && PCI && EXPERIMENTAL
+ depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL
select I2C_ALGOBIT
+ select FW_LOADER
select VIDEO_BTCX
select VIDEO_BUF
select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
---help---
This is a video4linux driver for Conexant 2388x based
TV cards.
@@ -319,10 +322,11 @@ config VIDEO_CX88
config VIDEO_CX88_DVB
tristate "DVB Support for cx2388x based TV cards"
- depends on VIDEO_CX88 && DVB_CORE && BROKEN
+ depends on VIDEO_CX88 && DVB_CORE
select VIDEO_BUF_DVB
+ select DVB_MT352
---help---
- This adds support for DVB cards based on the
+ This adds support for DVB/ATSC cards based on the
Connexant 2388x chip.
config VIDEO_OVCAMCHIP
Index: linux-2.6.11/drivers/media/video/cx88/cx88-video.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-video.c 2005-03-08 10:33:15.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-video.c 2005-03-08 10:33:20.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-video.c,v 1.46 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -428,7 +429,7 @@ static int start_video_dma(struct cx8800
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc01);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0011);
/* enable capture */
@@ -994,7 +995,7 @@ static int video_open(struct inode *inod
cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
dev->core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO);
+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
}
@@ -1002,7 +1003,7 @@ static int video_open(struct inode *inod
}
static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+video_read(struct file *file, char *data, size_t count, loff_t *ppos)
{
struct cx8800_fh *fh = file->private_data;
@@ -1083,6 +1084,8 @@ static int video_release(struct inode *i
res_free(dev,fh,RESOURCE_VBI);
}
+ videobuf_mmap_free(&fh->vidq);
+ videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
return 0;
@@ -1338,7 +1341,6 @@ static int video_do_ioctl(struct inode *
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
-
return 0;
}
@@ -1429,6 +1431,7 @@ static int video_do_ioctl(struct inode *
if (*i >= 4)
return -EINVAL;
down(&dev->lock);
+ cx88_newstation(core);
video_mux(dev,*i);
up(&dev->lock);
return 0;
@@ -1560,7 +1563,7 @@ static int video_do_ioctl(struct inode *
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- cx88_set_stereo(core, t->audmode);
+ cx88_set_stereo(core, t->audmode, 1);
return 0;
}
case VIDIOC_G_FREQUENCY:
@@ -1590,6 +1593,7 @@ static int video_do_ioctl(struct inode *
return -EINVAL;
down(&dev->lock);
dev->freq = f->frequency;
+ cx88_newstation(core);
#ifdef V4L2_I2C_CLIENTS
cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
#else
@@ -1880,19 +1884,18 @@ static irqreturn_t cx8800_irq(int irq, v
{
struct cx8800_dev *dev = dev_id;
struct cx88_core *core = dev->core;
- u32 status, mask;
+ u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x01);
- mask = cx_read(MO_PCI_INTMSK);
- if (0 == (status & mask))
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);
+ if (0 == status)
goto out;
cx_write(MO_PCI_INTSTAT, status);
handled = 1;
- if (status & mask & ~0x1f)
- cx88_irq(core,status,mask);
+ if (status & core->pci_irqmask)
+ cx88_core_irq(core,status);
if (status & 0x01)
cx8800_vid_irq(dev);
};
@@ -2055,6 +2058,7 @@ static int __devinit cx8800_initdev(stru
core->name,pci_dev->irq);
goto fail_core;
}
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* load and configure helper modules */
if (TUNER_ABSENT != core->tuner_type)
@@ -2156,7 +2160,7 @@ static void __devexit cx8800_finidev(str
kfree(dev);
}
-static int cx8800_suspend(struct pci_dev *pci_dev, u32 state)
+static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -2181,7 +2185,7 @@ static int cx8800_suspend(struct pci_dev
#endif
pci_save_state(pci_dev);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
@@ -2197,7 +2201,7 @@ static int cx8800_resume(struct pci_dev
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
Index: linux-2.6.11/drivers/media/video/cx88/cx88-mpeg.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-mpeg.c 2005-03-07 10:16:04.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-mpeg.c 2005-03-08 10:33:15.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-mpeg.c,v 1.14 2004/10/25 11:26:36 kraxel Exp $
+ * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -68,8 +69,14 @@ static int cx8802_start_dma(struct cx880
* also: move to cx88-blackbird + cx88-dvb source files? */
if (cx88_boards[core->board].dvb) {
- /* Setup TS portion of chip */
- cx_write(TS_GEN_CNTRL, 0x0c);
+ /* negedge driven & software reset */
+ cx_write(TS_GEN_CNTRL, 0x40);
+ udelay(100);
+ cx_write(MO_PINMUX_IO, 0x00);
+ cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00);
+ cx_write(TS_SOP_STAT,0x00);
+ cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
+ udelay(100);
}
if (cx88_boards[core->board].blackbird) {
@@ -93,7 +100,7 @@ static int cx8802_start_dma(struct cx880
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc04);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
cx_write(MO_TS_INTMSK, 0x1f0011);
/* start dma */
@@ -292,19 +299,18 @@ static irqreturn_t cx8802_irq(int irq, v
{
struct cx8802_dev *dev = dev_id;
struct cx88_core *core = dev->core;
- u32 status, mask;
+ u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x04);
- mask = cx_read(MO_PCI_INTMSK);
- if (0 == (status & mask))
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
+ if (0 == status)
goto out;
handled = 1;
cx_write(MO_PCI_INTSTAT, status);
- if (status & mask & ~0x1f)
- cx88_irq(core,status,mask);
+ if (status & core->pci_irqmask)
+ cx88_core_irq(core,status);
if (status & 0x04)
cx8802_mpeg_irq(dev);
};
@@ -323,6 +329,7 @@ static irqreturn_t cx8802_irq(int irq, v
int cx8802_init_common(struct cx8802_dev *dev)
{
+ struct cx88_core *core = dev->core;
int err;
/* pci init */
@@ -354,11 +361,6 @@ int cx8802_init_common(struct cx8802_dev
cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
MO_TS_DMACNTRL,0x11,0x00);
-#if 0 /* FIXME */
- /* initialize hardware */
- cx8802_reset(dev);
-#endif
-
/* get irq */
err = request_irq(dev->pci->irq, cx8802_irq,
SA_SHIRQ | SA_INTERRUPT, dev->core->name, dev);
@@ -367,11 +369,7 @@ int cx8802_init_common(struct cx8802_dev
dev->core->name, dev->pci->irq);
return err;
}
-
-#if 0 /* FIXME */
- /* register i2c bus + load i2c helpers */
- cx88_card_setup(dev);
-#endif
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* everything worked */
pci_set_drvdata(dev->pci,dev);
@@ -393,7 +391,7 @@ void cx8802_fini_common(struct cx8802_de
/* ----------------------------------------------------------- */
-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state)
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -413,7 +411,7 @@ int cx8802_suspend_common(struct pci_dev
#endif
pci_save_state(pci_dev);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
@@ -429,7 +427,7 @@ int cx8802_resume_common(struct pci_dev
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
Index: linux-2.6.11/drivers/media/video/cx88/cx88-tvaudio.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-tvaudio.c 2005-03-07 10:13:41.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-tvaudio.c 2005-03-08 10:33:20.000000000 +0100
@@ -1,5 +1,5 @@
/*
- $Id: cx88-tvaudio.c,v 1.24 2004/10/25 11:51:00 kraxel Exp $
+ $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
@@ -37,6 +37,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -56,7 +57,7 @@
#include "cx88.h"
-static unsigned int audio_debug = 1;
+static unsigned int audio_debug = 0;
module_param(audio_debug,int,0644);
MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]");
@@ -141,6 +142,13 @@ static void set_audio_finish(struct cx88
{
u32 volume;
+ if (cx88_boards[core->board].blackbird) {
+ // 'pass-thru mode': this enables the i2s output to the mpeg encoder
+ cx_set(AUD_CTL, 0x2000);
+ cx_write(AUD_I2SOUTPUTCNTL, 1);
+ //cx_write(AUD_APB_IN_RATE_ADJ, 0);
+ }
+
// finish programming
cx_write(AUD_SOFT_RESET, 0x0000);
@@ -263,6 +271,7 @@ static void set_audio_standard_BTSC(stru
set_audio_finish(core);
}
+#if 0
static void set_audio_standard_NICAM(struct cx88_core *core)
{
static const struct rlist nicam_common[] = {
@@ -335,128 +344,243 @@ static void set_audio_standard_NICAM(str
};
set_audio_finish(core);
}
+#endif
-static void set_audio_standard_NICAM_L(struct cx88_core *core)
+static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
{
- /* This is officially weird.. register dumps indicate windows
- * uses audio mode 4.. A2. Let's operate and find out. */
+ /* This is probably weird..
+ * Let's operate and find out. */
- static const struct rlist nicam_l[] = {
- // setup QAM registers
- { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x3d },
- { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
- { AUD_QAM_MODE, 0x00 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x4a },
+ static const struct rlist nicam_l_mono[] = {
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_IIR1_0_SEL, 0x00000000 },
- { AUD_IIR1_1_SEL, 0x00000002 },
- { AUD_IIR1_2_SEL, 0x00000023 },
- { AUD_IIR1_3_SEL, 0x00000004 },
- { AUD_IIR1_4_SEL, 0x00000005 },
- { AUD_IIR1_5_SEL, 0x00000007 },
- { AUD_IIR1_0_SHIFT, 0x00000007 },
- { AUD_IIR1_1_SHIFT, 0x00000000 },
- { AUD_IIR1_2_SHIFT, 0x00000000 },
- { AUD_IIR1_3_SHIFT, 0x00000007 },
- { AUD_IIR1_4_SHIFT, 0x00000007 },
- { AUD_IIR1_5_SHIFT, 0x00000007 },
- { AUD_IIR2_0_SEL, 0x00000002 },
- { AUD_IIR2_1_SEL, 0x00000003 },
- { AUD_IIR2_2_SEL, 0x00000004 },
- { AUD_IIR2_3_SEL, 0x00000005 },
- { AUD_IIR3_0_SEL, 0x00000007 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_IIR3_2_SEL, 0x00000016 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000000 },
- { AUD_IIR3_2_SHIFT, 0x00000002 },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_IIR4_1_SEL, 0x00000019 },
- { AUD_IIR4_2_SEL, 0x00000008 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000007 },
- { AUD_IIR4_2_SHIFT, 0x00000007 },
- { AUD_IIR4_0_CA0, 0x0003e57e },
- { AUD_IIR4_0_CA1, 0x00005e11 },
- { AUD_IIR4_0_CA2, 0x0003a7cf },
- { AUD_IIR4_0_CB0, 0x00002368 },
- { AUD_IIR4_0_CB1, 0x0003bf1b },
- { AUD_IIR4_1_CA0, 0x00006349 },
- { AUD_IIR4_1_CA1, 0x00006f27 },
- { AUD_IIR4_1_CA2, 0x0000e7a3 },
- { AUD_IIR4_1_CB0, 0x00005653 },
- { AUD_IIR4_1_CB1, 0x0000cf97 },
- { AUD_IIR4_2_CA0, 0x00006349 },
- { AUD_IIR4_2_CA1, 0x00006f27 },
- { AUD_IIR4_2_CA2, 0x0000e7a3 },
- { AUD_IIR4_2_CB0, 0x00005653 },
- { AUD_IIR4_2_CB1, 0x0000cf97 },
- { AUD_HP_MD_IIR4_1, 0x00000001 },
- { AUD_HP_PROG_IIR4_1, 0x0000001a },
- { AUD_DN0_FREQ, 0x00000000 },
- { AUD_DN1_FREQ, 0x00003318 },
- { AUD_DN1_SRC_SEL, 0x00000017 },
- { AUD_DN1_SHFT, 0x00000007 },
- { AUD_DN1_AFC, 0x00000000 },
- { AUD_DN1_FREQ_SHIFT, 0x00000000 },
- { AUD_DN2_FREQ, 0x00003551 },
- { AUD_DN2_SRC_SEL, 0x00000001 },
- { AUD_DN2_SHFT, 0x00000000 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DN2_FREQ_SHIFT, 0x00000000 },
- { AUD_PDET_SRC, 0x00000014 },
- { AUD_PDET_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH1_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH0_SHIFT, 0x00000000 },
- { AUD_DEEMPH1_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_G0, 0x00007000 },
- { AUD_DEEMPH0_A0, 0x00000000 },
- { AUD_DEEMPH0_B0, 0x00000000 },
- { AUD_DEEMPH0_A1, 0x00000000 },
- { AUD_DEEMPH0_B1, 0x00000000 },
- { AUD_DEEMPH1_G0, 0x00007000 },
- { AUD_DEEMPH1_A0, 0x00000000 },
- { AUD_DEEMPH1_B0, 0x00000000 },
- { AUD_DEEMPH1_A1, 0x00000000 },
- { AUD_DEEMPH1_B1, 0x00000000 },
- { AUD_DMD_RA_DDS, 0x00f5c285 },
- { AUD_RATE_ADJ1, 0x00000100 },
- { AUD_RATE_ADJ2, 0x00000200 },
- { AUD_RATE_ADJ3, 0x00000300 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00000500 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C2_LO_THR, 0x00005400 },
- { AUD_CTL, 0x0000100c },
- { AUD_DCOC_0_SRC, 0x00000021 },
- { AUD_DCOC_1_SRC, 0x00000003 },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000000 },
- { AUD_DCOC_2_SRC, 0x0000001b },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_PHASE_FIX_CTL, 0x00000000 },
- { AUD_CORDIC_SHIFT_1, 0x00000007 },
- { AUD_PLL_EN, 0x00000000 },
- { AUD_PLL_PRESCALE, 0x00000002 },
- { AUD_PLL_INT, 0x0000001e },
- { AUD_OUT1_SHIFT, 0x00000000 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
+ { AUD_QAM_MODE, 0x00 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x4a },
- { /* end of list */ },
- };
+ { AUD_DEEMPHGAIN_R, 0x6680 },
+ { AUD_DEEMPHNUMER1_R, 0x353DE },
+ { AUD_DEEMPHNUMER2_R, 0x1B1 },
+ { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x0 },
+ { AUD_FM_MODE_ENABLE, 0x7 },
+ { AUD_POLYPH80SCALEFAC, 0x3 },
+ { AUD_AFE_12DB_EN, 0x1 },
+ { AAGC_GAIN, 0x0 },
+ { AAGC_HYST, 0x18 },
+ { AAGC_DEF, 0x20 },
+ { AUD_DN0_FREQ, 0x0 },
+ { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
+ { AUD_DCOC_0_SRC, 0x21 },
+ { AUD_IIR1_0_SEL, 0x0 },
+ { AUD_IIR1_0_SHIFT, 0x7 },
+ { AUD_IIR1_1_SEL, 0x2 },
+ { AUD_IIR1_1_SHIFT, 0x0 },
+ { AUD_DCOC_1_SRC, 0x3 },
+ { AUD_DCOC1_SHIFT, 0x0 },
+ { AUD_DCOC_PASS_IN, 0x0 },
+ { AUD_IIR1_2_SEL, 0x23 },
+ { AUD_IIR1_2_SHIFT, 0x0 },
+ { AUD_IIR1_3_SEL, 0x4 },
+ { AUD_IIR1_3_SHIFT, 0x7 },
+ { AUD_IIR1_4_SEL, 0x5 },
+ { AUD_IIR1_4_SHIFT, 0x7 },
+ { AUD_IIR3_0_SEL, 0x7 },
+ { AUD_IIR3_0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_SRC_SEL, 0x11 },
+ { AUD_DEEMPH0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_G0, 0x7000 },
+ { AUD_DEEMPH0_A0, 0x0 },
+ { AUD_DEEMPH0_B0, 0x0 },
+ { AUD_DEEMPH0_A1, 0x0 },
+ { AUD_DEEMPH0_B1, 0x0 },
+ { AUD_DEEMPH1_SRC_SEL, 0x11 },
+ { AUD_DEEMPH1_SHIFT, 0x0 },
+ { AUD_DEEMPH1_G0, 0x7000 },
+ { AUD_DEEMPH1_A0, 0x0 },
+ { AUD_DEEMPH1_B0, 0x0 },
+ { AUD_DEEMPH1_A1, 0x0 },
+ { AUD_DEEMPH1_B1, 0x0 },
+ { AUD_OUT0_SEL, 0x3F },
+ { AUD_OUT1_SEL, 0x3F },
+ { AUD_DMD_RA_DDS, 0x0F5C285 },
+ { AUD_PLL_INT, 0x1E },
+ { AUD_PLL_DDS, 0x0 },
+ { AUD_PLL_FRAC, 0x0E542 },
- dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0004,
- 0 /* FIXME */);
- set_audio_registers(core, nicam_l);
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000100 },
+ { AUD_RATE_ADJ2, 0x00000200 },
+ { AUD_RATE_ADJ3, 0x00000300 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00000500 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ };
+
+ static const struct rlist nicam_l[] = {
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000060 },
+ { AUD_RATE_ADJ2, 0x000000F9 },
+ { AUD_RATE_ADJ3, 0x000001CC },
+ { AUD_RATE_ADJ4, 0x000002B3 },
+ { AUD_RATE_ADJ5, 0x00000726 },
+ { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_DMD_RA_DDS, 0x00C00000 },
+ { AUD_PLL_INT, 0x0000001E },
+ { AUD_PLL_DDS, 0x00000000 },
+ { AUD_PLL_FRAC, 0x0000E542 },
+ { AUD_START_TIMER, 0x00000000 },
+ { AUD_DEEMPHNUMER1_R, 0x000353DE },
+ { AUD_DEEMPHNUMER2_R, 0x000001B1 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x34 },
+ { AUD_PHACC_FREQ_8LSB, 0x4C },
+ { AUD_DEEMPHGAIN_R, 0x00006680 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ } ;
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* AM mono sound */
+ set_audio_start(core, 0x0004,
+ 0x100c /* FIXME again */);
+ set_audio_registers(core, nicam_l_mono);
+ } else {
+ set_audio_start(core, 0x0010,
+ 0x1924 /* FIXME again */);
+ set_audio_registers(core, nicam_l);
+ }
+ set_audio_finish(core);
+
+}
+
+static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
+{
+ static const struct rlist pal_i_fm_mono[] = {
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x3a},
+ {AUD_PHACC_FREQ_8LSB, 0x93},
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000004},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000060},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AAGC_HYST, 0x0000000a},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_DN0_FREQ, 0x000035a3},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_CRDC0_SRC_SEL, 0x00000511},
+ {AUD_IIR1_0_SEL, 0x00000001},
+ {AUD_IIR1_1_SEL, 0x00000000},
+ {AUD_IIR3_2_SEL, 0x00000003},
+ {AUD_IIR3_2_SHIFT, 0x00000000},
+ {AUD_IIR3_0_SEL, 0x00000002},
+ {AUD_IIR2_0_SEL, 0x00000021},
+ {AUD_IIR2_0_SHIFT, 0x00000002},
+ {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+ {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
+ };
+
+ static const struct rlist pal_i_nicam[] = {
+ { AUD_RATE_ADJ1, 0x00000010 },
+ { AUD_RATE_ADJ2, 0x00000040 },
+ { AUD_RATE_ADJ3, 0x00000100 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00001000 },
+ // { AUD_DMD_RA_DDS, 0x00c0d5ce },
+ { AUD_DEEMPHGAIN_R, 0x000023c2 },
+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
+ { AUD_DEEMPHNUMER2_R, 0x0003023e },
+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000fff },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x93 },
+ { /* end of list */ },
+ };
+
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ // FM mono
+ set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ set_audio_registers(core, pal_i_fm_mono);
+ } else {
+ // Nicam Stereo
+ set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ set_audio_registers(core, pal_i_nicam);
+ }
set_audio_finish(core);
}
@@ -553,13 +677,6 @@ static void set_audio_standard_A2(struct
set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
set_audio_registers(core, a2_common);
switch (core->tvaudio) {
- case WW_NICAM_I:
- /* gives at least mono according to the dscaler guys */
- /* so use use that while nicam is broken ... */
- dprintk("%s PAL-I mono (status: unknown)\n",__FUNCTION__);
- set_audio_registers(core, a2_table1);
- cx_write(AUD_CTL, EN_A2_FORCE_MONO1);
- break;
case WW_A2_BG:
dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
set_audio_registers(core, a2_table1);
@@ -646,11 +763,12 @@ void cx88_set_tvaudio(struct cx88_core *
case WW_BTSC:
set_audio_standard_BTSC(core,0);
break;
- // case WW_NICAM_I:
case WW_NICAM_BGDKL:
- set_audio_standard_NICAM(core);
+ set_audio_standard_NICAM_L(core,0);
break;
case WW_NICAM_I:
+ set_audio_standard_PAL_I(core,0);
+ break;
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
@@ -663,7 +781,7 @@ void cx88_set_tvaudio(struct cx88_core *
set_audio_standard_FM(core);
break;
case WW_SYSTEM_L_AM:
- set_audio_standard_NICAM_L(core);
+ set_audio_standard_NICAM_L(core, 1);
break;
case WW_NONE:
default:
@@ -674,6 +792,19 @@ void cx88_set_tvaudio(struct cx88_core *
return;
}
+void cx88_newstation(struct cx88_core *core)
+{
+ core->audiomode_manual = UNSET;
+
+ switch (core->tvaudio) {
+ case WW_SYSTEM_L_AM:
+ /* try nicam ... */
+ core->audiomode_current = V4L2_TUNER_MODE_STEREO;
+ set_audio_standard_NICAM_L(core, 1);
+ break;
+ }
+}
+
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
{
static char *m[] = {"stereo", "dual mono", "mono", "sap"};
@@ -721,22 +852,37 @@ void cx88_get_stereo(struct cx88_core *c
}
break;
case WW_NICAM_BGDKL:
- if (0 == mode)
+ if (0 == mode) {
t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ }
break;
+ case WW_SYSTEM_L_AM:
+ if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ }
+ break ;
default:
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- t->audmode = V4L2_TUNER_MODE_MONO;
+ /* nothing */
break;
}
return;
}
-void cx88_set_stereo(struct cx88_core *core, u32 mode)
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
{
u32 ctl = UNSET;
u32 mask = UNSET;
+ if (manual) {
+ core->audiomode_manual = mode;
+ } else {
+ if (UNSET != core->audiomode_manual)
+ return;
+ }
+ core->audiomode_current = mode;
+
switch (core->tvaudio) {
case WW_BTSC:
switch (mode) {
@@ -789,6 +935,28 @@ void cx88_set_stereo(struct cx88_core *c
break;
}
break;
+ case WW_SYSTEM_L_AM:
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1: /* FIXME */
+ set_audio_standard_NICAM_L(core, 0);
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ set_audio_standard_NICAM_L(core, 1);
+ break;
+ }
+ break;
+ case WW_NICAM_I:
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ set_audio_standard_PAL_I(core, 0);
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ set_audio_standard_PAL_I(core, 1);
+ break;
+ }
+ break;
case WW_FM:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
@@ -804,13 +972,11 @@ void cx88_set_stereo(struct cx88_core *c
}
if (UNSET != ctl) {
- cx_write(AUD_SOFT_RESET, 0x0001);
- cx_andor(AUD_CTL, mask, ctl);
- cx_write(AUD_SOFT_RESET, 0x0000);
dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
mask, ctl, cx_read(AUD_STATUS),
cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+ cx_andor(AUD_CTL, mask, ctl);
}
return;
}
@@ -819,16 +985,32 @@ int cx88_audio_thread(void *data)
{
struct cx88_core *core = data;
struct v4l2_tuner t;
+ u32 mode = 0;
dprintk("cx88: tvaudio thread started\n");
for (;;) {
+ msleep_interruptible(1000);
if (kthread_should_stop())
break;
/* just monitor the audio status for now ... */
memset(&t,0,sizeof(t));
cx88_get_stereo(core,&t);
- msleep_interruptible(1000);
+
+ if (UNSET != core->audiomode_manual)
+ /* manually set, don't do anything. */
+ continue;
+
+ /* monitor signal */
+ if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+ mode = V4L2_TUNER_MODE_STEREO;
+ else
+ mode = V4L2_TUNER_MODE_MONO;
+ if (mode == core->audiomode_current)
+ continue;
+
+ /* automatically switch to best available mode */
+ cx88_set_stereo(core, mode, 0);
}
dprintk("cx88: tvaudio thread exiting\n");
@@ -838,6 +1020,7 @@ int cx88_audio_thread(void *data)
/* ----------------------------------------------------------- */
EXPORT_SYMBOL(cx88_set_tvaudio);
+EXPORT_SYMBOL(cx88_newstation);
EXPORT_SYMBOL(cx88_set_stereo);
EXPORT_SYMBOL(cx88_get_stereo);
EXPORT_SYMBOL(cx88_audio_thread);
Index: linux-2.6.11/drivers/media/video/cx88/cx88-dvb.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-dvb.c 2005-03-08 10:33:15.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-dvb.c 2005-03-08 10:33:20.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-dvb.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
@@ -30,10 +30,20 @@
#include <linux/file.h>
#include <linux/suspend.h>
+/* those two frontends need merging via linuxtv cvs ... */
+#define HAVE_CX22702 0
+#define HAVE_OR51132 0
+
#include "cx88.h"
-#include "cx22702.h"
+#include "dvb-pll.h"
#include "mt352.h"
-#include "mt352_priv.h" /* FIXME */
+#include "mt352_priv.h"
+#if HAVE_CX22702
+# include "cx22702.h"
+#endif
+#if HAVE_OR51132
+# include "or51132.h"
+#endif
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -110,111 +120,144 @@ static int dvico_fusionhdtv_demod_init(s
return 0;
}
-#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
-
-static int lg_z201_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params, u8* pllbuf)
+static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
{
- u32 div;
- unsigned char cp = 0;
- unsigned char bs = 0;
-
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
- if (params->frequency < 542000000) cp = 0xbc;
- else if (params->frequency < 830000000) cp = 0xf4;
- else cp = 0xfc;
+ static u8 clock_config [] = { 0x89, 0x38, 0x39 };
+ static u8 reset [] = { 0x50, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+ 0x00, 0xFF, 0x00, 0x40, 0x40 };
+ static u8 dntv_extra[] = { 0xB5, 0x7A };
+ static u8 capt_range_cfg[] = { 0x75, 0x32 };
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 157500000) bs = 0x01;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x04;
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(2000);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
- pllbuf[0] = 0xC2; /* Note: non-linux standard PLL I2C address */
- pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ udelay(2000);
+ mt352_write(fe, dntv_extra, sizeof(dntv_extra));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
return 0;
}
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
- u8* pllbuf)
+static int mt352_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ u8* pllbuf)
{
- u32 div;
- unsigned char cp = 0;
- unsigned char bs = 0;
-
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
- if (params->frequency < 542000000) cp = 0xb4;
- else if (params->frequency < 771000000) cp = 0xbc;
- else cp = 0xf4;
-
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x08;
-
- pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
- pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ struct cx8802_dev *dev= fe->dvb->priv;
+ pllbuf[0] = dev->core->pll_addr << 1;
+ dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+ params->frequency,
+ params->u.ofdm.bandwidth);
return 0;
}
-struct mt352_config dvico_fusionhdtv_dvbt1 = {
+static struct mt352_config dvico_fusionhdtv = {
.demod_address = 0x0F,
.demod_init = dvico_fusionhdtv_demod_init,
- .pll_set = lg_z201_pll_set,
+ .pll_set = mt352_pll_set,
};
-struct mt352_config dvico_fusionhdtv_dvbt_plus = {
- .demod_address = 0x0F,
- .demod_init = dvico_fusionhdtv_demod_init,
- .pll_set = thomson_dtt7579_pll_set,
+static struct mt352_config dntv_live_dvbt_config = {
+ .demod_address = 0x0f,
+ .demod_init = dntv_live_dvbt_demod_init,
+ .pll_set = mt352_pll_set,
+};
+
+#if HAVE_CX22702
+static struct cx22702_config connexant_refboard_config = {
+ .demod_address = 0x43,
+ .pll_address = 0x60,
+ .pll_desc = &dvb_pll_thomson_dtt7579,
+};
+
+static struct cx22702_config hauppauge_novat_config = {
+ .demod_address = 0x43,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_thomson_dtt759x,
+};
+#endif
+
+#if HAVE_OR51132
+static int or51132_set_ts_param(struct dvb_frontend* fe,
+ int is_punctured)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+ return 0;
+}
+
+struct or51132_config pchdtv_hd3000 = {
+ .demod_address = 0x15,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_thomson_dtt7610,
+ .set_ts_params = or51132_set_ts_param,
};
+#endif
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
dev->dvb.name = dev->core->name;
+ dev->ts_gen_cntrl = 0x0c;
/* init frontend */
switch (dev->core->board) {
+#if HAVE_CX22702
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
+ &dev->core->i2c_adap);
+ break;
case CX88_BOARD_CONEXANT_DVB_T1:
- dev->dvb.frontend = cx22702_create(&dev->core->i2c_adap,
- dev->core->pll_addr,
- dev->core->pll_type,
- dev->core->demod_addr);
+ dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
+ &dev->core->i2c_adap);
break;
+#endif
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt1,
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_lg_z201;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
&dev->core->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops->info.frequency_min = 174000000;
- dev->dvb.frontend->ops->info.frequency_max = 862000000;
- }
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt_plus,
+ dev->core->pll_addr = 0x60;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+ &dev->core->i2c_adap);
+ break;
+ case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_unknown_1;
+ dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
&dev->core->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops->info.frequency_min = 174000000;
- dev->dvb.frontend->ops->info.frequency_max = 862000000;
- }
break;
+#if HAVE_OR51132
+ case CX88_BOARD_PCHDTV_HD3000:
+ dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
+ &dev->core->i2c_adap);
+ break;
+#endif
default:
- printk("%s: FIXME: frontend handling not here yet ...\n",
- dev->core->name);
+ printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n"
+ "%s: you might want to look out for patches here:\n"
+ "%s: http://dl.bytesex.org/patches/\n",
+ dev->core->name, dev->core->name, dev->core->name);
break;
}
- if (NULL == dev->dvb.frontend)
+ if (NULL == dev->dvb.frontend) {
+ printk("%s: frontend initialization failed\n",dev->core->name);
return -1;
+ }
+
+ if (dev->core->pll_desc) {
+ dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
+ dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
+ }
/* Copy the board name into the DVB structure */
strlcpy(dev->dvb.frontend->ops->info.name,
@@ -222,7 +265,7 @@ static int dvb_register(struct cx8802_de
sizeof(dev->dvb.frontend->ops->info.name));
/* register everything */
- return videobuf_dvb_register(&dev->dvb);
+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
/* ----------------------------------------------------------- */
Index: linux-2.6.11/drivers/media/video/cx88/cx88-input.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.11/drivers/media/video/cx88/cx88-input.c 2005-03-08 10:33:15.000000000 +0100
@@ -0,0 +1,396 @@
+/*
+ * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
+ *
+ * Device driver for GPIO attached remote control interfaces
+ * on Conexant 2388x based TV/DVB cards.
+ *
+ * Copyright (c) 2003 Pavel Machek
+ * Copyright (c) 2004 Gerd Knorr
+ * Copyright (c) 2004 Chris Pascoe
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <media/ir-common.h>
+
+#include "cx88.h"
+
+/* ---------------------------------------------------------------------- */
+
+/* DigitalNow DNTV Live DVB-T Remote */
+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_ESC, // 'go up a level?'
+ [ 0x01 ] = KEY_KP1, // '1'
+ [ 0x02 ] = KEY_KP2, // '2'
+ [ 0x03 ] = KEY_KP3, // '3'
+ [ 0x04 ] = KEY_KP4, // '4'
+ [ 0x05 ] = KEY_KP5, // '5'
+ [ 0x06 ] = KEY_KP6, // '6'
+ [ 0x07 ] = KEY_KP7, // '7'
+ [ 0x08 ] = KEY_KP8, // '8'
+ [ 0x09 ] = KEY_KP9, // '9'
+ [ 0x0a ] = KEY_KP0, // '0'
+ [ 0x0b ] = KEY_TUNER, // 'tv/fm'
+ [ 0x0c ] = KEY_SEARCH, // 'scan'
+ [ 0x0d ] = KEY_STOP, // 'stop'
+ [ 0x0e ] = KEY_PAUSE, // 'pause'
+ [ 0x0f ] = KEY_LIST, // 'source'
+
+ [ 0x10 ] = KEY_MUTE, // 'mute'
+ [ 0x11 ] = KEY_REWIND, // 'backward <<'
+ [ 0x12 ] = KEY_POWER, // 'power'
+ [ 0x13 ] = KEY_S, // 'snap'
+ [ 0x14 ] = KEY_AUDIO, // 'stereo'
+ [ 0x15 ] = KEY_CLEAR, // 'reset'
+ [ 0x16 ] = KEY_PLAY, // 'play'
+ [ 0x17 ] = KEY_ENTER, // 'enter'
+ [ 0x18 ] = KEY_ZOOM, // 'full screen'
+ [ 0x19 ] = KEY_FASTFORWARD, // 'forward >>'
+ [ 0x1a ] = KEY_CHANNELUP, // 'channel +'
+ [ 0x1b ] = KEY_VOLUMEUP, // 'volume +'
+ [ 0x1c ] = KEY_INFO, // 'preview'
+ [ 0x1d ] = KEY_RECORD, // 'record'
+ [ 0x1e ] = KEY_CHANNELDOWN, // 'channel -'
+ [ 0x1f ] = KEY_VOLUMEDOWN, // 'volume -'
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* IO-DATA BCTV7E Remote */
+static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
+ [ 0x40 ] = KEY_TV, // TV
+ [ 0x20 ] = KEY_RADIO, // FM
+ [ 0x60 ] = KEY_EPG, // EPG
+ [ 0x00 ] = KEY_POWER, // power
+
+ [ 0x50 ] = KEY_KP1, // 1
+ [ 0x30 ] = KEY_KP2, // 2
+ [ 0x70 ] = KEY_KP3, // 3
+ [ 0x10 ] = KEY_L, // Live
+
+ [ 0x48 ] = KEY_KP4, // 4
+ [ 0x28 ] = KEY_KP5, // 5
+ [ 0x68 ] = KEY_KP6, // 6
+ [ 0x08 ] = KEY_T, // Time Shift
+
+ [ 0x58 ] = KEY_KP7, // 7
+ [ 0x38 ] = KEY_KP8, // 8
+ [ 0x78 ] = KEY_KP9, // 9
+ [ 0x18 ] = KEY_PLAYPAUSE, // Play
+
+ [ 0x44 ] = KEY_KP0, // 10
+ [ 0x24 ] = KEY_ENTER, // 11
+ [ 0x64 ] = KEY_ESC, // 12
+ [ 0x04 ] = KEY_M, // Multi
+
+ [ 0x54 ] = KEY_VIDEO, // VIDEO
+ [ 0x34 ] = KEY_CHANNELUP, // channel +
+ [ 0x74 ] = KEY_VOLUMEUP, // volume +
+ [ 0x14 ] = KEY_MUTE, // Mute
+
+ [ 0x4c ] = KEY_S, // SVIDEO
+ [ 0x2c ] = KEY_CHANNELDOWN, // channel -
+ [ 0x6c ] = KEY_VOLUMEDOWN, // volume -
+ [ 0x0c ] = KEY_ZOOM, // Zoom
+
+ [ 0x5c ] = KEY_PAUSE, // pause
+ [ 0x3c ] = KEY_C, // || (red)
+ [ 0x7c ] = KEY_RECORD, // recording
+ [ 0x1c ] = KEY_STOP, // stop
+
+ [ 0x41 ] = KEY_REWIND, // backward <<
+ [ 0x21 ] = KEY_PLAY, // play
+ [ 0x61 ] = KEY_FASTFORWARD, // forward >>
+ [ 0x01 ] = KEY_NEXT, // skip >|
+};
+
+/* ---------------------------------------------------------------------- */
+
+struct cx88_IR {
+ struct cx88_core *core;
+ struct input_dev input;
+ struct ir_input_state ir;
+ char name[32];
+ char phys[32];
+
+ /* sample from gpio pin 16 */
+ int sampling;
+ u32 samples[16];
+ int scount;
+ unsigned long release;
+
+ /* poll external decoder */
+ int polling;
+ struct work_struct work;
+ struct timer_list timer;
+ u32 gpio_addr;
+ u32 last_gpio;
+ u32 mask_keycode;
+ u32 mask_keydown;
+ u32 mask_keyup;
+};
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644); /* debug level [IR] */
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define ir_dprintk(fmt, arg...) if (ir_debug) \
+ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
+
+/* ---------------------------------------------------------------------- */
+
+static void cx88_ir_handle_key(struct cx88_IR *ir)
+{
+ struct cx88_core *core = ir->core;
+ u32 gpio, data;
+
+ /* read gpio value */
+ gpio = cx_read(ir->gpio_addr);
+ if (ir->polling) {
+ if (ir->last_gpio == gpio)
+ return;
+ ir->last_gpio = gpio;
+ }
+
+ /* extract data */
+ data = ir_extract_bits(gpio, ir->mask_keycode);
+ ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
+ gpio, data,
+ ir->polling ? "poll" : "irq",
+ (gpio & ir->mask_keydown) ? " down" : "",
+ (gpio & ir->mask_keyup) ? " up" : "");
+
+ if (ir->mask_keydown) {
+ /* bit set on keydown */
+ if (gpio & ir->mask_keydown) {
+ ir_input_keydown(&ir->input,&ir->ir,data,data);
+ } else {
+ ir_input_nokey(&ir->input,&ir->ir);
+ }
+
+ } else if (ir->mask_keyup) {
+ /* bit cleared on keydown */
+ if (0 == (gpio & ir->mask_keyup)) {
+ ir_input_keydown(&ir->input,&ir->ir,data,data);
+ } else {
+ ir_input_nokey(&ir->input,&ir->ir);
+ }
+
+ } else {
+ /* can't distinguish keydown/up :-/ */
+ ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_nokey(&ir->input,&ir->ir);
+ }
+}
+
+static void ir_timer(unsigned long data)
+{
+ struct cx88_IR *ir = (struct cx88_IR*)data;
+
+ schedule_work(&ir->work);
+}
+
+static void cx88_ir_work(void *data)
+{
+ struct cx88_IR *ir = data;
+ unsigned long timeout;
+
+ cx88_ir_handle_key(ir);
+ timeout = jiffies + (ir->polling * HZ / 1000);
+ mod_timer(&ir->timer, timeout);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+{
+ struct cx88_IR *ir;
+ IR_KEYTAB_TYPE *ir_codes = NULL;
+ int ir_type = IR_TYPE_OTHER;
+
+ ir = kmalloc(sizeof(*ir),GFP_KERNEL);
+ if (NULL == ir)
+ return -ENOMEM;
+ memset(ir,0,sizeof(*ir));
+
+ /* detect & configure */
+ switch (core->board) {
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ ir_codes = ir_codes_dntv_live_dvb_t;
+ ir->gpio_addr = MO_GP1_IO;
+ ir->mask_keycode = 0x1f;
+ ir->mask_keyup = 0x60;
+ ir->polling = 50; // ms
+ break;
+ case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ ir_codes = ir_codes_hauppauge_new;
+ ir_type = IR_TYPE_RC5;
+ ir->sampling = 1;
+ break;
+ case CX88_BOARD_WINFAST2000XP_EXPERT:
+ ir_codes = ir_codes_winfast;
+ ir->gpio_addr = MO_GP0_IO;
+ ir->mask_keycode = 0x8f8;
+ ir->mask_keyup = 0x100;
+ ir->polling = 1; // ms
+ break;
+ case CX88_BOARD_IODATA_GVBCTV7E:
+ ir_codes = ir_codes_iodata_bctv7e;
+ ir->gpio_addr = MO_GP0_IO;
+ ir->mask_keycode = 0xfd;
+ ir->mask_keydown = 0x02;
+ ir->polling = 5; // ms
+ break;
+ }
+ if (NULL == ir_codes) {
+ kfree(ir);
+ return -ENODEV;
+ }
+
+ /* init input device */
+ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
+ cx88_boards[core->board].name);
+ snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
+ pci_name(pci));
+
+ ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
+ ir->input.name = ir->name;
+ ir->input.phys = ir->phys;
+ ir->input.id.bustype = BUS_PCI;
+ ir->input.id.version = 1;
+ if (pci->subsystem_vendor) {
+ ir->input.id.vendor = pci->subsystem_vendor;
+ ir->input.id.product = pci->subsystem_device;
+ } else {
+ ir->input.id.vendor = pci->vendor;
+ ir->input.id.product = pci->device;
+ }
+
+ /* record handles to ourself */
+ ir->core = core;
+ core->ir = ir;
+
+ if (ir->polling) {
+ INIT_WORK(&ir->work, cx88_ir_work, ir);
+ init_timer(&ir->timer);
+ ir->timer.function = ir_timer;
+ ir->timer.data = (unsigned long)ir;
+ schedule_work(&ir->work);
+ }
+ if (ir->sampling) {
+ core->pci_irqmask |= (1<<18); // IR_SMP_INT
+ cx_write(MO_DDS_IO, 0xa80a80); // 4 kHz sample rate
+ cx_write(MO_DDSCFG_IO, 0x5); // enable
+ }
+
+ /* all done */
+ input_register_device(&ir->input);
+ printk("%s: registered IR remote control\n", core->name);
+
+ return 0;
+}
+
+int cx88_ir_fini(struct cx88_core *core)
+{
+ struct cx88_IR *ir = core->ir;
+
+ /* skip detach on non attached boards */
+ if (NULL == ir)
+ return 0;
+
+ if (ir->polling) {
+ del_timer(&ir->timer);
+ flush_scheduled_work();
+ }
+
+ input_unregister_device(&ir->input);
+ kfree(ir);
+
+ /* done */
+ core->ir = NULL;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void cx88_ir_irq(struct cx88_core *core)
+{
+ struct cx88_IR *ir = core->ir;
+ u32 samples,rc5;
+ int i;
+
+ if (NULL == ir)
+ return;
+ if (!ir->sampling)
+ return;
+
+ samples = cx_read(MO_SAMPLE_IO);
+ if (0 != samples && 0xffffffff != samples) {
+ /* record sample data */
+ if (ir->scount < ARRAY_SIZE(ir->samples))
+ ir->samples[ir->scount++] = samples;
+ return;
+ }
+ if (!ir->scount) {
+ /* nothing to sample */
+ if (ir->ir.keypressed && time_after(jiffies,ir->release))
+ ir_input_nokey(&ir->input,&ir->ir);
+ return;
+ }
+
+ /* have a complete sample */
+ if (ir->scount < ARRAY_SIZE(ir->samples))
+ ir->samples[ir->scount++] = samples;
+ for (i = 0; i < ir->scount; i++)
+ ir->samples[i] = ~ir->samples[i];
+ if (ir_debug)
+ ir_dump_samples(ir->samples,ir->scount);
+
+ /* decode it */
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ rc5 = ir_decode_biphase(ir->samples,ir->scount,5,7);
+ ir_dprintk("biphase decoded: %x\n",rc5);
+ if ((rc5 & 0xfffff000) != 0x3000)
+ break;
+ ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
+ }
+
+ ir->scount = 0;
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
+MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
Index: linux-2.6.11/drivers/media/video/cx88/cx88-vbi.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-vbi.c 2005-03-07 10:13:49.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-vbi.c 2005-03-08 10:33:15.000000000 +0100
@@ -1,8 +1,9 @@
/*
- * $Id: cx88-vbi.c,v 1.14 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -64,7 +65,7 @@ int cx8800_start_vbi_dma(struct cx8800_d
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc01);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0088);
/* enable capture */
Index: linux-2.6.11/drivers/media/video/cx88/cx88.h
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88.h 2005-03-07 10:15:48.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88.h 2005-03-08 10:33:15.000000000 +0100
@@ -1,5 +1,5 @@
/*
- * $Id: cx88.h,v 1.40 2004/11/03 09:04:51 kraxel Exp $
+ * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -27,6 +27,7 @@
#include <linux/kdev_t.h>
#include <media/tuner.h>
+#include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/video-buf.h>
#include <media/video-buf-dvb.h>
@@ -139,7 +140,7 @@ extern struct sram_channel cx88_sram_cha
#define CX88_BOARD_GDI 2
#define CX88_BOARD_PIXELVIEW 3
#define CX88_BOARD_ATI_WONDER_PRO 4
-#define CX88_BOARD_WINFAST2000XP 5
+#define CX88_BOARD_WINFAST2000XP_EXPERT 5
#define CX88_BOARD_AVERTV_303 6
#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
#define CX88_BOARD_WINFAST_DV2000 8
@@ -156,6 +157,11 @@ extern struct sram_channel cx88_sram_cha
#define CX88_BOARD_CONEXANT_DVB_T1 19
#define CX88_BOARD_PROVIDEO_PV259 20
#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
+#define CX88_BOARD_PCHDTV_HD3000 22
+#define CX88_BOARD_DNTV_LIVE_DVB_T 23
+#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
+#define CX88_BOARD_DIGITALLOGIC_MEC 25
+#define CX88_BOARD_IODATA_GVBCTV7E 26
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -238,6 +244,7 @@ struct cx88_core {
u32 __iomem *lmmio;
u8 __iomem *bmmio;
u32 shadow[SHADOW_MAX];
+ int pci_irqmask;
/* i2c i/o */
struct i2c_adapter i2c_adap;
@@ -252,16 +259,20 @@ struct cx88_core {
unsigned int has_radio;
/* config info -- dvb */
- unsigned int pll_type;
+ struct dvb_pll_desc *pll_desc;
unsigned int pll_addr;
- unsigned int demod_addr;
/* state info */
struct task_struct *kthread;
struct cx88_tvnorm *tvnorm;
u32 tvaudio;
+ u32 audiomode_manual;
+ u32 audiomode_current;
u32 input;
u32 astat;
+
+ /* IR remote control state */
+ struct cx88_IR *ir;
};
struct cx8800_dev;
@@ -371,11 +382,16 @@ struct cx8802_dev {
struct list_head devlist;
struct video_device *mpeg_dev;
u32 mailbox;
+ int width;
+ int height;
/* for dvb only */
struct videobuf_dvb dvb;
void* fe_handle;
int (*fe_release)(void *handle);
+
+ /* for switching modulation types */
+ unsigned char ts_gen_cntrl;
};
/* ----------------------------------------------------------- */
@@ -411,7 +427,7 @@ extern void cx88_print_irqbits(char *nam
u32 bits, u32 mask);
extern void cx88_print_ioctl(char *name, unsigned int cmd);
-extern void cx88_irq(struct cx88_core *core, u32 status, u32 mask);
+extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
struct cx88_dmaqueue *q, u32 count);
extern void cx88_shutdown(struct cx88_core *core);
@@ -503,11 +519,19 @@ extern void cx88_card_setup(struct cx88_
#define WW_FM 12
void cx88_set_tvaudio(struct cx88_core *core);
+void cx88_newstation(struct cx88_core *core);
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
-void cx88_set_stereo(struct cx88_core *core, u32 mode);
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
int cx88_audio_thread(void *data);
/* ----------------------------------------------------------- */
+/* cx88-input.c */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
+int cx88_ir_fini(struct cx88_core *core);
+void cx88_ir_irq(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf);
@@ -517,7 +541,7 @@ void cx8802_cancel_buffers(struct cx8802
int cx8802_init_common(struct cx8802_dev *dev);
void cx8802_fini_common(struct cx8802_dev *dev);
-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state);
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
int cx8802_resume_common(struct pci_dev *pci_dev);
/*
Index: linux-2.6.11/drivers/media/video/cx88/Makefile
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/Makefile 2005-03-07 10:13:03.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/Makefile 2005-03-08 10:33:15.000000000 +0100
@@ -1,4 +1,5 @@
-cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o
+cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
+ cx88-input.o
cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
Index: linux-2.6.11/drivers/media/video/cx88/cx88-i2c.c
===================================================================
--- linux-2.6.11.orig/drivers/media/video/cx88/cx88-i2c.c 2005-03-07 10:13:32.000000000 +0100
+++ linux-2.6.11/drivers/media/video/cx88/cx88-i2c.c 2005-03-08 10:33:15.000000000 +0100
@@ -1,5 +1,5 @@
/*
- $Id: cx88-i2c.c,v 1.18 2004/10/13 10:39:00 kraxel Exp $
+ $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
cx88-i2c.c -- all the i2c code is here
@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/io.h>
--
#define printk(args...) fprintf(stderr, ## args)
^ permalink raw reply [flat|nested] 2+ messages in thread* [patch] v4l: cx88 driver update
@ 2004-06-18 10:02 Gerd Knorr
0 siblings, 0 replies; 2+ messages in thread
From: Gerd Knorr @ 2004-06-18 10:02 UTC (permalink / raw)
To: Andrew Morton, Kernel List
Hi,
This is a update for the cx88 tv card driver. Changes:
* finally make it build with gcc 2.95 ;)
* add new tv cards.
* plenty of fixes for the TV sound code.
* use v4l2 API for communication with tuner + tda9887
* misc other minor stuff.
please apply,
Gerd
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-cards.c linux/drivers/media/video/cx88/cx88-cards.c
--- linux-2.6.7/drivers/media/video/cx88/cx88-cards.c 2004-06-17 10:30:25.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-cards.c 2004-06-17 13:47:59.785272417 +0200
@@ -99,6 +99,10 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .gpio0 = 0x000003ff,
+ .gpio1 = 0x000000ff,
+ .gpio2 = 0x000000ff,
+ .gpio3 = 0x00000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -111,6 +115,7 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST2000XP] = {
.name = "Leadtek Winfast 2000XP Expert",
.tuner_type = 44,
+ .needs_tda9887 = 1,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -149,22 +154,33 @@ struct cx88_board cx88_boards[] = {
.vmux = 0,
}},
},
- [CX88_BOARD_MSI_TVANYWHERE] = {
+ [CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
+ //added gpio values thanks to Torsten Seeboth
+ //values for PAL from DScaler
.name = "MSI TV-@nywhere Master",
.tuner_type = 33,
+ .needs_tda9887 = 1,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .gpio0 = 0x000040bf,
+ .gpio1 = 0x000080c0,
+ .gpio2 = 0x0000ff40,
+ .gpio3 = 0x00000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- },{
- // temporarly for testing ...
- .type = CX88_VMUX_COMPOSITE2,
- .vmux = 2,
+ .gpio0 = 0x000040bf,
+ .gpio1 = 0x000080c0,
+ .gpio2 = 0x0000ff40,
+ .gpio3 = 0x00000000,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x000040bf,
+ .gpio1 = 0x000080c0,
+ .gpio2 = 0x0000ff40,
+ .gpio3 = 0x00000000,
}},
.radio = {
.type = CX88_RADIO,
@@ -199,8 +215,97 @@ struct cx88_board cx88_boards[] = {
.type = CX88_RADIO,
},
},
-
-
+ [CX88_BOARD_IODATA_GVVCP3PCI] = {
+ .name = "IODATA GV-VCP3/PCI",
+ .tuner_type = TUNER_ABSENT,
+ .needs_tda9887 = 0,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE2,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ },
+ [CX88_BOARD_PROLINK_PLAYTVPVR] = {
+ .name = "Prolink PlayTV PVR",
+ .tuner_type = 43,
+ .needs_tda9887 = 1,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xff00,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xff03,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xff03,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xff00,
+ },
+ },
+ [CX88_BOARD_ASUS_PVR_416] = {
+ .name = "ASUS PVR-416",
+ .tuner_type = 43,
+ .needs_tda9887 = 1,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0000fde6,
+ .gpio1 = 0x00000000, // possibly for mpeg data
+ .gpio2 = 0x000000e9,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+ .gpio1 = 0x00000000, // possibly for mpeg data
+ .gpio2 = 0x000000e9,
+ .gpio3 = 0x00000000,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0000fde2,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x000000e9,
+ .gpio3 = 0x00000000,
+ },
+ },
+ [CX88_BOARD_MSI_TVANYWHERE] = {
+ .name = "MSI TV-@nywhere",
+ .tuner_type = 33,
+ .needs_tda9887 = 1,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x00000fbf,
+ .gpio1 = 0x000000c0,
+ .gpio2 = 0x0000fc08,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x00000fbf,
+ .gpio1 = 0x000000c0,
+ .gpio2 = 0x0000fc68,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x00000fbf,
+ .gpio1 = 0x000000c0,
+ .gpio2 = 0x0000fc68,
+ .gpio3 = 0x00000000,
+ }},
+ },
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -242,6 +347,10 @@ struct cx88_subid cx88_subids[] = {
.card = CX88_BOARD_WINFAST_DV2000,
},{
.subvendor = 0x107d,
+ .subdevice = 0x663b,
+ .card = CX88_BOARD_LEADTEK_PVR2000,
+ },{
+ .subvendor = 0x107d,
.subdevice = 0x663C,
.card = CX88_BOARD_LEADTEK_PVR2000,
},{
@@ -251,12 +360,19 @@ struct cx88_subid cx88_subids[] = {
},{
.subvendor = 0x1462,
.subdevice = 0x8606,
- .card = CX88_BOARD_MSI_TVANYWHERE,
- }
+ .card = CX88_BOARD_MSI_TVANYWHERE_MASTER,
+ },{
+ .subvendor = 0x10fc,
+ .subdevice = 0xd003,
+ .card = CX88_BOARD_IODATA_GVVCP3PCI,
+ },{
+ .subvendor = 0x1043,
+ .subdevice = 0x4823, /* with mpeg encoder */
+ .card = CX88_BOARD_ASUS_PVR_416,
+ }
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
-
/* ----------------------------------------------------------------------- */
/* some leadtek specific stuff */
@@ -269,7 +385,7 @@ static void __devinit leadtek_eeprom(str
*/
if (eeprom_data[4] != 0x7d ||
- eeprom_data[5] != 0x10 ||
+ eeprom_data[5] != 0x10 ||
eeprom_data[7] != 0x66) {
printk(KERN_WARNING "%s Leadtek eeprom invalid.\n", dev->name);
return;
@@ -277,7 +393,7 @@ static void __devinit leadtek_eeprom(str
dev->has_radio = 1;
dev->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
-
+
printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: "
"tuner=%d, eeprom[0]=0x%02x\n",
dev->name, dev->tuner_type, eeprom_data[0]);
@@ -386,20 +502,22 @@ static struct {
[ 0x02 ] = { .id = TUNER_ABSENT,
.name = "PAL_B" },
[ 0x03 ] = { .id = TUNER_ABSENT,
- .name = "BAL_I" },
+ .name = "PAL_I" },
[ 0x04 ] = { .id = TUNER_ABSENT,
.name = "PAL_D" },
[ 0x05 ] = { .id = TUNER_ABSENT,
.name = "SECAM" },
- [ 0x10 ] = { .id = TUNER_ABSENT, .fm = 1,
+ [ 0x10 ] = { .id = TUNER_ABSENT,
+ .fm = 1,
.name = "TEMIC_4049" },
[ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
.name = "TEMIC_4136" },
[ 0x12 ] = { .id = TUNER_ABSENT,
.name = "TEMIC_4146" },
- [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, .fm = 1,
+ [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
+ .fm = 1,
.name = "PHILIPS_FQ1216_MK3" },
[ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
.name = "PHILIPS_FQ1236_MK3" },
@@ -454,7 +572,33 @@ i2c_eeprom(struct i2c_client *c, unsigne
return 0;
}
-void __devinit cx88_card_setup(struct cx8800_dev *dev)
+void cx88_card_list(struct cx8800_dev *dev)
+{
+ int i;
+
+ if (0 == dev->pci->subsystem_vendor &&
+ 0 == dev->pci->subsystem_device) {
+ printk("%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+ "%s: be autodetected. Please pass card=<n> insmod option to\n"
+ "%s: workaround that. Redirect complaints to the vendor of\n"
+ "%s: the TV card. Best regards,\n"
+ "%s: -- tux\n",
+ dev->name,dev->name,dev->name,dev->name,dev->name);
+ } else {
+ printk("%s: Your board isn't known (yet) to the driver. You can\n"
+ "%s: try to pick one of the existing card configs via\n"
+ "%s: card=<n> insmod option. Updating to the latest\n"
+ "%s: version might help as well.\n",
+ dev->name,dev->name,dev->name,dev->name);
+ }
+ printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+ dev->name);
+ for (i = 0; i < cx88_bcount; i++)
+ printk("%s: card=%d -> %s\n",
+ dev->name, i, cx88_boards[i].name);
+}
+
+void cx88_card_setup(struct cx8800_dev *dev)
{
static u8 eeprom[128];
@@ -474,6 +618,9 @@ void __devinit cx88_card_setup(struct cx
i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom));
leadtek_eeprom(dev,eeprom);
break;
+ case CX88_BOARD_ASUS_PVR_416:
+ dev->has_radio = 1;
+ break;
}
}
@@ -483,6 +630,7 @@ EXPORT_SYMBOL(cx88_boards);
EXPORT_SYMBOL(cx88_bcount);
EXPORT_SYMBOL(cx88_subids);
EXPORT_SYMBOL(cx88_idcount);
+EXPORT_SYMBOL(cx88_card_list);
EXPORT_SYMBOL(cx88_card_setup);
/*
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-i2c.c linux/drivers/media/video/cx88/cx88-i2c.c
--- linux-2.6.7/drivers/media/video/cx88/cx88-i2c.c 2004-06-17 10:28:38.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-i2c.c 2004-06-17 13:47:59.787272041 +0200
@@ -22,8 +22,6 @@
*/
-#define __NO_VERSION__ 1
-
#include <linux/module.h>
#include <linux/init.h>
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-reg.h linux/drivers/media/video/cx88/cx88-reg.h
--- linux-2.6.7/drivers/media/video/cx88/cx88-reg.h 2004-06-17 10:28:53.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-reg.h 2004-06-17 13:47:59.790271476 +0200
@@ -599,10 +599,20 @@
#define EN_I2SIN_STR2DAC 0x00004000
#define EN_I2SIN_ENABLE 0x00008000
+#if 0
+/* old */
#define EN_DMTRX_SUMDIFF 0x00000800
#define EN_DMTRX_SUMR 0x00000880
#define EN_DMTRX_LR 0x00000900
#define EN_DMTRX_MONO 0x00000980
+#else
+/* dscaler cvs */
+#define EN_DMTRX_SUMDIFF (0 << 7)
+#define EN_DMTRX_SUMR (1 << 7)
+#define EN_DMTRX_LR (2 << 7)
+#define EN_DMTRX_MONO (3 << 7)
+#define EN_DMTRX_BYPASS (1 << 11)
+#endif
// Video
#define VID_CAPTURE_CONTROL 0x310180
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-tvaudio.c linux/drivers/media/video/cx88/cx88-tvaudio.c
--- linux-2.6.7/drivers/media/video/cx88/cx88-tvaudio.c 2004-06-17 10:28:49.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-tvaudio.c 2004-06-17 13:47:59.794270724 +0200
@@ -48,6 +48,7 @@
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include "cx88.h"
@@ -60,6 +61,33 @@ MODULE_PARM_DESC(audio_debug,"enable deb
/* ----------------------------------------------------------- */
+static char *aud_ctl_names[64] =
+{
+ [ EN_BTSC_FORCE_MONO ] = "BTSC_FORCE_MONO",
+ [ EN_BTSC_FORCE_STEREO ] = "BTSC_FORCE_STEREO",
+ [ EN_BTSC_FORCE_SAP ] = "BTSC_FORCE_SAP",
+ [ EN_BTSC_AUTO_STEREO ] = "BTSC_AUTO_STEREO",
+ [ EN_BTSC_AUTO_SAP ] = "BTSC_AUTO_SAP",
+ [ EN_A2_FORCE_MONO1 ] = "A2_FORCE_MONO1",
+ [ EN_A2_FORCE_MONO2 ] = "A2_FORCE_MONO2",
+ [ EN_A2_FORCE_STEREO ] = "A2_FORCE_STEREO",
+ [ EN_A2_AUTO_MONO2 ] = "A2_AUTO_MONO2",
+ [ EN_A2_AUTO_STEREO ] = "A2_AUTO_STEREO",
+ [ EN_EIAJ_FORCE_MONO1 ] = "EIAJ_FORCE_MONO1",
+ [ EN_EIAJ_FORCE_MONO2 ] = "EIAJ_FORCE_MONO2",
+ [ EN_EIAJ_FORCE_STEREO ] = "EIAJ_FORCE_STEREO",
+ [ EN_EIAJ_AUTO_MONO2 ] = "EIAJ_AUTO_MONO2",
+ [ EN_EIAJ_AUTO_STEREO ] = "EIAJ_AUTO_STEREO",
+ [ EN_NICAM_FORCE_MONO1 ] = "NICAM_FORCE_MONO1",
+ [ EN_NICAM_FORCE_MONO2 ] = "NICAM_FORCE_MONO2",
+ [ EN_NICAM_FORCE_STEREO ] = "NICAM_FORCE_STEREO",
+ [ EN_NICAM_AUTO_MONO2 ] = "NICAM_AUTO_MONO2",
+ [ EN_NICAM_AUTO_STEREO ] = "NICAM_AUTO_STEREO",
+ [ EN_FMRADIO_FORCE_MONO ] = "FMRADIO_FORCE_MONO",
+ [ EN_FMRADIO_FORCE_STEREO ] = "FMRADIO_FORCE_STEREO",
+ [ EN_FMRADIO_AUTO_STEREO ] = "FMRADIO_AUTO_STEREO",
+};
+
struct rlist {
u32 reg;
u32 val;
@@ -125,26 +153,116 @@ static void set_audio_finish(struct cx88
static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap)
{
static const struct rlist btsc[] = {
- /* Magic stuff from leadtek driver + datasheet.*/
- { AUD_DBX_IN_GAIN, 0x4734 },
- { AUD_DBX_WBE_GAIN, 0x4640 },
- { AUD_DBX_SE_GAIN, 0x8D31 },
- { AUD_DEEMPH0_G0, 0x1604 },
- { AUD_PHASE_FIX_CTL, 0x0020 },
-
+ /* from dscaler */
+ { AUD_OUT1_SEL, 0x00000013 },
+ { AUD_OUT1_SHIFT, 0x00000000 },
+ { AUD_POLY0_DDS_CONSTANT, 0x0012010c },
+ { AUD_DMD_RA_DDS, 0x00c3e7aa },
+ { AUD_DBX_IN_GAIN, 0x00004734 },
+ { AUD_DBX_WBE_GAIN, 0x00004640 },
+ { AUD_DBX_SE_GAIN, 0x00008d31 },
+ { AUD_DCOC_0_SRC, 0x0000001a },
+ { AUD_IIR1_4_SEL, 0x00000021 },
+ { AUD_DCOC_PASS_IN, 0x00000003 },
+ { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
+ { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
+ { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
+ { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
+ { AUD_DN0_FREQ, 0x0000283b },
+ { AUD_DN2_SRC_SEL, 0x00000008 },
+ { AUD_DN2_FREQ, 0x00003000 },
+ { AUD_DN2_AFC, 0x00000002 },
+ { AUD_DN2_SHFT, 0x00000000 },
+ { AUD_IIR2_2_SEL, 0x00000020 },
+ { AUD_IIR2_2_SHIFT, 0x00000000 },
+ { AUD_IIR2_3_SEL, 0x0000001f },
+ { AUD_IIR2_3_SHIFT, 0x00000000 },
+ { AUD_CRDC1_SRC_SEL, 0x000003ce },
+ { AUD_CRDC1_SHIFT, 0x00000000 },
+ { AUD_CORDIC_SHIFT_1, 0x00000007 },
+ { AUD_DCOC_1_SRC, 0x0000001b },
+ { AUD_DCOC1_SHIFT, 0x00000000 },
+ { AUD_RDSI_SEL, 0x00000008 },
+ { AUD_RDSQ_SEL, 0x00000008 },
+ { AUD_RDSI_SHIFT, 0x00000000 },
+ { AUD_RDSQ_SHIFT, 0x00000000 },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
{ /* end of list */ },
};
-
- dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(dev, 0x0001,
- EN_BTSC_AUTO_STEREO);
- set_audio_registers(dev, btsc);
+ static const struct rlist btsc_sap[] = {
+ { AUD_DBX_IN_GAIN, 0x00007200 },
+ { AUD_DBX_WBE_GAIN, 0x00006200 },
+ { AUD_DBX_SE_GAIN, 0x00006200 },
+ { AUD_IIR1_1_SEL, 0x00000000 },
+ { AUD_IIR1_3_SEL, 0x00000001 },
+ { AUD_DN1_SRC_SEL, 0x00000007 },
+ { AUD_IIR1_4_SHIFT, 0x00000006 },
+ { AUD_IIR2_1_SHIFT, 0x00000000 },
+ { AUD_IIR2_2_SHIFT, 0x00000000 },
+ { AUD_IIR3_0_SHIFT, 0x00000000 },
+ { AUD_IIR3_1_SHIFT, 0x00000000 },
+ { AUD_IIR3_0_SEL, 0x0000000d },
+ { AUD_IIR3_1_SEL, 0x0000000e },
+ { AUD_DEEMPH1_SRC_SEL, 0x00000014 },
+ { AUD_DEEMPH1_SHIFT, 0x00000000 },
+ { AUD_DEEMPH1_G0, 0x00004000 },
+ { AUD_DEEMPH1_A0, 0x00000000 },
+ { AUD_DEEMPH1_B0, 0x00000000 },
+ { AUD_DEEMPH1_A1, 0x00000000 },
+ { AUD_DEEMPH1_B1, 0x00000000 },
+ { AUD_OUT0_SEL, 0x0000003f },
+ { AUD_OUT1_SEL, 0x0000003f },
+ { AUD_DN1_AFC, 0x00000002 },
+ { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
+ { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
+ { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
+ { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
+ { AUD_IIR1_0_SEL, 0x0000001d },
+ { AUD_IIR1_2_SEL, 0x0000001e },
+ { AUD_IIR2_1_SEL, 0x00000002 },
+ { AUD_IIR2_2_SEL, 0x00000004 },
+ { AUD_IIR3_2_SEL, 0x0000000f },
+ { AUD_DCOC2_SHIFT, 0x00000001 },
+ { AUD_IIR3_2_SHIFT, 0x00000001 },
+ { AUD_DEEMPH0_SRC_SEL, 0x00000014 },
+ { AUD_CORDIC_SHIFT_1, 0x00000006 },
+ { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
+ { AUD_DMD_RA_DDS, 0x00f696e6 },
+ { AUD_IIR2_3_SEL, 0x00000025 },
+ { AUD_IIR1_4_SEL, 0x00000021 },
+ { AUD_DN1_FREQ, 0x0000c965 },
+ { AUD_DCOC_PASS_IN, 0x00000003 },
+ { AUD_DCOC_0_SRC, 0x0000001a },
+ { AUD_DCOC_1_SRC, 0x0000001b },
+ { AUD_DCOC1_SHIFT, 0x00000000 },
+ { AUD_RDSI_SEL, 0x00000009 },
+ { AUD_RDSQ_SEL, 0x00000009 },
+ { AUD_RDSI_SHIFT, 0x00000000 },
+ { AUD_RDSQ_SHIFT, 0x00000000 },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { /* end of list */ },
+ };
+
+ // dscaler: exactly taken from driver,
+ // dscaler: don't know why to set EN_FMRADIO_EN_RDS
+ if (sap) {
+ dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
+ set_audio_start(dev, 0x0001,
+ EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
+ set_audio_registers(dev, btsc_sap);
+ } else {
+ dprintk("%s (status: known-good)\n",__FUNCTION__);
+ set_audio_start(dev, 0x0001,
+ EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
+ set_audio_registers(dev, btsc);
+ }
set_audio_finish(dev);
}
static void set_audio_standard_NICAM(struct cx8800_dev *dev)
{
- static const struct rlist nicam[] = {
+ static const struct rlist nicam_common[] = {
+ /* from dscaler */
{ AUD_RATE_ADJ1, 0x00000010 },
{ AUD_RATE_ADJ2, 0x00000040 },
{ AUD_RATE_ADJ3, 0x00000100 },
@@ -152,21 +270,64 @@ static void set_audio_standard_NICAM(str
{ AUD_RATE_ADJ5, 0x00001000 },
// { AUD_DMD_RA_DDS, 0x00c0d5ce },
+ // Deemphasis 1:
+ { AUD_DEEMPHGAIN_R, 0x000023c2 },
+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
+ { AUD_DEEMPHNUMER2_R, 0x0003023e },
+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+
+#if 0
+ // Deemphasis 2: (other tv norm?)
+ { AUD_DEEMPHGAIN_R, 0x0000c600 },
+ { AUD_DEEMPHNUMER1_R, 0x00066738 },
+ { AUD_DEEMPHNUMER2_R, 0x00066739 },
+ { AUD_DEEMPHDENOM1_R, 0x0001e88c },
+ { AUD_DEEMPHDENOM2_R, 0x0001e88c },
+#endif
+
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000fff },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+
// setup QAM registers
{ AUD_PDF_DDS_CNST_BYTE2, 0x06 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x82 },
{ AUD_PDF_DDS_CNST_BYTE0, 0x16 },
{ AUD_QAM_MODE, 0x05 },
+
+ { /* end of list */ },
+ };
+ static const struct rlist nicam_pal_i[] = {
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x93 },
+
+ { /* end of list */ },
+ };
+ static const struct rlist nicam_default[] = {
+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
{ AUD_PHACC_FREQ_8MSB, 0x34 },
{ AUD_PHACC_FREQ_8LSB, 0x4c },
{ /* end of list */ },
- };
+ };
- dprintk("%s (status: unknown)\n",__FUNCTION__);
set_audio_start(dev, 0x0010,
- EN_DMTRX_LR | EN_NICAM_FORCE_STEREO);
- set_audio_registers(dev, nicam);
+ EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ set_audio_registers(dev, nicam_common);
+ switch (dev->tvaudio) {
+ case WW_NICAM_I:
+ dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__);
+ set_audio_registers(dev, nicam_pal_i);
+ case WW_NICAM_BGDKL:
+ dprintk("%s PAL NICAM (status: unknown)\n",__FUNCTION__);
+ set_audio_registers(dev, nicam_default);
+ break;
+ };
set_audio_finish(dev);
}
@@ -185,104 +346,104 @@ static void set_audio_standard_NICAM_L(s
{ AUD_PHACC_FREQ_8LSB, 0x4a },
{ AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_IIR1_0_SEL, 0x00000000 },
- { AUD_IIR1_1_SEL, 0x00000002 },
- { AUD_IIR1_2_SEL, 0x00000023 },
- { AUD_IIR1_3_SEL, 0x00000004 },
- { AUD_IIR1_4_SEL, 0x00000005 },
- { AUD_IIR1_5_SEL, 0x00000007 },
- { AUD_IIR1_0_SHIFT, 0x00000007 },
- { AUD_IIR1_1_SHIFT, 0x00000000 },
- { AUD_IIR1_2_SHIFT, 0x00000000 },
- { AUD_IIR1_3_SHIFT, 0x00000007 },
- { AUD_IIR1_4_SHIFT, 0x00000007 },
- { AUD_IIR1_5_SHIFT, 0x00000007 },
- { AUD_IIR2_0_SEL, 0x00000002 },
+ { AUD_IIR1_0_SEL, 0x00000000 },
+ { AUD_IIR1_1_SEL, 0x00000002 },
+ { AUD_IIR1_2_SEL, 0x00000023 },
+ { AUD_IIR1_3_SEL, 0x00000004 },
+ { AUD_IIR1_4_SEL, 0x00000005 },
+ { AUD_IIR1_5_SEL, 0x00000007 },
+ { AUD_IIR1_0_SHIFT, 0x00000007 },
+ { AUD_IIR1_1_SHIFT, 0x00000000 },
+ { AUD_IIR1_2_SHIFT, 0x00000000 },
+ { AUD_IIR1_3_SHIFT, 0x00000007 },
+ { AUD_IIR1_4_SHIFT, 0x00000007 },
+ { AUD_IIR1_5_SHIFT, 0x00000007 },
+ { AUD_IIR2_0_SEL, 0x00000002 },
{ AUD_IIR2_1_SEL, 0x00000003 },
{ AUD_IIR2_2_SEL, 0x00000004 },
- { AUD_IIR2_3_SEL, 0x00000005 },
- { AUD_IIR3_0_SEL, 0x00000007 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_IIR3_2_SEL, 0x00000016 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000000 },
- { AUD_IIR3_2_SHIFT, 0x00000002 },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_IIR4_1_SEL, 0x00000019 },
- { AUD_IIR4_2_SEL, 0x00000008 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000007 },
- { AUD_IIR4_2_SHIFT, 0x00000007 },
- { AUD_IIR4_0_CA0, 0x0003e57e },
- { AUD_IIR4_0_CA1, 0x00005e11 },
- { AUD_IIR4_0_CA2, 0x0003a7cf },
- { AUD_IIR4_0_CB0, 0x00002368 },
- { AUD_IIR4_0_CB1, 0x0003bf1b },
- { AUD_IIR4_1_CA0, 0x00006349 },
- { AUD_IIR4_1_CA1, 0x00006f27 },
- { AUD_IIR4_1_CA2, 0x0000e7a3 },
+ { AUD_IIR2_3_SEL, 0x00000005 },
+ { AUD_IIR3_0_SEL, 0x00000007 },
+ { AUD_IIR3_1_SEL, 0x00000023 },
+ { AUD_IIR3_2_SEL, 0x00000016 },
+ { AUD_IIR4_0_SHIFT, 0x00000000 },
+ { AUD_IIR4_1_SHIFT, 0x00000000 },
+ { AUD_IIR3_2_SHIFT, 0x00000002 },
+ { AUD_IIR4_0_SEL, 0x0000001d },
+ { AUD_IIR4_1_SEL, 0x00000019 },
+ { AUD_IIR4_2_SEL, 0x00000008 },
+ { AUD_IIR4_0_SHIFT, 0x00000000 },
+ { AUD_IIR4_1_SHIFT, 0x00000007 },
+ { AUD_IIR4_2_SHIFT, 0x00000007 },
+ { AUD_IIR4_0_CA0, 0x0003e57e },
+ { AUD_IIR4_0_CA1, 0x00005e11 },
+ { AUD_IIR4_0_CA2, 0x0003a7cf },
+ { AUD_IIR4_0_CB0, 0x00002368 },
+ { AUD_IIR4_0_CB1, 0x0003bf1b },
+ { AUD_IIR4_1_CA0, 0x00006349 },
+ { AUD_IIR4_1_CA1, 0x00006f27 },
+ { AUD_IIR4_1_CA2, 0x0000e7a3 },
{ AUD_IIR4_1_CB0, 0x00005653 },
- { AUD_IIR4_1_CB1, 0x0000cf97 },
- { AUD_IIR4_2_CA0, 0x00006349 },
- { AUD_IIR4_2_CA1, 0x00006f27 },
- { AUD_IIR4_2_CA2, 0x0000e7a3 },
- { AUD_IIR4_2_CB0, 0x00005653 },
- { AUD_IIR4_2_CB1, 0x0000cf97 },
- { AUD_HP_MD_IIR4_1, 0x00000001 },
- { AUD_HP_PROG_IIR4_1, 0x0000001a },
+ { AUD_IIR4_1_CB1, 0x0000cf97 },
+ { AUD_IIR4_2_CA0, 0x00006349 },
+ { AUD_IIR4_2_CA1, 0x00006f27 },
+ { AUD_IIR4_2_CA2, 0x0000e7a3 },
+ { AUD_IIR4_2_CB0, 0x00005653 },
+ { AUD_IIR4_2_CB1, 0x0000cf97 },
+ { AUD_HP_MD_IIR4_1, 0x00000001 },
+ { AUD_HP_PROG_IIR4_1, 0x0000001a },
{ AUD_DN0_FREQ, 0x00000000 },
- { AUD_DN1_FREQ, 0x00003318 },
- { AUD_DN1_SRC_SEL, 0x00000017 },
- { AUD_DN1_SHFT, 0x00000007 },
- { AUD_DN1_AFC, 0x00000000 },
- { AUD_DN1_FREQ_SHIFT, 0x00000000 },
- { AUD_DN2_FREQ, 0x00003551 },
- { AUD_DN2_SRC_SEL, 0x00000001 },
- { AUD_DN2_SHFT, 0x00000000 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DN2_FREQ_SHIFT, 0x00000000 },
- { AUD_PDET_SRC, 0x00000014 },
- { AUD_PDET_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH1_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH0_SHIFT, 0x00000000 },
- { AUD_DEEMPH1_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_G0, 0x00007000 },
- { AUD_DEEMPH0_A0, 0x00000000 },
- { AUD_DEEMPH0_B0, 0x00000000 },
- { AUD_DEEMPH0_A1, 0x00000000 },
- { AUD_DEEMPH0_B1, 0x00000000 },
- { AUD_DEEMPH1_G0, 0x00007000 },
- { AUD_DEEMPH1_A0, 0x00000000 },
- { AUD_DEEMPH1_B0, 0x00000000 },
- { AUD_DEEMPH1_A1, 0x00000000 },
- { AUD_DEEMPH1_B1, 0x00000000 },
- { AUD_DMD_RA_DDS, 0x00f5c285 },
- { AUD_RATE_ADJ1, 0x00000100 },
- { AUD_RATE_ADJ2, 0x00000200 },
- { AUD_RATE_ADJ3, 0x00000300 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00000500 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C2_LO_THR, 0x00005400 },
- { AUD_CTL, 0x0000100c },
- { AUD_DCOC_0_SRC, 0x00000021 },
- { AUD_DCOC_1_SRC, 0x00000003 },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000000 },
- { AUD_DCOC_2_SRC, 0x0000001b },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_PHASE_FIX_CTL, 0x00000000 },
+ { AUD_DN1_FREQ, 0x00003318 },
+ { AUD_DN1_SRC_SEL, 0x00000017 },
+ { AUD_DN1_SHFT, 0x00000007 },
+ { AUD_DN1_AFC, 0x00000000 },
+ { AUD_DN1_FREQ_SHIFT, 0x00000000 },
+ { AUD_DN2_FREQ, 0x00003551 },
+ { AUD_DN2_SRC_SEL, 0x00000001 },
+ { AUD_DN2_SHFT, 0x00000000 },
+ { AUD_DN2_AFC, 0x00000002 },
+ { AUD_DN2_FREQ_SHIFT, 0x00000000 },
+ { AUD_PDET_SRC, 0x00000014 },
+ { AUD_PDET_SHIFT, 0x00000000 },
+ { AUD_DEEMPH0_SRC_SEL, 0x00000011 },
+ { AUD_DEEMPH1_SRC_SEL, 0x00000011 },
+ { AUD_DEEMPH0_SHIFT, 0x00000000 },
+ { AUD_DEEMPH1_SHIFT, 0x00000000 },
+ { AUD_DEEMPH0_G0, 0x00007000 },
+ { AUD_DEEMPH0_A0, 0x00000000 },
+ { AUD_DEEMPH0_B0, 0x00000000 },
+ { AUD_DEEMPH0_A1, 0x00000000 },
+ { AUD_DEEMPH0_B1, 0x00000000 },
+ { AUD_DEEMPH1_G0, 0x00007000 },
+ { AUD_DEEMPH1_A0, 0x00000000 },
+ { AUD_DEEMPH1_B0, 0x00000000 },
+ { AUD_DEEMPH1_A1, 0x00000000 },
+ { AUD_DEEMPH1_B1, 0x00000000 },
+ { AUD_DMD_RA_DDS, 0x00f5c285 },
+ { AUD_RATE_ADJ1, 0x00000100 },
+ { AUD_RATE_ADJ2, 0x00000200 },
+ { AUD_RATE_ADJ3, 0x00000300 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00000500 },
+ { AUD_C2_UP_THR, 0x00005400 },
+ { AUD_C2_LO_THR, 0x00003000 },
+ { AUD_C1_UP_THR, 0x00007000 },
+ { AUD_C2_LO_THR, 0x00005400 },
+ { AUD_CTL, 0x0000100c },
+ { AUD_DCOC_0_SRC, 0x00000021 },
+ { AUD_DCOC_1_SRC, 0x00000003 },
+ { AUD_DCOC1_SHIFT, 0x00000000 },
+ { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
+ { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
+ { AUD_DCOC_PASS_IN, 0x00000000 },
+ { AUD_DCOC_2_SRC, 0x0000001b },
+ { AUD_IIR4_0_SEL, 0x0000001d },
+ { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
+ { AUD_PHASE_FIX_CTL, 0x00000000 },
{ AUD_CORDIC_SHIFT_1, 0x00000007 },
- { AUD_PLL_EN, 0x00000000 },
+ { AUD_PLL_EN, 0x00000000 },
{ AUD_PLL_PRESCALE, 0x00000002 },
- { AUD_PLL_INT, 0x0000001e },
- { AUD_OUT1_SHIFT, 0x00000000 },
+ { AUD_PLL_INT, 0x0000001e },
+ { AUD_OUT1_SHIFT, 0x00000000 },
{ /* end of list */ },
};
@@ -297,14 +458,14 @@ static void set_audio_standard_NICAM_L(s
static void set_audio_standard_A2(struct cx8800_dev *dev)
{
/* from dscaler cvs */
- static const struct rlist a2[] = {
+ static const struct rlist a2_common[] = {
{ AUD_PDF_DDS_CNST_BYTE2, 0x06 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x82 },
{ AUD_PDF_DDS_CNST_BYTE0, 0x12 },
{ AUD_QAM_MODE, 0x05 },
{ AUD_PHACC_FREQ_8MSB, 0x34 },
{ AUD_PHACC_FREQ_8LSB, 0x4c },
-
+
{ AUD_RATE_ADJ1, 0x00001000 },
{ AUD_RATE_ADJ2, 0x00002000 },
{ AUD_RATE_ADJ3, 0x00003000 },
@@ -347,16 +508,20 @@ static void set_audio_standard_A2(struct
{ AUD_RDSQ_SHIFT, 0x00000000 },
{ AUD_POLYPH80SCALEFAC, 0x00000001 },
- // Table 1
+ { /* end of list */ },
+ };
+
+ static const struct rlist a2_table1[] = {
+ // PAL-BG
{ AUD_DMD_RA_DDS, 0x002a73bd },
{ AUD_C1_UP_THR, 0x00007000 },
{ AUD_C1_LO_THR, 0x00005400 },
{ AUD_C2_UP_THR, 0x00005400 },
{ AUD_C2_LO_THR, 0x00003000 },
-
-#if 0
- // found this in WDM-driver for A2, must country spec.
- // Table 2
+ { /* end of list */ },
+ };
+ static const struct rlist a2_table2[] = {
+ // PAL-DK
{ AUD_DMD_RA_DDS, 0x002a73bd },
{ AUD_C1_UP_THR, 0x00007000 },
{ AUD_C1_LO_THR, 0x00005400 },
@@ -364,8 +529,10 @@ static void set_audio_standard_A2(struct
{ AUD_C2_LO_THR, 0x00003000 },
{ AUD_DN0_FREQ, 0x00003a1c },
{ AUD_DN2_FREQ, 0x0000d2e0 },
-
- // Table 3
+ { /* end of list */ },
+ };
+ static const struct rlist a2_table3[] = {
+ // unknown, probably NTSC-M
{ AUD_DMD_RA_DDS, 0x002a2873 },
{ AUD_C1_UP_THR, 0x00003c00 },
{ AUD_C1_LO_THR, 0x00003000 },
@@ -375,140 +542,26 @@ static void set_audio_standard_A2(struct
{ AUD_DN1_FREQ, 0x00003418 },
{ AUD_DN2_FREQ, 0x000029c7 },
{ AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
-#endif
-
{ /* end of list */ },
};
- static const struct rlist a2_old[] = {
- { AUD_DN0_FREQ, 0x0000312b },
- { AUD_POLY0_DDS_CONSTANT, 0x000a62b4 },
- { AUD_IIR1_0_SEL, 0x00000000 },
- { AUD_IIR1_1_SEL, 0x00000001 },
- { AUD_IIR1_2_SEL, 0x0000001f },
- { AUD_IIR1_3_SEL, 0x00000020 },
- { AUD_IIR1_4_SEL, 0x00000023 },
- { AUD_IIR1_5_SEL, 0x00000007 },
- { AUD_IIR1_0_SHIFT, 0x00000000 },
- { AUD_IIR1_1_SHIFT, 0x00000000 },
- { AUD_IIR1_2_SHIFT, 0x00000007 },
- { AUD_IIR1_3_SHIFT, 0x00000007 },
- { AUD_IIR1_4_SHIFT, 0x00000007 },
- { AUD_IIR1_5_SHIFT, 0x00000000 },
- { AUD_IIR2_0_SEL, 0x00000002 },
- { AUD_IIR2_1_SEL, 0x00000003 },
- { AUD_IIR2_2_SEL, 0x00000004 },
- { AUD_IIR2_3_SEL, 0x00000005 },
- { AUD_IIR3_0_SEL, 0x00000021 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_IIR3_2_SEL, 0x00000016 },
- { AUD_IIR3_0_SHIFT, 0x00000000 },
- { AUD_IIR3_1_SHIFT, 0x00000000 },
- { AUD_IIR3_2_SHIFT, 0x00000000 },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_IIR4_1_SEL, 0x00000019 },
- { AUD_IIR4_2_SEL, 0x00000008 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000000 },
- { AUD_IIR4_2_SHIFT, 0x00000001 },
- { AUD_IIR4_0_CA0, 0x0003e57e },
- { AUD_IIR4_0_CA1, 0x00005e11 },
- { AUD_IIR4_0_CA2, 0x0003a7cf },
- { AUD_IIR4_0_CB0, 0x00002368 },
- { AUD_IIR4_0_CB1, 0x0003bf1b },
- { AUD_IIR4_1_CA0, 0x00006349 },
- { AUD_IIR4_1_CA1, 0x00006f27 },
- { AUD_IIR4_1_CA2, 0x0000e7a3 },
- { AUD_IIR4_1_CB0, 0x00005653 },
- { AUD_IIR4_1_CB1, 0x0000cf97 },
- { AUD_IIR4_2_CA0, 0x00006349 },
- { AUD_IIR4_2_CA1, 0x00006f27 },
- { AUD_IIR4_2_CA2, 0x0000e7a3 },
- { AUD_IIR4_2_CB0, 0x00005653 },
- { AUD_IIR4_2_CB1, 0x0000cf97 },
- { AUD_HP_MD_IIR4_1, 0x00000001 },
- { AUD_HP_PROG_IIR4_1, 0x00000017 },
- { AUD_DN1_FREQ, 0x00003618 },
- { AUD_DN1_SRC_SEL, 0x00000017 },
- { AUD_DN1_SHFT, 0x00000007 },
- { AUD_DN1_AFC, 0x00000000 },
- { AUD_DN1_FREQ_SHIFT, 0x00000000 },
- { AUD_DN2_SRC_SEL, 0x00000040 },
- { AUD_DN2_SHFT, 0x00000000 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DN2_FREQ, 0x0000caaf },
- { AUD_DN2_FREQ_SHIFT, 0x00000000 },
- { AUD_PDET_SRC, 0x00000014 },
- { AUD_PDET_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH1_SRC_SEL, 0x00000013 },
- { AUD_DEEMPH0_SHIFT, 0x00000000 },
- { AUD_DEEMPH1_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_G0, 0x000004da },
- { AUD_DEEMPH0_A0, 0x0000777a },
- { AUD_DEEMPH0_B0, 0x00000000 },
- { AUD_DEEMPH0_A1, 0x0003f062 },
- { AUD_DEEMPH0_B1, 0x00000000 },
- { AUD_DEEMPH1_G0, 0x000004da },
- { AUD_DEEMPH1_A0, 0x0000777a },
- { AUD_DEEMPH1_B0, 0x00000000 },
- { AUD_DEEMPH1_A1, 0x0003f062 },
- { AUD_DEEMPH1_B1, 0x00000000 },
- { AUD_PLL_EN, 0x00000000 },
- { AUD_DMD_RA_DDS, 0x002a4efb },
- { AUD_RATE_ADJ1, 0x00001000 },
- { AUD_RATE_ADJ2, 0x00002000 },
- { AUD_RATE_ADJ3, 0x00003000 },
- { AUD_RATE_ADJ4, 0x00004000 },
- { AUD_RATE_ADJ5, 0x00005000 },
- { AUD_C2_UP_THR, 0x0000ffff },
- { AUD_C2_LO_THR, 0x0000e800 },
- { AUD_C1_UP_THR, 0x00008c00 },
- { AUD_C1_LO_THR, 0x00006c00 },
-
- // ; Completely ditch AFC feedback
- { AUD_DCOC_0_SRC, 0x00000021 },
- { AUD_DCOC_1_SRC, 0x0000001a },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000000 },
- { AUD_IIR4_0_SEL, 0x00000023 },
-
- // ; Completely ditc FM-2 AFC feedback
- { AUD_DN1_AFC, 0x00000000 },
- { AUD_DCOC_2_SRC, 0x0000001b },
- { AUD_IIR4_1_SEL, 0x00000025 },
-
- // ; WARNING!!! THIS CHANGE WAS NOT EXPECTED!!!
- // ; Swap I & Q inputs into second rotator
- // ; to reverse frequency and therefor invert
- // ; phase from the cordic FM demodulator
- // ; (frequency rotation must also be reversed
- { AUD_DN2_SRC_SEL, 0x00000001 },
- { AUD_DN2_FREQ, 0x00003551 },
-
- // setup Audio PLL
- { AUD_PLL_PRESCALE, 0x00000002 },
- { AUD_PLL_INT, 0x0000001f },
-
- { /* end of list */ },
+ set_audio_start(dev, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
+ set_audio_registers(dev, a2_common);
+ switch (dev->tvaudio) {
+ case WW_A2_BG:
+ dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
+ set_audio_registers(dev, a2_table1);
+ break;
+ case WW_A2_DK:
+ dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
+ set_audio_registers(dev, a2_table2);
+ break;
+ case WW_A2_M:
+ dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
+ set_audio_registers(dev, a2_table3);
+ break;
};
-
-
- dprintk("%s (status: WorksForMe[tm])\n",__FUNCTION__);
-
- if (0) {
- /* old code */
- set_audio_start(dev, 0x0004, EN_DMTRX_SUMR | EN_A2_AUTO_STEREO);
- set_audio_registers(dev, a2_old);
- set_audio_finish(dev);
- } else {
- /* new code */
- set_audio_start(dev, 0x0004, EN_DMTRX_LR | EN_A2_AUTO_STEREO);
- set_audio_registers(dev, a2);
- set_audio_finish(dev);
- }
+ set_audio_finish(dev);
}
static void set_audio_standard_EIAJ(struct cx8800_dev *dev)
@@ -617,9 +670,9 @@ void cx88_get_stereo(struct cx8800_dev *
reg = cx_read(AUD_STATUS);
mode = reg & 0x03;
pilot = (reg >> 2) & 0x03;
- dprintk("AUD_STATUS: %s / %s [status=0x%x,ctl=0x%x,vol=0x%x]\n",
- m[mode], p[pilot], reg,
- cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+ dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
+ reg, m[mode], p[pilot],
+ aud_ctl_names[cx_read(AUD_CTL) & 63]);
t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
@@ -628,6 +681,8 @@ void cx88_get_stereo(struct cx8800_dev *
switch (dev->tvaudio) {
case WW_A2_BG:
+ case WW_A2_DK:
+ case WW_A2_M:
if (1 == pilot) {
/* stereo */
t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
@@ -659,6 +714,8 @@ void cx88_set_stereo(struct cx8800_dev *
switch (dev->tvaudio) {
case WW_A2_BG:
+ case WW_A2_DK:
+ case WW_A2_M:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
@@ -717,6 +774,32 @@ void cx88_set_stereo(struct cx8800_dev *
return;
}
+/* just monitor the audio status for now ... */
+int cx88_audio_thread(void *data)
+{
+ struct cx8800_dev *dev = data;
+ struct v4l2_tuner t;
+
+ daemonize("msp3400");
+ allow_signal(SIGTERM);
+ dprintk("cx88: tvaudio thread started\n");
+
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ*3);
+ if (signal_pending(current))
+ break;
+ if (dev->shutdown)
+ break;
+
+ memset(&t,0,sizeof(t));
+ cx88_get_stereo(dev,&t);
+ }
+
+ dprintk("cx88: tvaudio thread exiting\n");
+ complete_and_exit(&dev->texit, 0);
+}
+
/*
* Local variables:
* c-basic-offset: 8
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-vbi.c linux/drivers/media/video/cx88/cx88-vbi.c
--- linux-2.6.7/drivers/media/video/cx88/cx88-vbi.c 2004-06-17 10:28:57.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-vbi.c 2004-06-17 13:47:59.797270159 +0200
@@ -28,17 +28,14 @@ void cx8800_vbi_fmt(struct cx8800_dev *d
f->fmt.vbi.count[0] = VBI_LINE_COUNT;
f->fmt.vbi.count[1] = VBI_LINE_COUNT;
- switch (dev->tvnorm->id) {
- case V4L2_STD_NTSC_M:
- case V4L2_STD_NTSC_M_JP:
+ if (dev->tvnorm->id & V4L2_STD_525_60) {
+ /* ntsc */
f->fmt.vbi.sampling_rate = 28636363;
f->fmt.vbi.start[0] = 10 -1;
f->fmt.vbi.start[1] = 273 -1;
- break;
- case V4L2_STD_PAL_BG:
- case V4L2_STD_PAL_DK:
- case V4L2_STD_PAL_I:
- case V4L2_STD_SECAM:
+
+ } else if (V4L2_STD_625_50) {
+ /* pal */
f->fmt.vbi.sampling_rate = 35468950;
f->fmt.vbi.start[0] = 7 -1;
f->fmt.vbi.start[1] = 319 -1;
@@ -64,10 +61,10 @@ int cx8800_start_vbi_dma(struct cx8800_d
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc01);
cx_set(MO_VID_INTMSK, 0x0f0088);
-
+
/* enable capture */
cx_set(VID_CAPTURE_CONTROL,0x18);
-
+
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
cx_set(MO_VID_DMACNTRL, 0x88);
@@ -80,7 +77,7 @@ int cx8800_restart_vbi_queue(struct cx88
{
struct cx88_buffer *buf;
struct list_head *item;
-
+
if (list_empty(&q->active))
return 0;
@@ -104,7 +101,7 @@ void cx8800_vbi_timeout(unsigned long da
unsigned long flags;
cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH24]);
-
+
cx_clear(MO_VID_DMACNTRL, 0x88);
cx_clear(VID_CAPTURE_CONTROL, 0x18);
@@ -161,7 +158,7 @@ vbi_prepare(struct file *file, struct vi
cx88_risc_buffer(dev->pci, &buf->risc,
buf->vb.dma.sglist,
0, buf->vb.width * buf->vb.height,
- buf->vb.width, 0,
+ buf->vb.width, 0,
buf->vb.height);
}
buf->vb.state = STATE_PREPARED;
diff -up linux-2.6.7/drivers/media/video/cx88/cx88-video.c linux/drivers/media/video/cx88/cx88-video.c
--- linux-2.6.7/drivers/media/video/cx88/cx88-video.c 2004-06-17 10:29:27.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88-video.c 2004-06-17 13:47:59.805268654 +0200
@@ -2,7 +2,7 @@
* device driver for Conexant 2388x based TV cards
* video4linux video interface
*
- * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* 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
@@ -19,8 +19,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define __NO_VERSION__ 1
-
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -32,6 +30,8 @@
#include "cx88.h"
+#define V4L2_I2C_CLIENTS 1
+
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
@@ -194,8 +194,13 @@ static struct cx8800_tvnorm tvnorms[] =
.cxiformat = VideoFormatPAL60,
.cxoformat = 0x181f0008,
},{
- .name = "SECAM",
- .id = V4L2_STD_SECAM,
+ .name = "SECAM-L",
+ .id = V4L2_STD_SECAM_L,
+ .cxiformat = VideoFormatSECAM,
+ .cxoformat = 0x181f0008,
+ },{
+ .name = "SECAM-DK",
+ .id = V4L2_STD_SECAM_DK,
.cxiformat = VideoFormatSECAM,
.cxoformat = 0x181f0008,
}
@@ -331,7 +336,7 @@ static struct cx88_ctrl cx8800_ctls[] =
*/
.v = {
.id = V4L2_CID_SATURATION,
- .name = "Saturation",
+ .name = "Saturation",
.minimum = 0,
.maximum = 0xff,
.step = 1,
@@ -483,35 +488,38 @@ static int set_tvaudio(struct cx8800_dev
if (CX88_VMUX_TELEVISION != INPUT(dev->input)->type)
return 0;
- switch (dev->tvnorm->id) {
- case V4L2_STD_PAL_BG:
+ if (V4L2_STD_PAL_BG & dev->tvnorm->id) {
dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_BG;
- break;
- case V4L2_STD_PAL_DK:
+
+ } else if (V4L2_STD_PAL_DK & dev->tvnorm->id) {
dev->tvaudio = nicam ? WW_NICAM_BGDKL : WW_A2_DK;
- break;
- case V4L2_STD_PAL_I:
+
+ } else if (V4L2_STD_PAL_I & dev->tvnorm->id) {
dev->tvaudio = WW_NICAM_I;
- break;
- case V4L2_STD_SECAM:
- dev->tvaudio = WW_SYSTEM_L_AM; /* FIXME: fr != ru */
- break;
- case V4L2_STD_NTSC_M:
+
+ } else if (V4L2_STD_SECAM_L & dev->tvnorm->id) {
+ dev->tvaudio = WW_SYSTEM_L_AM;
+
+ } else if (V4L2_STD_SECAM_DK & dev->tvnorm->id) {
+ dev->tvaudio = WW_A2_DK;
+
+ } else if ((V4L2_STD_NTSC_M & dev->tvnorm->id) ||
+ (V4L2_STD_PAL_M & dev->tvnorm->id)) {
dev->tvaudio = WW_BTSC;
- break;
- case V4L2_STD_NTSC_M_JP:
+
+ } else if (V4L2_STD_NTSC_M_JP & dev->tvnorm->id) {
dev->tvaudio = WW_EIAJ;
- break;
- default:
- dprintk(1,"tvaudio support needs work for this tv norm [%s], sorry\n",
- dev->tvnorm->name);
+
+ } else {
+ printk("%s: tvaudio support needs work for this tv norm [%s], sorry\n",
+ dev->name, dev->tvnorm->name);
dev->tvaudio = 0;
return 0;
}
cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
cx88_set_tvaudio(dev);
- cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
+ // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */
cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */
@@ -526,7 +534,6 @@ static int set_tvnorm(struct cx8800_dev
u32 vdec_clock;
u64 tmp64;
u32 bdelay,agcdelay,htotal;
- struct video_channel c;
dev->tvnorm = norm;
fsc8 = norm_fsc8(norm);
@@ -592,30 +599,43 @@ static int set_tvnorm(struct cx8800_dev
set_tvaudio(dev);
// tell i2c chips
- memset(&c,0,sizeof(c));
- c.channel = dev->input;
- c.norm = VIDEO_MODE_PAL;
- if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
- c.norm = VIDEO_MODE_NTSC;
- if (norm->id & V4L2_STD_SECAM)
- c.norm = VIDEO_MODE_SECAM;
- cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c);
+#ifdef V4L2_I2C_CLIENTS
+ cx8800_call_i2c_clients(dev,VIDIOC_S_STD,&norm->id);
+#else
+ {
+ struct video_channel c;
+ memset(&c,0,sizeof(c));
+ c.channel = dev->input;
+ c.norm = VIDEO_MODE_PAL;
+ if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
+ c.norm = VIDEO_MODE_NTSC;
+ if (norm->id & V4L2_STD_SECAM)
+ c.norm = VIDEO_MODE_SECAM;
+ cx8800_call_i2c_clients(dev,VIDIOCSCHAN,&c);
+ }
+#endif
// done
return 0;
}
static int set_scale(struct cx8800_dev *dev, unsigned int width, unsigned int height,
- int interlaced)
+ enum v4l2_field field)
{
unsigned int swidth = norm_swidth(dev->tvnorm);
unsigned int sheight = norm_maxh(dev->tvnorm);
u32 value;
- dprintk(1,"set_scale: %dx%d [%s]\n", width, height, dev->tvnorm->name);
+ dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
+ V4L2_FIELD_HAS_TOP(field) ? "T" : "",
+ V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
+ dev->tvnorm->name);
+ if (!V4L2_FIELD_HAS_BOTH(field))
+ height *= 2;
// recalc H delay and scale registers
value = (width * norm_hdelay(dev->tvnorm)) / swidth;
+ value &= 0x3fe;
cx_write(MO_HDELAY_EVEN, value);
cx_write(MO_HDELAY_ODD, value);
dprintk(1,"set_scale: hdelay 0x%04x\n", value);
@@ -646,7 +666,7 @@ static int set_scale(struct cx8800_dev *
// setup filters
value = 0;
value |= (1 << 19); // CFILT (default)
- if (interlaced)
+ if (V4L2_FIELD_INTERLACED == field)
value |= (1 << 3); // VINT (interlaced vertical scaling)
if (width < 385)
value |= (1 << 0); // 3-tap interpolation
@@ -675,10 +695,12 @@ static int video_mux(struct cx8800_dev *
switch (INPUT(input)->type) {
case CX88_VMUX_SVIDEO:
- cx_andor(MO_AFECFG_IO, 0x01, 0x01);
+ cx_set(MO_AFECFG_IO, 0x00000001);
+ cx_set(MO_INPUT_FORMAT, 0x00010010);
break;
default:
- cx_andor(MO_AFECFG_IO, 0x01, 0x00);
+ cx_clear(MO_AFECFG_IO, 0x00000001);
+ cx_clear(MO_INPUT_FORMAT, 0x00010010);
break;
}
return 0;
@@ -693,7 +715,7 @@ static int start_video_dma(struct cx8800
/* setup fifo + format */
cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- set_scale(dev, buf->vb.width, buf->vb.height, 1);
+ set_scale(dev, buf->vb.width, buf->vb.height, buf->vb.field);
cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
/* reset counter */
@@ -1350,6 +1372,9 @@ static int get_control(struct cx8800_dev
case V4L2_CID_AUDIO_BALANCE:
ctl->value = (value & 0x40) ? (value & 0x3f) : (0x40 - (value & 0x3f));
break;
+ case V4L2_CID_AUDIO_VOLUME:
+ ctl->value = 0x3f - (value & 0x3f);
+ break;
default:
ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
break;
@@ -1378,6 +1403,9 @@ static int set_control(struct cx8800_dev
case V4L2_CID_AUDIO_BALANCE:
value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
break;
+ case V4L2_CID_AUDIO_VOLUME:
+ value = 0x3f - (ctl->value & 0x3f);
+ break;
case V4L2_CID_SATURATION:
/* special v_sat handling */
v_sat_value = ctl->value - (0x7f - 0x5a);
@@ -1409,7 +1437,7 @@ static void init_controls(struct cx8800_
};
static struct v4l2_control volume = {
.id = V4L2_CID_AUDIO_VOLUME,
- .value = 0,
+ .value = 0x3f,
};
set_control(dev,&mute);
@@ -1459,15 +1487,12 @@ static int cx8800_try_fmt(struct cx8800_
maxw = norm_maxw(dev->tvnorm);
maxh = norm_maxh(dev->tvnorm);
-#if 0
if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2)
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM;
}
-#else
- field = V4L2_FIELD_INTERLACED;
-#endif
+
switch (field) {
case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM:
@@ -1480,14 +1505,15 @@ static int cx8800_try_fmt(struct cx8800_
}
f->fmt.pix.field = field;
- if (f->fmt.pix.width < 48)
- f->fmt.pix.width = 48;
if (f->fmt.pix.height < 32)
f->fmt.pix.height = 32;
- if (f->fmt.pix.width > maxw)
- f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh)
f->fmt.pix.height = maxh;
+ if (f->fmt.pix.width < 48)
+ f->fmt.pix.width = 48;
+ if (f->fmt.pix.width > maxw)
+ f->fmt.pix.width = maxw;
+ f->fmt.pix.width &= ~0x03;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
@@ -1783,7 +1809,11 @@ static int video_do_ioctl(struct inode *
return -EINVAL;
down(&dev->lock);
dev->freq = f->frequency;
+#ifdef V4L2_I2C_CLIENTS
+ cx8800_call_i2c_clients(dev,VIDIOC_S_FREQUENCY,f);
+#else
cx8800_call_i2c_clients(dev,VIDIOCSFREQ,&dev->freq);
+#endif
up(&dev->lock);
return 0;
}
@@ -1836,7 +1866,7 @@ static int video_do_ioctl(struct inode *
case VIDIOC_STREAMOFF:
{
int res = get_ressource(fh);
-
+
err = videobuf_streamoff(file, get_queue(fh));
if (err < 0)
return err;
@@ -1885,7 +1915,6 @@ static int radio_do_ioctl(struct inode *
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
- struct video_tuner vt;
if (t->index > 0)
return -EINVAL;
@@ -1895,9 +1924,16 @@ static int radio_do_ioctl(struct inode *
t->rangelow = (int)(65*16);
t->rangehigh = (int)(108*16);
- memset(&vt,0,sizeof(vt));
- cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
- t->signal = vt.signal;
+#ifdef V4L2_I2C_CLIENTS
+ cx8800_call_i2c_clients(dev,VIDIOC_G_TUNER,t);
+#else
+ {
+ struct video_tuner vt;
+ memset(&vt,0,sizeof(vt));
+ cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
+ t->signal = vt.signal;
+ }
+#endif
return 0;
}
case VIDIOC_ENUMINPUT:
@@ -2281,11 +2317,6 @@ static void cx8800_unregister_video(stru
}
}
-/* debug that damn oops ... */
-static unsigned int oops = 0;
-MODULE_PARM(oops,"i");
-#define OOPS(msg) if (oops) printk("%s: %s\n",__FUNCTION__,msg);
-
static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
@@ -2299,7 +2330,6 @@ static int __devinit cx8800_initdev(stru
memset(dev,0,sizeof(*dev));
/* pci init */
- OOPS("pci init");
dev->pci = pci_dev;
if (pci_enable_device(pci_dev)) {
err = -EIO;
@@ -2308,7 +2338,6 @@ static int __devinit cx8800_initdev(stru
sprintf(dev->name,"cx%x[%d]",pci_dev->device,cx8800_devcount);
/* pci quirks */
- OOPS("pci quirks");
cx88_pci_quirks(dev->name, dev->pci, &latency);
if (UNSET != latency) {
printk(KERN_INFO "%s: setting pci latency timer to %d\n",
@@ -2317,7 +2346,6 @@ static int __devinit cx8800_initdev(stru
}
/* print pci info */
- OOPS("pci info");
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
@@ -2333,14 +2361,15 @@ static int __devinit cx8800_initdev(stru
}
/* board config */
- OOPS("board config");
dev->board = card[cx8800_devcount];
for (i = 0; UNSET == dev->board && i < cx88_idcount; i++)
if (pci_dev->subsystem_vendor == cx88_subids[i].subvendor &&
pci_dev->subsystem_device == cx88_subids[i].subdevice)
dev->board = cx88_subids[i].card;
- if (UNSET == dev->board)
+ if (UNSET == dev->board) {
dev->board = CX88_BOARD_UNKNOWN;
+ cx88_card_list(dev);
+ }
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor,
pci_dev->subsystem_device,cx88_boards[dev->board].name,
@@ -2352,7 +2381,6 @@ static int __devinit cx8800_initdev(stru
dev->tuner_type = cx88_boards[dev->board].tuner_type;
/* get mmio */
- OOPS("get mmio");
if (!request_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0),
dev->name)) {
@@ -2366,7 +2394,6 @@ static int __devinit cx8800_initdev(stru
dev->bmmio = (u8*)dev->lmmio;
/* initialize driver struct */
- OOPS("init structs");
init_MUTEX(&dev->lock);
dev->slock = SPIN_LOCK_UNLOCKED;
dev->tvnorm = tvnorms;
@@ -2390,11 +2417,9 @@ static int __devinit cx8800_initdev(stru
MO_VID_DMACNTRL,0x88,0x00);
/* initialize hardware */
- OOPS("reset hardware");
cx8800_reset(dev);
/* get irq */
- OOPS("install irq handler");
err = request_irq(pci_dev->irq, cx8800_irq,
SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
if (err < 0) {
@@ -2404,13 +2429,10 @@ static int __devinit cx8800_initdev(stru
}
/* register i2c bus + load i2c helpers */
- OOPS("i2c setup");
cx8800_i2c_init(dev);
- OOPS("card setup");
cx88_card_setup(dev);
/* load and configure helper modules */
- OOPS("configure i2c clients");
if (TUNER_ABSENT != dev->tuner_type)
request_module("tuner");
if (cx88_boards[dev->board].needs_tda9887)
@@ -2419,7 +2441,6 @@ static int __devinit cx8800_initdev(stru
cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type);
/* register v4l devices */
- OOPS("register video");
dev->video_dev = vdev_init(dev,&cx8800_video_template,"video");
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[cx8800_devcount]);
@@ -2431,7 +2452,6 @@ static int __devinit cx8800_initdev(stru
printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
dev->name,dev->video_dev->minor & 0x1f);
- OOPS("register vbi");
dev->vbi_dev = vdev_init(dev,&cx8800_vbi_template,"vbi");
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[cx8800_devcount]);
@@ -2444,7 +2464,6 @@ static int __devinit cx8800_initdev(stru
dev->name,dev->vbi_dev->minor & 0x1f);
if (dev->has_radio) {
- OOPS("register radio");
dev->radio_dev = vdev_init(dev,&cx8800_radio_template,"radio");
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[cx8800_devcount]);
@@ -2458,32 +2477,31 @@ static int __devinit cx8800_initdev(stru
}
/* everything worked */
- OOPS("finalize");
list_add_tail(&dev->devlist,&cx8800_devlist);
pci_set_drvdata(pci_dev,dev);
cx8800_devcount++;
/* initial device configuration */
- OOPS("init device");
down(&dev->lock);
init_controls(dev);
set_tvnorm(dev,tvnorms);
video_mux(dev,0);
up(&dev->lock);
+
+ /* start tvaudio thread */
+ init_completion(&dev->texit);
+ dev->tpid = kernel_thread(cx88_audio_thread, dev, 0);
return 0;
fail3:
- OOPS("fail3");
cx8800_unregister_video(dev);
if (0 == dev->i2c_rc)
i2c_bit_del_bus(&dev->i2c_adap);
free_irq(pci_dev->irq, dev);
fail2:
- OOPS("fail2");
release_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0));
fail1:
- OOPS("fail1");
kfree(dev);
return err;
}
@@ -2492,6 +2510,11 @@ static void __devexit cx8800_finidev(str
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+ /* stop thread */
+ dev->shutdown = 1;
+ if (dev->tpid >= 0)
+ wait_for_completion(&dev->texit);
+
cx8800_shutdown(dev);
pci_disable_device(pci_dev);
diff -up linux-2.6.7/drivers/media/video/cx88/cx88.h linux/drivers/media/video/cx88/cx88.h
--- linux-2.6.7/drivers/media/video/cx88/cx88.h 2004-06-17 10:31:18.000000000 +0200
+++ linux/drivers/media/video/cx88/cx88.h 2004-06-17 13:47:59.807268278 +0200
@@ -32,7 +32,7 @@
#include "cx88-reg.h"
#include <linux/version.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0,0,3)
+#define CX88_VERSION_CODE KERNEL_VERSION(0,0,4)
#ifndef TRUE
# define TRUE (1==1)
@@ -114,17 +114,20 @@ extern struct sram_channel cx88_sram_cha
/* card configuration */
#define CX88_BOARD_NOAUTO UNSET
-#define CX88_BOARD_UNKNOWN 0
-#define CX88_BOARD_HAUPPAUGE 1
-#define CX88_BOARD_GDI 2
-#define CX88_BOARD_PIXELVIEW 3
-#define CX88_BOARD_ATI_WONDER_PRO 4
-#define CX88_BOARD_WINFAST2000XP 5
-#define CX88_BOARD_AVERTV_303 6
-#define CX88_BOARD_MSI_TVANYWHERE 7
-#define CX88_BOARD_WINFAST_DV2000 8
-#define CX88_BOARD_LEADTEK_PVR2000 9
-
+#define CX88_BOARD_UNKNOWN 0
+#define CX88_BOARD_HAUPPAUGE 1
+#define CX88_BOARD_GDI 2
+#define CX88_BOARD_PIXELVIEW 3
+#define CX88_BOARD_ATI_WONDER_PRO 4
+#define CX88_BOARD_WINFAST2000XP 5
+#define CX88_BOARD_AVERTV_303 6
+#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
+#define CX88_BOARD_WINFAST_DV2000 8
+#define CX88_BOARD_LEADTEK_PVR2000 9
+#define CX88_BOARD_IODATA_GVVCP3PCI 10
+#define CX88_BOARD_PROLINK_PLAYTVPVR 11
+#define CX88_BOARD_ASUS_PVR_416 12
+#define CX88_BOARD_MSI_TVANYWHERE 13
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -263,6 +266,9 @@ struct cx8800_dev {
/* other global state info */
u32 shadow[SHADOW_MAX];
+ int shutdown;
+ pid_t tpid;
+ struct completion texit;
struct cx8800_suspend_state state;
};
@@ -351,7 +357,8 @@ extern const unsigned int cx88_bcount;
extern struct cx88_subid cx88_subids[];
extern const unsigned int cx88_idcount;
-extern void __devinit cx88_card_setup(struct cx8800_dev *dev);
+extern void cx88_card_list(struct cx8800_dev *dev);
+extern void cx88_card_setup(struct cx8800_dev *dev);
/* ----------------------------------------------------------- */
/* cx88-tvaudio.c */
@@ -372,6 +379,7 @@ extern void __devinit cx88_card_setup(st
void cx88_set_tvaudio(struct cx8800_dev *dev);
void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t);
void cx88_set_stereo(struct cx8800_dev *dev, u32 mode);
+int cx88_audio_thread(void *data);
/*
* Local variables:
--
Smoking Crack Organization
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2005-03-08 11:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-08 11:00 [patch] v4l: cx88 driver update Gerd Knorr
-- strict thread matches above, loose matches on Subject: below --
2004-06-18 10:02 Gerd Knorr
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox