File: /usr/src/linux/drivers/media/video/tvmixer.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/sched.h>
4 #include <linux/string.h>
5 #include <linux/timer.h>
6 #include <linux/delay.h>
7 #include <linux/errno.h>
8 #include <linux/slab.h>
9 #include <linux/i2c.h>
10 #include <linux/videodev.h>
11 #include <asm/semaphore.h>
12 #include <linux/init.h>
13
14 #include <linux/sound.h>
15 #include <linux/soundcard.h>
16 #include <asm/uaccess.h>
17
18 #include "audiochip.h"
19 #include "id.h"
20
21 #define DEV_MAX 4
22
23 static int debug = 0;
24 static int devnr = -1;
25
26 MODULE_PARM(debug,"i");
27 MODULE_PARM(devnr,"i");
28
29 /* ----------------------------------------------------------------------- */
30
31 struct TVMIXER {
32 struct i2c_client *dev;
33 int minor;
34 int count;
35 };
36
37 static struct TVMIXER devices[DEV_MAX];
38
39 static int tvmixer_adapters(struct i2c_adapter *adap);
40 static int tvmixer_clients(struct i2c_client *client);
41
42 static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
43 static int tvmixer_open(struct inode *inode, struct file *file);
44 static int tvmixer_release(struct inode *inode, struct file *file);
45
46
47 static struct i2c_driver driver = {
48 name: "tv card mixer driver",
49 id: I2C_DRIVERID_TVMIXER,
50 flags: I2C_DF_DUMMY,
51 attach_adapter: tvmixer_adapters,
52 detach_client: tvmixer_clients,
53 };
54
55 static struct file_operations tvmixer_fops = {
56 owner: THIS_MODULE,
57 llseek: no_llseek,
58 ioctl: tvmixer_ioctl,
59 open: tvmixer_open,
60 release: tvmixer_release,
61 };
62
63 /* ----------------------------------------------------------------------- */
64
65 static int mix_to_v4l(int i)
66 {
67 int r;
68
69 r = ((i & 0xff) * 65536 + 50) / 100;
70 if (r > 65535) r = 65535;
71 if (r < 0) r = 0;
72 return r;
73 }
74
75 static int v4l_to_mix(int i)
76 {
77 int r;
78
79 r = (i * 100 + 32768) / 65536;
80 if (r > 100) r = 100;
81 if (r < 0) r = 0;
82 return r | (r << 8);
83 }
84
85 static int v4l_to_mix2(int l, int r)
86 {
87 r = (r * 100 + 32768) / 65536;
88 if (r > 100) r = 100;
89 if (r < 0) r = 0;
90 l = (l * 100 + 32768) / 65536;
91 if (l > 100) l = 100;
92 if (l < 0) l = 0;
93 return (r << 8) | l;
94 }
95
96 static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
97 {
98 struct video_audio va;
99 int left,right,ret,val = 0;
100 struct TVMIXER *mix = file->private_data;
101 struct i2c_client *client = mix->dev;
102
103 if (NULL == client)
104 return -ENODEV;
105
106 if (cmd == SOUND_MIXER_INFO) {
107 mixer_info info;
108 strncpy(info.id, "tv card", sizeof(info.id));
109 strncpy(info.name, client->name, sizeof(info.name));
110 info.modify_counter = 42 /* FIXME */;
111 if (copy_to_user((void *)arg, &info, sizeof(info)))
112 return -EFAULT;
113 return 0;
114 }
115 if (cmd == SOUND_OLD_MIXER_INFO) {
116 _old_mixer_info info;
117 strncpy(info.id, "tv card", sizeof(info.id));
118 strncpy(info.name, client->name, sizeof(info.name));
119 if (copy_to_user((void *)arg, &info, sizeof(info)))
120 return -EFAULT;
121 return 0;
122 }
123 if (cmd == OSS_GETVERSION)
124 return put_user(SOUND_VERSION, (int *)arg);
125
126 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
127 if (get_user(val, (int *)arg))
128 return -EFAULT;
129
130 /* read state */
131 memset(&va,0,sizeof(va));
132 client->driver->command(client,VIDIOCGAUDIO,&va);
133
134 switch (cmd) {
135 case MIXER_READ(SOUND_MIXER_RECMASK):
136 case MIXER_READ(SOUND_MIXER_CAPS):
137 case MIXER_READ(SOUND_MIXER_RECSRC):
138 case MIXER_WRITE(SOUND_MIXER_RECSRC):
139 ret = 0;
140 break;
141
142 case MIXER_READ(SOUND_MIXER_STEREODEVS):
143 ret = SOUND_MASK_VOLUME;
144 break;
145 case MIXER_READ(SOUND_MIXER_DEVMASK):
146 ret = SOUND_MASK_VOLUME;
147 if (va.flags & VIDEO_AUDIO_BASS)
148 ret |= SOUND_MASK_BASS;
149 if (va.flags & VIDEO_AUDIO_TREBLE)
150 ret |= SOUND_MASK_TREBLE;
151 break;
152
153 case MIXER_WRITE(SOUND_MIXER_VOLUME):
154 left = mix_to_v4l(val);
155 right = mix_to_v4l(val >> 8);
156 va.volume = MAX(left,right);
157 va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1);
158 va.balance = (left<right) ? (65535-va.balance) : va.balance;
159 client->driver->command(client,VIDIOCSAUDIO,&va);
160 client->driver->command(client,VIDIOCGAUDIO,&va);
161 /* fall throuth */
162 case MIXER_READ(SOUND_MIXER_VOLUME):
163 left = (MIN(65536 - va.balance,32768) *
164 va.volume) / 32768;
165 right = (MIN(va.balance,32768) *
166 va.volume) / 32768;
167 ret = v4l_to_mix2(left,right);
168 break;
169
170 case MIXER_WRITE(SOUND_MIXER_BASS):
171 va.bass = mix_to_v4l(val);
172 client->driver->command(client,VIDIOCSAUDIO,&va);
173 client->driver->command(client,VIDIOCGAUDIO,&va);
174 /* fall throuth */
175 case MIXER_READ(SOUND_MIXER_BASS):
176 ret = v4l_to_mix(va.bass);
177 break;
178
179 case MIXER_WRITE(SOUND_MIXER_TREBLE):
180 va.treble = mix_to_v4l(val);
181 client->driver->command(client,VIDIOCSAUDIO,&va);
182 client->driver->command(client,VIDIOCGAUDIO,&va);
183 /* fall throuth */
184 case MIXER_READ(SOUND_MIXER_TREBLE):
185 ret = v4l_to_mix(va.treble);
186 break;
187
188 default:
189 return -EINVAL;
190 }
191 if (put_user(ret, (int *)arg))
192 return -EFAULT;
193 return 0;
194 }
195
196 static int tvmixer_open(struct inode *inode, struct file *file)
197 {
198 int i, minor = MINOR(inode->i_rdev);
199 struct TVMIXER *mix = NULL;
200 struct i2c_client *client = NULL;
201
202 for (i = 0; i < DEV_MAX; i++) {
203 if (devices[i].minor == minor) {
204 mix = devices+i;
205 client = mix->dev;
206 break;
207 }
208 }
209
210 if (NULL == client)
211 return -ENODEV;
212
213 /* lock bttv in memory while the mixer is in use */
214 file->private_data = mix;
215 if (client->adapter->inc_use)
216 client->adapter->inc_use(client->adapter);
217 return 0;
218 }
219
220 static int tvmixer_release(struct inode *inode, struct file *file)
221 {
222 struct TVMIXER *mix = file->private_data;
223 struct i2c_client *client;
224
225 client = mix->dev;
226 if (NULL == client) {
227 return -ENODEV;
228 }
229
230 if (client->adapter->dec_use)
231 client->adapter->dec_use(client->adapter);
232 return 0;
233 }
234
235 /* ----------------------------------------------------------------------- */
236
237 static int tvmixer_adapters(struct i2c_adapter *adap)
238 {
239 int i;
240
241 if (debug)
242 printk("tvmixer: adapter %s\n",adap->name);
243 for (i=0; i<I2C_CLIENT_MAX; i++) {
244 if (!adap->clients[i])
245 continue;
246 tvmixer_clients(adap->clients[i]);
247 }
248 return 0;
249 }
250
251 static int tvmixer_clients(struct i2c_client *client)
252 {
253 struct video_audio va;
254 int i,minor;
255
256 /* TV card ??? */
257 if (client->adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
258 if (debug)
259 printk("tvmixer: %s is not a tv card\n",
260 client->adapter->name);
261 return -1;
262 }
263 printk("tvmixer: debug: %s\n",client->name);
264
265 /* unregister ?? */
266 for (i = 0; i < DEV_MAX; i++) {
267 if (devices[i].dev == client) {
268 /* unregister */
269 unregister_sound_mixer(devices[i].minor);
270 devices[i].dev = NULL;
271 devices[i].minor = -1;
272 printk("tvmixer: %s unregistered (#1)\n",client->name);
273 return 0;
274 }
275 }
276
277 /* look for a free slot */
278 for (i = 0; i < DEV_MAX; i++)
279 if (NULL == devices[i].dev)
280 break;
281 if (i == DEV_MAX) {
282 printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
283 return -1;
284 }
285
286 /* audio chip with mixer ??? */
287 if (NULL == client->driver->command) {
288 if (debug)
289 printk("tvmixer: %s: driver->command is NULL\n",
290 client->driver->name);
291 return -1;
292 }
293 memset(&va,0,sizeof(va));
294 if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
295 if (debug)
296 printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
297 client->name);
298 return -1;
299 }
300 if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
301 if (debug)
302 printk("tvmixer: %s: has no volume control\n",
303 client->name);
304 return -1;
305 }
306
307 /* everything is fine, register */
308 if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
309 printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
310 return -1;
311 }
312
313 devices[i].minor = minor;
314 devices[i].count = 0;
315 devices[i].dev = client;
316 printk("tvmixer: %s (%s) registered with minor %d\n",
317 client->name,client->adapter->name,minor);
318
319 return 0;
320 }
321
322 /* ----------------------------------------------------------------------- */
323
324 int tvmixer_init_module(void)
325 {
326 int i;
327
328 for (i = 0; i < DEV_MAX; i++)
329 devices[i].minor = -1;
330 i2c_add_driver(&driver);
331 return 0;
332 }
333
334 void tvmixer_cleanup_module(void)
335 {
336 int i;
337
338 i2c_del_driver(&driver);
339 for (i = 0; i < DEV_MAX; i++) {
340 if (devices[i].minor != -1) {
341 unregister_sound_mixer(devices[i].minor);
342 printk("tvmixer: %s unregistered (#2)\n",
343 devices[i].dev->name);
344 }
345 }
346 }
347
348 module_init(tvmixer_init_module);
349 module_exit(tvmixer_cleanup_module);
350
351 /*
352 * Overrides for Emacs so that we follow Linus's tabbing style.
353 * ---------------------------------------------------------------------------
354 * Local variables:
355 * c-basic-offset: 8
356 * End:
357 */
358