brintos

brintos / linux-shallow public Read only

0
0
Text · 24.3 KiB · c3340b8 Raw
1088 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver4 *5 *  Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.6 *7 *  Documentation: ARM DDI 0173B8 */9#include <linux/module.h>10#include <linux/delay.h>11#include <linux/init.h>12#include <linux/ioport.h>13#include <linux/device.h>14#include <linux/spinlock.h>15#include <linux/interrupt.h>16#include <linux/err.h>17#include <linux/amba/bus.h>18#include <linux/io.h>19 20#include <sound/core.h>21#include <sound/initval.h>22#include <sound/ac97_codec.h>23#include <sound/pcm.h>24#include <sound/pcm_params.h>25 26#include "aaci.h"27 28#define DRIVER_NAME	"aaci-pl041"29 30#define FRAME_PERIOD_US	2131 32/*33 * PM support is not complete.  Turn it off.34 */35#undef CONFIG_PM36 37static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)38{39	u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);40 41	/*42	 * Ensure that the slot 1/2 RX registers are empty.43	 */44	v = readl(aaci->base + AACI_SLFR);45	if (v & SLFR_2RXV)46		readl(aaci->base + AACI_SL2RX);47	if (v & SLFR_1RXV)48		readl(aaci->base + AACI_SL1RX);49 50	if (maincr != readl(aaci->base + AACI_MAINCR)) {51		writel(maincr, aaci->base + AACI_MAINCR);52		readl(aaci->base + AACI_MAINCR);53		udelay(1);54	}55}56 57/*58 * P29:59 *  The recommended use of programming the external codec through slot 160 *  and slot 2 data is to use the channels during setup routines and the61 *  slot register at any other time.  The data written into slot 1, slot 262 *  and slot 12 registers is transmitted only when their corresponding63 *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR64 *  register.65 */66static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,67			    unsigned short val)68{69	struct aaci *aaci = ac97->private_data;70	int timeout;71	u32 v;72 73	if (ac97->num >= 4)74		return;75 76	mutex_lock(&aaci->ac97_sem);77 78	aaci_ac97_select_codec(aaci, ac97);79 80	/*81	 * P54: You must ensure that AACI_SL2TX is always written82	 * to, if required, before data is written to AACI_SL1TX.83	 */84	writel(val << 4, aaci->base + AACI_SL2TX);85	writel(reg << 12, aaci->base + AACI_SL1TX);86 87	/* Initially, wait one frame period */88	udelay(FRAME_PERIOD_US);89 90	/* And then wait an additional eight frame periods for it to be sent */91	timeout = FRAME_PERIOD_US * 8;92	do {93		udelay(1);94		v = readl(aaci->base + AACI_SLFR);95	} while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout);96 97	if (v & (SLFR_1TXB|SLFR_2TXB))98		dev_err(&aaci->dev->dev,99			"timeout waiting for write to complete\n");100 101	mutex_unlock(&aaci->ac97_sem);102}103 104/*105 * Read an AC'97 register.106 */107static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)108{109	struct aaci *aaci = ac97->private_data;110	int timeout, retries = 10;111	u32 v;112 113	if (ac97->num >= 4)114		return ~0;115 116	mutex_lock(&aaci->ac97_sem);117 118	aaci_ac97_select_codec(aaci, ac97);119 120	/*121	 * Write the register address to slot 1.122	 */123	writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);124 125	/* Initially, wait one frame period */126	udelay(FRAME_PERIOD_US);127 128	/* And then wait an additional eight frame periods for it to be sent */129	timeout = FRAME_PERIOD_US * 8;130	do {131		udelay(1);132		v = readl(aaci->base + AACI_SLFR);133	} while ((v & SLFR_1TXB) && --timeout);134 135	if (v & SLFR_1TXB) {136		dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");137		v = ~0;138		goto out;139	}140 141	/* Now wait for the response frame */142	udelay(FRAME_PERIOD_US);143 144	/* And then wait an additional eight frame periods for data */145	timeout = FRAME_PERIOD_US * 8;146	do {147		udelay(1);148		cond_resched();149		v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);150	} while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout);151 152	if (v != (SLFR_1RXV|SLFR_2RXV)) {153		dev_err(&aaci->dev->dev, "timeout on RX valid\n");154		v = ~0;155		goto out;156	}157 158	do {159		v = readl(aaci->base + AACI_SL1RX) >> 12;160		if (v == reg) {161			v = readl(aaci->base + AACI_SL2RX) >> 4;162			break;163		} else if (--retries) {164			dev_warn(&aaci->dev->dev,165				 "ac97 read back fail.  retry\n");166			continue;167		} else {168			dev_warn(&aaci->dev->dev,169				"wrong ac97 register read back (%x != %x)\n",170				v, reg);171			v = ~0;172		}173	} while (retries);174 out:175	mutex_unlock(&aaci->ac97_sem);176	return v;177}178 179static inline void180aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)181{182	u32 val;183	int timeout = 5000;184 185	do {186		udelay(1);187		val = readl(aacirun->base + AACI_SR);188	} while (val & mask && timeout--);189}190 191 192 193/*194 * Interrupt support.195 */196static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)197{198	if (mask & ISR_ORINTR) {199		dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);200		writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);201	}202 203	if (mask & ISR_RXTOINTR) {204		dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);205		writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);206	}207 208	if (mask & ISR_RXINTR) {209		struct aaci_runtime *aacirun = &aaci->capture;210		bool period_elapsed = false;211		void *ptr;212 213		if (!aacirun->substream || !aacirun->start) {214			dev_warn(&aaci->dev->dev, "RX interrupt???\n");215			writel(0, aacirun->base + AACI_IE);216			return;217		}218 219		spin_lock(&aacirun->lock);220 221		ptr = aacirun->ptr;222		do {223			unsigned int len = aacirun->fifo_bytes;224			u32 val;225 226			if (aacirun->bytes <= 0) {227				aacirun->bytes += aacirun->period;228				period_elapsed = true;229			}230			if (!(aacirun->cr & CR_EN))231				break;232 233			val = readl(aacirun->base + AACI_SR);234			if (!(val & SR_RXHF))235				break;236			if (!(val & SR_RXFF))237				len >>= 1;238 239			aacirun->bytes -= len;240 241			/* reading 16 bytes at a time */242			for( ; len > 0; len -= 16) {243				asm(244					"ldmia	%1, {r0, r1, r2, r3}\n\t"245					"stmia	%0!, {r0, r1, r2, r3}"246					: "+r" (ptr)247					: "r" (aacirun->fifo)248					: "r0", "r1", "r2", "r3", "cc");249 250				if (ptr >= aacirun->end)251					ptr = aacirun->start;252			}253		} while(1);254 255		aacirun->ptr = ptr;256 257		spin_unlock(&aacirun->lock);258 259		if (period_elapsed)260			snd_pcm_period_elapsed(aacirun->substream);261	}262 263	if (mask & ISR_URINTR) {264		dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);265		writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);266	}267 268	if (mask & ISR_TXINTR) {269		struct aaci_runtime *aacirun = &aaci->playback;270		bool period_elapsed = false;271		void *ptr;272 273		if (!aacirun->substream || !aacirun->start) {274			dev_warn(&aaci->dev->dev, "TX interrupt???\n");275			writel(0, aacirun->base + AACI_IE);276			return;277		}278 279		spin_lock(&aacirun->lock);280 281		ptr = aacirun->ptr;282		do {283			unsigned int len = aacirun->fifo_bytes;284			u32 val;285 286			if (aacirun->bytes <= 0) {287				aacirun->bytes += aacirun->period;288				period_elapsed = true;289			}290			if (!(aacirun->cr & CR_EN))291				break;292 293			val = readl(aacirun->base + AACI_SR);294			if (!(val & SR_TXHE))295				break;296			if (!(val & SR_TXFE))297				len >>= 1;298 299			aacirun->bytes -= len;300 301			/* writing 16 bytes at a time */302			for ( ; len > 0; len -= 16) {303				asm(304					"ldmia	%0!, {r0, r1, r2, r3}\n\t"305					"stmia	%1, {r0, r1, r2, r3}"306					: "+r" (ptr)307					: "r" (aacirun->fifo)308					: "r0", "r1", "r2", "r3", "cc");309 310				if (ptr >= aacirun->end)311					ptr = aacirun->start;312			}313		} while (1);314 315		aacirun->ptr = ptr;316 317		spin_unlock(&aacirun->lock);318 319		if (period_elapsed)320			snd_pcm_period_elapsed(aacirun->substream);321	}322}323 324static irqreturn_t aaci_irq(int irq, void *devid)325{326	struct aaci *aaci = devid;327	u32 mask;328	int i;329 330	mask = readl(aaci->base + AACI_ALLINTS);331	if (mask) {332		u32 m = mask;333		for (i = 0; i < 4; i++, m >>= 7) {334			if (m & 0x7f) {335				aaci_fifo_irq(aaci, i, m);336			}337		}338	}339 340	return mask ? IRQ_HANDLED : IRQ_NONE;341}342 343 344 345/*346 * ALSA support.347 */348static const struct snd_pcm_hardware aaci_hw_info = {349	.info			= SNDRV_PCM_INFO_MMAP |350				  SNDRV_PCM_INFO_MMAP_VALID |351				  SNDRV_PCM_INFO_INTERLEAVED |352				  SNDRV_PCM_INFO_BLOCK_TRANSFER |353				  SNDRV_PCM_INFO_RESUME,354 355	/*356	 * ALSA doesn't support 18-bit or 20-bit packed into 32-bit357	 * words.  It also doesn't support 12-bit at all.358	 */359	.formats		= SNDRV_PCM_FMTBIT_S16_LE,360 361	/* rates are setup from the AC'97 codec */362	.channels_min		= 2,363	.channels_max		= 2,364	.buffer_bytes_max	= 64 * 1024,365	.period_bytes_min	= 256,366	.period_bytes_max	= PAGE_SIZE,367	.periods_min		= 4,368	.periods_max		= PAGE_SIZE / 16,369};370 371/*372 * We can support two and four channel audio.  Unfortunately373 * six channel audio requires a non-standard channel ordering:374 *   2 -> FL(3), FR(4)375 *   4 -> FL(3), FR(4), SL(7), SR(8)376 *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)377 *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)378 * This requires an ALSA configuration file to correct.379 */380static int aaci_rule_channels(struct snd_pcm_hw_params *p,381	struct snd_pcm_hw_rule *rule)382{383	static const unsigned int channel_list[] = { 2, 4, 6 };384	struct aaci *aaci = rule->private;385	unsigned int mask = 1 << 0, slots;386 387	/* pcms[0] is the our 5.1 PCM instance. */388	slots = aaci->ac97_bus->pcms[0].r[0].slots;389	if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {390		mask |= 1 << 1;391		if (slots & (1 << AC97_SLOT_LFE))392			mask |= 1 << 2;393	}394 395	return snd_interval_list(hw_param_interval(p, rule->var),396				 ARRAY_SIZE(channel_list), channel_list, mask);397}398 399static int aaci_pcm_open(struct snd_pcm_substream *substream)400{401	struct snd_pcm_runtime *runtime = substream->runtime;402	struct aaci *aaci = substream->private_data;403	struct aaci_runtime *aacirun;404	int ret = 0;405 406	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {407		aacirun = &aaci->playback;408	} else {409		aacirun = &aaci->capture;410	}411 412	aacirun->substream = substream;413	runtime->private_data = aacirun;414	runtime->hw = aaci_hw_info;415	runtime->hw.rates = aacirun->pcm->rates;416	snd_pcm_limit_hw_rates(runtime);417 418	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {419		runtime->hw.channels_max = 6;420 421		/* Add rule describing channel dependency. */422		ret = snd_pcm_hw_rule_add(substream->runtime, 0,423					  SNDRV_PCM_HW_PARAM_CHANNELS,424					  aaci_rule_channels, aaci,425					  SNDRV_PCM_HW_PARAM_CHANNELS, -1);426		if (ret)427			return ret;428 429		if (aacirun->pcm->r[1].slots)430			snd_ac97_pcm_double_rate_rules(runtime);431	}432 433	/*434	 * ALSA wants the byte-size of the FIFOs.  As we only support435	 * 16-bit samples, this is twice the FIFO depth irrespective436	 * of whether it's in compact mode or not.437	 */438	runtime->hw.fifo_size = aaci->fifo_depth * 2;439 440	mutex_lock(&aaci->irq_lock);441	if (!aaci->users++) {442		ret = request_irq(aaci->dev->irq[0], aaci_irq,443			   IRQF_SHARED, DRIVER_NAME, aaci);444		if (ret != 0)445			aaci->users--;446	}447	mutex_unlock(&aaci->irq_lock);448 449	return ret;450}451 452 453/*454 * Common ALSA stuff455 */456static int aaci_pcm_close(struct snd_pcm_substream *substream)457{458	struct aaci *aaci = substream->private_data;459	struct aaci_runtime *aacirun = substream->runtime->private_data;460 461	WARN_ON(aacirun->cr & CR_EN);462 463	aacirun->substream = NULL;464 465	mutex_lock(&aaci->irq_lock);466	if (!--aaci->users)467		free_irq(aaci->dev->irq[0], aaci);468	mutex_unlock(&aaci->irq_lock);469 470	return 0;471}472 473static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)474{475	struct aaci_runtime *aacirun = substream->runtime->private_data;476 477	/*478	 * This must not be called with the device enabled.479	 */480	WARN_ON(aacirun->cr & CR_EN);481 482	if (aacirun->pcm_open)483		snd_ac97_pcm_close(aacirun->pcm);484	aacirun->pcm_open = 0;485 486	return 0;487}488 489/* Channel to slot mask */490static const u32 channels_to_slotmask[] = {491	[2] = CR_SL3 | CR_SL4,492	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,493	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,494};495 496static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,497			      struct snd_pcm_hw_params *params)498{499	struct aaci_runtime *aacirun = substream->runtime->private_data;500	struct aaci *aaci = substream->private_data;501	unsigned int channels = params_channels(params);502	unsigned int rate = params_rate(params);503	int dbl = rate > 48000;504	int err;505 506	aaci_pcm_hw_free(substream);507	if (aacirun->pcm_open) {508		snd_ac97_pcm_close(aacirun->pcm);509		aacirun->pcm_open = 0;510	}511 512	/* channels is already limited to 2, 4, or 6 by aaci_rule_channels */513	if (dbl && channels != 2)514		return -EINVAL;515 516	err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,517				aacirun->pcm->r[dbl].slots);518 519	aacirun->pcm_open = err == 0;520	aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;521	aacirun->cr |= channels_to_slotmask[channels + dbl * 2];522 523	/*524	 * fifo_bytes is the number of bytes we transfer to/from525	 * the FIFO, including padding.  So that's x4.  As we're526	 * in compact mode, the FIFO is half the size.527	 */528	aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;529 530	return err;531}532 533static int aaci_pcm_prepare(struct snd_pcm_substream *substream)534{535	struct snd_pcm_runtime *runtime = substream->runtime;536	struct aaci_runtime *aacirun = runtime->private_data;537 538	aacirun->period	= snd_pcm_lib_period_bytes(substream);539	aacirun->start	= runtime->dma_area;540	aacirun->end	= aacirun->start + snd_pcm_lib_buffer_bytes(substream);541	aacirun->ptr	= aacirun->start;542	aacirun->bytes	= aacirun->period;543 544	return 0;545}546 547static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)548{549	struct snd_pcm_runtime *runtime = substream->runtime;550	struct aaci_runtime *aacirun = runtime->private_data;551	ssize_t bytes = aacirun->ptr - aacirun->start;552 553	return bytes_to_frames(runtime, bytes);554}555 556 557/*558 * Playback specific ALSA stuff559 */560static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)561{562	u32 ie;563 564	ie = readl(aacirun->base + AACI_IE);565	ie &= ~(IE_URIE|IE_TXIE);566	writel(ie, aacirun->base + AACI_IE);567	aacirun->cr &= ~CR_EN;568	aaci_chan_wait_ready(aacirun, SR_TXB);569	writel(aacirun->cr, aacirun->base + AACI_TXCR);570}571 572static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)573{574	u32 ie;575 576	aaci_chan_wait_ready(aacirun, SR_TXB);577	aacirun->cr |= CR_EN;578 579	ie = readl(aacirun->base + AACI_IE);580	ie |= IE_URIE | IE_TXIE;581	writel(ie, aacirun->base + AACI_IE);582	writel(aacirun->cr, aacirun->base + AACI_TXCR);583}584 585static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)586{587	struct aaci_runtime *aacirun = substream->runtime->private_data;588	unsigned long flags;589	int ret = 0;590 591	spin_lock_irqsave(&aacirun->lock, flags);592 593	switch (cmd) {594	case SNDRV_PCM_TRIGGER_START:595		aaci_pcm_playback_start(aacirun);596		break;597 598	case SNDRV_PCM_TRIGGER_RESUME:599		aaci_pcm_playback_start(aacirun);600		break;601 602	case SNDRV_PCM_TRIGGER_STOP:603		aaci_pcm_playback_stop(aacirun);604		break;605 606	case SNDRV_PCM_TRIGGER_SUSPEND:607		aaci_pcm_playback_stop(aacirun);608		break;609 610	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:611		break;612 613	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:614		break;615 616	default:617		ret = -EINVAL;618	}619 620	spin_unlock_irqrestore(&aacirun->lock, flags);621 622	return ret;623}624 625static const struct snd_pcm_ops aaci_playback_ops = {626	.open		= aaci_pcm_open,627	.close		= aaci_pcm_close,628	.hw_params	= aaci_pcm_hw_params,629	.hw_free	= aaci_pcm_hw_free,630	.prepare	= aaci_pcm_prepare,631	.trigger	= aaci_pcm_playback_trigger,632	.pointer	= aaci_pcm_pointer,633};634 635static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)636{637	u32 ie;638 639	aaci_chan_wait_ready(aacirun, SR_RXB);640 641	ie = readl(aacirun->base + AACI_IE);642	ie &= ~(IE_ORIE | IE_RXIE);643	writel(ie, aacirun->base+AACI_IE);644 645	aacirun->cr &= ~CR_EN;646 647	writel(aacirun->cr, aacirun->base + AACI_RXCR);648}649 650static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)651{652	u32 ie;653 654	aaci_chan_wait_ready(aacirun, SR_RXB);655 656#ifdef DEBUG657	/* RX Timeout value: bits 28:17 in RXCR */658	aacirun->cr |= 0xf << 17;659#endif660 661	aacirun->cr |= CR_EN;662	writel(aacirun->cr, aacirun->base + AACI_RXCR);663 664	ie = readl(aacirun->base + AACI_IE);665	ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full666	writel(ie, aacirun->base + AACI_IE);667}668 669static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)670{671	struct aaci_runtime *aacirun = substream->runtime->private_data;672	unsigned long flags;673	int ret = 0;674 675	spin_lock_irqsave(&aacirun->lock, flags);676 677	switch (cmd) {678	case SNDRV_PCM_TRIGGER_START:679		aaci_pcm_capture_start(aacirun);680		break;681 682	case SNDRV_PCM_TRIGGER_RESUME:683		aaci_pcm_capture_start(aacirun);684		break;685 686	case SNDRV_PCM_TRIGGER_STOP:687		aaci_pcm_capture_stop(aacirun);688		break;689 690	case SNDRV_PCM_TRIGGER_SUSPEND:691		aaci_pcm_capture_stop(aacirun);692		break;693 694	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:695		break;696 697	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:698		break;699 700	default:701		ret = -EINVAL;702	}703 704	spin_unlock_irqrestore(&aacirun->lock, flags);705 706	return ret;707}708 709static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)710{711	struct snd_pcm_runtime *runtime = substream->runtime;712	struct aaci *aaci = substream->private_data;713 714	aaci_pcm_prepare(substream);715 716	/* allow changing of sample rate */717	aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */718	aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);719	aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);720 721	/* Record select: Mic: 0, Aux: 3, Line: 4 */722	aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);723 724	return 0;725}726 727static const struct snd_pcm_ops aaci_capture_ops = {728	.open		= aaci_pcm_open,729	.close		= aaci_pcm_close,730	.hw_params	= aaci_pcm_hw_params,731	.hw_free	= aaci_pcm_hw_free,732	.prepare	= aaci_pcm_capture_prepare,733	.trigger	= aaci_pcm_capture_trigger,734	.pointer	= aaci_pcm_pointer,735};736 737/*738 * Power Management.739 */740static int aaci_do_suspend(struct snd_card *card)741{742	snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);743	return 0;744}745 746static int aaci_do_resume(struct snd_card *card)747{748	snd_power_change_state(card, SNDRV_CTL_POWER_D0);749	return 0;750}751 752static int aaci_suspend(struct device *dev)753{754	struct snd_card *card = dev_get_drvdata(dev);755	return card ? aaci_do_suspend(card) : 0;756}757 758static int aaci_resume(struct device *dev)759{760	struct snd_card *card = dev_get_drvdata(dev);761	return card ? aaci_do_resume(card) : 0;762}763 764static DEFINE_SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);765 766static const struct ac97_pcm ac97_defs[] = {767	[0] = {	/* Front PCM */768		.exclusive = 1,769		.r = {770			[0] = {771				.slots	= (1 << AC97_SLOT_PCM_LEFT) |772					  (1 << AC97_SLOT_PCM_RIGHT) |773					  (1 << AC97_SLOT_PCM_CENTER) |774					  (1 << AC97_SLOT_PCM_SLEFT) |775					  (1 << AC97_SLOT_PCM_SRIGHT) |776					  (1 << AC97_SLOT_LFE),777			},778			[1] = {779				.slots	= (1 << AC97_SLOT_PCM_LEFT) |780					  (1 << AC97_SLOT_PCM_RIGHT) |781					  (1 << AC97_SLOT_PCM_LEFT_0) |782					  (1 << AC97_SLOT_PCM_RIGHT_0),783			},784		},785	},786	[1] = {	/* PCM in */787		.stream = 1,788		.exclusive = 1,789		.r = {790			[0] = {791				.slots	= (1 << AC97_SLOT_PCM_LEFT) |792					  (1 << AC97_SLOT_PCM_RIGHT),793			},794		},795	},796	[2] = {	/* Mic in */797		.stream = 1,798		.exclusive = 1,799		.r = {800			[0] = {801				.slots	= (1 << AC97_SLOT_MIC),802			},803		},804	}805};806 807static const struct snd_ac97_bus_ops aaci_bus_ops = {808	.write	= aaci_ac97_write,809	.read	= aaci_ac97_read,810};811 812static int aaci_probe_ac97(struct aaci *aaci)813{814	struct snd_ac97_template ac97_template;815	struct snd_ac97_bus *ac97_bus;816	struct snd_ac97 *ac97;817	int ret;818 819	/*820	 * Assert AACIRESET for 2us821	 */822	writel(0, aaci->base + AACI_RESET);823	udelay(2);824	writel(RESET_NRST, aaci->base + AACI_RESET);825 826	/*827	 * Give the AC'97 codec more than enough time828	 * to wake up. (42us = ~2 frames at 48kHz.)829	 */830	udelay(FRAME_PERIOD_US * 2);831 832	ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);833	if (ret)834		goto out;835 836	ac97_bus->clock = 48000;837	aaci->ac97_bus = ac97_bus;838 839	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));840	ac97_template.private_data = aaci;841	ac97_template.num = 0;842	ac97_template.scaps = AC97_SCAP_SKIP_MODEM;843 844	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);845	if (ret)846		goto out;847	aaci->ac97 = ac97;848 849	/*850	 * Disable AC97 PC Beep input on audio codecs.851	 */852	if (ac97_is_audio(ac97))853		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);854 855	ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);856	if (ret)857		goto out;858 859	aaci->playback.pcm = &ac97_bus->pcms[0];860	aaci->capture.pcm  = &ac97_bus->pcms[1];861 862 out:863	return ret;864}865 866static void aaci_free_card(struct snd_card *card)867{868	struct aaci *aaci = card->private_data;869 870	iounmap(aaci->base);871}872 873static struct aaci *aaci_init_card(struct amba_device *dev)874{875	struct aaci *aaci;876	struct snd_card *card;877	int err;878 879	err = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,880			   THIS_MODULE, sizeof(struct aaci), &card);881	if (err < 0)882		return NULL;883 884	card->private_free = aaci_free_card;885 886	strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));887	strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));888	snprintf(card->longname, sizeof(card->longname),889		 "%s PL%03x rev%u at 0x%08llx, irq %d",890		 card->shortname, amba_part(dev), amba_rev(dev),891		 (unsigned long long)dev->res.start, dev->irq[0]);892 893	aaci = card->private_data;894	mutex_init(&aaci->ac97_sem);895	mutex_init(&aaci->irq_lock);896	aaci->card = card;897	aaci->dev = dev;898 899	/* Set MAINCR to allow slot 1 and 2 data IO */900	aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |901		       MAINCR_SL2RXEN | MAINCR_SL2TXEN;902 903	return aaci;904}905 906static int aaci_init_pcm(struct aaci *aaci)907{908	struct snd_pcm *pcm;909	int ret;910 911	ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);912	if (ret == 0) {913		aaci->pcm = pcm;914		pcm->private_data = aaci;915		pcm->info_flags = 0;916 917		strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));918 919		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);920		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);921		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,922					       aaci->card->dev,923					       0, 64 * 1024);924	}925 926	return ret;927}928 929static unsigned int aaci_size_fifo(struct aaci *aaci)930{931	struct aaci_runtime *aacirun = &aaci->playback;932	int i;933 934	/*935	 * Enable the channel, but don't assign it to any slots, so936	 * it won't empty onto the AC'97 link.937	 */938	writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);939 940	for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)941		writel(0, aacirun->fifo);942 943	writel(0, aacirun->base + AACI_TXCR);944 945	/*946	 * Re-initialise the AACI after the FIFO depth test, to947	 * ensure that the FIFOs are empty.  Unfortunately, merely948	 * disabling the channel doesn't clear the FIFO.949	 */950	writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);951	readl(aaci->base + AACI_MAINCR);952	udelay(1);953	writel(aaci->maincr, aaci->base + AACI_MAINCR);954 955	/*956	 * If we hit 4096 entries, we failed.  Go back to the specified957	 * fifo depth.958	 */959	if (i == 4096)960		i = 8;961 962	return i;963}964 965static int aaci_probe(struct amba_device *dev,966		      const struct amba_id *id)967{968	struct aaci *aaci;969	int ret, i;970 971	ret = amba_request_regions(dev, NULL);972	if (ret)973		return ret;974 975	aaci = aaci_init_card(dev);976	if (!aaci) {977		ret = -ENOMEM;978		goto out;979	}980 981	aaci->base = ioremap(dev->res.start, resource_size(&dev->res));982	if (!aaci->base) {983		ret = -ENOMEM;984		goto out;985	}986 987	/*988	 * Playback uses AACI channel 0989	 */990	spin_lock_init(&aaci->playback.lock);991	aaci->playback.base = aaci->base + AACI_CSCH1;992	aaci->playback.fifo = aaci->base + AACI_DR1;993 994	/*995	 * Capture uses AACI channel 0996	 */997	spin_lock_init(&aaci->capture.lock);998	aaci->capture.base = aaci->base + AACI_CSCH1;999	aaci->capture.fifo = aaci->base + AACI_DR1;1000 1001	for (i = 0; i < 4; i++) {1002		void __iomem *base = aaci->base + i * 0x14;1003 1004		writel(0, base + AACI_IE);1005		writel(0, base + AACI_TXCR);1006		writel(0, base + AACI_RXCR);1007	}1008 1009	writel(0x1fff, aaci->base + AACI_INTCLR);1010	writel(aaci->maincr, aaci->base + AACI_MAINCR);1011	/*1012	 * Fix: ac97 read back fail errors by reading1013	 * from any arbitrary aaci register.1014	 */1015	readl(aaci->base + AACI_CSCH1);1016	ret = aaci_probe_ac97(aaci);1017	if (ret)1018		goto out;1019 1020	/*1021	 * Size the FIFOs (must be multiple of 16).1022	 * This is the number of entries in the FIFO.1023	 */1024	aaci->fifo_depth = aaci_size_fifo(aaci);1025	if (aaci->fifo_depth & 15) {1026		printk(KERN_WARNING "AACI: FIFO depth %d not supported\n",1027		       aaci->fifo_depth);1028		ret = -ENODEV;1029		goto out;1030	}1031 1032	ret = aaci_init_pcm(aaci);1033	if (ret)1034		goto out;1035 1036	ret = snd_card_register(aaci->card);1037	if (ret == 0) {1038		dev_info(&dev->dev, "%s\n", aaci->card->longname);1039		dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth);1040		amba_set_drvdata(dev, aaci->card);1041		return ret;1042	}1043 1044 out:1045	if (aaci)1046		snd_card_free(aaci->card);1047	amba_release_regions(dev);1048	return ret;1049}1050 1051static void aaci_remove(struct amba_device *dev)1052{1053	struct snd_card *card = amba_get_drvdata(dev);1054 1055	if (card) {1056		struct aaci *aaci = card->private_data;1057		writel(0, aaci->base + AACI_MAINCR);1058 1059		snd_card_free(card);1060		amba_release_regions(dev);1061	}1062}1063 1064static struct amba_id aaci_ids[] = {1065	{1066		.id	= 0x00041041,1067		.mask	= 0x000fffff,1068	},1069	{ 0, 0 },1070};1071 1072MODULE_DEVICE_TABLE(amba, aaci_ids);1073 1074static struct amba_driver aaci_driver = {1075	.drv		= {1076		.name	= DRIVER_NAME,1077		.pm	= &aaci_dev_pm_ops,1078	},1079	.probe		= aaci_probe,1080	.remove		= aaci_remove,1081	.id_table	= aaci_ids,1082};1083 1084module_amba_driver(aaci_driver);1085 1086MODULE_LICENSE("GPL");1087MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");1088