tvmixer.c 8.2 KB

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