xref: /openbmc/linux/sound/soc/sh/hac.c (revision c4c3c32d)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Hitachi Audio Controller (AC97) support for SH7760/SH7780
4 //
5 // Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
6 //
7 // dont forget to set IPSEL/OMSEL register bits (in your board code) to
8 // enable HAC output pins!
9 
10 /* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only
11  * the FIRST can be used since ASoC does not pass any information to the
12  * ac97_read/write() functions regarding WHICH unit to use.  You'll have
13  * to edit the code a bit to use the other AC97 unit.		--mlau
14  */
15 
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/interrupt.h>
20 #include <linux/wait.h>
21 #include <linux/delay.h>
22 #include <sound/core.h>
23 #include <sound/pcm.h>
24 #include <sound/ac97_codec.h>
25 #include <sound/initval.h>
26 #include <sound/soc.h>
27 
28 /* regs and bits */
29 #define HACCR		0x08
30 #define HACCSAR		0x20
31 #define HACCSDR		0x24
32 #define HACPCML		0x28
33 #define HACPCMR		0x2C
34 #define HACTIER		0x50
35 #define	HACTSR		0x54
36 #define HACRIER		0x58
37 #define HACRSR		0x5C
38 #define HACACR		0x60
39 
40 #define CR_CR		(1 << 15)	/* "codec-ready" indicator */
41 #define CR_CDRT		(1 << 11)	/* cold reset */
42 #define CR_WMRT		(1 << 10)	/* warm reset */
43 #define CR_B9		(1 << 9)	/* the mysterious "bit 9" */
44 #define CR_ST		(1 << 5)	/* AC97 link start bit */
45 
46 #define CSAR_RD		(1 << 19)	/* AC97 data read bit */
47 #define CSAR_WR		(0)
48 
49 #define TSR_CMDAMT	(1 << 31)
50 #define TSR_CMDDMT	(1 << 30)
51 
52 #define RSR_STARY	(1 << 22)
53 #define RSR_STDRY	(1 << 21)
54 
55 #define ACR_DMARX16	(1 << 30)
56 #define ACR_DMATX16	(1 << 29)
57 #define ACR_TX12ATOM	(1 << 26)
58 #define ACR_DMARX20	((1 << 24) | (1 << 22))
59 #define ACR_DMATX20	((1 << 23) | (1 << 21))
60 
61 #define CSDR_SHIFT	4
62 #define CSDR_MASK	(0xffff << CSDR_SHIFT)
63 #define CSAR_SHIFT	12
64 #define CSAR_MASK	(0x7f << CSAR_SHIFT)
65 
66 #define AC97_WRITE_RETRY	1
67 #define AC97_READ_RETRY		5
68 
69 /* manual-suggested AC97 codec access timeouts (us) */
70 #define TMO_E1	500	/* 21 < E1 < 1000 */
71 #define TMO_E2	13	/* 13 < E2 */
72 #define TMO_E3	21	/* 21 < E3 */
73 #define TMO_E4	500	/* 21 < E4 < 1000 */
74 
75 struct hac_priv {
76 	unsigned long mmio;	/* HAC base address */
77 } hac_cpu_data[] = {
78 #if defined(CONFIG_CPU_SUBTYPE_SH7760)
79 	{
80 		.mmio	= 0xFE240000,
81 	},
82 	{
83 		.mmio	= 0xFE250000,
84 	},
85 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
86 	{
87 		.mmio	= 0xFFE40000,
88 	},
89 #else
90 #error "Unsupported SuperH SoC"
91 #endif
92 };
93 
94 #define HACREG(reg)	(*(unsigned long *)(hac->mmio + (reg)))
95 
96 /*
97  * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906)
98  */
99 static int hac_get_codec_data(struct hac_priv *hac, unsigned short r,
100 			      unsigned short *v)
101 {
102 	unsigned int to1, to2, i;
103 	unsigned short adr;
104 
105 	for (i = AC97_READ_RETRY; i; i--) {
106 		*v = 0;
107 		/* wait for HAC to receive something from the codec */
108 		for (to1 = TMO_E4;
109 		     to1 && !(HACREG(HACRSR) & RSR_STARY);
110 		     --to1)
111 			udelay(1);
112 		for (to2 = TMO_E4;
113 		     to2 && !(HACREG(HACRSR) & RSR_STDRY);
114 		     --to2)
115 			udelay(1);
116 
117 		if (!to1 && !to2)
118 			return 0;	/* codec comm is down */
119 
120 		adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT);
121 		*v  = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT);
122 
123 		HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
124 
125 		if (r == adr)
126 			break;
127 
128 		/* manual says: wait at least 21 usec before retrying */
129 		udelay(21);
130 	}
131 	HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
132 	return i;
133 }
134 
135 static unsigned short hac_read_codec_aux(struct hac_priv *hac,
136 					 unsigned short reg)
137 {
138 	unsigned short val;
139 	unsigned int i, to;
140 
141 	for (i = AC97_READ_RETRY; i; i--) {
142 		/* send_read_request */
143 		local_irq_disable();
144 		HACREG(HACTSR) &= ~(TSR_CMDAMT);
145 		HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD;
146 		local_irq_enable();
147 
148 		for (to = TMO_E3;
149 		     to && !(HACREG(HACTSR) & TSR_CMDAMT);
150 		     --to)
151 			udelay(1);
152 
153 		HACREG(HACTSR) &= ~TSR_CMDAMT;
154 		val = 0;
155 		if (hac_get_codec_data(hac, reg, &val) != 0)
156 			break;
157 	}
158 
159 	return i ? val : ~0;
160 }
161 
162 static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
163 			   unsigned short val)
164 {
165 	int unit_id = 0 /* ac97->private_data */;
166 	struct hac_priv *hac = &hac_cpu_data[unit_id];
167 	unsigned int i, to;
168 	/* write_codec_aux */
169 	for (i = AC97_WRITE_RETRY; i; i--) {
170 		/* send_write_request */
171 		local_irq_disable();
172 		HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT);
173 		HACREG(HACCSDR) = (val << CSDR_SHIFT);
174 		HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD);
175 		local_irq_enable();
176 
177 		/* poll-wait for CMDAMT and CMDDMT */
178 		for (to = TMO_E1;
179 		     to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT));
180 		     --to)
181 			udelay(1);
182 
183 		HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT);
184 		if (to)
185 			break;
186 		/* timeout, try again */
187 	}
188 }
189 
190 static unsigned short hac_ac97_read(struct snd_ac97 *ac97,
191 				    unsigned short reg)
192 {
193 	int unit_id = 0 /* ac97->private_data */;
194 	struct hac_priv *hac = &hac_cpu_data[unit_id];
195 	return hac_read_codec_aux(hac, reg);
196 }
197 
198 static void hac_ac97_warmrst(struct snd_ac97 *ac97)
199 {
200 	int unit_id = 0 /* ac97->private_data */;
201 	struct hac_priv *hac = &hac_cpu_data[unit_id];
202 	unsigned int tmo;
203 
204 	HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9;
205 	msleep(10);
206 	HACREG(HACCR) = CR_ST | CR_B9;
207 	for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--)
208 		udelay(1);
209 
210 	if (!tmo)
211 		printk(KERN_INFO "hac: reset: AC97 link down!\n");
212 	/* settings this bit lets us have a conversation with codec */
213 	HACREG(HACACR) |= ACR_TX12ATOM;
214 }
215 
216 static void hac_ac97_coldrst(struct snd_ac97 *ac97)
217 {
218 	int unit_id = 0 /* ac97->private_data */;
219 	struct hac_priv *hac;
220 	hac = &hac_cpu_data[unit_id];
221 
222 	HACREG(HACCR) = 0;
223 	HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9;
224 	msleep(10);
225 	hac_ac97_warmrst(ac97);
226 }
227 
228 static struct snd_ac97_bus_ops hac_ac97_ops = {
229 	.read	= hac_ac97_read,
230 	.write	= hac_ac97_write,
231 	.reset	= hac_ac97_coldrst,
232 	.warm_reset = hac_ac97_warmrst,
233 };
234 
235 static int hac_hw_params(struct snd_pcm_substream *substream,
236 			 struct snd_pcm_hw_params *params,
237 			 struct snd_soc_dai *dai)
238 {
239 	struct hac_priv *hac = &hac_cpu_data[dai->id];
240 	int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
241 
242 	switch (params->msbits) {
243 	case 16:
244 		HACREG(HACACR) |= d ?  ACR_DMARX16 :  ACR_DMATX16;
245 		HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20;
246 		break;
247 	case 20:
248 		HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16;
249 		HACREG(HACACR) |= d ?  ACR_DMARX20 :  ACR_DMATX20;
250 		break;
251 	default:
252 		pr_debug("hac: invalid depth %d bit\n", params->msbits);
253 		return -EINVAL;
254 		break;
255 	}
256 
257 	return 0;
258 }
259 
260 #define AC97_RATES	\
261 	SNDRV_PCM_RATE_8000_192000
262 
263 #define AC97_FMTS	\
264 	SNDRV_PCM_FMTBIT_S16_LE
265 
266 static const struct snd_soc_dai_ops hac_dai_ops = {
267 	.hw_params	= hac_hw_params,
268 };
269 
270 static struct snd_soc_dai_driver sh4_hac_dai[] = {
271 {
272 	.name			= "hac-dai.0",
273 	.playback = {
274 		.rates		= AC97_RATES,
275 		.formats	= AC97_FMTS,
276 		.channels_min	= 2,
277 		.channels_max	= 2,
278 	},
279 	.capture = {
280 		.rates		= AC97_RATES,
281 		.formats	= AC97_FMTS,
282 		.channels_min	= 2,
283 		.channels_max	= 2,
284 	},
285 	.ops = &hac_dai_ops,
286 },
287 #ifdef CONFIG_CPU_SUBTYPE_SH7760
288 {
289 	.name			= "hac-dai.1",
290 	.id			= 1,
291 	.playback = {
292 		.rates		= AC97_RATES,
293 		.formats	= AC97_FMTS,
294 		.channels_min	= 2,
295 		.channels_max	= 2,
296 	},
297 	.capture = {
298 		.rates		= AC97_RATES,
299 		.formats	= AC97_FMTS,
300 		.channels_min	= 2,
301 		.channels_max	= 2,
302 	},
303 	.ops = &hac_dai_ops,
304 
305 },
306 #endif
307 };
308 
309 static const struct snd_soc_component_driver sh4_hac_component = {
310 	.name			= "sh4-hac",
311 	.legacy_dai_naming	= 1,
312 };
313 
314 static int hac_soc_platform_probe(struct platform_device *pdev)
315 {
316 	int ret;
317 
318 	ret = snd_soc_set_ac97_ops(&hac_ac97_ops);
319 	if (ret != 0)
320 		return ret;
321 
322 	return devm_snd_soc_register_component(&pdev->dev, &sh4_hac_component,
323 					  sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
324 }
325 
326 static void hac_soc_platform_remove(struct platform_device *pdev)
327 {
328 	snd_soc_set_ac97_ops(NULL);
329 }
330 
331 static struct platform_driver hac_pcm_driver = {
332 	.driver = {
333 			.name = "hac-pcm-audio",
334 	},
335 
336 	.probe = hac_soc_platform_probe,
337 	.remove_new = hac_soc_platform_remove,
338 };
339 
340 module_platform_driver(hac_pcm_driver);
341 
342 MODULE_LICENSE("GPL v2");
343 MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
344 MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
345