Commit | Line | Data |
---|---|---|
d855497e MI |
1 | /* |
2 | * | |
d855497e MI |
3 | * |
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | |
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | * | |
20 | */ | |
21 | ||
22 | #include "pvrusb2-audio.h" | |
23 | #include "pvrusb2-hdw-internal.h" | |
24 | #include "pvrusb2-debug.h" | |
25 | #include <linux/videodev2.h> | |
26 | #include <media/msp3400.h> | |
27 | #include <media/v4l2-common.h> | |
28 | ||
29 | struct pvr2_msp3400_handler { | |
30 | struct pvr2_hdw *hdw; | |
31 | struct pvr2_i2c_client *client; | |
32 | struct pvr2_i2c_handler i2c_handler; | |
d855497e MI |
33 | unsigned long stale_mask; |
34 | }; | |
35 | ||
36 | ||
f5174af2 | 37 | |
acd92d40 | 38 | |
f5174af2 MI |
39 | struct routing_scheme { |
40 | const int *def; | |
41 | unsigned int cnt; | |
42 | }; | |
43 | ||
44 | static const int routing_scheme0[] = { | |
45 | [PVR2_CVAL_INPUT_TV] = MSP_INPUT_DEFAULT, | |
46 | [PVR2_CVAL_INPUT_RADIO] = MSP_INPUT(MSP_IN_SCART2, | |
47 | MSP_IN_TUNER1, | |
48 | MSP_DSP_IN_SCART, | |
49 | MSP_DSP_IN_SCART), | |
50 | [PVR2_CVAL_INPUT_COMPOSITE] = MSP_INPUT(MSP_IN_SCART1, | |
51 | MSP_IN_TUNER1, | |
52 | MSP_DSP_IN_SCART, | |
53 | MSP_DSP_IN_SCART), | |
54 | [PVR2_CVAL_INPUT_SVIDEO] = MSP_INPUT(MSP_IN_SCART1, | |
55 | MSP_IN_TUNER1, | |
56 | MSP_DSP_IN_SCART, | |
57 | MSP_DSP_IN_SCART), | |
58 | }; | |
59 | ||
60 | static const struct routing_scheme routing_schemes[] = { | |
61 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { | |
62 | .def = routing_scheme0, | |
63 | .cnt = ARRAY_SIZE(routing_scheme0), | |
64 | }, | |
65 | }; | |
66 | ||
d855497e MI |
67 | /* This function selects the correct audio input source */ |
68 | static void set_stereo(struct pvr2_msp3400_handler *ctxt) | |
69 | { | |
70 | struct pvr2_hdw *hdw = ctxt->hdw; | |
71 | struct v4l2_routing route; | |
f5174af2 MI |
72 | const struct routing_scheme *sp; |
73 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | |
d855497e MI |
74 | |
75 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); | |
76 | ||
f5174af2 | 77 | if ((sid < ARRAY_SIZE(routing_schemes)) && |
a6a3a17b | 78 | ((sp = routing_schemes + sid) != NULL) && |
f5174af2 MI |
79 | (hdw->input_val >= 0) && |
80 | (hdw->input_val < sp->cnt)) { | |
81 | route.input = sp->def[hdw->input_val]; | |
82 | } else { | |
83 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | |
84 | "*** WARNING *** i2c msp3400 v4l2 set_stereo:" | |
85 | " Invalid routing scheme (%u) and/or input (%d)", | |
86 | sid,hdw->input_val); | |
87 | return; | |
d855497e | 88 | } |
f5174af2 | 89 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); |
d855497e MI |
90 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); |
91 | } | |
92 | ||
93 | ||
94 | static int check_stereo(struct pvr2_msp3400_handler *ctxt) | |
95 | { | |
96 | struct pvr2_hdw *hdw = ctxt->hdw; | |
606cf9ca | 97 | return hdw->input_dirty; |
d855497e MI |
98 | } |
99 | ||
100 | ||
101 | struct pvr2_msp3400_ops { | |
102 | void (*update)(struct pvr2_msp3400_handler *); | |
103 | int (*check)(struct pvr2_msp3400_handler *); | |
104 | }; | |
105 | ||
106 | ||
107 | static const struct pvr2_msp3400_ops msp3400_ops[] = { | |
108 | { .update = set_stereo, .check = check_stereo}, | |
109 | }; | |
110 | ||
111 | ||
112 | static int msp3400_check(struct pvr2_msp3400_handler *ctxt) | |
113 | { | |
114 | unsigned long msk; | |
115 | unsigned int idx; | |
116 | ||
27c7b710 | 117 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { |
d855497e MI |
118 | msk = 1 << idx; |
119 | if (ctxt->stale_mask & msk) continue; | |
120 | if (msp3400_ops[idx].check(ctxt)) { | |
121 | ctxt->stale_mask |= msk; | |
122 | } | |
123 | } | |
124 | return ctxt->stale_mask != 0; | |
125 | } | |
126 | ||
127 | ||
128 | static void msp3400_update(struct pvr2_msp3400_handler *ctxt) | |
129 | { | |
130 | unsigned long msk; | |
131 | unsigned int idx; | |
132 | ||
27c7b710 | 133 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { |
d855497e MI |
134 | msk = 1 << idx; |
135 | if (!(ctxt->stale_mask & msk)) continue; | |
136 | ctxt->stale_mask &= ~msk; | |
137 | msp3400_ops[idx].update(ctxt); | |
138 | } | |
139 | } | |
140 | ||
141 | ||
d855497e MI |
142 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) |
143 | { | |
a0fd1cb1 | 144 | ctxt->client->handler = NULL; |
d855497e MI |
145 | kfree(ctxt); |
146 | } | |
147 | ||
148 | ||
149 | static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, | |
150 | char *buf,unsigned int cnt) | |
151 | { | |
152 | return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); | |
153 | } | |
154 | ||
155 | ||
c5a69d57 | 156 | static const struct pvr2_i2c_handler_functions msp3400_funcs = { |
d855497e MI |
157 | .detach = (void (*)(void *))pvr2_msp3400_detach, |
158 | .check = (int (*)(void *))msp3400_check, | |
159 | .update = (void (*)(void *))msp3400_update, | |
160 | .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, | |
161 | }; | |
162 | ||
163 | ||
164 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |
165 | { | |
166 | struct pvr2_msp3400_handler *ctxt; | |
d855497e MI |
167 | if (cp->handler) return 0; |
168 | ||
ca545f7c | 169 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); |
d855497e | 170 | if (!ctxt) return 0; |
d855497e MI |
171 | |
172 | ctxt->i2c_handler.func_data = ctxt; | |
173 | ctxt->i2c_handler.func_table = &msp3400_funcs; | |
174 | ctxt->client = cp; | |
175 | ctxt->hdw = hdw; | |
27c7b710 | 176 | ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; |
d855497e | 177 | cp->handler = &ctxt->i2c_handler; |
d855497e MI |
178 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", |
179 | cp->client->addr); | |
180 | return !0; | |
181 | } | |
182 | ||
183 | ||
acd92d40 | 184 | |
d855497e MI |
185 | /* |
186 | Stuff for Emacs to see, in order to encourage consistent editing style: | |
187 | *** Local Variables: *** | |
188 | *** mode: c *** | |
189 | *** fill-column: 70 *** | |
190 | *** tab-width: 8 *** | |
191 | *** c-basic-offset: 8 *** | |
192 | *** End: *** | |
193 | */ |