lists.zerezo.com
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH resend] Implement proper cx88 deactivation
Also includes full support for the Kworld PlusTV HD PCI 120 card,
pending a rework of the tuner core.
Signed-off-by: Daniel Gimpelevich <daniel@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
diff -r 78442352b885 linux/Documentation/video4linux/CARDLIST.cx88
--- a/linux/Documentation/video4linux/CARDLIST.cx88 Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/Documentation/video4linux/CARDLIST.cx88 Tue Jun 17 13:04:00 2008 -0700
@@ -60,7 +60,7 @@
59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530]
60 -> Pinnacle Hybrid PCTV [12ab:1788]
61 -> Winfast TV2000 XP Global [107d:6f18]
- 62 -> PowerColor RA330 [14f1:ea3d]
+ 62 -> PowerColor Real Angel 330 [14f1:ea3d]
63 -> Geniatech X8000-MT DVBT [14f1:8852]
64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30]
65 -> DViCO FusionHDTV 7 Gold [18ac:d610]
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-cards.c
--- a/linux/drivers/media/video/cx88/cx88-cards.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-cards.c Tue Jun 17 13:04:00 2008 -0700
@@ -55,8 +55,11 @@
MODULE_PARM_DESC(card,"card type");
static unsigned int latency = UNSET;
+static unsigned int tuner_debug;
module_param(latency,int,0444);
+module_param(tuner_debug, int, 0444);
MODULE_PARM_DESC(latency,"pci latency timer");
+MODULE_PARM_DESC(tuner_debug, "enable debug messages [tuner]");
#define info_printk(core, fmt, arg...) \
printk(KERN_INFO "%s: " fmt, core->name , ## arg)
@@ -66,6 +69,10 @@
#define err_printk(core, fmt, arg...) \
printk(KERN_ERR "%s: " fmt, core->name , ## arg)
+
+#define dprintk(core, fmt, arg...) do {\
+ if (tuner_debug)\
+ printk(KERN_DEBUG "%s: " fmt, core->name , ## arg); } while (0)
/* ------------------------------------------------------------------ */
@@ -1425,10 +1432,6 @@
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.input = {{
- .type = CX88_VMUX_DEBUG,
- .vmux = 3,
- .gpio0 = 0x04ff,
- },{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x07fa,
@@ -1437,6 +1440,10 @@
.vmux = 2,
.gpio0 = 0x07fa,
}},
+ .off = {
+ .type = CX88_OFF,
+ .gpio0 = 0x04ff,
+ },
},
[CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
.name = "Pinnacle PCTV HD 800i",
@@ -1547,35 +1554,39 @@
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
.input = { {
- .type = CX88_VMUX_DEBUG,
- .vmux = 3, /* Due to the way the cx88 driver is written, */
- .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */
- .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */
- .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */
- }, { /* from the tuner on boot for a little while. */
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x00ff,
- .gpio1 = 0xf35d,
- .gpio3 = 0x0000,
+ .gpio0 = 0x00ff,
+ .gpio1 = 0xf35d,
+ .gpio3 = 0x0000,
+ .audioroute = 1,
}, {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x00ff,
- .gpio1 = 0xf37d,
- .gpio3 = 0x0000,
+ .gpio0 = 0x00ff,
+ .gpio1 = 0xf37d,
+ .gpio3 = 0x0000,
+ .audioroute = 1,
}, {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x000ff,
.gpio1 = 0x0f37d,
.gpio3 = 0x00000,
+ .audioroute = 1,
} },
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x000ff,
.gpio1 = 0x0f35d,
.gpio3 = 0x00000,
+ .audioroute = 1,
+ },
+ .off = {
+ .type = CX88_OFF,
+ .gpio0 = 0x00ff,
+ .gpio1 = 0xf39d,
+ .gpio3 = 0x0000,
},
},
[CX88_BOARD_GENIATECH_X8000_MT] = {
@@ -1682,7 +1693,7 @@
tuner-xc3028 without doing an i2c probe.
*/
[CX88_BOARD_KWORLD_ATSC_120] = {
- .name = "Kworld PlusTV HD PCI 120 (ATSC 120)",
+ .name = "Kworld ATSC 120",
.tuner_type = TUNER_XC2028,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
@@ -1692,25 +1703,40 @@
.vmux = 0,
.gpio0 = 0x000000ff,
.gpio1 = 0x0000f35d,
- .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ .audioroute = 1,
}, {
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x000000ff,
.gpio1 = 0x0000f37e,
- .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ .audioroute = 1,
}, {
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x000000ff,
.gpio1 = 0x0000f37e,
- .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ .audioroute = 1,
+ }, {
+ .type = CX88_VMUX_DVB,
+ .gpio0 = 0x000000ff,
+ .gpio1 = 0x0000f39e,
+ .gpio3 = 0x00000000,
} },
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x000000ff,
.gpio1 = 0x0000f35d,
- .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ .audioroute = 1,
+ },
+ .off = {
+ .type = CX88_OFF,
+ .gpio0 = 0x000000ff,
+ .gpio1 = 0x0000f39e,
+ .gpio3 = 0x00000000,
},
.mpeg = CX88_MPEG_DVB,
},
@@ -2396,10 +2422,10 @@
switch (core->board.tuner_type) {
case TUNER_XC2028:
- info_printk(core, "Calling XC2028/3028 callback\n");
+ dprintk(core, "Calling XC2028/3028 callback\n");
return cx88_xc2028_tuner_callback(core, command, arg);
case TUNER_XC5000:
- info_printk(core, "Calling XC5000 callback\n");
+ dprintk(core, "Calling XC5000 callback\n");
return cx88_xc5000_tuner_callback(core, command, arg);
}
err_printk(core, "Error: Calling callback for tuner %d\n",
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-core.c
--- a/linux/drivers/media/video/cx88/cx88-core.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-core.c Tue Jun 17 13:04:00 2008 -0700
@@ -605,6 +605,9 @@
int cx88_reset(struct cx88_core *core)
{
dprintk(1,"%s\n",__func__);
+ core->i2c_algo.data = core;
+ if (core->board.tuner_type == TUNER_XC2028)
+ cx88_tuner_callback(&(core->i2c_algo), XC2028_TUNER_RESET, 0);
cx88_shutdown(core);
/* clear irq status */
@@ -854,10 +857,11 @@
{
v4l2_std_id norm = core->tvnorm;
- if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
+ if (CX88_VMUX_TELEVISION != INPUT(core->input).type) {
+ core->tvaudio = WW_NONE;
return 0;
- if (V4L2_STD_PAL_BG & norm) {
+ } else if (V4L2_STD_PAL_BG & norm) {
core->tvaudio = WW_BG;
} else if (V4L2_STD_PAL_DK & norm) {
@@ -882,7 +886,7 @@
} else {
printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
core->name, v4l2_norm_to_name(core->tvnorm));
- core->tvaudio = 0;
+ core->tvaudio = WW_NONE;
return 0;
}
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-input.c
--- a/linux/drivers/media/video/cx88/cx88-input.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-input.c Tue Jun 17 13:04:00 2008 -0700
@@ -336,6 +336,11 @@
ir->mask_keycode = 0x7e;
ir->polling = 100; /* ms */
break;
+ case CX88_BOARD_KWORLD_ATSC_120:
+ ir_codes = ir_codes_powercolor_real_angel;
+ ir_type = IR_TYPE_RC5;
+ ir->sampling = 1;
+ break;
}
if (NULL == ir_codes) {
@@ -445,9 +450,8 @@
ir_dump_samples(ir->samples, ir->scount);
/* decode it */
- switch (core->boardnr) {
- case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
- case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ switch (ir->ir.ir_type) {
+ case IR_TYPE_PD:
ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
if (ircode == 0xffffffff) { /* decoding error */
@@ -478,13 +482,7 @@
ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
ir->release = jiffies + msecs_to_jiffies(120);
break;
- case CX88_BOARD_HAUPPAUGE:
- case CX88_BOARD_HAUPPAUGE_DVB_T1:
- case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
- case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
- case CX88_BOARD_HAUPPAUGE_HVR1100:
- case CX88_BOARD_HAUPPAUGE_HVR3000:
- case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+ case IR_TYPE_RC5:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
if ((ircode & 0xfffff000) != 0x3000)
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-mpeg.c
--- a/linux/drivers/media/video/cx88/cx88-mpeg.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c Tue Jun 17 13:04:00 2008 -0700
@@ -665,13 +665,21 @@
static int cx8802_request_acquire(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
+ unsigned int input;
/* Fail a request for hardware if the device is busy. */
if (core->active_type_id != CX88_BOARD_NONE &&
core->active_type_id != drv->type_id)
return -EBUSY;
- core->input = CX88_VMUX_DVB;
+ for (input = 0; input < MAX_CX88_INPUT; input++)
+ if (INPUT(input).type == CX88_VMUX_DVB)
+ break;
+
+ if (input == MAX_CX88_INPUT)
+ return -EINVAL;
+
+ cx88_video_mux(core, input);
if (drv->advise_acquire)
{
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-tvaudio.c
--- a/linux/drivers/media/video/cx88/cx88-tvaudio.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-tvaudio.c Tue Jun 17 13:04:00 2008 -0700
@@ -774,6 +774,7 @@
set_audio_standard_FM(core, radio_deemphasis);
break;
case WW_NONE:
+ break;
default:
printk("%s/0: unknown tv audio mode [%d]\n",
core->name, core->tvaudio);
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88-video.c
--- a/linux/drivers/media/video/cx88/cx88-video.c Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-video.c Tue Jun 17 13:04:00 2008 -0700
@@ -418,25 +418,23 @@
INPUT(input).gpio0,INPUT(input).gpio1,
INPUT(input).gpio2,INPUT(input).gpio3);
core->input = input;
- cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
+ if (!(input & ~0xFF))
+ cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
cx_write(MO_GP3_IO, INPUT(input).gpio3);
cx_write(MO_GP0_IO, INPUT(input).gpio0);
cx_write(MO_GP1_IO, INPUT(input).gpio1);
cx_write(MO_GP2_IO, INPUT(input).gpio2);
- switch (INPUT(input).type) {
- case CX88_VMUX_SVIDEO:
+ if (INPUT(input).type == CX88_VMUX_SVIDEO) {
cx_set(MO_AFECFG_IO, 0x00000001);
cx_set(MO_INPUT_FORMAT, 0x00010010);
cx_set(MO_FILTER_EVEN, 0x00002020);
cx_set(MO_FILTER_ODD, 0x00002020);
- break;
- default:
+ } else {
cx_clear(MO_AFECFG_IO, 0x00000001);
cx_clear(MO_INPUT_FORMAT, 0x00010010);
cx_clear(MO_FILTER_EVEN, 0x00002020);
cx_clear(MO_FILTER_ODD, 0x00002020);
- break;
}
/* if there are audioroutes defined, we have an external
@@ -448,15 +446,17 @@
When used with S-Video, that ADC is busy dealing with
chroma, so an external must be used for baseband audio */
- if (INPUT(input).type != CX88_VMUX_TELEVISION &&
- INPUT(input).type != CX88_RADIO) {
+ switch (INPUT(input).type) {
+ case CX88_VMUX_TELEVISION:
+ case CX88_RADIO:
+ /* Normal mode */
+ cx_write(AUD_I2SCNTL, 0x0);
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ break;
+ default:
/* "ADC mode" */
cx_write(AUD_I2SCNTL, 0x1);
cx_set(AUD_CTL, EN_I2SIN_ENABLE);
- } else {
- /* Normal mode */
- cx_write(AUD_I2SCNTL, 0x0);
- cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
}
/* The wm8775 module has the "2" route hardwired into
@@ -1033,6 +1033,9 @@
core = dev->core;
+ if (radio?core->vinst:core->rinst)
+ return -EBUSY;
+
dprintk(1,"open minor=%d radio=%d type=%s\n",
minor,radio,v4l2_type_names[type]);
@@ -1061,17 +1064,16 @@
sizeof(struct cx88_buffer),
fh);
- if (fh->radio) {
+ if (radio) {
dprintk(1,"video_open: setting radio device\n");
- cx_write(MO_GP3_IO, core->board.radio.gpio3);
- cx_write(MO_GP0_IO, core->board.radio.gpio0);
- cx_write(MO_GP1_IO, core->board.radio.gpio1);
- cx_write(MO_GP2_IO, core->board.radio.gpio2);
+ core->rinst++;
+ cx88_video_mux(core, CX88_RADIO<<8);
core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
- }
+ } else
+ core->vinst++;
return 0;
}
@@ -1130,8 +1132,14 @@
static int video_release(struct inode *inode, struct file *file)
{
- struct cx8800_fh *fh = file->private_data;
- struct cx8800_dev *dev = fh->dev;
+ struct cx8800_fh *fh = file->private_data;
+ struct cx8800_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
+
+ if (fh->radio)
+ core->rinst--;
+ else
+ core->vinst--;
/* turn off overlay */
if (res_check(fh, RESOURCE_OVERLAY)) {
@@ -1159,6 +1167,12 @@
videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
+
+ if (core->vinst || core->rinst || core->input == CX88_RADIO<<8)
+ return 0;
+
+ if (core->board.off.type == CX88_OFF)
+ cx88_video_mux(core, CX88_OFF<<8);
cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
@@ -1507,7 +1521,7 @@
unsigned int n;
n = i->index;
- if (n >= 4)
+ if (n >= MAX_CX88_INPUT)
return -EINVAL;
if (0 == INPUT(n).type)
return -EINVAL;
@@ -1802,6 +1816,12 @@
return 0;
}
+static int radio_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
static int radio_s_input (struct file *file, void *fh, unsigned int i)
{
return 0;
@@ -1815,7 +1835,7 @@
if (c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1)
return -EINVAL;
- if (c->id == V4L2_CID_AUDIO_MUTE) {
+ if (c->id == V4L2_CID_AUDIO_MUTE || c->id == V4L2_CID_AUDIO_VOLUME) {
for (i = 0; i < CX8800_CTLS; i++)
if (cx8800_ctls[i].v.id == c->id)
break;
@@ -2036,6 +2056,7 @@
.vidioc_g_audio = radio_g_audio,
.vidioc_s_tuner = radio_s_tuner,
.vidioc_s_audio = radio_s_audio,
+ .vidioc_g_input = radio_g_input,
.vidioc_s_input = radio_s_input,
.vidioc_queryctrl = radio_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
@@ -2215,9 +2236,8 @@
/* initial device configuration */
mutex_lock(&core->lock);
- cx88_set_tvnorm(core,core->tvnorm);
init_controls(core);
- cx88_video_mux(core,0);
+ core->input = CX88_OFF<<8;
mutex_unlock(&core->lock);
/* start tvaudio thread */
diff -r 78442352b885 linux/drivers/media/video/cx88/cx88.h
--- a/linux/drivers/media/video/cx88/cx88.h Sun Jun 15 10:33:42 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88.h Tue Jun 17 13:04:00 2008 -0700
@@ -236,6 +236,7 @@
CX88_VMUX_DVB,
CX88_VMUX_DEBUG,
CX88_RADIO,
+ CX88_OFF,
};
struct cx88_input {
@@ -253,7 +254,7 @@
unsigned char radio_addr;
int tda9887_conf;
struct cx88_input input[MAX_CX88_INPUT];
- struct cx88_input radio;
+ struct cx88_input radio, off;
enum cx88_board_type mpeg;
enum audiochip audio_chip;
};
@@ -264,7 +265,8 @@
u32 card;
};
-#define INPUT(nr) (core->board.input[nr])
+#define INPUT(nr) ((nr & ~0xFF)?(nr == CX88_RADIO<<8?\
+ core->board.radio:core->board.off):core->board.input[nr])
/* ----------------------------------------------------------- */
/* device / file handle status */
@@ -341,6 +343,7 @@
u32 input;
u32 astat;
u32 use_nicam;
+ u32 vinst, rinst;
/* IR remote control state */
struct cx88_IR *ir;
@@ -643,15 +646,15 @@
/* ----------------------------------------------------------- */
/* cx88-tvaudio.c */
-#define WW_NONE 1
-#define WW_BTSC 2
-#define WW_BG 3
-#define WW_DK 4
-#define WW_I 5
-#define WW_L 6
-#define WW_EIAJ 7
-#define WW_I2SPT 8
-#define WW_FM 9
+#define WW_NONE 0
+#define WW_BTSC 1
+#define WW_BG 2
+#define WW_DK 3
+#define WW_I 4
+#define WW_L 5
+#define WW_EIAJ 6
+#define WW_I2SPT 7
+#define WW_FM 8
void cx88_set_tvaudio(struct cx88_core *core);
void cx88_newstation(struct cx88_core *core);
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list