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>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 2cca817..b6714c4 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -49,34 +49,65 @@
 };
 
 
+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",