| Manuel Lauss | 4a161d2 | 2008-07-09 16:27:56 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | * Sample Au12x0/Au1550 PSC AC97 sound machine. | 
|  | 3 | * | 
|  | 4 | * Copyright (c) 2007-2008 Manuel Lauss <mano@roarinelk.homelinux.net> | 
|  | 5 | * | 
|  | 6 | *  This program is free software; you can redistribute it and/or modify | 
|  | 7 | *  it under the terms outlined in the file COPYING at the root of this | 
|  | 8 | *  source archive. | 
|  | 9 | * | 
|  | 10 | * This is a very generic AC97 sound machine driver for boards which | 
|  | 11 | * have (AC97) audio at PSC1 (e.g. DB1200 demoboards). | 
|  | 12 | */ | 
|  | 13 |  | 
|  | 14 | #include <linux/module.h> | 
|  | 15 | #include <linux/moduleparam.h> | 
|  | 16 | #include <linux/timer.h> | 
|  | 17 | #include <linux/interrupt.h> | 
|  | 18 | #include <linux/platform_device.h> | 
|  | 19 | #include <sound/core.h> | 
|  | 20 | #include <sound/pcm.h> | 
|  | 21 | #include <sound/soc.h> | 
|  | 22 | #include <sound/soc-dapm.h> | 
|  | 23 | #include <asm/mach-au1x00/au1000.h> | 
|  | 24 | #include <asm/mach-au1x00/au1xxx_psc.h> | 
|  | 25 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | 
|  | 26 |  | 
|  | 27 | #include "../codecs/ac97.h" | 
|  | 28 | #include "psc.h" | 
|  | 29 |  | 
|  | 30 | static int au1xpsc_sample_ac97_init(struct snd_soc_codec *codec) | 
|  | 31 | { | 
|  | 32 | snd_soc_dapm_sync(codec); | 
|  | 33 | return 0; | 
|  | 34 | } | 
|  | 35 |  | 
|  | 36 | static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = { | 
|  | 37 | .name		= "AC97", | 
|  | 38 | .stream_name	= "AC97 HiFi", | 
|  | 39 | .cpu_dai	= &au1xpsc_ac97_dai,	/* see psc-ac97.c */ | 
|  | 40 | .codec_dai	= &ac97_dai,		/* see codecs/ac97.c */ | 
|  | 41 | .init		= au1xpsc_sample_ac97_init, | 
|  | 42 | .ops		= NULL, | 
|  | 43 | }; | 
|  | 44 |  | 
| Mark Brown | 8750654 | 2008-11-18 20:50:34 +0000 | [diff] [blame] | 45 | static struct snd_soc_card au1xpsc_sample_ac97_machine = { | 
| Manuel Lauss | 4a161d2 | 2008-07-09 16:27:56 +0200 | [diff] [blame] | 46 | .name		= "Au1xxx PSC AC97 Audio", | 
|  | 47 | .dai_link	= &au1xpsc_sample_ac97_dai, | 
|  | 48 | .num_links	= 1, | 
|  | 49 | }; | 
|  | 50 |  | 
|  | 51 | static struct snd_soc_device au1xpsc_sample_ac97_devdata = { | 
| Mark Brown | 8750654 | 2008-11-18 20:50:34 +0000 | [diff] [blame] | 52 | .card		= &au1xpsc_sample_ac97_machine, | 
| Manuel Lauss | 4a161d2 | 2008-07-09 16:27:56 +0200 | [diff] [blame] | 53 | .platform	= &au1xpsc_soc_platform, /* see dbdma2.c */ | 
|  | 54 | .codec_dev	= &soc_codec_dev_ac97, | 
|  | 55 | }; | 
|  | 56 |  | 
|  | 57 | static struct resource au1xpsc_psc1_res[] = { | 
|  | 58 | [0] = { | 
|  | 59 | .start	= CPHYSADDR(PSC1_BASE_ADDR), | 
|  | 60 | .end	= CPHYSADDR(PSC1_BASE_ADDR) + 0x000fffff, | 
|  | 61 | .flags	= IORESOURCE_MEM, | 
|  | 62 | }, | 
|  | 63 | [1] = { | 
|  | 64 | #ifdef CONFIG_SOC_AU1200 | 
|  | 65 | .start	= AU1200_PSC1_INT, | 
|  | 66 | .end	= AU1200_PSC1_INT, | 
|  | 67 | #elif defined(CONFIG_SOC_AU1550) | 
|  | 68 | .start	= AU1550_PSC1_INT, | 
|  | 69 | .end	= AU1550_PSC1_INT, | 
|  | 70 | #endif | 
|  | 71 | .flags	= IORESOURCE_IRQ, | 
|  | 72 | }, | 
|  | 73 | [2] = { | 
|  | 74 | .start	= DSCR_CMD0_PSC1_TX, | 
|  | 75 | .end	= DSCR_CMD0_PSC1_TX, | 
|  | 76 | .flags	= IORESOURCE_DMA, | 
|  | 77 | }, | 
|  | 78 | [3] = { | 
|  | 79 | .start	= DSCR_CMD0_PSC1_RX, | 
|  | 80 | .end	= DSCR_CMD0_PSC1_RX, | 
|  | 81 | .flags	= IORESOURCE_DMA, | 
|  | 82 | }, | 
|  | 83 | }; | 
|  | 84 |  | 
|  | 85 | static struct platform_device *au1xpsc_sample_ac97_dev; | 
|  | 86 |  | 
|  | 87 | static int __init au1xpsc_sample_ac97_load(void) | 
|  | 88 | { | 
|  | 89 | int ret; | 
|  | 90 |  | 
|  | 91 | #ifdef CONFIG_SOC_AU1200 | 
|  | 92 | unsigned long io; | 
|  | 93 |  | 
|  | 94 | /* modify sys_pinfunc for AC97 on PSC1 */ | 
|  | 95 | io = au_readl(SYS_PINFUNC); | 
|  | 96 | io |= SYS_PINFUNC_P1C; | 
|  | 97 | io &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B); | 
|  | 98 | au_writel(io, SYS_PINFUNC); | 
|  | 99 | au_sync(); | 
|  | 100 | #endif | 
|  | 101 |  | 
|  | 102 | ret = -ENOMEM; | 
|  | 103 |  | 
|  | 104 | /* setup PSC clock source for AC97 part: external clock provided | 
|  | 105 | * by codec.  The psc-ac97.c driver depends on this setting! | 
|  | 106 | */ | 
|  | 107 | au_writel(PSC_SEL_CLK_SERCLK, PSC1_BASE_ADDR + PSC_SEL_OFFSET); | 
|  | 108 | au_sync(); | 
|  | 109 |  | 
|  | 110 | au1xpsc_sample_ac97_dev = platform_device_alloc("soc-audio", -1); | 
|  | 111 | if (!au1xpsc_sample_ac97_dev) | 
|  | 112 | goto out; | 
|  | 113 |  | 
|  | 114 | au1xpsc_sample_ac97_dev->resource = | 
|  | 115 | kmemdup(au1xpsc_psc1_res, sizeof(struct resource) * | 
|  | 116 | ARRAY_SIZE(au1xpsc_psc1_res), GFP_KERNEL); | 
|  | 117 | au1xpsc_sample_ac97_dev->num_resources = ARRAY_SIZE(au1xpsc_psc1_res); | 
|  | 118 | au1xpsc_sample_ac97_dev->id = 1; | 
|  | 119 |  | 
|  | 120 | platform_set_drvdata(au1xpsc_sample_ac97_dev, | 
|  | 121 | &au1xpsc_sample_ac97_devdata); | 
|  | 122 | au1xpsc_sample_ac97_devdata.dev = &au1xpsc_sample_ac97_dev->dev; | 
|  | 123 | ret = platform_device_add(au1xpsc_sample_ac97_dev); | 
|  | 124 |  | 
|  | 125 | if (ret) { | 
|  | 126 | platform_device_put(au1xpsc_sample_ac97_dev); | 
|  | 127 | au1xpsc_sample_ac97_dev = NULL; | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | out: | 
|  | 131 | return ret; | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | static void __exit au1xpsc_sample_ac97_exit(void) | 
|  | 135 | { | 
|  | 136 | platform_device_unregister(au1xpsc_sample_ac97_dev); | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | module_init(au1xpsc_sample_ac97_load); | 
|  | 140 | module_exit(au1xpsc_sample_ac97_exit); | 
|  | 141 |  | 
|  | 142 | MODULE_LICENSE("GPL"); | 
|  | 143 | MODULE_DESCRIPTION("Au1xxx PSC sample AC97 machine"); | 
|  | 144 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); |