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