brintos

brintos / linux-shallow public Read only

0
0
Text · 12.5 KiB · 8a59a50 Raw
498 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Au12x0/Au1550 PSC ALSA ASoC audio support.4 *5 * (c) 2007-2009 MSC Vertriebsges.m.b.H.,6 *	Manuel Lauss <manuel.lauss@gmail.com>7 *8 * Au1xxx-PSC AC97 glue.9 */10 11#include <linux/init.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/device.h>15#include <linux/delay.h>16#include <linux/mutex.h>17#include <linux/suspend.h>18#include <sound/core.h>19#include <sound/pcm.h>20#include <sound/initval.h>21#include <sound/soc.h>22#include <asm/mach-au1x00/au1000.h>23#include <asm/mach-au1x00/au1xxx_psc.h>24 25#include "psc.h"26 27/* how often to retry failed codec register reads/writes */28#define AC97_RW_RETRIES	529 30#define AC97_DIR	\31	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)32 33#define AC97_RATES	\34	SNDRV_PCM_RATE_8000_4800035 36#define AC97_FMTS	\37	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)38 39#define AC97PCR_START(stype)	\40	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)41#define AC97PCR_STOP(stype)	\42	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)43#define AC97PCR_CLRFIFO(stype)	\44	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)45 46#define AC97STAT_BUSY(stype)	\47	((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)48 49/* instance data. There can be only one, MacLeod!!!! */50static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;51 52#if 053 54/* this could theoretically work, but ac97->bus->card->private_data can be NULL55 * when snd_ac97_mixer() is called; I don't know if the rest further down the56 * chain are always valid either.57 */58static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)59{60	struct snd_soc_card *c = x->bus->card->private_data;61	return snd_soc_dai_get_drvdata(c->snd_soc_rtd_to_cpu(rtd, 0));62}63 64#else65 66#define ac97_to_pscdata(x)	au1xpsc_ac97_workdata67 68#endif69 70/* AC97 controller reads codec register */71static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,72					unsigned short reg)73{74	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);75	unsigned short retry, tmo;76	unsigned long data;77 78	__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));79	wmb(); /* drain writebuffer */80 81	retry = AC97_RW_RETRIES;82	do {83		mutex_lock(&pscdata->lock);84 85		__raw_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),86			  AC97_CDC(pscdata));87		wmb(); /* drain writebuffer */88 89		tmo = 20;90		do {91			udelay(21);92			if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)93				break;94		} while (--tmo);95 96		data = __raw_readl(AC97_CDC(pscdata));97 98		__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));99		wmb(); /* drain writebuffer */100 101		mutex_unlock(&pscdata->lock);102 103		if (reg != ((data >> 16) & 0x7f))104			tmo = 1;	/* wrong register, try again */105 106	} while (--retry && !tmo);107 108	return retry ? data & 0xffff : 0xffff;109}110 111/* AC97 controller writes to codec register */112static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,113				unsigned short val)114{115	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);116	unsigned int tmo, retry;117 118	__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));119	wmb(); /* drain writebuffer */120 121	retry = AC97_RW_RETRIES;122	do {123		mutex_lock(&pscdata->lock);124 125		__raw_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),126			  AC97_CDC(pscdata));127		wmb(); /* drain writebuffer */128 129		tmo = 20;130		do {131			udelay(21);132			if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)133				break;134		} while (--tmo);135 136		__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));137		wmb(); /* drain writebuffer */138 139		mutex_unlock(&pscdata->lock);140	} while (--retry && !tmo);141}142 143/* AC97 controller asserts a warm reset */144static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)145{146	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);147 148	__raw_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));149	wmb(); /* drain writebuffer */150	msleep(10);151	__raw_writel(0, AC97_RST(pscdata));152	wmb(); /* drain writebuffer */153}154 155static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)156{157	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);158	int i;159 160	/* disable PSC during cold reset */161	__raw_writel(0, AC97_CFG(au1xpsc_ac97_workdata));162	wmb(); /* drain writebuffer */163	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));164	wmb(); /* drain writebuffer */165 166	/* issue cold reset */167	__raw_writel(PSC_AC97RST_RST, AC97_RST(pscdata));168	wmb(); /* drain writebuffer */169	msleep(500);170	__raw_writel(0, AC97_RST(pscdata));171	wmb(); /* drain writebuffer */172 173	/* enable PSC */174	__raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));175	wmb(); /* drain writebuffer */176 177	/* wait for PSC to indicate it's ready */178	i = 1000;179	while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))180		msleep(1);181 182	if (i == 0) {183		printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");184		return;185	}186 187	/* enable the ac97 function */188	__raw_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));189	wmb(); /* drain writebuffer */190 191	/* wait for AC97 core to become ready */192	i = 1000;193	while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))194		msleep(1);195	if (i == 0)196		printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");197}198 199/* AC97 controller operations */200static struct snd_ac97_bus_ops psc_ac97_ops = {201	.read		= au1xpsc_ac97_read,202	.write		= au1xpsc_ac97_write,203	.reset		= au1xpsc_ac97_cold_reset,204	.warm_reset	= au1xpsc_ac97_warm_reset,205};206 207static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,208				  struct snd_pcm_hw_params *params,209				  struct snd_soc_dai *dai)210{211	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);212	unsigned long r, ro, stat;213	int chans, t, stype = substream->stream;214 215	chans = params_channels(params);216 217	r = ro = __raw_readl(AC97_CFG(pscdata));218	stat = __raw_readl(AC97_STAT(pscdata));219 220	/* already active? */221	if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {222		/* reject parameters not currently set up */223		if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||224		    (pscdata->rate != params_rate(params)))225			return -EINVAL;226	} else {227 228		/* set sample bitdepth: REG[24:21]=(BITS-2)/2 */229		r &= ~PSC_AC97CFG_LEN_MASK;230		r |= PSC_AC97CFG_SET_LEN(params->msbits);231 232		/* channels: enable slots for front L/R channel */233		if (stype == SNDRV_PCM_STREAM_PLAYBACK) {234			r &= ~PSC_AC97CFG_TXSLOT_MASK;235			r |= PSC_AC97CFG_TXSLOT_ENA(3);236			r |= PSC_AC97CFG_TXSLOT_ENA(4);237		} else {238			r &= ~PSC_AC97CFG_RXSLOT_MASK;239			r |= PSC_AC97CFG_RXSLOT_ENA(3);240			r |= PSC_AC97CFG_RXSLOT_ENA(4);241		}242 243		/* do we need to poke the hardware? */244		if (!(r ^ ro))245			goto out;246 247		/* ac97 engine is about to be disabled */248		mutex_lock(&pscdata->lock);249 250		/* disable AC97 device controller first... */251		__raw_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));252		wmb(); /* drain writebuffer */253 254		/* ...wait for it... */255		t = 100;256		while ((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)257			msleep(1);258 259		if (!t)260			printk(KERN_ERR "PSC-AC97: can't disable!\n");261 262		/* ...write config... */263		__raw_writel(r, AC97_CFG(pscdata));264		wmb(); /* drain writebuffer */265 266		/* ...enable the AC97 controller again... */267		__raw_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));268		wmb(); /* drain writebuffer */269 270		/* ...and wait for ready bit */271		t = 100;272		while ((!(__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)273			msleep(1);274 275		if (!t)276			printk(KERN_ERR "PSC-AC97: can't enable!\n");277 278		mutex_unlock(&pscdata->lock);279 280		pscdata->cfg = r;281		pscdata->rate = params_rate(params);282	}283 284out:285	return 0;286}287 288static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,289				int cmd, struct snd_soc_dai *dai)290{291	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);292	int ret, stype = substream->stream;293 294	ret = 0;295 296	switch (cmd) {297	case SNDRV_PCM_TRIGGER_START:298	case SNDRV_PCM_TRIGGER_RESUME:299		__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));300		wmb(); /* drain writebuffer */301		__raw_writel(AC97PCR_START(stype), AC97_PCR(pscdata));302		wmb(); /* drain writebuffer */303		break;304	case SNDRV_PCM_TRIGGER_STOP:305	case SNDRV_PCM_TRIGGER_SUSPEND:306		__raw_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));307		wmb(); /* drain writebuffer */308 309		while (__raw_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))310			asm volatile ("nop");311 312		__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));313		wmb(); /* drain writebuffer */314 315		break;316	default:317		ret = -EINVAL;318	}319	return ret;320}321 322static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,323				struct snd_soc_dai *dai)324{325	struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);326	snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);327	return 0;328}329 330static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)331{332	return au1xpsc_ac97_workdata ? 0 : -ENODEV;333}334 335static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {336	.probe		= au1xpsc_ac97_probe,337	.startup	= au1xpsc_ac97_startup,338	.trigger	= au1xpsc_ac97_trigger,339	.hw_params	= au1xpsc_ac97_hw_params,340};341 342static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {343	.playback = {344		.rates		= AC97_RATES,345		.formats	= AC97_FMTS,346		.channels_min	= 2,347		.channels_max	= 2,348	},349	.capture = {350		.rates		= AC97_RATES,351		.formats	= AC97_FMTS,352		.channels_min	= 2,353		.channels_max	= 2,354	},355	.ops = &au1xpsc_ac97_dai_ops,356};357 358static const struct snd_soc_component_driver au1xpsc_ac97_component = {359	.name			= "au1xpsc-ac97",360	.legacy_dai_naming	= 1,361};362 363static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)364{365	int ret;366	struct resource *dmares;367	unsigned long sel;368	struct au1xpsc_audio_data *wd;369 370	wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),371			  GFP_KERNEL);372	if (!wd)373		return -ENOMEM;374 375	mutex_init(&wd->lock);376 377	wd->mmio = devm_platform_ioremap_resource(pdev, 0);378	if (IS_ERR(wd->mmio))379		return PTR_ERR(wd->mmio);380 381	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);382	if (!dmares)383		return -EBUSY;384	wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;385 386	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);387	if (!dmares)388		return -EBUSY;389	wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;390 391	/* configuration: max dma trigger threshold, enable ac97 */392	wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |393		  PSC_AC97CFG_DE_ENABLE;394 395	/* preserve PSC clock source set up by platform	 */396	sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;397	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));398	wmb(); /* drain writebuffer */399	__raw_writel(0, PSC_SEL(wd));400	wmb(); /* drain writebuffer */401	__raw_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));402	wmb(); /* drain writebuffer */403 404	/* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */405	memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,406	       sizeof(struct snd_soc_dai_driver));407	wd->dai_drv.name = dev_name(&pdev->dev);408 409	platform_set_drvdata(pdev, wd);410 411	ret = snd_soc_set_ac97_ops(&psc_ac97_ops);412	if (ret)413		return ret;414 415	ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,416					 &wd->dai_drv, 1);417	if (ret)418		return ret;419 420	au1xpsc_ac97_workdata = wd;421	return 0;422}423 424static void au1xpsc_ac97_drvremove(struct platform_device *pdev)425{426	struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);427 428	snd_soc_unregister_component(&pdev->dev);429 430	/* disable PSC completely */431	__raw_writel(0, AC97_CFG(wd));432	wmb(); /* drain writebuffer */433	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));434	wmb(); /* drain writebuffer */435 436	au1xpsc_ac97_workdata = NULL;	/* MDEV */437}438 439#ifdef CONFIG_PM440static int au1xpsc_ac97_drvsuspend(struct device *dev)441{442	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);443 444	/* save interesting registers and disable PSC */445	wd->pm[0] = __raw_readl(PSC_SEL(wd));446 447	__raw_writel(0, AC97_CFG(wd));448	wmb(); /* drain writebuffer */449	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));450	wmb(); /* drain writebuffer */451 452	return 0;453}454 455static int au1xpsc_ac97_drvresume(struct device *dev)456{457	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);458 459	/* restore PSC clock config */460	__raw_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));461	wmb(); /* drain writebuffer */462 463	/* after this point the ac97 core will cold-reset the codec.464	 * During cold-reset the PSC is reinitialized and the last465	 * configuration set up in hw_params() is restored.466	 */467	return 0;468}469 470static const struct dev_pm_ops au1xpscac97_pmops = {471	.suspend	= au1xpsc_ac97_drvsuspend,472	.resume		= au1xpsc_ac97_drvresume,473};474 475#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops476 477#else478 479#define AU1XPSCAC97_PMOPS NULL480 481#endif482 483static struct platform_driver au1xpsc_ac97_driver = {484	.driver	= {485		.name	= "au1xpsc_ac97",486		.pm	= AU1XPSCAC97_PMOPS,487	},488	.probe		= au1xpsc_ac97_drvprobe,489	.remove		= au1xpsc_ac97_drvremove,490};491 492module_platform_driver(au1xpsc_ac97_driver);493 494MODULE_LICENSE("GPL");495MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");496MODULE_AUTHOR("Manuel Lauss");497 498