adlib.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * AdLib FM card driver.
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/isa.h>
  7. #include <sound/core.h>
  8. #include <sound/initval.h>
  9. #include <sound/opl3.h>
  10. #define CRD_NAME "AdLib FM"
  11. #define DEV_NAME "adlib"
  12. MODULE_DESCRIPTION(CRD_NAME);
  13. MODULE_AUTHOR("Rene Herman");
  14. MODULE_LICENSE("GPL");
  15. static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  16. static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
  17. static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
  18. static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  19. module_param_array(index, int, NULL, 0444);
  20. MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
  21. module_param_array(id, charp, NULL, 0444);
  22. MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
  23. module_param_array(enable, bool, NULL, 0444);
  24. MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
  25. module_param_array(port, long, NULL, 0444);
  26. MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
  27. static int snd_adlib_match(struct device *dev, unsigned int n)
  28. {
  29. if (!enable[n])
  30. return 0;
  31. if (port[n] == SNDRV_AUTO_PORT) {
  32. dev_err(dev, "please specify port\n");
  33. return 0;
  34. }
  35. return 1;
  36. }
  37. static void snd_adlib_free(struct snd_card *card)
  38. {
  39. release_and_free_resource(card->private_data);
  40. }
  41. static int snd_adlib_probe(struct device *dev, unsigned int n)
  42. {
  43. struct snd_card *card;
  44. struct snd_opl3 *opl3;
  45. int error;
  46. error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
  47. if (error < 0) {
  48. dev_err(dev, "could not create card\n");
  49. return error;
  50. }
  51. card->private_data = request_region(port[n], 4, CRD_NAME);
  52. if (!card->private_data) {
  53. dev_err(dev, "could not grab ports\n");
  54. error = -EBUSY;
  55. goto out;
  56. }
  57. card->private_free = snd_adlib_free;
  58. strcpy(card->driver, DEV_NAME);
  59. strcpy(card->shortname, CRD_NAME);
  60. sprintf(card->longname, CRD_NAME " at %#lx", port[n]);
  61. error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
  62. if (error < 0) {
  63. dev_err(dev, "could not create OPL\n");
  64. goto out;
  65. }
  66. error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
  67. if (error < 0) {
  68. dev_err(dev, "could not create FM\n");
  69. goto out;
  70. }
  71. error = snd_card_register(card);
  72. if (error < 0) {
  73. dev_err(dev, "could not register card\n");
  74. goto out;
  75. }
  76. dev_set_drvdata(dev, card);
  77. return 0;
  78. out: snd_card_free(card);
  79. return error;
  80. }
  81. static int snd_adlib_remove(struct device *dev, unsigned int n)
  82. {
  83. snd_card_free(dev_get_drvdata(dev));
  84. return 0;
  85. }
  86. static struct isa_driver snd_adlib_driver = {
  87. .match = snd_adlib_match,
  88. .probe = snd_adlib_probe,
  89. .remove = snd_adlib_remove,
  90. .driver = {
  91. .name = DEV_NAME
  92. }
  93. };
  94. static int __init alsa_card_adlib_init(void)
  95. {
  96. return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS);
  97. }
  98. static void __exit alsa_card_adlib_exit(void)
  99. {
  100. isa_unregister_driver(&snd_adlib_driver);
  101. }
  102. module_init(alsa_card_adlib_init);
  103. module_exit(alsa_card_adlib_exit);