tvmixer.c 8.7 KB

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