Commit | Line | Data |
---|---|---|
4a161d23 ML |
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 | ||
87506549 | 45 | static struct snd_soc_card au1xpsc_sample_ac97_machine = { |
4a161d23 ML |
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 = { | |
87506549 | 52 | .card = &au1xpsc_sample_ac97_machine, |
4a161d23 ML |
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>"); |