Portability cleanup as required by Linus.
[linux-2.6/linux-mips.git] / drivers / char / tvmixer.c
blob0ef5bbd0300f3cdd8ca3af1a096e5c526162f21c
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/malloc.h>
9 #include <linux/i2c.h>
10 #include <linux/videodev.h>
11 #include <asm/semaphore.h>
12 #include <linux/init.h>
14 #include <linux/sound.h>
15 #include <linux/soundcard.h>
16 #include <asm/uaccess.h>
18 #include "audiochip.h"
20 #define DEV_MAX 4
22 static int debug = 0;
23 static int devnr = -1;
25 MODULE_PARM(debug,"i");
26 MODULE_PARM(devnr,"i");
28 /* ----------------------------------------------------------------------- */
30 struct TVMIXER {
31 struct i2c_client *dev;
32 int minor;
33 int count;
36 static struct TVMIXER devices[DEV_MAX];
38 static int tvmixer_adapters(struct i2c_adapter *adap);
39 static int tvmixer_clients(struct i2c_client *client);
41 static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
42 static int tvmixer_open(struct inode *inode, struct file *file);
43 static int tvmixer_release(struct inode *inode, struct file *file);
44 static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin);
47 static struct i2c_driver driver = {
48 "tv card mixer driver",
49 42 /* I2C_DRIVERID_FIXME */,
50 I2C_DF_DUMMY,
51 tvmixer_adapters,
52 tvmixer_clients,
55 static struct file_operations tvmixer_fops = {
56 owner: THIS_MODULE,
57 llseek: tvmixer_llseek,
58 ioctl: tvmixer_ioctl,
59 open: tvmixer_open,
60 release: tvmixer_release,
63 /* ----------------------------------------------------------------------- */
65 static int mix_to_v4l(int i)
67 int r;
69 r = ((i & 0xff) * 65536 + 50) / 100;
70 if (r > 65535) r = 65535;
71 if (r < 0) r = 0;
72 return r;
75 static int v4l_to_mix(int i)
77 int r;
79 r = (i * 100 + 32768) / 65536;
80 if (r > 100) r = 100;
81 if (r < 0) r = 0;
82 return r | (r << 8);
85 static int v4l_to_mix2(int l, int r)
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;
96 static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
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;
103 if (NULL == client)
104 return -ENODEV;
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;
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;
123 if (cmd == OSS_GETVERSION)
124 return put_user(SOUND_VERSION, (int *)arg);
126 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
127 if (get_user(val, (int *)arg))
128 return -EFAULT;
130 /* read state */
131 memset(&va,0,sizeof(va));
132 client->driver->command(client,VIDIOCGAUDIO,&va);
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;
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;
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;
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;
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;
188 default:
189 return -EINVAL;
191 if (put_user(ret, (int *)arg))
192 return -EFAULT;
193 return 0;
196 static int tvmixer_open(struct inode *inode, struct file *file)
198 int i, minor = MINOR(inode->i_rdev);
199 struct TVMIXER *mix = NULL;
200 struct i2c_client *client = NULL;
202 for (i = 0; i < DEV_MAX; i++) {
203 if (devices[i].minor == minor) {
204 mix = devices+i;
205 client = mix->dev;
206 break;
210 if (NULL == client)
211 return -ENODEV;
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;
220 static int tvmixer_release(struct inode *inode, struct file *file)
222 struct TVMIXER *mix = file->private_data;
223 struct i2c_client *client = mix->dev;
225 if (NULL == client)
226 return -ENODEV;
228 if (client->adapter->dec_use)
229 client->adapter->dec_use(client->adapter);
230 return 0;
233 static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin)
235 return -ESPIPE;
238 /* ----------------------------------------------------------------------- */
240 static int tvmixer_adapters(struct i2c_adapter *adap)
242 return 0;
245 static int tvmixer_clients(struct i2c_client *client)
247 struct video_audio va;
248 int i,minor;
250 /* TV card ??? */
251 if (client->adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
252 if (debug)
253 printk("tvmixer: %s is not a tv card\n",
254 client->adapter->name);
255 return -1;
257 printk("tvmixer: debug: %s\n",client->name);
259 /* unregister ?? */
260 for (i = 0; i < DEV_MAX; i++) {
261 if (devices[i].dev == client) {
262 /* unregister */
263 unregister_sound_mixer(devices[i].minor);
264 devices[i].dev = NULL;
265 devices[i].minor = -1;
266 printk("tvmixer: %s unregistered (#1)\n",client->name);
267 return 0;
271 /* look for a free slot */
272 for (i = 0; i < DEV_MAX; i++)
273 if (NULL == devices[i].dev)
274 break;
275 if (i == DEV_MAX) {
276 printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
277 return -1;
280 /* audio chip with mixer ??? */
281 if (NULL == client->driver->command) {
282 if (debug)
283 printk("tvmixer: %s: driver->command is NULL\n",
284 client->driver->name);
285 return -1;
287 memset(&va,0,sizeof(va));
288 if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
289 if (debug)
290 printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
291 client->name);
292 return -1;
294 if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
295 if (debug)
296 printk("tvmixer: %s: has no volume control\n",
297 client->name);
298 return -1;
301 /* everything is fine, register */
302 if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
303 printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
304 return -1;
307 devices[i].minor = minor;
308 devices[i].count = 0;
309 devices[i].dev = client;
310 printk("tvmixer: %s (%s) registered with minor %d\n",
311 client->name,client->adapter->name,minor);
313 return 0;
316 /* ----------------------------------------------------------------------- */
318 int tvmixer_init_module(void)
320 int i;
322 for (i = 0; i < DEV_MAX; i++)
323 devices[i].minor = -1;
324 i2c_add_driver(&driver);
325 return 0;
328 void tvmixer_cleanup_module(void)
330 int i;
332 i2c_del_driver(&driver);
333 for (i = 0; i < DEV_MAX; i++) {
334 if (devices[i].minor != -1) {
335 unregister_sound_mixer(devices[i].minor);
336 printk("tvmixer: %s unregistered (#2)\n",
337 devices[i].dev->name);
342 module_init(tvmixer_init_module);
343 module_exit(tvmixer_cleanup_module);
346 * Overrides for Emacs so that we follow Linus's tabbing style.
347 * ---------------------------------------------------------------------------
348 * Local variables:
349 * c-basic-offset: 8
350 * End: