blob: ffdc45c324e5d24936de4557da279af46314ee8d [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
3 * $Id$
4 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23/*
24
25 This source file is specifically designed to interface with the
26 cx2584x, in kernels 2.6.16 or newer.
27
28*/
29
30#include "pvrusb2-cx2584x-v4l.h"
31#include "pvrusb2-video-v4l.h"
32#include "pvrusb2-i2c-cmd-v4l2.h"
33
34
35#include "pvrusb2-hdw-internal.h"
36#include "pvrusb2-debug.h"
37#include <media/cx25840.h>
38#include <linux/videodev2.h>
39#include <media/v4l2-common.h>
40#include <linux/errno.h>
41#include <linux/slab.h>
42
43struct pvr2_v4l_cx2584x {
44 struct pvr2_i2c_handler handler;
45 struct pvr2_decoder_ctrl ctrl;
46 struct pvr2_i2c_client *client;
47 struct pvr2_hdw *hdw;
48 unsigned long stale_mask;
49};
50
51
Mike Iselyf5174af2007-11-26 02:07:26 -030052struct routing_scheme_item {
53 int vid;
54 int aud;
55};
56
57struct routing_scheme {
58 const struct routing_scheme_item *def;
59 unsigned int cnt;
60};
61
62static const struct routing_scheme_item routing_scheme0[] = {
63 [PVR2_CVAL_INPUT_TV] = {
64 .vid = CX25840_COMPOSITE7,
65 .aud = CX25840_AUDIO8,
66 },
67 [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
68 .vid = CX25840_COMPOSITE3,
69 .aud = CX25840_AUDIO_SERIAL,
70 },
71 [PVR2_CVAL_INPUT_COMPOSITE] = {
72 .vid = CX25840_COMPOSITE3,
73 .aud = CX25840_AUDIO_SERIAL,
74 },
75 [PVR2_CVAL_INPUT_SVIDEO] = {
76 .vid = CX25840_SVIDEO1,
77 .aud = CX25840_AUDIO_SERIAL,
78 },
79};
80
Mike Isely9e2e3ae2007-11-26 02:14:23 -030081/* Specific to gotview device */
82static const struct routing_scheme_item routing_schemegv[] = {
83 [PVR2_CVAL_INPUT_TV] = {
84 .vid = CX25840_COMPOSITE2,
85 .aud = CX25840_AUDIO5,
86 },
87 [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
88 .vid = CX25840_COMPOSITE1,
89 .aud = CX25840_AUDIO_SERIAL,
90 },
91 [PVR2_CVAL_INPUT_COMPOSITE] = {
92 .vid = CX25840_COMPOSITE1,
93 .aud = CX25840_AUDIO_SERIAL,
94 },
95 [PVR2_CVAL_INPUT_SVIDEO] = {
96 .vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4),
97 .aud = CX25840_AUDIO_SERIAL,
98 },
99};
100
Mike Iselyf5174af2007-11-26 02:07:26 -0300101static const struct routing_scheme routing_schemes[] = {
102 [PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
103 .def = routing_scheme0,
104 .cnt = ARRAY_SIZE(routing_scheme0),
105 },
Mike Isely9e2e3ae2007-11-26 02:14:23 -0300106 [PVR2_ROUTING_SCHEME_GOTVIEW] = {
107 .def = routing_schemegv,
108 .cnt = ARRAY_SIZE(routing_schemegv),
109 },
Mike Iselyf5174af2007-11-26 02:07:26 -0300110};
111
Mike Iselyd8554972006-06-26 20:58:46 -0300112static void set_input(struct pvr2_v4l_cx2584x *ctxt)
113{
114 struct pvr2_hdw *hdw = ctxt->hdw;
115 struct v4l2_routing route;
116 enum cx25840_video_input vid_input;
117 enum cx25840_audio_input aud_input;
Mike Iselyf5174af2007-11-26 02:07:26 -0300118 const struct routing_scheme *sp;
119 unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
Mike Iselyd8554972006-06-26 20:58:46 -0300120
121 memset(&route,0,sizeof(route));
122
Mike Iselyf5174af2007-11-26 02:07:26 -0300123 if ((sid < ARRAY_SIZE(routing_schemes)) &&
124 ((sp = routing_schemes + sid) != 0) &&
125 (hdw->input_val >= 0) &&
126 (hdw->input_val < sp->cnt)) {
127 vid_input = sp->def[hdw->input_val].vid;
128 aud_input = sp->def[hdw->input_val].aud;
129 } else {
130 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
131 "*** WARNING *** i2c cx2584x set_input:"
132 " Invalid routing scheme (%u) and/or input (%d)",
133 sid,hdw->input_val);
134 return;
Mike Iselyd8554972006-06-26 20:58:46 -0300135 }
136
137 pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
138 vid_input,aud_input);
139 route.input = (u32)vid_input;
140 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
141 route.input = (u32)aud_input;
142 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
143}
144
145
146static int check_input(struct pvr2_v4l_cx2584x *ctxt)
147{
148 struct pvr2_hdw *hdw = ctxt->hdw;
149 return hdw->input_dirty != 0;
150}
151
152
153static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
154{
155 u32 val;
156 struct pvr2_hdw *hdw = ctxt->hdw;
157
158 pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
159 hdw->srate_val);
160 switch (hdw->srate_val) {
161 default:
Mike Iselyb30d2442006-06-25 20:05:01 -0300162 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
Mike Iselyd8554972006-06-26 20:58:46 -0300163 val = 48000;
164 break;
Mike Iselyb30d2442006-06-25 20:05:01 -0300165 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
Mike Iselyd8554972006-06-26 20:58:46 -0300166 val = 44100;
167 break;
Mike Iselyb30d2442006-06-25 20:05:01 -0300168 case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
169 val = 32000;
170 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300171 }
172 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
173}
174
175
176static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
177{
178 struct pvr2_hdw *hdw = ctxt->hdw;
179 return hdw->srate_dirty != 0;
180}
181
182
183struct pvr2_v4l_cx2584x_ops {
184 void (*update)(struct pvr2_v4l_cx2584x *);
185 int (*check)(struct pvr2_v4l_cx2584x *);
186};
187
188
189static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
190 { .update = set_input, .check = check_input},
191 { .update = set_audio, .check = check_audio},
192};
193
194
195static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
196{
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300197 ctxt->client->handler = NULL;
Mike Isely681c7392007-11-26 01:48:52 -0300198 pvr2_hdw_set_decoder(ctxt->hdw,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300199 kfree(ctxt);
200}
201
202
203static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
204{
205 unsigned long msk;
206 unsigned int idx;
207
Mike Isely27c7b712007-01-20 00:39:17 -0300208 for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
Mike Iselyd8554972006-06-26 20:58:46 -0300209 msk = 1 << idx;
210 if (ctxt->stale_mask & msk) continue;
211 if (decoder_ops[idx].check(ctxt)) {
212 ctxt->stale_mask |= msk;
213 }
214 }
215 return ctxt->stale_mask != 0;
216}
217
218
219static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
220{
221 unsigned long msk;
222 unsigned int idx;
223
Mike Isely27c7b712007-01-20 00:39:17 -0300224 for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
Mike Iselyd8554972006-06-26 20:58:46 -0300225 msk = 1 << idx;
226 if (!(ctxt->stale_mask & msk)) continue;
227 ctxt->stale_mask &= ~msk;
228 decoder_ops[idx].update(ctxt);
229 }
230}
231
232
233static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
234{
235 pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
236 pvr2_v4l2_cmd_stream(ctxt->client,fl);
237}
238
239
240static int decoder_detect(struct pvr2_i2c_client *cp)
241{
242 int ret;
243 /* Attempt to query the decoder - let's see if it will answer */
244 struct v4l2_queryctrl qc;
245
246 memset(&qc,0,sizeof(qc));
247
248 qc.id = V4L2_CID_BRIGHTNESS;
249
250 ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
251 return ret == 0; /* Return true if it answered */
252}
253
254
Mike Iselyd8554972006-06-26 20:58:46 -0300255static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
256 char *buf,unsigned int cnt)
257{
258 return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
259}
260
261
262static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
263{
264 int ret;
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300265 ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300266 pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
267}
268
269
Tobias Klauserc5a69d52007-02-17 20:11:19 +0100270static const struct pvr2_i2c_handler_functions hfuncs = {
Mike Iselyd8554972006-06-26 20:58:46 -0300271 .detach = (void (*)(void *))decoder_detach,
272 .check = (int (*)(void *))decoder_check,
273 .update = (void (*)(void *))decoder_update,
274 .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
275};
276
277
278int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
279 struct pvr2_i2c_client *cp)
280{
281 struct pvr2_v4l_cx2584x *ctxt;
282
283 if (hdw->decoder_ctrl) return 0;
284 if (cp->handler) return 0;
285 if (!decoder_detect(cp)) return 0;
286
Mike Iselyca545f72007-01-20 00:37:11 -0300287 ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300288 if (!ctxt) return 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300289
290 ctxt->handler.func_data = ctxt;
291 ctxt->handler.func_table = &hfuncs;
292 ctxt->ctrl.ctxt = ctxt;
293 ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
294 ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
Mike Iselyd8554972006-06-26 20:58:46 -0300295 ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
296 ctxt->client = cp;
297 ctxt->hdw = hdw;
Mike Isely27c7b712007-01-20 00:39:17 -0300298 ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
Mike Isely681c7392007-11-26 01:48:52 -0300299 pvr2_hdw_set_decoder(hdw,&ctxt->ctrl);
Mike Iselyd8554972006-06-26 20:58:46 -0300300 cp->handler = &ctxt->handler;
Mike Iselyff67c612006-11-19 20:50:31 -0300301 {
302 /*
303 Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
304 of nuttiness for cx25840 causes that module to
305 correctly set up its video scaling. This is really
306 a problem in the cx25840 module itself, but we work
307 around it here. The problem has not been seen in
308 ivtv because there VBI is supported and set up. We
309 don't do VBI here (at least not yet) and thus we
310 never attempted to even set it up.
311 */
312 struct v4l2_format fmt;
313 memset(&fmt,0,sizeof(fmt));
314 fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
315 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
316 }
Mike Iselyd8554972006-06-26 20:58:46 -0300317 pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
318 cp->client->addr);
319 return !0;
320}
321
322
323
324
325/*
326 Stuff for Emacs to see, in order to encourage consistent editing style:
327 *** Local Variables: ***
328 *** mode: c ***
329 *** fill-column: 70 ***
330 *** tab-width: 8 ***
331 *** c-basic-offset: 8 ***
332 *** End: ***
333 */