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>
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"
23 static int devnr
= -1;
25 MODULE_PARM(debug
,"i");
26 MODULE_PARM(devnr
,"i");
28 /* ----------------------------------------------------------------------- */
31 struct i2c_client
*dev
;
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 */,
55 static struct file_operations tvmixer_fops
= {
57 llseek
: tvmixer_llseek
,
60 release
: tvmixer_release
,
63 /* ----------------------------------------------------------------------- */
65 static int mix_to_v4l(int i
)
69 r
= ((i
& 0xff) * 65536 + 50) / 100;
70 if (r
> 65535) r
= 65535;
75 static int v4l_to_mix(int i
)
79 r
= (i
* 100 + 32768) / 65536;
85 static int v4l_to_mix2(int l
, int r
)
87 r
= (r
* 100 + 32768) / 65536;
90 l
= (l
* 100 + 32768) / 65536;
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
;
106 if (cmd
== SOUND_MIXER_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
)))
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
)))
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
))
131 memset(&va
,0,sizeof(va
));
132 client
->driver
->command(client
,VIDIOCGAUDIO
,&va
);
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
):
142 case MIXER_READ(SOUND_MIXER_STEREODEVS
):
143 ret
= SOUND_MASK_VOLUME
;
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
;
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
);
162 case MIXER_READ(SOUND_MIXER_VOLUME
):
163 left
= (MIN(65536 - va
.balance
,32768) *
165 right
= (MIN(va
.balance
,32768) *
167 ret
= v4l_to_mix2(left
,right
);
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
);
175 case MIXER_READ(SOUND_MIXER_BASS
):
176 ret
= v4l_to_mix(va
.bass
);
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
);
184 case MIXER_READ(SOUND_MIXER_TREBLE
):
185 ret
= v4l_to_mix(va
.treble
);
191 if (put_user(ret
, (int *)arg
))
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
) {
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
);
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
;
228 if (client
->adapter
->dec_use
)
229 client
->adapter
->dec_use(client
->adapter
);
233 static loff_t
tvmixer_llseek(struct file
*file
, loff_t offset
, int origin
)
238 /* ----------------------------------------------------------------------- */
240 static int tvmixer_adapters(struct i2c_adapter
*adap
)
245 static int tvmixer_clients(struct i2c_client
*client
)
247 struct video_audio va
;
251 if (client
->adapter
->id
!= (I2C_ALGO_BIT
| I2C_HW_B_BT848
)) {
253 printk("tvmixer: %s is not a tv card\n",
254 client
->adapter
->name
);
257 printk("tvmixer: debug: %s\n",client
->name
);
260 for (i
= 0; i
< DEV_MAX
; i
++) {
261 if (devices
[i
].dev
== client
) {
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
);
271 /* look for a free slot */
272 for (i
= 0; i
< DEV_MAX
; i
++)
273 if (NULL
== devices
[i
].dev
)
276 printk(KERN_WARNING
"tvmixer: DEV_MAX too small\n");
280 /* audio chip with mixer ??? */
281 if (NULL
== client
->driver
->command
) {
283 printk("tvmixer: %s: driver->command is NULL\n",
284 client
->driver
->name
);
287 memset(&va
,0,sizeof(va
));
288 if (0 != client
->driver
->command(client
,VIDIOCGAUDIO
,&va
)) {
290 printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
294 if (0 == (va
.flags
& VIDEO_AUDIO_VOLUME
)) {
296 printk("tvmixer: %s: has no volume control\n",
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");
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
);
316 /* ----------------------------------------------------------------------- */
318 int tvmixer_init_module(void)
322 for (i
= 0; i
< DEV_MAX
; i
++)
323 devices
[i
].minor
= -1;
324 i2c_add_driver(&driver
);
328 void tvmixer_cleanup_module(void)
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 * ---------------------------------------------------------------------------