tvmixer.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. */
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/string.h>
  6. #include <linux/timer.h>
  7. #include <linux/delay.h>
  8. #include <linux/errno.h>
  9. #include <linux/slab.h>
  10. #include <linux/i2c.h>
  11. #include <linux/videodev.h>
  12. #include <linux/init.h>
  13. #include <linux/kdev_t.h>
  14. #include <linux/sound.h>
  15. #include <linux/soundcard.h>
  16. #include <asm/semaphore.h>
  17. #include <asm/uaccess.h>
  18. #define DEV_MAX 4
  19. static int devnr = -1;
  20. module_param(devnr, int, 0644);
  21. MODULE_AUTHOR("Gerd Knorr");
  22. MODULE_LICENSE("GPL");
  23. /* ----------------------------------------------------------------------- */
  24. struct TVMIXER {
  25. struct i2c_client *dev;
  26. int minor;
  27. int count;
  28. };
  29. static struct TVMIXER devices[DEV_MAX];
  30. static int tvmixer_adapters(struct i2c_adapter *adap);
  31. static int tvmixer_clients(struct i2c_client *client);
  32. /* ----------------------------------------------------------------------- */
  33. static int mix_to_v4l(int i)
  34. {
  35. int r;
  36. r = ((i & 0xff) * 65536 + 50) / 100;
  37. if (r > 65535) r = 65535;
  38. if (r < 0) r = 0;
  39. return r;
  40. }
  41. static int v4l_to_mix(int i)
  42. {
  43. int r;
  44. r = (i * 100 + 32768) / 65536;
  45. if (r > 100) r = 100;
  46. if (r < 0) r = 0;
  47. return r | (r << 8);
  48. }
  49. static int v4l_to_mix2(int l, int r)
  50. {
  51. r = (r * 100 + 32768) / 65536;
  52. if (r > 100) r = 100;
  53. if (r < 0) r = 0;
  54. l = (l * 100 + 32768) / 65536;
  55. if (l > 100) l = 100;
  56. if (l < 0) l = 0;
  57. return (r << 8) | l;
  58. }
  59. static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  60. {
  61. struct video_audio va;
  62. int left,right,ret,val = 0;
  63. struct TVMIXER *mix = file->private_data;
  64. struct i2c_client *client = mix->dev;
  65. void __user *argp = (void __user *)arg;
  66. int __user *p = argp;
  67. if (NULL == client)
  68. return -ENODEV;
  69. if (cmd == SOUND_MIXER_INFO) {
  70. mixer_info info;
  71. strlcpy(info.id, "tv card", sizeof(info.id));
  72. strlcpy(info.name, client->name, sizeof(info.name));
  73. info.modify_counter = 42 /* FIXME */;
  74. if (copy_to_user(argp, &info, sizeof(info)))
  75. return -EFAULT;
  76. return 0;
  77. }
  78. if (cmd == SOUND_OLD_MIXER_INFO) {
  79. _old_mixer_info info;
  80. strlcpy(info.id, "tv card", sizeof(info.id));
  81. strlcpy(info.name, client->name, sizeof(info.name));
  82. if (copy_to_user(argp, &info, sizeof(info)))
  83. return -EFAULT;
  84. return 0;
  85. }
  86. if (cmd == OSS_GETVERSION)
  87. return put_user(SOUND_VERSION, p);
  88. if (_SIOC_DIR(cmd) & _SIOC_WRITE)
  89. if (get_user(val, p))
  90. return -EFAULT;
  91. /* read state */
  92. memset(&va,0,sizeof(va));
  93. client->driver->command(client,VIDIOCGAUDIO,&va);
  94. switch (cmd) {
  95. case MIXER_READ(SOUND_MIXER_RECMASK):
  96. case MIXER_READ(SOUND_MIXER_CAPS):
  97. case MIXER_READ(SOUND_MIXER_RECSRC):
  98. case MIXER_WRITE(SOUND_MIXER_RECSRC):
  99. ret = 0;
  100. break;
  101. case MIXER_READ(SOUND_MIXER_STEREODEVS):
  102. ret = SOUND_MASK_VOLUME;
  103. break;
  104. case MIXER_READ(SOUND_MIXER_DEVMASK):
  105. ret = SOUND_MASK_VOLUME;
  106. if (va.flags & VIDEO_AUDIO_BASS)
  107. ret |= SOUND_MASK_BASS;
  108. if (va.flags & VIDEO_AUDIO_TREBLE)
  109. ret |= SOUND_MASK_TREBLE;
  110. break;
  111. case MIXER_WRITE(SOUND_MIXER_VOLUME):
  112. left = mix_to_v4l(val);
  113. right = mix_to_v4l(val >> 8);
  114. va.volume = max(left,right);
  115. va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1);
  116. va.balance = (left<right) ? (65535-va.balance) : va.balance;
  117. if (va.volume)
  118. va.flags &= ~VIDEO_AUDIO_MUTE;
  119. client->driver->command(client,VIDIOCSAUDIO,&va);
  120. client->driver->command(client,VIDIOCGAUDIO,&va);
  121. /* fall throuth */
  122. case MIXER_READ(SOUND_MIXER_VOLUME):
  123. left = (min(65536 - va.balance,32768) *
  124. va.volume) / 32768;
  125. right = (min(va.balance,(u16)32768) *
  126. va.volume) / 32768;
  127. ret = v4l_to_mix2(left,right);
  128. break;
  129. case MIXER_WRITE(SOUND_MIXER_BASS):
  130. va.bass = mix_to_v4l(val);
  131. client->driver->command(client,VIDIOCSAUDIO,&va);
  132. client->driver->command(client,VIDIOCGAUDIO,&va);
  133. /* fall throuth */
  134. case MIXER_READ(SOUND_MIXER_BASS):
  135. ret = v4l_to_mix(va.bass);
  136. break;
  137. case MIXER_WRITE(SOUND_MIXER_TREBLE):
  138. va.treble = mix_to_v4l(val);
  139. client->driver->command(client,VIDIOCSAUDIO,&va);
  140. client->driver->command(client,VIDIOCGAUDIO,&va);
  141. /* fall throuth */
  142. case MIXER_READ(SOUND_MIXER_TREBLE):
  143. ret = v4l_to_mix(va.treble);
  144. break;
  145. default:
  146. return -EINVAL;
  147. }
  148. if (put_user(ret, p))
  149. return -EFAULT;
  150. return 0;
  151. }
  152. static int tvmixer_open(struct inode *inode, struct file *file)
  153. {
  154. int i, minor = iminor(inode);
  155. struct TVMIXER *mix = NULL;
  156. struct i2c_client *client = NULL;
  157. for (i = 0; i < DEV_MAX; i++) {
  158. if (devices[i].minor == minor) {
  159. mix = devices+i;
  160. client = mix->dev;
  161. break;
  162. }
  163. }
  164. if (NULL == client)
  165. return -ENODEV;
  166. /* lock bttv in memory while the mixer is in use */
  167. file->private_data = mix;
  168. if (client->adapter->owner)
  169. try_module_get(client->adapter->owner);
  170. return 0;
  171. }
  172. static int tvmixer_release(struct inode *inode, struct file *file)
  173. {
  174. struct TVMIXER *mix = file->private_data;
  175. struct i2c_client *client;
  176. client = mix->dev;
  177. if (NULL == client) {
  178. return -ENODEV;
  179. }
  180. module_put(client->adapter->owner);
  181. return 0;
  182. }
  183. static struct i2c_driver driver = {
  184. .driver = {
  185. .name = "tvmixer",
  186. },
  187. .id = I2C_DRIVERID_TVMIXER,
  188. .detach_adapter = tvmixer_adapters,
  189. .attach_adapter = tvmixer_adapters,
  190. .detach_client = tvmixer_clients,
  191. };
  192. static const struct file_operations tvmixer_fops = {
  193. .owner = THIS_MODULE,
  194. .llseek = no_llseek,
  195. .ioctl = tvmixer_ioctl,
  196. .open = tvmixer_open,
  197. .release = tvmixer_release,
  198. };
  199. /* ----------------------------------------------------------------------- */
  200. static int tvmixer_adapters(struct i2c_adapter *adap)
  201. {
  202. struct i2c_client *client;
  203. list_for_each_entry(client, &adap->clients, list)
  204. tvmixer_clients(client);
  205. return 0;
  206. }
  207. static int tvmixer_clients(struct i2c_client *client)
  208. {
  209. struct video_audio va;
  210. int i,minor;
  211. if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
  212. return -1;
  213. /* unregister ?? */
  214. for (i = 0; i < DEV_MAX; i++) {
  215. if (devices[i].dev == client) {
  216. /* unregister */
  217. unregister_sound_mixer(devices[i].minor);
  218. devices[i].dev = NULL;
  219. devices[i].minor = -1;
  220. printk("tvmixer: %s unregistered (#1)\n",
  221. client->name);
  222. return 0;
  223. }
  224. }
  225. /* look for a free slot */
  226. for (i = 0; i < DEV_MAX; i++)
  227. if (NULL == devices[i].dev)
  228. break;
  229. if (i == DEV_MAX) {
  230. printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
  231. return -1;
  232. }
  233. /* audio chip with mixer ??? */
  234. if (NULL == client->driver->command)
  235. return -1;
  236. memset(&va,0,sizeof(va));
  237. if (0 != client->driver->command(client,VIDIOCGAUDIO,&va))
  238. return -1;
  239. if (0 == (va.flags & VIDEO_AUDIO_VOLUME))
  240. return -1;
  241. /* everything is fine, register */
  242. if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
  243. printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
  244. return -1;
  245. }
  246. devices[i].minor = minor;
  247. devices[i].count = 0;
  248. devices[i].dev = client;
  249. printk("tvmixer: %s (%s) registered with minor %d\n",
  250. client->name,client->adapter->name,minor);
  251. return 0;
  252. }
  253. /* ----------------------------------------------------------------------- */
  254. static int __init tvmixer_init_module(void)
  255. {
  256. int i;
  257. for (i = 0; i < DEV_MAX; i++)
  258. devices[i].minor = -1;
  259. return i2c_add_driver(&driver);
  260. }
  261. static void __exit tvmixer_cleanup_module(void)
  262. {
  263. int i;
  264. i2c_del_driver(&driver);
  265. for (i = 0; i < DEV_MAX; i++) {
  266. if (devices[i].minor != -1) {
  267. unregister_sound_mixer(devices[i].minor);
  268. printk("tvmixer: %s unregistered (#2)\n",
  269. devices[i].dev->name);
  270. }
  271. }
  272. }
  273. module_init(tvmixer_init_module);
  274. module_exit(tvmixer_cleanup_module);
  275. /*
  276. * Overrides for Emacs so that we follow Linus's tabbing style.
  277. * ---------------------------------------------------------------------------
  278. * Local variables:
  279. * c-basic-offset: 8
  280. * End:
  281. */