GNU Linux-libre 6.9.1-gnu
[releases.git] / drivers / media / usb / pvrusb2 / pvrusb2-cx2584x-v4l.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5  *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6  */
7
8 /*
9
10    This source file is specifically designed to interface with the
11    cx2584x, in kernels 2.6.16 or newer.
12
13 */
14
15 #include "pvrusb2-cx2584x-v4l.h"
16
17
18 #include "pvrusb2-hdw-internal.h"
19 #include "pvrusb2-debug.h"
20 #include <media/drv-intf/cx25840.h>
21 #include <linux/videodev2.h>
22 #include <media/v4l2-common.h>
23 #include <linux/errno.h>
24
25
26 struct routing_scheme_item {
27         int vid;
28         int aud;
29 };
30
31 struct routing_scheme {
32         const struct routing_scheme_item *def;
33         unsigned int cnt;
34 };
35
36 static const struct routing_scheme_item routing_scheme0[] = {
37         [PVR2_CVAL_INPUT_TV] = {
38                 .vid = CX25840_COMPOSITE7,
39                 .aud = CX25840_AUDIO8,
40         },
41         [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
42                 .vid = CX25840_COMPOSITE3,
43                 .aud = CX25840_AUDIO_SERIAL,
44         },
45         [PVR2_CVAL_INPUT_COMPOSITE] = {
46                 .vid = CX25840_COMPOSITE3,
47                 .aud = CX25840_AUDIO_SERIAL,
48         },
49         [PVR2_CVAL_INPUT_SVIDEO] = {
50                 .vid = CX25840_SVIDEO1,
51                 .aud = CX25840_AUDIO_SERIAL,
52         },
53 };
54
55 static const struct routing_scheme routing_def0 = {
56         .def = routing_scheme0,
57         .cnt = ARRAY_SIZE(routing_scheme0),
58 };
59
60 /* Specific to gotview device */
61 static const struct routing_scheme_item routing_schemegv[] = {
62         [PVR2_CVAL_INPUT_TV] = {
63                 .vid = CX25840_COMPOSITE2,
64                 .aud = CX25840_AUDIO5,
65         },
66         [PVR2_CVAL_INPUT_RADIO] = {
67                 /* line-in is used for radio and composite.  A GPIO is
68                    used to switch between the two choices. */
69                 .vid = CX25840_COMPOSITE1,
70                 .aud = CX25840_AUDIO_SERIAL,
71         },
72         [PVR2_CVAL_INPUT_COMPOSITE] = {
73                 .vid = CX25840_COMPOSITE1,
74                 .aud = CX25840_AUDIO_SERIAL,
75         },
76         [PVR2_CVAL_INPUT_SVIDEO] = {
77                 .vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4),
78                 .aud = CX25840_AUDIO_SERIAL,
79         },
80 };
81
82 static const struct routing_scheme routing_defgv = {
83         .def = routing_schemegv,
84         .cnt = ARRAY_SIZE(routing_schemegv),
85 };
86
87 /* Specific to grabster av400 device */
88 static const struct routing_scheme_item routing_schemeav400[] = {
89         [PVR2_CVAL_INPUT_COMPOSITE] = {
90                 .vid = CX25840_COMPOSITE1,
91                 .aud = CX25840_AUDIO_SERIAL,
92         },
93         [PVR2_CVAL_INPUT_SVIDEO] = {
94                 .vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4),
95                 .aud = CX25840_AUDIO_SERIAL,
96         },
97 };
98
99 static const struct routing_scheme routing_defav400 = {
100         .def = routing_schemeav400,
101         .cnt = ARRAY_SIZE(routing_schemeav400),
102 };
103
104 static const struct routing_scheme_item routing_scheme160xxx[] = {
105         [PVR2_CVAL_INPUT_TV] = {
106                 .vid = CX25840_COMPOSITE7,
107                 .aud = CX25840_AUDIO8,
108         },
109         [PVR2_CVAL_INPUT_RADIO] = {
110                 .vid = CX25840_COMPOSITE4,
111                 .aud = CX25840_AUDIO6,
112         },
113         [PVR2_CVAL_INPUT_COMPOSITE] = {
114                 .vid = CX25840_COMPOSITE3,
115                 .aud = CX25840_AUDIO_SERIAL,
116         },
117         [PVR2_CVAL_INPUT_SVIDEO] = {
118                 .vid = CX25840_SVIDEO1,
119                 .aud = CX25840_AUDIO_SERIAL,
120         },
121 };
122
123 static const struct routing_scheme routing_def160xxx = {
124         .def = routing_scheme160xxx,
125         .cnt = ARRAY_SIZE(routing_scheme160xxx),
126 };
127
128 static const struct routing_scheme *routing_schemes[] = {
129         [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
130         [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
131         [PVR2_ROUTING_SCHEME_AV400] = &routing_defav400,
132         [PVR2_ROUTING_SCHEME_HAUP160XXX] = &routing_def160xxx,
133 };
134
135 void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
136 {
137         pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
138         if (hdw->input_dirty || hdw->force_dirty) {
139                 enum cx25840_video_input vid_input;
140                 enum cx25840_audio_input aud_input;
141                 const struct routing_scheme *sp;
142                 unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
143
144                 sp = (sid < ARRAY_SIZE(routing_schemes)) ?
145                         routing_schemes[sid] : NULL;
146                 if ((sp == NULL) ||
147                     (hdw->input_val < 0) ||
148                     (hdw->input_val >= sp->cnt)) {
149                         pvr2_trace(PVR2_TRACE_ERROR_LEGS,
150                                    "*** WARNING *** subdev cx2584x set_input: Invalid routing scheme (%u) and/or input (%d)",
151                                    sid, hdw->input_val);
152                         return;
153                 }
154                 vid_input = sp->def[hdw->input_val].vid;
155                 aud_input = sp->def[hdw->input_val].aud;
156                 pvr2_trace(PVR2_TRACE_CHIPS,
157                            "subdev cx2584x set_input vid=0x%x aud=0x%x",
158                            vid_input, aud_input);
159                 sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0);
160                 sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0);
161         }
162 }