Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf40a310 authored by Rene Herman's avatar Rene Herman Committed by Jaroslav Kysela
Browse files

[ALSA] AdLib FM card driver



Attached you'll find an ALSA driver for AdLib FM cards. An AdLib card is
just an OPL2, which was already supported by sound/drivers/opl3, so only
very minimal bus-glue is needed. The patch applies cleanly to both
2.6.16 and 2.6.16-mm1.

The driver has been tested with an actual ancient 8-bit ISA AdLib card
and works fine. It also works fine for an OPL3 {,emulation} as still
found on many ISA soundcards but given that AdLib cards don't have their
own mixer, upping the volume from 0 might be a problem without the card
driver already loaded and driving the OPL3.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 060d77b9
Loading
Loading
Loading
Loading
+28 −0
Original line number Original line Diff line number Diff line
@@ -120,6 +120,34 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
    enable  	- enable card
    enable  	- enable card
		- Default: enabled, for PCI and ISA PnP cards
		- Default: enabled, for PCI and ISA PnP cards


  Module snd-adlib
  ----------------

    Module for AdLib FM cards.

    port	- port # for OPL chip

    This module supports multiple cards. It does not support autoprobe, so
    the port must be specified. For actual AdLib FM cards it will be 0x388.
    Note that this card does not have PCM support and no mixer; only FM
    synthesis.

    Make sure you have "sbiload" from the alsa-tools package available and,
    after loading the module, find out the assigned ALSA sequencer port
    number through "sbiload -l". Example output:

      Port     Client name                       Port name
      64:0     OPL2 FM synth                     OPL2 FM Port

    Load the std.sb and drums.sb patches also supplied by sbiload:

      sbiload -p 64:0 std.sb drums.sb

    If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
    instead. To have the card produce sound, use aplaymidi from alsa-utils:

      aplaymidi -p 64:0 foo.mid

  Module snd-ad1816a
  Module snd-ad1816a
  ------------------
  ------------------


+9 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,15 @@ config SND_CS4231_LIB
        tristate
        tristate
        select SND_PCM
        select SND_PCM


config SND_ADLIB
	tristate "AdLib FM card"
	select SND_OPL3_LIB
	help
	  Say Y here to include support for AdLib FM cards.

	  To compile this driver as a module, choose M here: the module
	  will be called snd-adlib.

config SND_AD1816A
config SND_AD1816A
	tristate "Analog Devices SoundPort AD1816A"
	tristate "Analog Devices SoundPort AD1816A"
	depends on SND && PNP && ISA
	depends on SND && PNP && ISA
+2 −0
Original line number Original line Diff line number Diff line
@@ -3,6 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
#


snd-adlib-objs := adlib.o
snd-als100-objs := als100.o
snd-als100-objs := als100.o
snd-azt2320-objs := azt2320.o
snd-azt2320-objs := azt2320.o
snd-cmi8330-objs := cmi8330.o
snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o
snd-sscape-objs := sscape.o
snd-sscape-objs := sscape.o


# Toplevel Module Dependency
# Toplevel Module Dependency
obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
obj-$(CONFIG_SND_ALS100) += snd-als100.o
obj-$(CONFIG_SND_ALS100) += snd-als100.o
obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o

sound/isa/adlib.c

0 → 100644
+161 −0
Original line number Original line Diff line number Diff line
/*
 * AdLib FM card driver.
 */

#include <sound/driver.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/opl3.h>

#define CRD_NAME "AdLib FM"
#define DRV_NAME "snd_adlib"

MODULE_DESCRIPTION(CRD_NAME);
MODULE_AUTHOR("Rene Herman");
MODULE_LICENSE("GPL");

static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;

module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");

static struct platform_device *devices[SNDRV_CARDS];

static void snd_adlib_free(struct snd_card *card)
{
	release_and_free_resource(card->private_data);
}

static int __devinit snd_adlib_probe(struct platform_device *device)
{
	struct snd_card *card;
	struct snd_opl3 *opl3;

	int error;
	int i = device->id;

	if (port[i] == SNDRV_AUTO_PORT) {
		snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
		error = -EINVAL;
		goto out0;
	}

	card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
	if (!card) {
		snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
		error = -EINVAL;
		goto out0;
	}

	card->private_data = request_region(port[i], 4, CRD_NAME);
	if (!card->private_data) {
		snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
		error = -EBUSY;
		goto out1;
	}
	card->private_free = snd_adlib_free;

	error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
	if (error < 0) {
		snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
		goto out1;
	}

	error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
	if (error < 0) {
		snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
		goto out1;
	}

	strcpy(card->driver, DRV_NAME);
	strcpy(card->shortname, CRD_NAME);
	sprintf(card->longname, CRD_NAME " at %#lx", port[i]);

	snd_card_set_dev(card, &device->dev);

	error = snd_card_register(card);
	if (error < 0) {
		snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
		goto out1;
	}

	platform_set_drvdata(device, card);
	return 0;

out1:	snd_card_free(card);
 out0:	error = -EINVAL; /* FIXME: should be the original error code */
	return error;
}

static int __devexit snd_adlib_remove(struct platform_device *device)
{
	snd_card_free(platform_get_drvdata(device));
	platform_set_drvdata(device, NULL);
	return 0;
}

static struct platform_driver snd_adlib_driver = {
	.probe		= snd_adlib_probe,
	.remove		= __devexit_p(snd_adlib_remove),

	.driver		= {
		.name	= DRV_NAME
	}
};

static int __init alsa_card_adlib_init(void)
{
	int i, cards;

	if (platform_driver_register(&snd_adlib_driver) < 0) {
		snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
		return -ENODEV;
	}

	for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
		struct platform_device *device;

		if (!enable[i])
			continue;

		device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
		if (IS_ERR(device))
			continue;

		devices[i] = device;
		cards++;
	}

	if (!cards) {
#ifdef MODULE
		printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
#endif
		platform_driver_unregister(&snd_adlib_driver);
		return -ENODEV;
	}
	return 0;
}

static void __exit alsa_card_adlib_exit(void)
{
	int i;

	for (i = 0; i < SNDRV_CARDS; i++)
		platform_device_unregister(devices[i]);
	platform_driver_unregister(&snd_adlib_driver);
}

module_init(alsa_card_adlib_init);
module_exit(alsa_card_adlib_exit);