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

Commit 7d13211c authored by Manuel Lauss's avatar Manuel Lauss Committed by Takashi Iwai
Browse files

ALSA: au1x00: convert to platform device



Make sound/mips/au1x00.c a proper platform_driver.

[minor coding style fixes, cleanup and forward-ported by tiwai]

Cc: Charles Eidsness <charles@cooper-street.com>
Signed-off-by: default avatarManuel Lauss <mano@roarinelk.homelinux.net>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent a4f2473d
Loading
Loading
Loading
Loading
+141 −98
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h>
@@ -98,6 +99,7 @@ struct snd_au1000 {

	struct snd_pcm *pcm;
	struct audio_stream *stream[2];	/* playback & capture */
	int dmaid[2];		/* tx(0)/rx(1) DMA ids */
};

/*--------------------------- Local Functions --------------------------------*/
@@ -465,15 +467,17 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000)
	spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);

	flags = claim_dma_lock();
	if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
	au1000->stream[PLAYBACK]->dma = request_au1000_dma(au1000->dmaid[0],
			"AC97 TX", au1000_dma_interrupt, 0,
			au1000->stream[PLAYBACK])) < 0) {
			au1000->stream[PLAYBACK]);
	if (au1000->stream[PLAYBACK]->dma < 0) {
		release_dma_lock(flags);
		return -EBUSY;
	}
	if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
	au1000->stream[CAPTURE]->dma = request_au1000_dma(au1000->dmaid[1],
			"AC97 RX", au1000_dma_interrupt, 0,
			au1000->stream[CAPTURE])) < 0){
			au1000->stream[CAPTURE]);
	if (au1000->stream[CAPTURE]->dma < 0){
		release_dma_lock(flags);
		return -EBUSY;
	}
@@ -552,69 +556,12 @@ get the interrupt driven case to work efficiently */
	spin_unlock(&au1000->ac97_lock);
}

static int
snd_au1000_ac97_new(struct snd_au1000 *au1000)
{
	int err;
	struct snd_ac97_bus *pbus;
	struct snd_ac97_template ac97;
 	static struct snd_ac97_bus_ops ops = {
		.write = snd_au1000_ac97_write,
		.read = snd_au1000_ac97_read,
	};

	if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG),
	       		0x100000, "Au1x00 AC97")) == NULL) {
		snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n");
		return -EBUSY;
	}
	au1000->ac97_ioport = (struct au1000_ac97_reg *)
		KSEG1ADDR(au1000->ac97_res_port->start);

	spin_lock_init(&au1000->ac97_lock);

	/* configure pins for AC'97
	TODO: move to board_setup.c */
	au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);

	/* Initialise Au1000's AC'97 Control Block */
	au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE;
	udelay(10);
	au1000->ac97_ioport->cntrl = AC97C_CE;
	udelay(10);

	/* Initialise External CODEC -- cold reset */
	au1000->ac97_ioport->config = AC97C_RESET;
	udelay(10);
	au1000->ac97_ioport->config = 0x0;
	mdelay(5);

	/* Initialise AC97 middle-layer */
	if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
 		return err;

	memset(&ac97, 0, sizeof(ac97));
	ac97.private_data = au1000;
	if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
		return err;

	return 0;
}

/*------------------------------ Setup / Destroy ----------------------------*/

void
snd_au1000_free(struct snd_card *card)
static void snd_au1000_free(struct snd_card *card)
{
	struct snd_au1000 *au1000 = card->private_data;

	if (au1000->ac97_res_port) {
		/* put internal AC97 block into reset */
		au1000->ac97_ioport->cntrl = AC97C_RS;
		au1000->ac97_ioport = NULL;
		release_and_free_resource(au1000->ac97_res_port);
	}

	if (au1000->stream[PLAYBACK]) {
	  	if (au1000->stream[PLAYBACK]->dma >= 0)
			free_au1000_dma(au1000->stream[PLAYBACK]->dma);
@@ -626,71 +573,167 @@ snd_au1000_free(struct snd_card *card)
			free_au1000_dma(au1000->stream[CAPTURE]->dma);
		kfree(au1000->stream[CAPTURE]);
	}
}

	if (au1000->ac97_res_port) {
		/* put internal AC97 block into reset */
		if (au1000->ac97_ioport) {
			au1000->ac97_ioport->cntrl = AC97C_RS;
			iounmap(au1000->ac97_ioport);
			au1000->ac97_ioport = NULL;
		}
		release_and_free_resource(au1000->ac97_res_port);
		au1000->ac97_res_port = NULL;
	}
}

static struct snd_card *au1000_card;
static struct snd_ac97_bus_ops ops = {
	.write	= snd_au1000_ac97_write,
	.read	= snd_au1000_ac97_read,
};

