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 | } |
163 | |