mirror of https://gitee.com/openkylin/linux.git
V4L/DVB (6698): pvrusb2: Implement signal routing schemes
The exact routing of video and audio signals within a device is a device-specific attribute. Hauppauge devices do it one way; other types of device may route things differently. Unfortunately it is rather impractical to define chip-specific routing at the device attribute level, so instead what happens here is that "schemes" are defined. Each chip level interface implements its part of a given scheme and the scheme as a whole is made into a device specific attribute controlled via a table entry in pvrusb2-devattr.c. The only scheme defined here is for Hauppauge devices, but clearly this opens the door for other possibilities to follow. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
aaf7884db3
commit
f5174af201
|
@ -35,34 +35,58 @@ struct pvr2_msp3400_handler {
|
|||
};
|
||||
|
||||
|
||||
|
||||
struct routing_scheme {
|
||||
const int *def;
|
||||
unsigned int cnt;
|
||||
};
|
||||
|
||||
static const int routing_scheme0[] = {
|
||||
[PVR2_CVAL_INPUT_TV] = MSP_INPUT_DEFAULT,
|
||||
[PVR2_CVAL_INPUT_RADIO] = MSP_INPUT(MSP_IN_SCART2,
|
||||
MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART,
|
||||
MSP_DSP_IN_SCART),
|
||||
[PVR2_CVAL_INPUT_COMPOSITE] = MSP_INPUT(MSP_IN_SCART1,
|
||||
MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART,
|
||||
MSP_DSP_IN_SCART),
|
||||
[PVR2_CVAL_INPUT_SVIDEO] = MSP_INPUT(MSP_IN_SCART1,
|
||||
MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART,
|
||||
MSP_DSP_IN_SCART),
|
||||
};
|
||||
|
||||
static const struct routing_scheme routing_schemes[] = {
|
||||
[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
|
||||
.def = routing_scheme0,
|
||||
.cnt = ARRAY_SIZE(routing_scheme0),
|
||||
},
|
||||
};
|
||||
|
||||
/* This function selects the correct audio input source */
|
||||
static void set_stereo(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
struct v4l2_routing route;
|
||||
const struct routing_scheme *sp;
|
||||
unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
|
||||
|
||||
route.input = MSP_INPUT_DEFAULT;
|
||||
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
|
||||
switch (hdw->input_val) {
|
||||
case PVR2_CVAL_INPUT_TV:
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_RADIO:
|
||||
/* Assume that msp34xx also handle FM decoding, in which case
|
||||
we're still using the tuner. */
|
||||
/* HV: actually it is more likely to be the SCART2 input if
|
||||
the ivtv experience is any indication. */
|
||||
route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_SVIDEO:
|
||||
case PVR2_CVAL_INPUT_COMPOSITE:
|
||||
/* SCART 1 input */
|
||||
route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
|
||||
break;
|
||||
if ((sid < ARRAY_SIZE(routing_schemes)) &&
|
||||
((sp = routing_schemes + sid) != 0) &&
|
||||
(hdw->input_val >= 0) &&
|
||||
(hdw->input_val < sp->cnt)) {
|
||||
route.input = sp->def[hdw->input_val];
|
||||
} else {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"*** WARNING *** i2c msp3400 v4l2 set_stereo:"
|
||||
" Invalid routing scheme (%u) and/or input (%d)",
|
||||
sid,hdw->input_val);
|
||||
return;
|
||||
}
|
||||
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,34 +49,65 @@ struct pvr2_v4l_cx2584x {
|
|||
};
|
||||
|
||||
|
||||
struct routing_scheme_item {
|
||||
int vid;
|
||||
int aud;
|
||||
};
|
||||
|
||||
struct routing_scheme {
|
||||
const struct routing_scheme_item *def;
|
||||
unsigned int cnt;
|
||||
};
|
||||
|
||||
static const struct routing_scheme_item routing_scheme0[] = {
|
||||
[PVR2_CVAL_INPUT_TV] = {
|
||||
.vid = CX25840_COMPOSITE7,
|
||||
.aud = CX25840_AUDIO8,
|
||||
},
|
||||
[PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
|
||||
.vid = CX25840_COMPOSITE3,
|
||||
.aud = CX25840_AUDIO_SERIAL,
|
||||
},
|
||||
[PVR2_CVAL_INPUT_COMPOSITE] = {
|
||||
.vid = CX25840_COMPOSITE3,
|
||||
.aud = CX25840_AUDIO_SERIAL,
|
||||
},
|
||||
[PVR2_CVAL_INPUT_SVIDEO] = {
|
||||
.vid = CX25840_SVIDEO1,
|
||||
.aud = CX25840_AUDIO_SERIAL,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct routing_scheme routing_schemes[] = {
|
||||
[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
|
||||
.def = routing_scheme0,
|
||||
.cnt = ARRAY_SIZE(routing_scheme0),
|
||||
},
|
||||
};
|
||||
|
||||
static void set_input(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
struct v4l2_routing route;
|
||||
enum cx25840_video_input vid_input;
|
||||
enum cx25840_audio_input aud_input;
|
||||
const struct routing_scheme *sp;
|
||||
unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
|
||||
|
||||
memset(&route,0,sizeof(route));
|
||||
|
||||
switch(hdw->input_val) {
|
||||
case PVR2_CVAL_INPUT_TV:
|
||||
vid_input = CX25840_COMPOSITE7;
|
||||
aud_input = CX25840_AUDIO8;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_RADIO: // Treat same as composite
|
||||
case PVR2_CVAL_INPUT_COMPOSITE:
|
||||
vid_input = CX25840_COMPOSITE3;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_SVIDEO:
|
||||
vid_input = CX25840_SVIDEO1;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
default:
|
||||
// Just set it to be composite input for now...
|
||||
vid_input = CX25840_COMPOSITE3;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
if ((sid < ARRAY_SIZE(routing_schemes)) &&
|
||||
((sp = routing_schemes + sid) != 0) &&
|
||||
(hdw->input_val >= 0) &&
|
||||
(hdw->input_val < sp->cnt)) {
|
||||
vid_input = sp->def[hdw->input_val].vid;
|
||||
aud_input = sp->def[hdw->input_val].aud;
|
||||
} else {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"*** WARNING *** i2c cx2584x set_input:"
|
||||
" Invalid routing scheme (%u) and/or input (%d)",
|
||||
sid,hdw->input_val);
|
||||
return;
|
||||
}
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
|
||||
|
|
|
@ -73,6 +73,7 @@ const struct pvr2_device_desc pvr2_device_descriptions[] = {
|
|||
.fx2_firmware.lst = pvr2_fw1_names_29xxx,
|
||||
.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
|
||||
.flag_has_hauppauge_rom = !0,
|
||||
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
|
||||
},
|
||||
[PVR2_HDW_TYPE_24XXX] = {
|
||||
.description = "WinTV PVR USB2 Model Category 24xxxx",
|
||||
|
@ -84,6 +85,7 @@ const struct pvr2_device_desc pvr2_device_descriptions[] = {
|
|||
.flag_has_cx25840 = !0,
|
||||
.flag_has_wm8775 = !0,
|
||||
.flag_has_hauppauge_rom = !0,
|
||||
.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ struct pvr2_string_table {
|
|||
unsigned int cnt;
|
||||
};
|
||||
|
||||
#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
|
||||
|
||||
/* This describes a particular hardware type (except for the USB device ID
|
||||
which must live in a separate structure due to environmental
|
||||
|
@ -55,6 +56,14 @@ struct pvr2_device_desc {
|
|||
was initialized from internal ROM. */
|
||||
struct pvr2_string_table fx2_firmware;
|
||||
|
||||
/* Signal routing scheme used by device, contains one of
|
||||
PVR2_ROUTING_SCHEME_XXX. Schemes have to be defined as we
|
||||
encounter them. This is an arbitrary integer scheme id; its
|
||||
meaning is contained entirely within the driver and is
|
||||
interpreted by logic which must send commands to the chip-level
|
||||
drivers (search for things which touch this field). */
|
||||
unsigned int signal_routing_scheme;
|
||||
|
||||
/* V4L tuner type ID to use with this device (only used if the
|
||||
driver could not discover the type any other way). */
|
||||
int default_tuner_type;
|
||||
|
|
|
@ -49,29 +49,50 @@ struct pvr2_v4l_decoder {
|
|||
};
|
||||
|
||||
|
||||
struct routing_scheme {
|
||||
const int *def;
|
||||
unsigned int cnt;
|
||||
};
|
||||
|
||||
|
||||
static const int routing_scheme0[] = {
|
||||
[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
|
||||
/* In radio mode, we mute the video, but point at one
|
||||
spot just to stay consistent */
|
||||
[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
|
||||
[PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE5,
|
||||
[PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2,
|
||||
};
|
||||
|
||||
static const struct routing_scheme routing_schemes[] = {
|
||||
[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
|
||||
.def = routing_scheme0,
|
||||
.cnt = ARRAY_SIZE(routing_scheme0),
|
||||
},
|
||||
};
|
||||
|
||||
static void set_input(struct pvr2_v4l_decoder *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
struct v4l2_routing route;
|
||||
const struct routing_scheme *sp;
|
||||
unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
|
||||
switch(hdw->input_val) {
|
||||
case PVR2_CVAL_INPUT_TV:
|
||||
route.input = SAA7115_COMPOSITE4;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_COMPOSITE:
|
||||
route.input = SAA7115_COMPOSITE5;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_SVIDEO:
|
||||
route.input = SAA7115_SVIDEO2;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_RADIO:
|
||||
// In radio mode, we mute the video, but point at one
|
||||
// spot just to stay consistent
|
||||
route.input = SAA7115_COMPOSITE5;
|
||||
default:
|
||||
|
||||
if ((sid < ARRAY_SIZE(routing_schemes)) &&
|
||||
((sp = routing_schemes + sid) != 0) &&
|
||||
(hdw->input_val >= 0) &&
|
||||
(hdw->input_val < sp->cnt)) {
|
||||
route.input = sp->def[hdw->input_val];
|
||||
} else {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"*** WARNING *** i2c v4l2 set_input:"
|
||||
" Invalid routing scheme (%u) and/or input (%d)",
|
||||
sid,hdw->input_val);
|
||||
return;
|
||||
}
|
||||
|
||||
route.output = 0;
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue