diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2012-03-16 04:56:42 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-01 06:28:27 -0400 |
commit | dfa1a10785cf861c725aed0492f0ab69662bffea (patch) | |
tree | b673bcb4ef40c1864c070e5f695796319e41d15e /sound/soc/fsl | |
parent | 8f549d7e7795e5e07ff871a79708bf2e387104dd (diff) |
ASoC: fsl: make fsl_ssi driver compilable on ARM/IMX
Provide different pair of accessors for accessing SSI registers on
PowerPC and ARM/IMX, so that fsl_ssi driver can be built on both
architectures.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Acked-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 2eb407fa3b48..db9a73404385 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -11,11 +11,14 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/io.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/of_address.h> | ||
21 | #include <linux/of_irq.h> | ||
19 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
20 | 23 | ||
21 | #include <sound/core.h> | 24 | #include <sound/core.h> |
@@ -26,6 +29,25 @@ | |||
26 | 29 | ||
27 | #include "fsl_ssi.h" | 30 | #include "fsl_ssi.h" |
28 | 31 | ||
32 | #ifdef PPC | ||
33 | #define read_ssi(addr) in_be32(addr) | ||
34 | #define write_ssi(val, addr) out_be32(addr, val) | ||
35 | #define write_ssi_mask(addr, clear, set) clrsetbits_be32(addr, clear, set) | ||
36 | #elif defined ARM | ||
37 | #define read_ssi(addr) readl(addr) | ||
38 | #define write_ssi(val, addr) writel(val, addr) | ||
39 | /* | ||
40 | * FIXME: Proper locking should be added at write_ssi_mask caller level | ||
41 | * to ensure this register read/modify/write sequence is race free. | ||
42 | */ | ||
43 | static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | ||
44 | { | ||
45 | u32 val = readl(addr); | ||
46 | val = (val & ~clear) | set; | ||
47 | writel(val, addr); | ||
48 | } | ||
49 | #endif | ||
50 | |||
29 | /** | 51 | /** |
30 | * FSLSSI_I2S_RATES: sample rates supported by the I2S | 52 | * FSLSSI_I2S_RATES: sample rates supported by the I2S |
31 | * | 53 | * |
@@ -145,7 +167,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
145 | were interrupted for. We mask it with the Interrupt Enable register | 167 | were interrupted for. We mask it with the Interrupt Enable register |
146 | so that we only check for events that we're interested in. | 168 | so that we only check for events that we're interested in. |
147 | */ | 169 | */ |
148 | sisr = in_be32(&ssi->sisr) & SIER_FLAGS; | 170 | sisr = read_ssi(&ssi->sisr) & SIER_FLAGS; |
149 | 171 | ||
150 | if (sisr & CCSR_SSI_SISR_RFRC) { | 172 | if (sisr & CCSR_SSI_SISR_RFRC) { |
151 | ssi_private->stats.rfrc++; | 173 | ssi_private->stats.rfrc++; |
@@ -260,7 +282,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
260 | 282 | ||
261 | /* Clear the bits that we set */ | 283 | /* Clear the bits that we set */ |
262 | if (sisr2) | 284 | if (sisr2) |
263 | out_be32(&ssi->sisr, sisr2); | 285 | write_ssi(sisr2, &ssi->sisr); |
264 | 286 | ||
265 | return ret; | 287 | return ret; |
266 | } | 288 | } |
@@ -295,7 +317,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
295 | * SSI needs to be disabled before updating the registers we set | 317 | * SSI needs to be disabled before updating the registers we set |
296 | * here. | 318 | * here. |
297 | */ | 319 | */ |
298 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 320 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); |
299 | 321 | ||
300 | /* | 322 | /* |
301 | * Program the SSI into I2S Slave Non-Network Synchronous mode. | 323 | * Program the SSI into I2S Slave Non-Network Synchronous mode. |
@@ -303,20 +325,18 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
303 | * | 325 | * |
304 | * FIXME: Little-endian samples require a different shift dir | 326 | * FIXME: Little-endian samples require a different shift dir |
305 | */ | 327 | */ |
306 | clrsetbits_be32(&ssi->scr, | 328 | write_ssi_mask(&ssi->scr, |
307 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, | 329 | CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, |
308 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE | 330 | CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE |
309 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); | 331 | | (synchronous ? CCSR_SSI_SCR_SYN : 0)); |
310 | 332 | ||
311 | out_be32(&ssi->stcr, | 333 | write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | |
312 | CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | | ||
313 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | | 334 | CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | |
314 | CCSR_SSI_STCR_TSCKP); | 335 | CCSR_SSI_STCR_TSCKP, &ssi->stcr); |
315 | 336 | ||
316 | out_be32(&ssi->srcr, | 337 | write_ssi(CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | |
317 | CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | | ||
318 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | | 338 | CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | |
319 | CCSR_SSI_SRCR_RSCKP); | 339 | CCSR_SSI_SRCR_RSCKP, &ssi->srcr); |
320 | 340 | ||
321 | /* | 341 | /* |
322 | * The DC and PM bits are only used if the SSI is the clock | 342 | * The DC and PM bits are only used if the SSI is the clock |
@@ -324,7 +344,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
324 | */ | 344 | */ |
325 | 345 | ||
326 | /* Enable the interrupts and DMA requests */ | 346 | /* Enable the interrupts and DMA requests */ |
327 | out_be32(&ssi->sier, SIER_FLAGS); | 347 | write_ssi(SIER_FLAGS, &ssi->sier); |
328 | 348 | ||
329 | /* | 349 | /* |
330 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We | 350 | * Set the watermark for transmit FIFI 0 and receive FIFO 0. We |
@@ -339,9 +359,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
339 | * make this value larger (and maybe we should), but this way | 359 | * make this value larger (and maybe we should), but this way |
340 | * data will be written to memory as soon as it's available. | 360 | * data will be written to memory as soon as it's available. |
341 | */ | 361 | */ |
342 | out_be32(&ssi->sfcsr, | 362 | write_ssi(CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | |
343 | CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | | 363 | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2), |
344 | CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2)); | 364 | &ssi->sfcsr); |
345 | 365 | ||
346 | /* | 366 | /* |
347 | * We keep the SSI disabled because if we enable it, then the | 367 | * We keep the SSI disabled because if we enable it, then the |
@@ -417,7 +437,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
417 | unsigned int sample_size = | 437 | unsigned int sample_size = |
418 | snd_pcm_format_width(params_format(hw_params)); | 438 | snd_pcm_format_width(params_format(hw_params)); |
419 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | 439 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); |
420 | int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN; | 440 | int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; |
421 | 441 | ||
422 | /* | 442 | /* |
423 | * If we're in synchronous mode, and the SSI is already enabled, | 443 | * If we're in synchronous mode, and the SSI is already enabled, |
@@ -439,9 +459,9 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
439 | /* In synchronous mode, the SSI uses STCCR for capture */ | 459 | /* In synchronous mode, the SSI uses STCCR for capture */ |
440 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || | 460 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || |
441 | ssi_private->cpu_dai_drv.symmetric_rates) | 461 | ssi_private->cpu_dai_drv.symmetric_rates) |
442 | clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); | 462 | write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
443 | else | 463 | else |
444 | clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); | 464 | write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); |
445 | 465 | ||
446 | return 0; | 466 | return 0; |
447 | } | 467 | } |
@@ -466,19 +486,19 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
466 | case SNDRV_PCM_TRIGGER_START: | 486 | case SNDRV_PCM_TRIGGER_START: |
467 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 487 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
468 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 488 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
469 | setbits32(&ssi->scr, | 489 | write_ssi_mask(&ssi->scr, 0, |
470 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); | 490 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); |
471 | else | 491 | else |
472 | setbits32(&ssi->scr, | 492 | write_ssi_mask(&ssi->scr, 0, |
473 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); | 493 | CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); |
474 | break; | 494 | break; |
475 | 495 | ||
476 | case SNDRV_PCM_TRIGGER_STOP: | 496 | case SNDRV_PCM_TRIGGER_STOP: |
477 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 497 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
478 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 498 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
479 | clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); | 499 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_TE, 0); |
480 | else | 500 | else |
481 | clrbits32(&ssi->scr, CCSR_SSI_SCR_RE); | 501 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_RE, 0); |
482 | break; | 502 | break; |
483 | 503 | ||
484 | default: | 504 | default: |
@@ -510,7 +530,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | |||
510 | if (!ssi_private->first_stream) { | 530 | if (!ssi_private->first_stream) { |
511 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 531 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
512 | 532 | ||
513 | clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); | 533 | write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0); |
514 | } | 534 | } |
515 | } | 535 | } |
516 | 536 | ||