18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
58c2ecf20Sopenharmony_ci *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci   This source file is specifically designed to interface with the
118c2ecf20Sopenharmony_ci   cx2584x, in kernels 2.6.16 or newer.
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci*/
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include "pvrusb2-cx2584x-v4l.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "pvrusb2-hdw-internal.h"
198c2ecf20Sopenharmony_ci#include "pvrusb2-debug.h"
208c2ecf20Sopenharmony_ci#include <media/drv-intf/cx25840.h>
218c2ecf20Sopenharmony_ci#include <linux/videodev2.h>
228c2ecf20Sopenharmony_ci#include <media/v4l2-common.h>
238c2ecf20Sopenharmony_ci#include <linux/errno.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistruct routing_scheme_item {
278c2ecf20Sopenharmony_ci	int vid;
288c2ecf20Sopenharmony_ci	int aud;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistruct routing_scheme {
328c2ecf20Sopenharmony_ci	const struct routing_scheme_item *def;
338c2ecf20Sopenharmony_ci	unsigned int cnt;
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistatic const struct routing_scheme_item routing_scheme0[] = {
378c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_TV] = {
388c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE7,
398c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO8,
408c2ecf20Sopenharmony_ci	},
418c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
428c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE3,
438c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
448c2ecf20Sopenharmony_ci	},
458c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_COMPOSITE] = {
468c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE3,
478c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
488c2ecf20Sopenharmony_ci	},
498c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_SVIDEO] = {
508c2ecf20Sopenharmony_ci		.vid = CX25840_SVIDEO1,
518c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
528c2ecf20Sopenharmony_ci	},
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic const struct routing_scheme routing_def0 = {
568c2ecf20Sopenharmony_ci	.def = routing_scheme0,
578c2ecf20Sopenharmony_ci	.cnt = ARRAY_SIZE(routing_scheme0),
588c2ecf20Sopenharmony_ci};
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* Specific to gotview device */
618c2ecf20Sopenharmony_cistatic const struct routing_scheme_item routing_schemegv[] = {
628c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_TV] = {
638c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE2,
648c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO5,
658c2ecf20Sopenharmony_ci	},
668c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_RADIO] = {
678c2ecf20Sopenharmony_ci		/* line-in is used for radio and composite.  A GPIO is
688c2ecf20Sopenharmony_ci		   used to switch between the two choices. */
698c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE1,
708c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
718c2ecf20Sopenharmony_ci	},
728c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_COMPOSITE] = {
738c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE1,
748c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
758c2ecf20Sopenharmony_ci	},
768c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_SVIDEO] = {
778c2ecf20Sopenharmony_ci		.vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4),
788c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
798c2ecf20Sopenharmony_ci	},
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic const struct routing_scheme routing_defgv = {
838c2ecf20Sopenharmony_ci	.def = routing_schemegv,
848c2ecf20Sopenharmony_ci	.cnt = ARRAY_SIZE(routing_schemegv),
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* Specific to grabster av400 device */
888c2ecf20Sopenharmony_cistatic const struct routing_scheme_item routing_schemeav400[] = {
898c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_COMPOSITE] = {
908c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE1,
918c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
928c2ecf20Sopenharmony_ci	},
938c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_SVIDEO] = {
948c2ecf20Sopenharmony_ci		.vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4),
958c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
968c2ecf20Sopenharmony_ci	},
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic const struct routing_scheme routing_defav400 = {
1008c2ecf20Sopenharmony_ci	.def = routing_schemeav400,
1018c2ecf20Sopenharmony_ci	.cnt = ARRAY_SIZE(routing_schemeav400),
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic const struct routing_scheme_item routing_scheme160xxx[] = {
1058c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_TV] = {
1068c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE7,
1078c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO8,
1088c2ecf20Sopenharmony_ci	},
1098c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_RADIO] = {
1108c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE4,
1118c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO6,
1128c2ecf20Sopenharmony_ci	},
1138c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_COMPOSITE] = {
1148c2ecf20Sopenharmony_ci		.vid = CX25840_COMPOSITE3,
1158c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
1168c2ecf20Sopenharmony_ci	},
1178c2ecf20Sopenharmony_ci	[PVR2_CVAL_INPUT_SVIDEO] = {
1188c2ecf20Sopenharmony_ci		.vid = CX25840_SVIDEO1,
1198c2ecf20Sopenharmony_ci		.aud = CX25840_AUDIO_SERIAL,
1208c2ecf20Sopenharmony_ci	},
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic const struct routing_scheme routing_def160xxx = {
1248c2ecf20Sopenharmony_ci	.def = routing_scheme160xxx,
1258c2ecf20Sopenharmony_ci	.cnt = ARRAY_SIZE(routing_scheme160xxx),
1268c2ecf20Sopenharmony_ci};
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic const struct routing_scheme *routing_schemes[] = {
1298c2ecf20Sopenharmony_ci	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
1308c2ecf20Sopenharmony_ci	[PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
1318c2ecf20Sopenharmony_ci	[PVR2_ROUTING_SCHEME_AV400] = &routing_defav400,
1328c2ecf20Sopenharmony_ci	[PVR2_ROUTING_SCHEME_HAUP160XXX] = &routing_def160xxx,
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_civoid pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
1388c2ecf20Sopenharmony_ci	if (hdw->input_dirty || hdw->force_dirty) {
1398c2ecf20Sopenharmony_ci		enum cx25840_video_input vid_input;
1408c2ecf20Sopenharmony_ci		enum cx25840_audio_input aud_input;
1418c2ecf20Sopenharmony_ci		const struct routing_scheme *sp;
1428c2ecf20Sopenharmony_ci		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci		sp = (sid < ARRAY_SIZE(routing_schemes)) ?
1458c2ecf20Sopenharmony_ci			routing_schemes[sid] : NULL;
1468c2ecf20Sopenharmony_ci		if ((sp == NULL) ||
1478c2ecf20Sopenharmony_ci		    (hdw->input_val < 0) ||
1488c2ecf20Sopenharmony_ci		    (hdw->input_val >= sp->cnt)) {
1498c2ecf20Sopenharmony_ci			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
1508c2ecf20Sopenharmony_ci				   "*** WARNING *** subdev cx2584x set_input: Invalid routing scheme (%u) and/or input (%d)",
1518c2ecf20Sopenharmony_ci				   sid, hdw->input_val);
1528c2ecf20Sopenharmony_ci			return;
1538c2ecf20Sopenharmony_ci		}
1548c2ecf20Sopenharmony_ci		vid_input = sp->def[hdw->input_val].vid;
1558c2ecf20Sopenharmony_ci		aud_input = sp->def[hdw->input_val].aud;
1568c2ecf20Sopenharmony_ci		pvr2_trace(PVR2_TRACE_CHIPS,
1578c2ecf20Sopenharmony_ci			   "subdev cx2584x set_input vid=0x%x aud=0x%x",
1588c2ecf20Sopenharmony_ci			   vid_input, aud_input);
1598c2ecf20Sopenharmony_ci		sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0);
1608c2ecf20Sopenharmony_ci		sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0);
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci}
163