1*2504ba9fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20c0d06caSMauro Carvalho Chehab /*
30c0d06caSMauro Carvalho Chehab  *
40c0d06caSMauro Carvalho Chehab  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
50c0d06caSMauro Carvalho Chehab  *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
60c0d06caSMauro Carvalho Chehab  */
70c0d06caSMauro Carvalho Chehab 
80c0d06caSMauro Carvalho Chehab /*
90c0d06caSMauro Carvalho Chehab 
100c0d06caSMauro Carvalho Chehab    This source file is specifically designed to interface with the
110c0d06caSMauro Carvalho Chehab    saa711x support that is available in the v4l available starting
120c0d06caSMauro Carvalho Chehab    with linux 2.6.15.
130c0d06caSMauro Carvalho Chehab 
140c0d06caSMauro Carvalho Chehab */
150c0d06caSMauro Carvalho Chehab 
160c0d06caSMauro Carvalho Chehab #include "pvrusb2-video-v4l.h"
170c0d06caSMauro Carvalho Chehab 
180c0d06caSMauro Carvalho Chehab 
190c0d06caSMauro Carvalho Chehab 
200c0d06caSMauro Carvalho Chehab #include "pvrusb2-hdw-internal.h"
210c0d06caSMauro Carvalho Chehab #include "pvrusb2-debug.h"
220c0d06caSMauro Carvalho Chehab #include <linux/videodev2.h>
230c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
24b5dcee22SMauro Carvalho Chehab #include <media/i2c/saa7115.h>
250c0d06caSMauro Carvalho Chehab #include <linux/errno.h>
260c0d06caSMauro Carvalho Chehab 
270c0d06caSMauro Carvalho Chehab struct routing_scheme {
280c0d06caSMauro Carvalho Chehab 	const int *def;
290c0d06caSMauro Carvalho Chehab 	unsigned int cnt;
300c0d06caSMauro Carvalho Chehab };
310c0d06caSMauro Carvalho Chehab 
320c0d06caSMauro Carvalho Chehab 
330c0d06caSMauro Carvalho Chehab static const int routing_scheme0[] = {
340c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
350c0d06caSMauro Carvalho Chehab 	/* In radio mode, we mute the video, but point at one
360c0d06caSMauro Carvalho Chehab 	   spot just to stay consistent */
370c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
380c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE5,
390c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2,
400c0d06caSMauro Carvalho Chehab };
410c0d06caSMauro Carvalho Chehab 
420c0d06caSMauro Carvalho Chehab static const struct routing_scheme routing_def0 = {
430c0d06caSMauro Carvalho Chehab 	.def = routing_scheme0,
440c0d06caSMauro Carvalho Chehab 	.cnt = ARRAY_SIZE(routing_scheme0),
450c0d06caSMauro Carvalho Chehab };
460c0d06caSMauro Carvalho Chehab 
470c0d06caSMauro Carvalho Chehab static const int routing_scheme1[] = {
480c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
490c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
500c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3,
510c0d06caSMauro Carvalho Chehab 	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
520c0d06caSMauro Carvalho Chehab };
530c0d06caSMauro Carvalho Chehab 
540c0d06caSMauro Carvalho Chehab static const struct routing_scheme routing_def1 = {
550c0d06caSMauro Carvalho Chehab 	.def = routing_scheme1,
560c0d06caSMauro Carvalho Chehab 	.cnt = ARRAY_SIZE(routing_scheme1),
570c0d06caSMauro Carvalho Chehab };
580c0d06caSMauro Carvalho Chehab 
590c0d06caSMauro Carvalho Chehab static const struct routing_scheme *routing_schemes[] = {
600c0d06caSMauro Carvalho Chehab 	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
610c0d06caSMauro Carvalho Chehab 	[PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
620c0d06caSMauro Carvalho Chehab };
630c0d06caSMauro Carvalho Chehab 
pvr2_saa7115_subdev_update(struct pvr2_hdw * hdw,struct v4l2_subdev * sd)640c0d06caSMauro Carvalho Chehab void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
650c0d06caSMauro Carvalho Chehab {
660c0d06caSMauro Carvalho Chehab 	if (hdw->input_dirty || hdw->force_dirty) {
670c0d06caSMauro Carvalho Chehab 		const struct routing_scheme *sp;
680c0d06caSMauro Carvalho Chehab 		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
690c0d06caSMauro Carvalho Chehab 		u32 input;
700c0d06caSMauro Carvalho Chehab 
710c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
720c0d06caSMauro Carvalho Chehab 			   hdw->input_val);
730c0d06caSMauro Carvalho Chehab 
740c0d06caSMauro Carvalho Chehab 		sp = (sid < ARRAY_SIZE(routing_schemes)) ?
750c0d06caSMauro Carvalho Chehab 			routing_schemes[sid] : NULL;
760c0d06caSMauro Carvalho Chehab 		if ((sp == NULL) ||
770c0d06caSMauro Carvalho Chehab 		    (hdw->input_val < 0) ||
780c0d06caSMauro Carvalho Chehab 		    (hdw->input_val >= sp->cnt)) {
790c0d06caSMauro Carvalho Chehab 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
8096292c89SMauro Carvalho Chehab 				   "*** WARNING *** subdev v4l2 set_input: Invalid routing scheme (%u) and/or input (%d)",
810c0d06caSMauro Carvalho Chehab 				   sid, hdw->input_val);
820c0d06caSMauro Carvalho Chehab 			return;
830c0d06caSMauro Carvalho Chehab 		}
840c0d06caSMauro Carvalho Chehab 		input = sp->def[hdw->input_val];
850c0d06caSMauro Carvalho Chehab 		sd->ops->video->s_routing(sd, input, 0, 0);
860c0d06caSMauro Carvalho Chehab 	}
870c0d06caSMauro Carvalho Chehab }
88