Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / drivers / media / video / pvrusb2 / pvrusb2-audio.c
1 /*
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 #include "pvrusb2-audio.h"
24 #include "pvrusb2-hdw-internal.h"
25 #include "pvrusb2-debug.h"
26 #include <linux/videodev2.h>
27 #include <media/msp3400.h>
28 #include <media/v4l2-common.h>
29
30 struct pvr2_msp3400_handler {
31         struct pvr2_hdw *hdw;
32         struct pvr2_i2c_client *client;
33         struct pvr2_i2c_handler i2c_handler;
34         struct pvr2_audio_stat astat;
35         unsigned long stale_mask;
36 };
37
38
39 /* This function selects the correct audio input source */
40 static void set_stereo(struct pvr2_msp3400_handler *ctxt)
41 {
42         struct pvr2_hdw *hdw = ctxt->hdw;
43         struct v4l2_routing route;
44
45         pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
46
47         if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
48                 struct v4l2_tuner vt;
49                 memset(&vt,0,sizeof(vt));
50                 vt.audmode = hdw->audiomode_val;
51                 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
52         }
53
54         route.input = MSP_INPUT_DEFAULT;
55         route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
56         switch (hdw->input_val) {
57         case PVR2_CVAL_INPUT_TV:
58                 break;
59         case PVR2_CVAL_INPUT_RADIO:
60                 /* Assume that msp34xx also handle FM decoding, in which case
61                    we're still using the tuner. */
62                 /* HV: actually it is more likely to be the SCART2 input if
63                    the ivtv experience is any indication. */
64                 route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
65                                     MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
66                 break;
67         case PVR2_CVAL_INPUT_SVIDEO:
68         case PVR2_CVAL_INPUT_COMPOSITE:
69                 /* SCART 1 input */
70                 route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
71                                     MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
72                 break;
73         }
74         pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
75 }
76
77
78 static int check_stereo(struct pvr2_msp3400_handler *ctxt)
79 {
80         struct pvr2_hdw *hdw = ctxt->hdw;
81         return (hdw->input_dirty ||
82                 hdw->audiomode_dirty);
83 }
84
85
86 struct pvr2_msp3400_ops {
87         void (*update)(struct pvr2_msp3400_handler *);
88         int (*check)(struct pvr2_msp3400_handler *);
89 };
90
91
92 static const struct pvr2_msp3400_ops msp3400_ops[] = {
93         { .update = set_stereo, .check = check_stereo},
94 };
95
96
97 static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
98 {
99         unsigned long msk;
100         unsigned int idx;
101
102         for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
103              idx++) {
104                 msk = 1 << idx;
105                 if (ctxt->stale_mask & msk) continue;
106                 if (msp3400_ops[idx].check(ctxt)) {
107                         ctxt->stale_mask |= msk;
108                 }
109         }
110         return ctxt->stale_mask != 0;
111 }
112
113
114 static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
115 {
116         unsigned long msk;
117         unsigned int idx;
118
119         for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
120              idx++) {
121                 msk = 1 << idx;
122                 if (!(ctxt->stale_mask & msk)) continue;
123                 ctxt->stale_mask &= ~msk;
124                 msp3400_ops[idx].update(ctxt);
125         }
126 }
127
128
129 /* This reads back the current signal type */
130 static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
131 {
132         struct v4l2_tuner vt;
133         int stat;
134
135         memset(&vt,0,sizeof(vt));
136         stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
137         if (stat < 0) return stat;
138
139         ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
140         ctxt->hdw->flag_bilingual =
141                 (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
142         return 0;
143 }
144
145
146 static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
147 {
148         ctxt->client->handler = NULL;
149         ctxt->hdw->audio_stat = NULL;
150         kfree(ctxt);
151 }
152
153
154 static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
155                                           char *buf,unsigned int cnt)
156 {
157         return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
158 }
159
160
161 const static struct pvr2_i2c_handler_functions msp3400_funcs = {
162         .detach = (void (*)(void *))pvr2_msp3400_detach,
163         .check = (int (*)(void *))msp3400_check,
164         .update = (void (*)(void *))msp3400_update,
165         .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
166 };
167
168
169 int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
170 {
171         struct pvr2_msp3400_handler *ctxt;
172         if (hdw->audio_stat) return 0;
173         if (cp->handler) return 0;
174
175         ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
176         if (!ctxt) return 0;
177         memset(ctxt,0,sizeof(*ctxt));
178
179         ctxt->i2c_handler.func_data = ctxt;
180         ctxt->i2c_handler.func_table = &msp3400_funcs;
181         ctxt->client = cp;
182         ctxt->hdw = hdw;
183         ctxt->astat.ctxt = ctxt;
184         ctxt->astat.status = (int (*)(void *))get_audio_status;
185         ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
186         ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
187                                   sizeof(msp3400_ops[0]))) - 1;
188         cp->handler = &ctxt->i2c_handler;
189         hdw->audio_stat = &ctxt->astat;
190         pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
191                    cp->client->addr);
192         return !0;
193 }
194
195
196 /*
197   Stuff for Emacs to see, in order to encourage consistent editing style:
198   *** Local Variables: ***
199   *** mode: c ***
200   *** fill-column: 70 ***
201   *** tab-width: 8 ***
202   *** c-basic-offset: 8 ***
203   *** End: ***
204   */