brintos

brintos / linux-shallow public Read only

0
0
Text · 21.9 KiB · 402b5f6 Raw
876 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for Atmel AC97C4 *5 * Copyright (C) 2005-2009 Atmel Corporation6 */7#include <linux/clk.h>8#include <linux/delay.h>9#include <linux/bitmap.h>10#include <linux/device.h>11#include <linux/atmel_pdc.h>12#include <linux/gpio/consumer.h>13#include <linux/init.h>14#include <linux/interrupt.h>15#include <linux/mod_devicetable.h>16#include <linux/module.h>17#include <linux/platform_device.h>18#include <linux/mutex.h>19#include <linux/types.h>20#include <linux/io.h>21 22#include <sound/core.h>23#include <sound/initval.h>24#include <sound/pcm.h>25#include <sound/pcm_params.h>26#include <sound/ac97_codec.h>27#include <sound/memalloc.h>28 29#include "ac97c.h"30 31/* Serialize access to opened variable */32static DEFINE_MUTEX(opened_mutex);33 34struct atmel_ac97c {35	struct clk			*pclk;36	struct platform_device		*pdev;37 38	struct snd_pcm_substream	*playback_substream;39	struct snd_pcm_substream	*capture_substream;40	struct snd_card			*card;41	struct snd_pcm			*pcm;42	struct snd_ac97			*ac97;43	struct snd_ac97_bus		*ac97_bus;44 45	u64				cur_format;46	unsigned int			cur_rate;47	int				playback_period, capture_period;48	/* Serialize access to opened variable */49	spinlock_t			lock;50	void __iomem			*regs;51	int				irq;52	int				opened;53	struct gpio_desc		*reset_pin;54};55 56#define get_chip(card) ((struct atmel_ac97c *)(card)->private_data)57 58#define ac97c_writel(chip, reg, val)			\59	__raw_writel((val), (chip)->regs + AC97C_##reg)60#define ac97c_readl(chip, reg)				\61	__raw_readl((chip)->regs + AC97C_##reg)62 63static const struct snd_pcm_hardware atmel_ac97c_hw = {64	.info			= (SNDRV_PCM_INFO_MMAP65				  | SNDRV_PCM_INFO_MMAP_VALID66				  | SNDRV_PCM_INFO_INTERLEAVED67				  | SNDRV_PCM_INFO_BLOCK_TRANSFER68				  | SNDRV_PCM_INFO_JOINT_DUPLEX69				  | SNDRV_PCM_INFO_RESUME70				  | SNDRV_PCM_INFO_PAUSE),71	.formats		= (SNDRV_PCM_FMTBIT_S16_BE72				  | SNDRV_PCM_FMTBIT_S16_LE),73	.rates			= (SNDRV_PCM_RATE_CONTINUOUS),74	.rate_min		= 4000,75	.rate_max		= 48000,76	.channels_min		= 1,77	.channels_max		= 2,78	.buffer_bytes_max	= 2 * 2 * 64 * 2048,79	.period_bytes_min	= 4096,80	.period_bytes_max	= 4096,81	.periods_min		= 6,82	.periods_max		= 64,83};84 85static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)86{87	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);88	struct snd_pcm_runtime *runtime = substream->runtime;89 90	mutex_lock(&opened_mutex);91	chip->opened++;92	runtime->hw = atmel_ac97c_hw;93	if (chip->cur_rate) {94		runtime->hw.rate_min = chip->cur_rate;95		runtime->hw.rate_max = chip->cur_rate;96	}97	if (chip->cur_format)98		runtime->hw.formats = pcm_format_to_bits(chip->cur_format);99	mutex_unlock(&opened_mutex);100	chip->playback_substream = substream;101	return 0;102}103 104static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)105{106	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);107	struct snd_pcm_runtime *runtime = substream->runtime;108 109	mutex_lock(&opened_mutex);110	chip->opened++;111	runtime->hw = atmel_ac97c_hw;112	if (chip->cur_rate) {113		runtime->hw.rate_min = chip->cur_rate;114		runtime->hw.rate_max = chip->cur_rate;115	}116	if (chip->cur_format)117		runtime->hw.formats = pcm_format_to_bits(chip->cur_format);118	mutex_unlock(&opened_mutex);119	chip->capture_substream = substream;120	return 0;121}122 123static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream)124{125	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);126 127	mutex_lock(&opened_mutex);128	chip->opened--;129	if (!chip->opened) {130		chip->cur_rate = 0;131		chip->cur_format = 0;132	}133	mutex_unlock(&opened_mutex);134 135	chip->playback_substream = NULL;136 137	return 0;138}139 140static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream)141{142	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);143 144	mutex_lock(&opened_mutex);145	chip->opened--;146	if (!chip->opened) {147		chip->cur_rate = 0;148		chip->cur_format = 0;149	}150	mutex_unlock(&opened_mutex);151 152	chip->capture_substream = NULL;153 154	return 0;155}156 157static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,158		struct snd_pcm_hw_params *hw_params)159{160	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);161 162	/* Set restrictions to params. */163	mutex_lock(&opened_mutex);164	chip->cur_rate = params_rate(hw_params);165	chip->cur_format = params_format(hw_params);166	mutex_unlock(&opened_mutex);167 168	return 0;169}170 171static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,172		struct snd_pcm_hw_params *hw_params)173{174	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);175 176	/* Set restrictions to params. */177	mutex_lock(&opened_mutex);178	chip->cur_rate = params_rate(hw_params);179	chip->cur_format = params_format(hw_params);180	mutex_unlock(&opened_mutex);181 182	return 0;183}184 185static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)186{187	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);188	struct snd_pcm_runtime *runtime = substream->runtime;189	int block_size = frames_to_bytes(runtime, runtime->period_size);190	unsigned long word = ac97c_readl(chip, OCA);191	int retval;192 193	chip->playback_period = 0;194	word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));195 196	/* assign channels to AC97C channel A */197	switch (runtime->channels) {198	case 1:199		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);200		break;201	case 2:202		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)203			| AC97C_CH_ASSIGN(PCM_RIGHT, A);204		break;205	default:206		/* TODO: support more than two channels */207		return -EINVAL;208	}209	ac97c_writel(chip, OCA, word);210 211	/* configure sample format and size */212	word = ac97c_readl(chip, CAMR);213	if (chip->opened <= 1)214		word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;215	else216		word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;217 218	switch (runtime->format) {219	case SNDRV_PCM_FORMAT_S16_LE:220		break;221	case SNDRV_PCM_FORMAT_S16_BE:222		word &= ~(AC97C_CMR_CEM_LITTLE);223		break;224	default:225		word = ac97c_readl(chip, OCA);226		word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));227		ac97c_writel(chip, OCA, word);228		return -EINVAL;229	}230 231	/* Enable underrun interrupt on channel A */232	word |= AC97C_CSR_UNRUN;233 234	ac97c_writel(chip, CAMR, word);235 236	/* Enable channel A event interrupt */237	word = ac97c_readl(chip, IMR);238	word |= AC97C_SR_CAEVT;239	ac97c_writel(chip, IER, word);240 241	/* set variable rate if needed */242	if (runtime->rate != 48000) {243		word = ac97c_readl(chip, MR);244		word |= AC97C_MR_VRA;245		ac97c_writel(chip, MR, word);246	} else {247		word = ac97c_readl(chip, MR);248		word &= ~(AC97C_MR_VRA);249		ac97c_writel(chip, MR, word);250	}251 252	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,253			runtime->rate);254	if (retval)255		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",256				runtime->rate);257 258	/* Initialize and start the PDC */259	writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);260	writel(block_size / 2, chip->regs + ATMEL_PDC_TCR);261	writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_TNPR);262	writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);263 264	return retval;265}266 267static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)268{269	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);270	struct snd_pcm_runtime *runtime = substream->runtime;271	int block_size = frames_to_bytes(runtime, runtime->period_size);272	unsigned long word = ac97c_readl(chip, ICA);273	int retval;274 275	chip->capture_period = 0;276	word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));277 278	/* assign channels to AC97C channel A */279	switch (runtime->channels) {280	case 1:281		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);282		break;283	case 2:284		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)285			| AC97C_CH_ASSIGN(PCM_RIGHT, A);286		break;287	default:288		/* TODO: support more than two channels */289		return -EINVAL;290	}291	ac97c_writel(chip, ICA, word);292 293	/* configure sample format and size */294	word = ac97c_readl(chip, CAMR);295	if (chip->opened <= 1)296		word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;297	else298		word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;299 300	switch (runtime->format) {301	case SNDRV_PCM_FORMAT_S16_LE:302		break;303	case SNDRV_PCM_FORMAT_S16_BE:304		word &= ~(AC97C_CMR_CEM_LITTLE);305		break;306	default:307		word = ac97c_readl(chip, ICA);308		word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));309		ac97c_writel(chip, ICA, word);310		return -EINVAL;311	}312 313	/* Enable overrun interrupt on channel A */314	word |= AC97C_CSR_OVRUN;315 316	ac97c_writel(chip, CAMR, word);317 318	/* Enable channel A event interrupt */319	word = ac97c_readl(chip, IMR);320	word |= AC97C_SR_CAEVT;321	ac97c_writel(chip, IER, word);322 323	/* set variable rate if needed */324	if (runtime->rate != 48000) {325		word = ac97c_readl(chip, MR);326		word |= AC97C_MR_VRA;327		ac97c_writel(chip, MR, word);328	} else {329		word = ac97c_readl(chip, MR);330		word &= ~(AC97C_MR_VRA);331		ac97c_writel(chip, MR, word);332	}333 334	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE,335			runtime->rate);336	if (retval)337		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",338				runtime->rate);339 340	/* Initialize and start the PDC */341	writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);342	writel(block_size / 2, chip->regs + ATMEL_PDC_RCR);343	writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_RNPR);344	writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);345 346	return retval;347}348 349static int350atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)351{352	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);353	unsigned long camr, ptcr = 0;354 355	camr = ac97c_readl(chip, CAMR);356 357	switch (cmd) {358	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:359	case SNDRV_PCM_TRIGGER_RESUME:360	case SNDRV_PCM_TRIGGER_START:361		ptcr = ATMEL_PDC_TXTEN;362		camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX;363		break;364	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:365	case SNDRV_PCM_TRIGGER_SUSPEND:366	case SNDRV_PCM_TRIGGER_STOP:367		ptcr |= ATMEL_PDC_TXTDIS;368		if (chip->opened <= 1)369			camr &= ~AC97C_CMR_CENA;370		break;371	default:372		return -EINVAL;373	}374 375	ac97c_writel(chip, CAMR, camr);376	writel(ptcr, chip->regs + ATMEL_PDC_PTCR);377	return 0;378}379 380static int381atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)382{383	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);384	unsigned long camr, ptcr = 0;385 386	camr = ac97c_readl(chip, CAMR);387	ptcr = readl(chip->regs + ATMEL_PDC_PTSR);388 389	switch (cmd) {390	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:391	case SNDRV_PCM_TRIGGER_RESUME:392	case SNDRV_PCM_TRIGGER_START:393		ptcr = ATMEL_PDC_RXTEN;394		camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX;395		break;396	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:397	case SNDRV_PCM_TRIGGER_SUSPEND:398	case SNDRV_PCM_TRIGGER_STOP:399		ptcr |= ATMEL_PDC_RXTDIS;400		if (chip->opened <= 1)401			camr &= ~AC97C_CMR_CENA;402		break;403	default:404		return -EINVAL;405	}406 407	ac97c_writel(chip, CAMR, camr);408	writel(ptcr, chip->regs + ATMEL_PDC_PTCR);409	return 0;410}411 412static snd_pcm_uframes_t413atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream)414{415	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);416	struct snd_pcm_runtime	*runtime = substream->runtime;417	snd_pcm_uframes_t	frames;418	unsigned long		bytes;419 420	bytes = readl(chip->regs + ATMEL_PDC_TPR);421	bytes -= runtime->dma_addr;422 423	frames = bytes_to_frames(runtime, bytes);424	if (frames >= runtime->buffer_size)425		frames -= runtime->buffer_size;426	return frames;427}428 429static snd_pcm_uframes_t430atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)431{432	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);433	struct snd_pcm_runtime	*runtime = substream->runtime;434	snd_pcm_uframes_t	frames;435	unsigned long		bytes;436 437	bytes = readl(chip->regs + ATMEL_PDC_RPR);438	bytes -= runtime->dma_addr;439 440	frames = bytes_to_frames(runtime, bytes);441	if (frames >= runtime->buffer_size)442		frames -= runtime->buffer_size;443	return frames;444}445 446static const struct snd_pcm_ops atmel_ac97_playback_ops = {447	.open		= atmel_ac97c_playback_open,448	.close		= atmel_ac97c_playback_close,449	.hw_params	= atmel_ac97c_playback_hw_params,450	.prepare	= atmel_ac97c_playback_prepare,451	.trigger	= atmel_ac97c_playback_trigger,452	.pointer	= atmel_ac97c_playback_pointer,453};454 455static const struct snd_pcm_ops atmel_ac97_capture_ops = {456	.open		= atmel_ac97c_capture_open,457	.close		= atmel_ac97c_capture_close,458	.hw_params	= atmel_ac97c_capture_hw_params,459	.prepare	= atmel_ac97c_capture_prepare,460	.trigger	= atmel_ac97c_capture_trigger,461	.pointer	= atmel_ac97c_capture_pointer,462};463 464static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)465{466	struct atmel_ac97c	*chip  = (struct atmel_ac97c *)dev;467	irqreturn_t		retval = IRQ_NONE;468	u32			sr     = ac97c_readl(chip, SR);469	u32			casr   = ac97c_readl(chip, CASR);470	u32			cosr   = ac97c_readl(chip, COSR);471	u32			camr   = ac97c_readl(chip, CAMR);472 473	if (sr & AC97C_SR_CAEVT) {474		struct snd_pcm_runtime *runtime;475		int offset, next_period, block_size;476		dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",477			(casr & AC97C_CSR_OVRUN)   ? " OVRUN"   : "",478			(casr & AC97C_CSR_RXRDY)   ? " RXRDY"   : "",479			(casr & AC97C_CSR_UNRUN)   ? " UNRUN"   : "",480			(casr & AC97C_CSR_TXEMPTY) ? " TXEMPTY" : "",481			(casr & AC97C_CSR_TXRDY)   ? " TXRDY"   : "",482			!casr                      ? " NONE"    : "");483		if ((casr & camr) & AC97C_CSR_ENDTX) {484			runtime = chip->playback_substream->runtime;485			block_size = frames_to_bytes(runtime, runtime->period_size);486			chip->playback_period++;487 488			if (chip->playback_period == runtime->periods)489				chip->playback_period = 0;490			next_period = chip->playback_period + 1;491			if (next_period == runtime->periods)492				next_period = 0;493 494			offset = block_size * next_period;495 496			writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_TNPR);497			writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);498 499			snd_pcm_period_elapsed(chip->playback_substream);500		}501		if ((casr & camr) & AC97C_CSR_ENDRX) {502			runtime = chip->capture_substream->runtime;503			block_size = frames_to_bytes(runtime, runtime->period_size);504			chip->capture_period++;505 506			if (chip->capture_period == runtime->periods)507				chip->capture_period = 0;508			next_period = chip->capture_period + 1;509			if (next_period == runtime->periods)510				next_period = 0;511 512			offset = block_size * next_period;513 514			writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_RNPR);515			writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);516			snd_pcm_period_elapsed(chip->capture_substream);517		}518		retval = IRQ_HANDLED;519	}520 521	if (sr & AC97C_SR_COEVT) {522		dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n",523			 (cosr & AC97C_CSR_OVRUN)   ? " OVRUN"   : "",524			 (cosr & AC97C_CSR_RXRDY)   ? " RXRDY"   : "",525			 (cosr & AC97C_CSR_TXEMPTY) ? " TXEMPTY" : "",526			 (cosr & AC97C_CSR_TXRDY)   ? " TXRDY"   : "",527			 !cosr                      ? " NONE"    : "");528		retval = IRQ_HANDLED;529	}530 531	if (retval == IRQ_NONE) {532		dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x "533				"casr 0x%08x cosr 0x%08x\n", sr, casr, cosr);534	}535 536	return retval;537}538 539static const struct ac97_pcm at91_ac97_pcm_defs[] = {540	/* Playback */541	{542		.exclusive = 1,543		.r = { {544			.slots = ((1 << AC97_SLOT_PCM_LEFT)545				  | (1 << AC97_SLOT_PCM_RIGHT)),546		} },547	},548	/* PCM in */549	{550		.stream = 1,551		.exclusive = 1,552		.r = { {553			.slots = ((1 << AC97_SLOT_PCM_LEFT)554					| (1 << AC97_SLOT_PCM_RIGHT)),555		} }556	},557	/* Mic in */558	{559		.stream = 1,560		.exclusive = 1,561		.r = { {562			.slots = (1<<AC97_SLOT_MIC),563		} }564	},565};566 567static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)568{569	struct snd_pcm		*pcm;570	struct snd_pcm_hardware	hw = atmel_ac97c_hw;571	int			retval;572 573	retval = snd_ac97_pcm_assign(chip->ac97_bus,574				     ARRAY_SIZE(at91_ac97_pcm_defs),575				     at91_ac97_pcm_defs);576	if (retval)577		return retval;578 579	retval = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm);580	if (retval)581		return retval;582 583	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops);584	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops);585 586	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,587			&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,588			hw.buffer_bytes_max);589 590	pcm->private_data = chip;591	pcm->info_flags = 0;592	strcpy(pcm->name, chip->card->shortname);593	chip->pcm = pcm;594 595	return 0;596}597 598static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip)599{600	struct snd_ac97_template template;601	memset(&template, 0, sizeof(template));602	template.private_data = chip;603	return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97);604}605 606static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg,607		unsigned short val)608{609	struct atmel_ac97c *chip = get_chip(ac97);610	unsigned long word;611	int timeout = 40;612 613	word = (reg & 0x7f) << 16 | val;614 615	do {616		if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) {617			ac97c_writel(chip, COTHR, word);618			return;619		}620		udelay(1);621	} while (--timeout);622 623	dev_dbg(&chip->pdev->dev, "codec write timeout\n");624}625 626static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97,627		unsigned short reg)628{629	struct atmel_ac97c *chip = get_chip(ac97);630	unsigned long word;631	int timeout = 40;632	int write = 10;633 634	word = (0x80 | (reg & 0x7f)) << 16;635 636	if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0)637		ac97c_readl(chip, CORHR);638 639retry_write:640	timeout = 40;641 642	do {643		if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) {644			ac97c_writel(chip, COTHR, word);645			goto read_reg;646		}647		udelay(10);648	} while (--timeout);649 650	if (!--write)651		goto timed_out;652	goto retry_write;653 654read_reg:655	do {656		if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) {657			unsigned short val = ac97c_readl(chip, CORHR);658			return val;659		}660		udelay(10);661	} while (--timeout);662 663	if (!--write)664		goto timed_out;665	goto retry_write;666 667timed_out:668	dev_dbg(&chip->pdev->dev, "codec read timeout\n");669	return 0xffff;670}671 672static void atmel_ac97c_reset(struct atmel_ac97c *chip)673{674	ac97c_writel(chip, MR,   0);675	ac97c_writel(chip, MR,   AC97C_MR_ENA);676	ac97c_writel(chip, CAMR, 0);677	ac97c_writel(chip, COMR, 0);678 679	if (!IS_ERR(chip->reset_pin)) {680		gpiod_set_value(chip->reset_pin, 0);681		/* AC97 v2.2 specifications says minimum 1 us. */682		udelay(2);683		gpiod_set_value(chip->reset_pin, 1);684	} else {685		ac97c_writel(chip, MR, AC97C_MR_WRST | AC97C_MR_ENA);686		udelay(2);687		ac97c_writel(chip, MR, AC97C_MR_ENA);688	}689}690 691static const struct of_device_id atmel_ac97c_dt_ids[] = {692	{ .compatible = "atmel,at91sam9263-ac97c", },693	{ }694};695MODULE_DEVICE_TABLE(of, atmel_ac97c_dt_ids);696 697static int atmel_ac97c_probe(struct platform_device *pdev)698{699	struct device			*dev = &pdev->dev;700	struct snd_card			*card;701	struct atmel_ac97c		*chip;702	struct resource			*regs;703	struct clk			*pclk;704	static const struct snd_ac97_bus_ops	ops = {705		.write	= atmel_ac97c_write,706		.read	= atmel_ac97c_read,707	};708	int				retval;709	int				irq;710 711	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);712	if (!regs) {713		dev_dbg(&pdev->dev, "no memory resource\n");714		return -ENXIO;715	}716 717	irq = platform_get_irq(pdev, 0);718	if (irq < 0) {719		dev_dbg(&pdev->dev, "could not get irq: %d\n", irq);720		return irq;721	}722 723	pclk = clk_get(&pdev->dev, "ac97_clk");724	if (IS_ERR(pclk)) {725		dev_dbg(&pdev->dev, "no peripheral clock\n");726		return PTR_ERR(pclk);727	}728	retval = clk_prepare_enable(pclk);729	if (retval)730		goto err_prepare_enable;731 732	retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1,733			      SNDRV_DEFAULT_STR1, THIS_MODULE,734			      sizeof(struct atmel_ac97c), &card);735	if (retval) {736		dev_dbg(&pdev->dev, "could not create sound card device\n");737		goto err_snd_card_new;738	}739 740	chip = get_chip(card);741 742	retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip);743	if (retval) {744		dev_dbg(&pdev->dev, "unable to request irq %d\n", irq);745		goto err_request_irq;746	}747	chip->irq = irq;748 749	spin_lock_init(&chip->lock);750 751	strcpy(card->driver, "Atmel AC97C");752	strcpy(card->shortname, "Atmel AC97C");753	sprintf(card->longname, "Atmel AC97 controller");754 755	chip->card = card;756	chip->pclk = pclk;757	chip->pdev = pdev;758	chip->regs = ioremap(regs->start, resource_size(regs));759 760	if (!chip->regs) {761		dev_dbg(&pdev->dev, "could not remap register memory\n");762		retval = -ENOMEM;763		goto err_ioremap;764	}765 766	chip->reset_pin = devm_gpiod_get_index(dev, "ac97", 2, GPIOD_OUT_HIGH);767	if (IS_ERR(chip->reset_pin))768		dev_dbg(dev, "reset pin not available\n");769 770	atmel_ac97c_reset(chip);771 772	/* Enable overrun interrupt from codec channel */773	ac97c_writel(chip, COMR, AC97C_CSR_OVRUN);774	ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT);775 776	retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);777	if (retval) {778		dev_dbg(&pdev->dev, "could not register on ac97 bus\n");779		goto err_ac97_bus;780	}781 782	retval = atmel_ac97c_mixer_new(chip);783	if (retval) {784		dev_dbg(&pdev->dev, "could not register ac97 mixer\n");785		goto err_ac97_bus;786	}787 788	retval = atmel_ac97c_pcm_new(chip);789	if (retval) {790		dev_dbg(&pdev->dev, "could not register ac97 pcm device\n");791		goto err_ac97_bus;792	}793 794	retval = snd_card_register(card);795	if (retval) {796		dev_dbg(&pdev->dev, "could not register sound card\n");797		goto err_ac97_bus;798	}799 800	platform_set_drvdata(pdev, card);801 802	dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p, irq = %d\n",803			chip->regs, irq);804 805	return 0;806 807err_ac97_bus:808	iounmap(chip->regs);809err_ioremap:810	free_irq(irq, chip);811err_request_irq:812	snd_card_free(card);813err_snd_card_new:814	clk_disable_unprepare(pclk);815err_prepare_enable:816	clk_put(pclk);817	return retval;818}819 820#ifdef CONFIG_PM_SLEEP821static int atmel_ac97c_suspend(struct device *pdev)822{823	struct snd_card *card = dev_get_drvdata(pdev);824	struct atmel_ac97c *chip = card->private_data;825 826	clk_disable_unprepare(chip->pclk);827	return 0;828}829 830static int atmel_ac97c_resume(struct device *pdev)831{832	struct snd_card *card = dev_get_drvdata(pdev);833	struct atmel_ac97c *chip = card->private_data;834	int ret = clk_prepare_enable(chip->pclk);835 836	return ret;837}838 839static SIMPLE_DEV_PM_OPS(atmel_ac97c_pm, atmel_ac97c_suspend, atmel_ac97c_resume);840#define ATMEL_AC97C_PM_OPS	&atmel_ac97c_pm841#else842#define ATMEL_AC97C_PM_OPS	NULL843#endif844 845static void atmel_ac97c_remove(struct platform_device *pdev)846{847	struct snd_card *card = platform_get_drvdata(pdev);848	struct atmel_ac97c *chip = get_chip(card);849 850	ac97c_writel(chip, CAMR, 0);851	ac97c_writel(chip, COMR, 0);852	ac97c_writel(chip, MR,   0);853 854	clk_disable_unprepare(chip->pclk);855	clk_put(chip->pclk);856	iounmap(chip->regs);857	free_irq(chip->irq, chip);858 859	snd_card_free(card);860}861 862static struct platform_driver atmel_ac97c_driver = {863	.probe		= atmel_ac97c_probe,864	.remove_new	= atmel_ac97c_remove,865	.driver		= {866		.name	= "atmel_ac97c",867		.pm	= ATMEL_AC97C_PM_OPS,868		.of_match_table = atmel_ac97c_dt_ids,869	},870};871module_platform_driver(atmel_ac97c_driver);872 873MODULE_LICENSE("GPL");874MODULE_DESCRIPTION("Driver for Atmel AC97 controller");875MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");876