Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: Add ALSA driver for Atmel AC97 controller

This patch adds ALSA support for the AC97 controller found on Atmel
AVR32 devices.

Tested on ATSTK1006 + ATSTK1000 with a development board with a AC97
codec.

Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Hans-Christian Egtvedt and committed by
Takashi Iwai
4ede028f e4967d60

+1053
+40
include/sound/atmel-ac97c.h
··· 1 + /* 2 + * Driver for the Atmel AC97C controller 3 + * 4 + * Copyright (C) 2005-2009 Atmel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + #ifndef __INCLUDE_SOUND_ATMEL_AC97C_H 11 + #define __INCLUDE_SOUND_ATMEL_AC97C_H 12 + 13 + #include <linux/dw_dmac.h> 14 + 15 + #define AC97C_CAPTURE 0x01 16 + #define AC97C_PLAYBACK 0x02 17 + #define AC97C_BOTH (AC97C_CAPTURE | AC97C_PLAYBACK) 18 + 19 + /** 20 + * struct atmel_ac97c_pdata - board specific AC97C configuration 21 + * @rx_dws: DMA slave interface to use for sound capture. 22 + * @tx_dws: DMA slave interface to use for sound playback. 23 + * @reset_pin: GPIO pin wired to the reset input on the external AC97 codec, 24 + * optional to use, set to -ENODEV if not in use. AC97 layer will 25 + * try to do a software reset of the external codec anyway. 26 + * @flags: Flags for which directions should be enabled. 27 + * 28 + * If the user do not want to use a DMA channel for playback or capture, i.e. 29 + * only one feature is required on the board. The slave for playback or capture 30 + * can be set to NULL. The AC97C driver will take use of this when setting up 31 + * the sound streams. 32 + */ 33 + struct ac97c_platform_data { 34 + struct dw_dma_slave rx_dws; 35 + struct dw_dma_slave tx_dws; 36 + unsigned int flags; 37 + int reset_pin; 38 + }; 39 + 40 + #endif /* __INCLUDE_SOUND_ATMEL_AC97C_H */
+8
sound/atmel/Kconfig
··· 8 8 help 9 9 ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). 10 10 11 + config SND_ATMEL_AC97C 12 + tristate "Atmel AC97 Controller (AC97C) driver" 13 + select SND_PCM 14 + select SND_AC97_CODEC 15 + depends on DW_DMAC && AVR32 16 + help 17 + ALSA sound driver for the Atmel AC97 controller. 18 + 11 19 endmenu
+2
sound/atmel/Makefile
··· 1 1 snd-atmel-abdac-objs := abdac.o 2 + snd-atmel-ac97c-objs := ac97c.o 2 3 3 4 obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o 5 + obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o
+932
sound/atmel/ac97c.c
··· 1 + /* 2 + * Driver for the Atmel AC97C controller 3 + * 4 + * Copyright (C) 2005-2009 Atmel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published by 8 + * the Free Software Foundation. 9 + */ 10 + #include <linux/clk.h> 11 + #include <linux/delay.h> 12 + #include <linux/bitmap.h> 13 + #include <linux/dmaengine.h> 14 + #include <linux/dma-mapping.h> 15 + #include <linux/init.h> 16 + #include <linux/interrupt.h> 17 + #include <linux/module.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/mutex.h> 20 + #include <linux/gpio.h> 21 + #include <linux/io.h> 22 + 23 + #include <sound/core.h> 24 + #include <sound/initval.h> 25 + #include <sound/pcm.h> 26 + #include <sound/pcm_params.h> 27 + #include <sound/ac97_codec.h> 28 + #include <sound/atmel-ac97c.h> 29 + #include <sound/memalloc.h> 30 + 31 + #include <linux/dw_dmac.h> 32 + 33 + #include "ac97c.h" 34 + 35 + enum { 36 + DMA_TX_READY = 0, 37 + DMA_RX_READY, 38 + DMA_TX_CHAN_PRESENT, 39 + DMA_RX_CHAN_PRESENT, 40 + }; 41 + 42 + /* Serialize access to opened variable */ 43 + static DEFINE_MUTEX(opened_mutex); 44 + 45 + struct atmel_ac97c_dma { 46 + struct dma_chan *rx_chan; 47 + struct dma_chan *tx_chan; 48 + }; 49 + 50 + struct atmel_ac97c { 51 + struct clk *pclk; 52 + struct platform_device *pdev; 53 + struct atmel_ac97c_dma dma; 54 + 55 + struct snd_pcm_substream *playback_substream; 56 + struct snd_pcm_substream *capture_substream; 57 + struct snd_card *card; 58 + struct snd_pcm *pcm; 59 + struct snd_ac97 *ac97; 60 + struct snd_ac97_bus *ac97_bus; 61 + 62 + u64 cur_format; 63 + unsigned int cur_rate; 64 + unsigned long flags; 65 + /* Serialize access to opened variable */ 66 + spinlock_t lock; 67 + void __iomem *regs; 68 + int opened; 69 + int reset_pin; 70 + }; 71 + 72 + #define get_chip(card) ((struct atmel_ac97c *)(card)->private_data) 73 + 74 + #define ac97c_writel(chip, reg, val) \ 75 + __raw_writel((val), (chip)->regs + AC97C_##reg) 76 + #define ac97c_readl(chip, reg) \ 77 + __raw_readl((chip)->regs + AC97C_##reg) 78 + 79 + /* This function is called by the DMA driver. */ 80 + static void atmel_ac97c_dma_playback_period_done(void *arg) 81 + { 82 + struct atmel_ac97c *chip = arg; 83 + snd_pcm_period_elapsed(chip->playback_substream); 84 + } 85 + 86 + static void atmel_ac97c_dma_capture_period_done(void *arg) 87 + { 88 + struct atmel_ac97c *chip = arg; 89 + snd_pcm_period_elapsed(chip->capture_substream); 90 + } 91 + 92 + static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, 93 + struct snd_pcm_substream *substream, 94 + enum dma_data_direction direction) 95 + { 96 + struct dma_chan *chan; 97 + struct dw_cyclic_desc *cdesc; 98 + struct snd_pcm_runtime *runtime = substream->runtime; 99 + unsigned long buffer_len, period_len; 100 + 101 + /* 102 + * We don't do DMA on "complex" transfers, i.e. with 103 + * non-halfword-aligned buffers or lengths. 104 + */ 105 + if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { 106 + dev_dbg(&chip->pdev->dev, "too complex transfer\n"); 107 + return -EINVAL; 108 + } 109 + 110 + if (direction == DMA_TO_DEVICE) 111 + chan = chip->dma.tx_chan; 112 + else 113 + chan = chip->dma.rx_chan; 114 + 115 + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); 116 + period_len = frames_to_bytes(runtime, runtime->period_size); 117 + 118 + cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, 119 + period_len, direction); 120 + if (IS_ERR(cdesc)) { 121 + dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); 122 + return PTR_ERR(cdesc); 123 + } 124 + 125 + if (direction == DMA_TO_DEVICE) { 126 + cdesc->period_callback = atmel_ac97c_dma_playback_period_done; 127 + set_bit(DMA_TX_READY, &chip->flags); 128 + } else { 129 + cdesc->period_callback = atmel_ac97c_dma_capture_period_done; 130 + set_bit(DMA_RX_READY, &chip->flags); 131 + } 132 + 133 + cdesc->period_callback_param = chip; 134 + 135 + return 0; 136 + } 137 + 138 + static struct snd_pcm_hardware atmel_ac97c_hw = { 139 + .info = (SNDRV_PCM_INFO_MMAP 140 + | SNDRV_PCM_INFO_MMAP_VALID 141 + | SNDRV_PCM_INFO_INTERLEAVED 142 + | SNDRV_PCM_INFO_BLOCK_TRANSFER 143 + | SNDRV_PCM_INFO_JOINT_DUPLEX 144 + | SNDRV_PCM_INFO_RESUME 145 + | SNDRV_PCM_INFO_PAUSE), 146 + .formats = (SNDRV_PCM_FMTBIT_S16_BE 147 + | SNDRV_PCM_FMTBIT_S16_LE), 148 + .rates = (SNDRV_PCM_RATE_CONTINUOUS), 149 + .rate_min = 4000, 150 + .rate_max = 48000, 151 + .channels_min = 1, 152 + .channels_max = 2, 153 + .buffer_bytes_max = 64 * 4096, 154 + .period_bytes_min = 4096, 155 + .period_bytes_max = 4096, 156 + .periods_min = 4, 157 + .periods_max = 64, 158 + }; 159 + 160 + static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) 161 + { 162 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 163 + struct snd_pcm_runtime *runtime = substream->runtime; 164 + 165 + mutex_lock(&opened_mutex); 166 + chip->opened++; 167 + runtime->hw = atmel_ac97c_hw; 168 + if (chip->cur_rate) { 169 + runtime->hw.rate_min = chip->cur_rate; 170 + runtime->hw.rate_max = chip->cur_rate; 171 + } 172 + if (chip->cur_format) 173 + runtime->hw.formats = (1ULL << chip->cur_format); 174 + mutex_unlock(&opened_mutex); 175 + chip->playback_substream = substream; 176 + return 0; 177 + } 178 + 179 + static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) 180 + { 181 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 182 + struct snd_pcm_runtime *runtime = substream->runtime; 183 + 184 + mutex_lock(&opened_mutex); 185 + chip->opened++; 186 + runtime->hw = atmel_ac97c_hw; 187 + if (chip->cur_rate) { 188 + runtime->hw.rate_min = chip->cur_rate; 189 + runtime->hw.rate_max = chip->cur_rate; 190 + } 191 + if (chip->cur_format) 192 + runtime->hw.formats = (1ULL << chip->cur_format); 193 + mutex_unlock(&opened_mutex); 194 + chip->capture_substream = substream; 195 + return 0; 196 + } 197 + 198 + static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream) 199 + { 200 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 201 + 202 + mutex_lock(&opened_mutex); 203 + chip->opened--; 204 + if (!chip->opened) { 205 + chip->cur_rate = 0; 206 + chip->cur_format = 0; 207 + } 208 + mutex_unlock(&opened_mutex); 209 + 210 + chip->playback_substream = NULL; 211 + 212 + return 0; 213 + } 214 + 215 + static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream) 216 + { 217 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 218 + 219 + mutex_lock(&opened_mutex); 220 + chip->opened--; 221 + if (!chip->opened) { 222 + chip->cur_rate = 0; 223 + chip->cur_format = 0; 224 + } 225 + mutex_unlock(&opened_mutex); 226 + 227 + chip->capture_substream = NULL; 228 + 229 + return 0; 230 + } 231 + 232 + static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, 233 + struct snd_pcm_hw_params *hw_params) 234 + { 235 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 236 + int retval; 237 + 238 + retval = snd_pcm_lib_malloc_pages(substream, 239 + params_buffer_bytes(hw_params)); 240 + if (retval < 0) 241 + return retval; 242 + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ 243 + if (retval == 1) 244 + if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) 245 + dw_dma_cyclic_free(chip->dma.tx_chan); 246 + 247 + /* Set restrictions to params. */ 248 + mutex_lock(&opened_mutex); 249 + chip->cur_rate = params_rate(hw_params); 250 + chip->cur_format = params_format(hw_params); 251 + mutex_unlock(&opened_mutex); 252 + 253 + return retval; 254 + } 255 + 256 + static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, 257 + struct snd_pcm_hw_params *hw_params) 258 + { 259 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 260 + int retval; 261 + 262 + retval = snd_pcm_lib_malloc_pages(substream, 263 + params_buffer_bytes(hw_params)); 264 + if (retval < 0) 265 + return retval; 266 + /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ 267 + if (retval == 1) 268 + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) 269 + dw_dma_cyclic_free(chip->dma.rx_chan); 270 + 271 + /* Set restrictions to params. */ 272 + mutex_lock(&opened_mutex); 273 + chip->cur_rate = params_rate(hw_params); 274 + chip->cur_format = params_format(hw_params); 275 + mutex_unlock(&opened_mutex); 276 + 277 + return retval; 278 + } 279 + 280 + static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) 281 + { 282 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 283 + if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) 284 + dw_dma_cyclic_free(chip->dma.tx_chan); 285 + return snd_pcm_lib_free_pages(substream); 286 + } 287 + 288 + static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) 289 + { 290 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 291 + if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) 292 + dw_dma_cyclic_free(chip->dma.rx_chan); 293 + return snd_pcm_lib_free_pages(substream); 294 + } 295 + 296 + static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) 297 + { 298 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 299 + struct snd_pcm_runtime *runtime = substream->runtime; 300 + unsigned long word = 0; 301 + int retval; 302 + 303 + /* assign channels to AC97C channel A */ 304 + switch (runtime->channels) { 305 + case 1: 306 + word |= AC97C_CH_ASSIGN(PCM_LEFT, A); 307 + break; 308 + case 2: 309 + word |= AC97C_CH_ASSIGN(PCM_LEFT, A) 310 + | AC97C_CH_ASSIGN(PCM_RIGHT, A); 311 + break; 312 + default: 313 + /* TODO: support more than two channels */ 314 + return -EINVAL; 315 + break; 316 + } 317 + ac97c_writel(chip, OCA, word); 318 + 319 + /* configure sample format and size */ 320 + word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; 321 + 322 + switch (runtime->format) { 323 + case SNDRV_PCM_FORMAT_S16_LE: 324 + word |= AC97C_CMR_CEM_LITTLE; 325 + break; 326 + case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ 327 + default: 328 + word &= ~(AC97C_CMR_CEM_LITTLE); 329 + break; 330 + } 331 + 332 + ac97c_writel(chip, CAMR, word); 333 + 334 + /* set variable rate if needed */ 335 + if (runtime->rate != 48000) { 336 + word = ac97c_readl(chip, MR); 337 + word |= AC97C_MR_VRA; 338 + ac97c_writel(chip, MR, word); 339 + } else { 340 + word = ac97c_readl(chip, MR); 341 + word &= ~(AC97C_MR_VRA); 342 + ac97c_writel(chip, MR, word); 343 + } 344 + 345 + retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, 346 + runtime->rate); 347 + if (retval) 348 + dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", 349 + runtime->rate); 350 + 351 + if (!test_bit(DMA_TX_READY, &chip->flags)) 352 + retval = atmel_ac97c_prepare_dma(chip, substream, 353 + DMA_TO_DEVICE); 354 + 355 + return retval; 356 + } 357 + 358 + static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) 359 + { 360 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 361 + struct snd_pcm_runtime *runtime = substream->runtime; 362 + unsigned long word = 0; 363 + int retval; 364 + 365 + /* assign channels to AC97C channel A */ 366 + switch (runtime->channels) { 367 + case 1: 368 + word |= AC97C_CH_ASSIGN(PCM_LEFT, A); 369 + break; 370 + case 2: 371 + word |= AC97C_CH_ASSIGN(PCM_LEFT, A) 372 + | AC97C_CH_ASSIGN(PCM_RIGHT, A); 373 + break; 374 + default: 375 + /* TODO: support more than two channels */ 376 + return -EINVAL; 377 + break; 378 + } 379 + ac97c_writel(chip, ICA, word); 380 + 381 + /* configure sample format and size */ 382 + word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; 383 + 384 + switch (runtime->format) { 385 + case SNDRV_PCM_FORMAT_S16_LE: 386 + word |= AC97C_CMR_CEM_LITTLE; 387 + break; 388 + case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ 389 + default: 390 + word &= ~(AC97C_CMR_CEM_LITTLE); 391 + break; 392 + } 393 + 394 + ac97c_writel(chip, CAMR, word); 395 + 396 + /* set variable rate if needed */ 397 + if (runtime->rate != 48000) { 398 + word = ac97c_readl(chip, MR); 399 + word |= AC97C_MR_VRA; 400 + ac97c_writel(chip, MR, word); 401 + } else { 402 + word = ac97c_readl(chip, MR); 403 + word &= ~(AC97C_MR_VRA); 404 + ac97c_writel(chip, MR, word); 405 + } 406 + 407 + retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, 408 + runtime->rate); 409 + if (retval) 410 + dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", 411 + runtime->rate); 412 + 413 + if (!test_bit(DMA_RX_READY, &chip->flags)) 414 + retval = atmel_ac97c_prepare_dma(chip, substream, 415 + DMA_FROM_DEVICE); 416 + 417 + return retval; 418 + } 419 + 420 + static int 421 + atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) 422 + { 423 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 424 + unsigned long camr; 425 + int retval = 0; 426 + 427 + camr = ac97c_readl(chip, CAMR); 428 + 429 + switch (cmd) { 430 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ 431 + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ 432 + case SNDRV_PCM_TRIGGER_START: 433 + retval = dw_dma_cyclic_start(chip->dma.tx_chan); 434 + if (retval) 435 + goto out; 436 + camr |= AC97C_CMR_CENA; 437 + break; 438 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ 439 + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ 440 + case SNDRV_PCM_TRIGGER_STOP: 441 + dw_dma_cyclic_stop(chip->dma.tx_chan); 442 + if (chip->opened <= 1) 443 + camr &= ~AC97C_CMR_CENA; 444 + break; 445 + default: 446 + retval = -EINVAL; 447 + goto out; 448 + } 449 + 450 + ac97c_writel(chip, CAMR, camr); 451 + out: 452 + return retval; 453 + } 454 + 455 + static int 456 + atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) 457 + { 458 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 459 + unsigned long camr; 460 + int retval = 0; 461 + 462 + camr = ac97c_readl(chip, CAMR); 463 + 464 + switch (cmd) { 465 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ 466 + case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ 467 + case SNDRV_PCM_TRIGGER_START: 468 + retval = dw_dma_cyclic_start(chip->dma.rx_chan); 469 + if (retval) 470 + goto out; 471 + camr |= AC97C_CMR_CENA; 472 + break; 473 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ 474 + case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ 475 + case SNDRV_PCM_TRIGGER_STOP: 476 + dw_dma_cyclic_stop(chip->dma.rx_chan); 477 + if (chip->opened <= 1) 478 + camr &= ~AC97C_CMR_CENA; 479 + break; 480 + default: 481 + retval = -EINVAL; 482 + break; 483 + } 484 + 485 + ac97c_writel(chip, CAMR, camr); 486 + out: 487 + return retval; 488 + } 489 + 490 + static snd_pcm_uframes_t 491 + atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) 492 + { 493 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 494 + struct snd_pcm_runtime *runtime = substream->runtime; 495 + snd_pcm_uframes_t frames; 496 + unsigned long bytes; 497 + 498 + bytes = dw_dma_get_src_addr(chip->dma.tx_chan); 499 + bytes -= runtime->dma_addr; 500 + 501 + frames = bytes_to_frames(runtime, bytes); 502 + if (frames >= runtime->buffer_size) 503 + frames -= runtime->buffer_size; 504 + return frames; 505 + } 506 + 507 + static snd_pcm_uframes_t 508 + atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) 509 + { 510 + struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 511 + struct snd_pcm_runtime *runtime = substream->runtime; 512 + snd_pcm_uframes_t frames; 513 + unsigned long bytes; 514 + 515 + bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); 516 + bytes -= runtime->dma_addr; 517 + 518 + frames = bytes_to_frames(runtime, bytes); 519 + if (frames >= runtime->buffer_size) 520 + frames -= runtime->buffer_size; 521 + return frames; 522 + } 523 + 524 + static struct snd_pcm_ops atmel_ac97_playback_ops = { 525 + .open = atmel_ac97c_playback_open, 526 + .close = atmel_ac97c_playback_close, 527 + .ioctl = snd_pcm_lib_ioctl, 528 + .hw_params = atmel_ac97c_playback_hw_params, 529 + .hw_free = atmel_ac97c_playback_hw_free, 530 + .prepare = atmel_ac97c_playback_prepare, 531 + .trigger = atmel_ac97c_playback_trigger, 532 + .pointer = atmel_ac97c_playback_pointer, 533 + }; 534 + 535 + static struct snd_pcm_ops atmel_ac97_capture_ops = { 536 + .open = atmel_ac97c_capture_open, 537 + .close = atmel_ac97c_capture_close, 538 + .ioctl = snd_pcm_lib_ioctl, 539 + .hw_params = atmel_ac97c_capture_hw_params, 540 + .hw_free = atmel_ac97c_capture_hw_free, 541 + .prepare = atmel_ac97c_capture_prepare, 542 + .trigger = atmel_ac97c_capture_trigger, 543 + .pointer = atmel_ac97c_capture_pointer, 544 + }; 545 + 546 + static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip) 547 + { 548 + struct snd_pcm *pcm; 549 + struct snd_pcm_hardware hw = atmel_ac97c_hw; 550 + int capture, playback, retval; 551 + 552 + capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); 553 + playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); 554 + 555 + retval = snd_pcm_new(chip->card, chip->card->shortname, 556 + chip->pdev->id, playback, capture, &pcm); 557 + if (retval) 558 + return retval; 559 + 560 + if (capture) 561 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 562 + &atmel_ac97_capture_ops); 563 + if (playback) 564 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 565 + &atmel_ac97_playback_ops); 566 + 567 + retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 568 + &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, 569 + hw.buffer_bytes_max); 570 + if (retval) 571 + return retval; 572 + 573 + pcm->private_data = chip; 574 + pcm->info_flags = 0; 575 + strcpy(pcm->name, chip->card->shortname); 576 + chip->pcm = pcm; 577 + 578 + return 0; 579 + } 580 + 581 + static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip) 582 + { 583 + struct snd_ac97_template template; 584 + memset(&template, 0, sizeof(template)); 585 + template.private_data = chip; 586 + return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97); 587 + } 588 + 589 + static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg, 590 + unsigned short val) 591 + { 592 + struct atmel_ac97c *chip = get_chip(ac97); 593 + unsigned long word; 594 + int timeout = 40; 595 + 596 + word = (reg & 0x7f) << 16 | val; 597 + 598 + do { 599 + if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) { 600 + ac97c_writel(chip, COTHR, word); 601 + return; 602 + } 603 + udelay(1); 604 + } while (--timeout); 605 + 606 + dev_dbg(&chip->pdev->dev, "codec write timeout\n"); 607 + } 608 + 609 + static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97, 610 + unsigned short reg) 611 + { 612 + struct atmel_ac97c *chip = get_chip(ac97); 613 + unsigned long word; 614 + int timeout = 40; 615 + int write = 10; 616 + 617 + word = (0x80 | (reg & 0x7f)) << 16; 618 + 619 + if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) 620 + ac97c_readl(chip, CORHR); 621 + 622 + retry_write: 623 + timeout = 40; 624 + 625 + do { 626 + if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) { 627 + ac97c_writel(chip, COTHR, word); 628 + goto read_reg; 629 + } 630 + udelay(10); 631 + } while (--timeout); 632 + 633 + if (!--write) 634 + goto timed_out; 635 + goto retry_write; 636 + 637 + read_reg: 638 + do { 639 + if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) { 640 + unsigned short val = ac97c_readl(chip, CORHR); 641 + return val; 642 + } 643 + udelay(10); 644 + } while (--timeout); 645 + 646 + if (!--write) 647 + goto timed_out; 648 + goto retry_write; 649 + 650 + timed_out: 651 + dev_dbg(&chip->pdev->dev, "codec read timeout\n"); 652 + return 0xffff; 653 + } 654 + 655 + static bool filter(struct dma_chan *chan, void *slave) 656 + { 657 + struct dw_dma_slave *dws = slave; 658 + 659 + if (dws->dma_dev == chan->device->dev) { 660 + chan->private = dws; 661 + return true; 662 + } else 663 + return false; 664 + } 665 + 666 + static void atmel_ac97c_reset(struct atmel_ac97c *chip) 667 + { 668 + ac97c_writel(chip, MR, AC97C_MR_WRST); 669 + 670 + if (gpio_is_valid(chip->reset_pin)) { 671 + gpio_set_value(chip->reset_pin, 0); 672 + /* AC97 v2.2 specifications says minimum 1 us. */ 673 + udelay(10); 674 + gpio_set_value(chip->reset_pin, 1); 675 + } 676 + 677 + udelay(1); 678 + ac97c_writel(chip, MR, AC97C_MR_ENA); 679 + } 680 + 681 + static int __devinit atmel_ac97c_probe(struct platform_device *pdev) 682 + { 683 + struct snd_card *card; 684 + struct atmel_ac97c *chip; 685 + struct resource *regs; 686 + struct ac97c_platform_data *pdata; 687 + struct clk *pclk; 688 + static struct snd_ac97_bus_ops ops = { 689 + .write = atmel_ac97c_write, 690 + .read = atmel_ac97c_read, 691 + }; 692 + int retval; 693 + 694 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 695 + if (!regs) { 696 + dev_dbg(&pdev->dev, "no memory resource\n"); 697 + return -ENXIO; 698 + } 699 + 700 + pdata = pdev->dev.platform_data; 701 + if (!pdata) { 702 + dev_dbg(&pdev->dev, "no platform data\n"); 703 + return -ENXIO; 704 + } 705 + 706 + pclk = clk_get(&pdev->dev, "pclk"); 707 + if (IS_ERR(pclk)) { 708 + dev_dbg(&pdev->dev, "no peripheral clock\n"); 709 + return PTR_ERR(pclk); 710 + } 711 + clk_enable(pclk); 712 + 713 + retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 714 + THIS_MODULE, sizeof(struct atmel_ac97c), &card); 715 + if (retval) { 716 + dev_dbg(&pdev->dev, "could not create sound card device\n"); 717 + goto err_snd_card_new; 718 + } 719 + 720 + chip = get_chip(card); 721 + 722 + spin_lock_init(&chip->lock); 723 + 724 + strcpy(card->driver, "Atmel AC97C"); 725 + strcpy(card->shortname, "Atmel AC97C"); 726 + sprintf(card->longname, "Atmel AC97 controller"); 727 + 728 + chip->card = card; 729 + chip->pclk = pclk; 730 + chip->pdev = pdev; 731 + chip->regs = ioremap(regs->start, regs->end - regs->start + 1); 732 + 733 + if (!chip->regs) { 734 + dev_dbg(&pdev->dev, "could not remap register memory\n"); 735 + goto err_ioremap; 736 + } 737 + 738 + if (gpio_is_valid(pdata->reset_pin)) { 739 + if (gpio_request(pdata->reset_pin, "reset_pin")) { 740 + dev_dbg(&pdev->dev, "reset pin not available\n"); 741 + chip->reset_pin = -ENODEV; 742 + } else { 743 + gpio_direction_output(pdata->reset_pin, 1); 744 + chip->reset_pin = pdata->reset_pin; 745 + } 746 + } 747 + 748 + snd_card_set_dev(card, &pdev->dev); 749 + 750 + retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); 751 + if (retval) { 752 + dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); 753 + goto err_ac97_bus; 754 + } 755 + 756 + atmel_ac97c_reset(chip); 757 + 758 + retval = atmel_ac97c_mixer_new(chip); 759 + if (retval) { 760 + dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); 761 + goto err_ac97_bus; 762 + } 763 + 764 + if (pdata->rx_dws.dma_dev) { 765 + struct dw_dma_slave *dws = &pdata->rx_dws; 766 + dma_cap_mask_t mask; 767 + 768 + dws->rx_reg = regs->start + AC97C_CARHR + 2; 769 + 770 + dma_cap_zero(mask); 771 + dma_cap_set(DMA_SLAVE, mask); 772 + 773 + chip->dma.rx_chan = dma_request_channel(mask, filter, dws); 774 + 775 + dev_info(&chip->pdev->dev, "using %s for DMA RX\n", 776 + chip->dma.rx_chan->dev->device.bus_id); 777 + set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); 778 + } 779 + 780 + if (pdata->tx_dws.dma_dev) { 781 + struct dw_dma_slave *dws = &pdata->tx_dws; 782 + dma_cap_mask_t mask; 783 + 784 + dws->tx_reg = regs->start + AC97C_CATHR + 2; 785 + 786 + dma_cap_zero(mask); 787 + dma_cap_set(DMA_SLAVE, mask); 788 + 789 + chip->dma.tx_chan = dma_request_channel(mask, filter, dws); 790 + 791 + dev_info(&chip->pdev->dev, "using %s for DMA TX\n", 792 + chip->dma.tx_chan->dev->device.bus_id); 793 + set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); 794 + } 795 + 796 + if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && 797 + !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { 798 + dev_dbg(&pdev->dev, "DMA not available\n"); 799 + retval = -ENODEV; 800 + goto err_dma; 801 + } 802 + 803 + retval = atmel_ac97c_pcm_new(chip); 804 + if (retval) { 805 + dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); 806 + goto err_dma; 807 + } 808 + 809 + retval = snd_card_register(card); 810 + if (retval) { 811 + dev_dbg(&pdev->dev, "could not register sound card\n"); 812 + goto err_ac97_bus; 813 + } 814 + 815 + platform_set_drvdata(pdev, card); 816 + 817 + dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n", 818 + chip->regs); 819 + 820 + return 0; 821 + 822 + err_dma: 823 + if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) 824 + dma_release_channel(chip->dma.rx_chan); 825 + if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) 826 + dma_release_channel(chip->dma.tx_chan); 827 + clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); 828 + clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); 829 + chip->dma.rx_chan = NULL; 830 + chip->dma.tx_chan = NULL; 831 + err_ac97_bus: 832 + snd_card_set_dev(card, NULL); 833 + 834 + if (gpio_is_valid(chip->reset_pin)) 835 + gpio_free(chip->reset_pin); 836 + 837 + iounmap(chip->regs); 838 + err_ioremap: 839 + snd_card_free(card); 840 + err_snd_card_new: 841 + clk_disable(pclk); 842 + clk_put(pclk); 843 + return retval; 844 + } 845 + 846 + #ifdef CONFIG_PM 847 + static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) 848 + { 849 + struct snd_card *card = platform_get_drvdata(pdev); 850 + struct atmel_ac97c *chip = card->private_data; 851 + 852 + if (test_bit(DMA_RX_READY, &chip->flags)) 853 + dw_dma_cyclic_stop(chip->dma.rx_chan); 854 + if (test_bit(DMA_TX_READY, &chip->flags)) 855 + dw_dma_cyclic_stop(chip->dma.tx_chan); 856 + clk_disable(chip->pclk); 857 + 858 + return 0; 859 + } 860 + 861 + static int atmel_ac97c_resume(struct platform_device *pdev) 862 + { 863 + struct snd_card *card = platform_get_drvdata(pdev); 864 + struct atmel_ac97c *chip = card->private_data; 865 + 866 + clk_enable(chip->pclk); 867 + if (test_bit(DMA_RX_READY, &chip->flags)) 868 + dw_dma_cyclic_start(chip->dma.rx_chan); 869 + if (test_bit(DMA_TX_READY, &chip->flags)) 870 + dw_dma_cyclic_start(chip->dma.tx_chan); 871 + 872 + return 0; 873 + } 874 + #else 875 + #define atmel_ac97c_suspend NULL 876 + #define atmel_ac97c_resume NULL 877 + #endif 878 + 879 + static int __devexit atmel_ac97c_remove(struct platform_device *pdev) 880 + { 881 + struct snd_card *card = platform_get_drvdata(pdev); 882 + struct atmel_ac97c *chip = get_chip(card); 883 + 884 + if (gpio_is_valid(chip->reset_pin)) 885 + gpio_free(chip->reset_pin); 886 + 887 + clk_disable(chip->pclk); 888 + clk_put(chip->pclk); 889 + iounmap(chip->regs); 890 + 891 + if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) 892 + dma_release_channel(chip->dma.rx_chan); 893 + if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) 894 + dma_release_channel(chip->dma.tx_chan); 895 + clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); 896 + clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); 897 + chip->dma.rx_chan = NULL; 898 + chip->dma.tx_chan = NULL; 899 + 900 + snd_card_set_dev(card, NULL); 901 + snd_card_free(card); 902 + 903 + platform_set_drvdata(pdev, NULL); 904 + 905 + return 0; 906 + } 907 + 908 + static struct platform_driver atmel_ac97c_driver = { 909 + .remove = __devexit_p(atmel_ac97c_remove), 910 + .driver = { 911 + .name = "atmel_ac97c", 912 + }, 913 + .suspend = atmel_ac97c_suspend, 914 + .resume = atmel_ac97c_resume, 915 + }; 916 + 917 + static int __init atmel_ac97c_init(void) 918 + { 919 + return platform_driver_probe(&atmel_ac97c_driver, 920 + atmel_ac97c_probe); 921 + } 922 + module_init(atmel_ac97c_init); 923 + 924 + static void __exit atmel_ac97c_exit(void) 925 + { 926 + platform_driver_unregister(&atmel_ac97c_driver); 927 + } 928 + module_exit(atmel_ac97c_exit); 929 + 930 + MODULE_LICENSE("GPL"); 931 + MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); 932 + MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");
+71
sound/atmel/ac97c.h
··· 1 + /* 2 + * Register definitions for the Atmel AC97C controller 3 + * 4 + * Copyright (C) 2005-2009 Atmel Corporation 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published 8 + * by the Free Software Foundation. 9 + */ 10 + #ifndef __SOUND_ATMEL_AC97C_H 11 + #define __SOUND_ATMEL_AC97C_H 12 + 13 + #define AC97C_MR 0x08 14 + #define AC97C_ICA 0x10 15 + #define AC97C_OCA 0x14 16 + #define AC97C_CARHR 0x20 17 + #define AC97C_CATHR 0x24 18 + #define AC97C_CASR 0x28 19 + #define AC97C_CAMR 0x2c 20 + #define AC97C_CBRHR 0x30 21 + #define AC97C_CBTHR 0x34 22 + #define AC97C_CBSR 0x38 23 + #define AC97C_CBMR 0x3c 24 + #define AC97C_CORHR 0x40 25 + #define AC97C_COTHR 0x44 26 + #define AC97C_COSR 0x48 27 + #define AC97C_COMR 0x4c 28 + #define AC97C_SR 0x50 29 + #define AC97C_IER 0x54 30 + #define AC97C_IDR 0x58 31 + #define AC97C_IMR 0x5c 32 + #define AC97C_VERSION 0xfc 33 + 34 + #define AC97C_CATPR PDC_TPR 35 + #define AC97C_CATCR PDC_TCR 36 + #define AC97C_CATNPR PDC_TNPR 37 + #define AC97C_CATNCR PDC_TNCR 38 + #define AC97C_CARPR PDC_RPR 39 + #define AC97C_CARCR PDC_RCR 40 + #define AC97C_CARNPR PDC_RNPR 41 + #define AC97C_CARNCR PDC_RNCR 42 + #define AC97C_PTCR PDC_PTCR 43 + 44 + #define AC97C_MR_ENA (1 << 0) 45 + #define AC97C_MR_WRST (1 << 1) 46 + #define AC97C_MR_VRA (1 << 2) 47 + 48 + #define AC97C_CSR_TXRDY (1 << 0) 49 + #define AC97C_CSR_UNRUN (1 << 2) 50 + #define AC97C_CSR_RXRDY (1 << 4) 51 + #define AC97C_CSR_ENDTX (1 << 10) 52 + #define AC97C_CSR_ENDRX (1 << 14) 53 + 54 + #define AC97C_CMR_SIZE_20 (0 << 16) 55 + #define AC97C_CMR_SIZE_18 (1 << 16) 56 + #define AC97C_CMR_SIZE_16 (2 << 16) 57 + #define AC97C_CMR_SIZE_10 (3 << 16) 58 + #define AC97C_CMR_CEM_LITTLE (1 << 18) 59 + #define AC97C_CMR_CEM_BIG (0 << 18) 60 + #define AC97C_CMR_CENA (1 << 21) 61 + #define AC97C_CMR_DMAEN (1 << 22) 62 + 63 + #define AC97C_SR_CAEVT (1 << 3) 64 + 65 + #define AC97C_CH_ASSIGN(slot, channel) \ 66 + (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) 67 + #define AC97C_CHANNEL_NONE 0x0 68 + #define AC97C_CHANNEL_A 0x1 69 + #define AC97C_CHANNEL_B 0x2 70 + 71 + #endif /* __SOUND_ATMEL_AC97C_H */