static int __init
au1000_init(void)
static int au1000_ac97_probe(struct platform_device *pdev)
{
	int err;
	void __iomem *io;
	struct resource *r;
	struct snd_card *card;
	struct snd_au1000 *au1000;
	struct snd_ac97_bus *pbus;
	struct snd_ac97_template ac97;

	err = snd_card_create(-1, "AC97", THIS_MODULE,
				sizeof(struct snd_au1000), &card);
	if (err < 0)
		return err;

	card->private_free = snd_au1000_free;
	au1000 = card->private_data;
	au1000->card = card;
	spin_lock_init(&au1000->ac97_lock);

	au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
	au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
	/* so that snd_au1000_free will work as intended */
 	au1000->ac97_res_port = NULL;
	if (au1000->stream[PLAYBACK])
		au1000->stream[PLAYBACK]->dma = -1;
	if (au1000->stream[CAPTURE ])
		au1000->stream[CAPTURE ]->dma = -1;
	/* from here on let ALSA call the special freeing function */
	card->private_free = snd_au1000_free;

	if (au1000->stream[PLAYBACK] == NULL ||
	    au1000->stream[CAPTURE ] == NULL) {
		snd_card_free(card);
		return -ENOMEM;
	/* TX DMA ID */
	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
	if (!r) {
		err = -ENODEV;
		snd_printk(KERN_INFO "no TX DMA platform resource!\n");
		goto out;
	}
	au1000->dmaid[0] = r->start;

	if ((err = snd_au1000_ac97_new(au1000)) < 0 ) {
		snd_card_free(card);
		return err;
	/* RX DMA ID */
	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
	if (!r) {
		err = -ENODEV;
		snd_printk(KERN_INFO "no RX DMA platform resource!\n");
		goto out;
	}
	au1000->dmaid[1] = r->start;

	if ((err = snd_au1000_pcm_new(au1000)) < 0) {
		snd_card_free(card);
		return err;
	au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream),
					   GFP_KERNEL);
	if (!au1000->stream[PLAYBACK])
		goto out;
	au1000->stream[PLAYBACK]->dma = -1;

	au1000->stream[CAPTURE] = kmalloc(sizeof(struct audio_stream),
					  GFP_KERNEL);
	if (!au1000->stream[CAPTURE])
		goto out;
	au1000->stream[CAPTURE]->dma = -1;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r)
		goto out;

	err = -EBUSY;
	au1000->ac97_res_port = request_mem_region(r->start,
					r->end - r->start + 1, pdev->name);
	if (!au1000->ac97_res_port) {
		snd_printk(KERN_ERR "ALSA AC97: can't grab AC97 port\n");
		goto out;
	}

	io = ioremap(r->start, r->end - r->start + 1);
	if (!io)
		goto out;

	au1000->ac97_ioport = (struct au1000_ac97_reg *)io;

	/* configure pins for AC'97
	TODO: move to board_setup.c */
	au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);

	/* Initialise Au1000's AC'97 Control Block */
	au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE;
	udelay(10);
	au1000->ac97_ioport->cntrl = AC97C_CE;
	udelay(10);

	/* Initialise External CODEC -- cold reset */
	au1000->ac97_ioport->config = AC97C_RESET;
	udelay(10);
	au1000->ac97_ioport->config = 0x0;
	mdelay(5);

	/* Initialise AC97 middle-layer */
	err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus);
	if (err < 0)
		goto out;

	memset(&ac97, 0, sizeof(ac97));
	ac97.private_data = au1000;
	err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97);
	if (err < 0)
		goto out;

	err = snd_au1000_pcm_new(au1000);
	if (err < 0)
		goto out;

	strcpy(card->driver, "Au1000-AC97");
	strcpy(card->shortname, "AMD Au1000-AC97");
	sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver");

	if ((err = snd_card_register(card)) < 0) {
	err = snd_card_register(card);
	if (err < 0)
		goto out;

	printk(KERN_INFO "ALSA AC97: Driver Initialized\n");

	platform_set_drvdata(pdev, card);

	return 0;

 out:
	snd_card_free(card);
	return err;
}

	printk(KERN_INFO "ALSA AC97: Driver Initialized\n");
	au1000_card = card;
	return 0;
static int au1000_ac97_remove(struct platform_device *pdev)
{
	return snd_card_free(platform_get_drvdata(pdev));
}

static void __exit au1000_exit(void)
struct platform_driver au1000_ac97c_driver = {
	.driver	= {
		.name	= "au1000-ac97c",
		.owner	= THIS_MODULE,
	},
	.probe		= au1000_ac97_probe,
	.remove		= au1000_ac97_remove,
};

static int __init au1000_ac97_load(void)
{
	snd_card_free(au1000_card);
	return platform_driver_register(&au1000_ac97c_driver);
}

module_init(au1000_init);
module_exit(au1000_exit);
static void __exit au1000_ac97_unload(void)
{
	platform_driver_unregister(&au1000_ac97c_driver);
}

module_init(au1000_ac97_load);
module_exit(au1000_ac97_unload);