radio-maestro.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Maestro PCI sound card radio driver for Linux support
  2.  * (c) 2000 A. Tlalka, atlka@pg.gda.pl
  3.  * Notes on the hardware
  4.  *
  5.  *  + Frequency control is done digitally 
  6.  *  + No volume control - only mute/unmute - you have to use Aux line volume
  7.  *  control on Maestro card to set the volume
  8.  *  + Radio status (tuned/not_tuned and stereo/mono) is valid some time after
  9.  *  frequency setting (>100ms) and only when the radio is unmuted.
  10.  *  version 0.02
  11.  *  + io port is automatically detected - only the first radio is used
  12.  *  version 0.03
  13.  *  + thread access locking additions
  14.  *  version 0.04
  15.  * + code improvements
  16.  * + VIDEO_TUNER_LOW is permanent
  17.  */
  18. #include <linux/module.h>
  19. #include <linux/init.h>
  20. #include <linux/ioport.h>
  21. #include <linux/delay.h>
  22. #include <linux/sched.h>
  23. #include <asm/io.h>
  24. #include <asm/uaccess.h>
  25. #include <asm/semaphore.h>
  26. #include <linux/pci.h>
  27. #include <linux/videodev.h>
  28. #define DRIVER_VERSION "0.04"
  29. #define PCI_VENDOR_ESS                  0x125D
  30. #define PCI_DEVICE_ID_ESS_ESS1968       0x1968          /* Maestro 2    */
  31. #define PCI_DEVICE_ID_ESS_ESS1978       0x1978          /* Maestro 2E   */
  32. #define GPIO_DATA       0x60   /* port offset from ESS_IO_BASE */
  33. #define IO_MASK 4      /* mask      register offset from GPIO_DATA
  34. bits 1=unmask write to given bit */
  35. #define IO_DIR 8      /* direction register offset from GPIO_DATA
  36. bits 0/1=read/write direction */
  37. #define GPIO6           0x0040 /* mask bits for GPIO lines */
  38. #define GPIO7           0x0080
  39. #define GPIO8           0x0100
  40. #define GPIO9           0x0200
  41. #define STR_DATA        GPIO6  /* radio TEA5757 pins and GPIO bits */
  42. #define STR_CLK         GPIO7
  43. #define STR_WREN        GPIO8
  44. #define STR_MOST        GPIO9
  45. #define FREQ_LO  50*16000
  46. #define FREQ_HI 150*16000
  47. #define FREQ_IF         171200 /* 10.7*16000   */
  48. #define FREQ_STEP       200    /* 12.5*16      */
  49. #define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))
  50. /(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
  51. #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
  52. static int radio_nr = -1;
  53. MODULE_PARM(radio_nr, "i");
  54. static int radio_open(struct video_device *, int);
  55. static int radio_ioctl(struct video_device *, unsigned int, void *);
  56. static void radio_close(struct video_device *);
  57. static struct video_device maestro_radio=
  58. {
  59. owner: THIS_MODULE,
  60. name: "Maestro radio",
  61. type: VID_TYPE_TUNER,
  62. hardware: VID_HARDWARE_SF16MI,
  63. open: radio_open,
  64. close: radio_close,
  65. ioctl: radio_ioctl,
  66. };
  67. static struct radio_device
  68. {
  69. __u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
  70. muted, /* VIDEO_AUDIO_MUTE */
  71. stereo, /* VIDEO_TUNER_STEREO_ON */
  72. tuned; /* signal strength (0 or 0xffff) */
  73. struct  semaphore lock;
  74. } radio_unit = {0, 0, 0, 0, };
  75. static int users = 0;
  76. static void sleep_125ms(void)
  77. {
  78. current->state = TASK_INTERRUPTIBLE;
  79. schedule_timeout(HZ >> 3);
  80. }
  81. static void udelay2(void)
  82. {
  83. udelay(2);
  84. }
  85. static void udelay4(void)
  86. {
  87. udelay(4);
  88. }
  89. static void udelay16(void)
  90. {
  91. udelay(16);
  92. }
  93. static __u32 radio_bits_get(struct radio_device *dev)
  94. {
  95. register __u16 io=dev->io, l, rdata;
  96. register __u32 data=0;
  97. __u16 omask;
  98. omask = inw(io + IO_MASK);
  99. outw(~(STR_CLK | STR_WREN), io + IO_MASK);
  100. outw(0, io);
  101. udelay16();
  102. for (l=24;l--;) {
  103. outw(STR_CLK, io); /* HI state */
  104. udelay2();
  105. if(!l) 
  106. dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
  107. outw(0, io); /* LO state */
  108. udelay2();
  109. data <<= 1; /* shift data */
  110. rdata = inw(io);
  111. if(!l)
  112. dev->stereo =  rdata & STR_MOST ? 
  113. 0 : VIDEO_TUNER_STEREO_ON;
  114. else
  115. if(rdata & STR_DATA)
  116. data++;
  117. udelay2();
  118. }
  119. if(dev->muted)
  120. outw(STR_WREN, io);
  121. udelay4();
  122. outw(omask, io + IO_MASK);
  123. return data & 0x3ffe;
  124. }
  125. static void radio_bits_set(struct radio_device *dev, __u32 data)
  126. {
  127. register __u16 io=dev->io, l, bits;
  128. __u16 omask, odir;
  129. omask = inw(io + IO_MASK);
  130. odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
  131. outw(odir | STR_DATA, io + IO_DIR);
  132. outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
  133. udelay16();
  134. for (l=25;l;l--) {
  135. bits = ((data >> 18) & STR_DATA) | STR_WREN ;
  136. data <<= 1; /* shift data */
  137. outw(bits, io); /* start strobe */
  138. udelay2();
  139. outw(bits | STR_CLK, io); /* HI level */
  140. udelay2();   
  141. outw(bits, io); /* LO level */
  142. udelay4();
  143. }
  144. if(!dev->muted)
  145. outw(0, io);
  146. udelay4();
  147. outw(omask, io + IO_MASK);
  148. outw(odir, io + IO_DIR);
  149. sleep_125ms();
  150. }
  151. inline static int radio_function(struct video_device *dev, 
  152.  unsigned int cmd, void *arg)
  153. {
  154. struct radio_device *card=dev->priv;
  155. switch(cmd) {
  156. case VIDIOCGCAP: {
  157. struct video_capability v;
  158. strcpy(v.name, "Maestro radio");
  159. v.type=VID_TYPE_TUNER;
  160. v.channels=v.audios=1;
  161. v.maxwidth=v.maxheight=v.minwidth=v.minheight=0;
  162. if(copy_to_user(arg,&v,sizeof(v)))
  163. return -EFAULT;
  164. return 0;
  165. }
  166. case VIDIOCGTUNER: {
  167. struct video_tuner v;
  168. if(copy_from_user(&v, arg,sizeof(v))!=0)
  169. return -EFAULT;
  170. if(v.tuner)
  171. return -EINVAL;
  172. (void)radio_bits_get(card);
  173. v.flags = VIDEO_TUNER_LOW | card->stereo;
  174. v.signal = card->tuned;
  175. strcpy(v.name, "FM");
  176. v.rangelow = FREQ_LO;
  177. v.rangehigh = FREQ_HI;
  178. v.mode = VIDEO_MODE_AUTO;
  179. if(copy_to_user(arg,&v, sizeof(v)))
  180. return -EFAULT;
  181.         return 0;
  182. }
  183. case VIDIOCSTUNER: {
  184. struct video_tuner v;
  185. if(copy_from_user(&v, arg, sizeof(v)))
  186. return -EFAULT;
  187. if(v.tuner!=0)
  188. return -EINVAL;
  189. return 0;
  190. }
  191. case VIDIOCGFREQ: {
  192. unsigned long tmp=BITS2FREQ(radio_bits_get(card));
  193. if(copy_to_user(arg, &tmp, sizeof(tmp)))
  194. return -EFAULT;
  195. return 0;
  196. }
  197. case VIDIOCSFREQ: {
  198. unsigned long tmp;
  199. if(copy_from_user(&tmp, arg, sizeof(tmp)))
  200. return -EFAULT;
  201. if ( tmp<FREQ_LO || tmp>FREQ_HI )
  202. return -EINVAL;
  203. radio_bits_set(card, FREQ2BITS(tmp));
  204. return 0;
  205. }
  206. case VIDIOCGAUDIO: {
  207. struct video_audio v;
  208. strcpy(v.name, "Radio");
  209. v.audio=v.volume=v.bass=v.treble=v.balance=v.step=0;
  210. v.flags=VIDEO_AUDIO_MUTABLE | card->muted;
  211. v.mode=VIDEO_SOUND_STEREO;
  212. if(copy_to_user(arg,&v, sizeof(v)))
  213. return -EFAULT;
  214. return 0;
  215. }
  216. case VIDIOCSAUDIO: {
  217. struct video_audio v;
  218. if(copy_from_user(&v, arg, sizeof(v)))
  219. return -EFAULT;
  220. if(v.audio)
  221. return -EINVAL;
  222. {
  223. register __u16 io=card->io;
  224. register __u16 omask = inw(io + IO_MASK);
  225. outw(~STR_WREN, io + IO_MASK);
  226. outw((card->muted = v.flags & VIDEO_AUDIO_MUTE)
  227.      ? STR_WREN : 0, io);
  228. udelay4();
  229. outw(omask, io + IO_MASK);
  230. sleep_125ms();
  231. return 0;
  232. }
  233. }
  234. case VIDIOCGUNIT: {
  235. struct video_unit v;
  236. v.video=VIDEO_NO_UNIT;
  237. v.vbi=VIDEO_NO_UNIT;
  238. v.radio=dev->minor;
  239. v.audio=0;
  240. v.teletext=VIDEO_NO_UNIT;
  241. if(copy_to_user(arg, &v, sizeof(v)))
  242. return -EFAULT;
  243. return 0;
  244. }
  245. default: return -ENOIOCTLCMD;
  246. }
  247. }
  248. static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
  249. {
  250. struct radio_device *card=dev->priv;
  251. int ret;
  252. down(&card->lock);
  253. ret = radio_function(dev, cmd, arg);
  254. up(&card->lock);
  255. return ret;
  256. }
  257. static int radio_open(struct video_device *dev, int flags)
  258. {
  259. if(users)
  260. return -EBUSY;
  261. users++;
  262. return 0;
  263. }
  264. static void radio_close(struct video_device *dev)
  265. {
  266. users--;
  267. }
  268. inline static __u16 radio_install(struct pci_dev *pcidev);
  269. MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
  270. MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
  271. MODULE_LICENSE("GPL");
  272. EXPORT_NO_SYMBOLS;
  273. void __exit maestro_radio_exit(void)
  274. {
  275. video_unregister_device(&maestro_radio);
  276. }
  277. int __init maestro_radio_init(void)
  278. {
  279. register __u16 found=0;
  280. struct pci_dev *pcidev = NULL;
  281. if(!pci_present())
  282. return -ENODEV;
  283. while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, 
  284.   PCI_DEVICE_ID_ESS_ESS1968,
  285.   pcidev)))
  286. found |= radio_install(pcidev);
  287. while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
  288.   PCI_DEVICE_ID_ESS_ESS1978, 
  289.   pcidev)))
  290. found |= radio_install(pcidev);
  291. if(!found) {
  292. printk(KERN_INFO "radio-maestro: no devices found.n");
  293. return -ENODEV;
  294. }
  295. return 0;
  296. }
  297. module_init(maestro_radio_init);
  298. module_exit(maestro_radio_exit);
  299. inline static __u16 radio_power_on(struct radio_device *dev)
  300. {
  301. register __u16 io=dev->io;
  302. register __u32 ofreq;
  303. __u16 omask, odir;
  304. omask = inw(io + IO_MASK);
  305. odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
  306. outw(odir & ~STR_WREN, io + IO_DIR);
  307. dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
  308. outw(odir, io + IO_DIR);
  309. outw(~(STR_WREN | STR_CLK), io + IO_MASK);
  310. outw(dev->muted ? 0 : STR_WREN, io);
  311. udelay16();
  312. outw(omask, io + IO_MASK);
  313. ofreq = radio_bits_get(dev);
  314. if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
  315. ofreq = FREQ2BITS(FREQ_LO);
  316. radio_bits_set(dev, ofreq);
  317. return (ofreq == radio_bits_get(dev));
  318. }
  319. inline static __u16 radio_install(struct pci_dev *pcidev)
  320. {
  321. if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
  322. return 0;
  323. radio_unit.io = pcidev->resource[0].start + GPIO_DATA;
  324. maestro_radio.priv = &radio_unit;
  325. init_MUTEX(&radio_unit.lock);
  326. if(radio_power_on(&radio_unit)) {
  327. if(video_register_device(&maestro_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
  328. printk("radio-maestro: can't register device!");
  329. return 0;
  330. }
  331. printk(KERN_INFO "radio-maestro: version "
  332.        DRIVER_VERSION 
  333.        " time " 
  334.        __TIME__ "  "
  335.        __DATE__
  336.        "n");
  337. printk(KERN_INFO "radio-maestro: radio chip initializedn");
  338. return 1;
  339. } else
  340. return 0;   
  341. }