opl4_lib.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Functions for accessing OPL4 devices
  4. * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
  5. */
  6. #include "opl4_local.h"
  7. #include <sound/initval.h>
  8. #include <linux/ioport.h>
  9. #include <linux/slab.h>
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/io.h>
  13. MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  14. MODULE_DESCRIPTION("OPL4 driver");
  15. MODULE_LICENSE("GPL");
  16. static inline void snd_opl4_wait(struct snd_opl4 *opl4)
  17. {
  18. int timeout = 10;
  19. while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
  20. ;
  21. }
  22. void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value)
  23. {
  24. snd_opl4_wait(opl4);
  25. outb(reg, opl4->pcm_port);
  26. snd_opl4_wait(opl4);
  27. outb(value, opl4->pcm_port + 1);
  28. }
  29. EXPORT_SYMBOL(snd_opl4_write);
  30. u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
  31. {
  32. snd_opl4_wait(opl4);
  33. outb(reg, opl4->pcm_port);
  34. snd_opl4_wait(opl4);
  35. return inb(opl4->pcm_port + 1);
  36. }
  37. EXPORT_SYMBOL(snd_opl4_read);
  38. void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size)
  39. {
  40. unsigned long flags;
  41. u8 memcfg;
  42. spin_lock_irqsave(&opl4->reg_lock, flags);
  43. memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
  44. snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
  45. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
  46. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
  47. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
  48. snd_opl4_wait(opl4);
  49. outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
  50. snd_opl4_wait(opl4);
  51. insb(opl4->pcm_port + 1, buf, size);
  52. snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
  53. spin_unlock_irqrestore(&opl4->reg_lock, flags);
  54. }
  55. EXPORT_SYMBOL(snd_opl4_read_memory);
  56. void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size)
  57. {
  58. unsigned long flags;
  59. u8 memcfg;
  60. spin_lock_irqsave(&opl4->reg_lock, flags);
  61. memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
  62. snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
  63. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
  64. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
  65. snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
  66. snd_opl4_wait(opl4);
  67. outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
  68. snd_opl4_wait(opl4);
  69. outsb(opl4->pcm_port + 1, buf, size);
  70. snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
  71. spin_unlock_irqrestore(&opl4->reg_lock, flags);
  72. }
  73. EXPORT_SYMBOL(snd_opl4_write_memory);
  74. static void snd_opl4_enable_opl4(struct snd_opl4 *opl4)
  75. {
  76. outb(OPL3_REG_MODE, opl4->fm_port + 2);
  77. inb(opl4->fm_port);
  78. inb(opl4->fm_port);
  79. outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3);
  80. inb(opl4->fm_port);
  81. inb(opl4->fm_port);
  82. }
  83. static int snd_opl4_detect(struct snd_opl4 *opl4)
  84. {
  85. u8 id1, id2;
  86. snd_opl4_enable_opl4(opl4);
  87. id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
  88. dev_dbg(opl4->card->dev, "OPL4[02]=%02x\n", id1);
  89. switch (id1 & OPL4_DEVICE_ID_MASK) {
  90. case 0x20:
  91. opl4->hardware = OPL3_HW_OPL4;
  92. break;
  93. case 0x40:
  94. opl4->hardware = OPL3_HW_OPL4_ML;
  95. break;
  96. default:
  97. return -ENODEV;
  98. }
  99. snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00);
  100. snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff);
  101. id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM);
  102. id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM);
  103. dev_dbg(opl4->card->dev, "OPL4 id1=%02x id2=%02x\n", id1, id2);
  104. if (id1 != 0x00 || id2 != 0xff)
  105. return -ENODEV;
  106. snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f);
  107. snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f);
  108. snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00);
  109. return 0;
  110. }
  111. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  112. static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
  113. {
  114. struct snd_opl4 *opl4 = seq_dev->private_data;
  115. opl4->seq_dev = NULL;
  116. }
  117. static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device)
  118. {
  119. opl4->seq_dev_num = seq_device;
  120. if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4,
  121. sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) {
  122. strcpy(opl4->seq_dev->name, "OPL4 Wavetable");
  123. *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
  124. opl4->seq_dev->private_data = opl4;
  125. opl4->seq_dev->private_free = snd_opl4_seq_dev_free;
  126. }
  127. return 0;
  128. }
  129. #endif
  130. static void snd_opl4_free(struct snd_opl4 *opl4)
  131. {
  132. snd_opl4_free_proc(opl4);
  133. release_and_free_resource(opl4->res_fm_port);
  134. release_and_free_resource(opl4->res_pcm_port);
  135. kfree(opl4);
  136. }
  137. static int snd_opl4_dev_free(struct snd_device *device)
  138. {
  139. struct snd_opl4 *opl4 = device->device_data;
  140. snd_opl4_free(opl4);
  141. return 0;
  142. }
  143. int snd_opl4_create(struct snd_card *card,
  144. unsigned long fm_port, unsigned long pcm_port,
  145. int seq_device,
  146. struct snd_opl3 **ropl3, struct snd_opl4 **ropl4)
  147. {
  148. struct snd_opl4 *opl4;
  149. struct snd_opl3 *opl3;
  150. int err;
  151. static const struct snd_device_ops ops = {
  152. .dev_free = snd_opl4_dev_free
  153. };
  154. if (ropl3)
  155. *ropl3 = NULL;
  156. if (ropl4)
  157. *ropl4 = NULL;
  158. opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL);
  159. if (!opl4)
  160. return -ENOMEM;
  161. opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM");
  162. opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX");
  163. if (!opl4->res_fm_port || !opl4->res_pcm_port) {
  164. dev_err(card->dev, "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port);
  165. snd_opl4_free(opl4);
  166. return -EBUSY;
  167. }
  168. opl4->card = card;
  169. opl4->fm_port = fm_port;
  170. opl4->pcm_port = pcm_port;
  171. spin_lock_init(&opl4->reg_lock);
  172. mutex_init(&opl4->access_mutex);
  173. err = snd_opl4_detect(opl4);
  174. if (err < 0) {
  175. snd_opl4_free(opl4);
  176. dev_dbg(card->dev, "OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port);
  177. return err;
  178. }
  179. err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops);
  180. if (err < 0) {
  181. snd_opl4_free(opl4);
  182. return err;
  183. }
  184. err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3);
  185. if (err < 0) {
  186. snd_device_free(card, opl4);
  187. return err;
  188. }
  189. /* opl3 initialization disabled opl4, so reenable */
  190. snd_opl4_enable_opl4(opl4);
  191. snd_opl4_create_mixer(opl4);
  192. snd_opl4_create_proc(opl4);
  193. #if IS_ENABLED(CONFIG_SND_SEQUENCER)
  194. opl4->seq_client = -1;
  195. if (opl4->hardware < OPL3_HW_OPL4_ML)
  196. snd_opl4_create_seq_dev(opl4, seq_device);
  197. #endif
  198. if (ropl3)
  199. *ropl3 = opl3;
  200. if (ropl4)
  201. *ropl4 = opl4;
  202. return 0;
  203. }
  204. EXPORT_SYMBOL(snd_opl4_create);