Part 3: S3C ASoC I2S-V2 drivers, used by S3C2412-I2S and S3C64XX-I2S. Add the callback functions for the DMA drivers. These callback functions are registered in the probe phase.
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c 2009-08-24 13:28:58.000000000 +0800 +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c 2009-08-24 15:17:02.000000000 +0800 @@ -53,6 +53,12 @@
#define S3C2412_I2S_DEBUG_CON 0
+struct s3c2412_i2s_trigger_internal_data { + struct snd_pcm_substream *substream; + int cmd; + struct snd_soc_dai *dai; +}; + static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) { return cpu_dai->private_data; @@ -383,14 +389,45 @@ struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct s3c24xx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct s3c2410_dma_client *client = dma_params->client; + struct s3c2412_i2s_trigger_internal_data callback_params; + int ret = 0; + + callback_params.substream = substream; + callback_params.cmd = cmd; + callback_params.dai = dai; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + client->event = S3C2410_DMA_TRIGGER_START;; + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + client->event = S3C2410_DMA_TRIGGER_STOP; + break; + default: + return -EINVAL; + } + + client->private_data = &callback_params; + return s3c2410_dma_trigger(client); +} + +static int s3c2412_i2s_trigger_internal(struct s3c2412_i2s_trigger_internal_data *data) +{ + struct snd_soc_pcm_runtime *rtd = data->substream->private_data; struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); + int capture = (data->substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; int ret = 0;
pr_debug("Entered %s\n", __func__);
- switch (cmd) { + switch (data->cmd) { case SNDRV_PCM_TRIGGER_START: /* On start, ensure that the FIFOs are cleared and reset. */
@@ -627,6 +664,14 @@ s3c2412_snd_txctrl(i2s, 0); s3c2412_snd_rxctrl(i2s, 0);
+ if(i2s->dma_playback && i2s->dma_playback->client) { + i2s->dma_playback->client->gen_request = (void*)s3c2412_i2s_trigger_internal; + i2s->dma_playback->client->end_request = (void*)s3c2412_i2s_trigger_internal; + } + if(i2s->dma_capture && i2s->dma_capture->client) { + i2s->dma_capture->client->gen_request = (void*)s3c2412_i2s_trigger_internal; + i2s->dma_capture->client->end_request = (void*)s3c2412_i2s_trigger_internal; + } return 0; } EXPORT_SYMBOL_GPL(s3c_i2sv2_probe); --- a/sound/soc/s3c24xx/s3c2412-i2s.c 2009-08-24 13:28:58.000000000 +0800 +++ b/sound/soc/s3c24xx/s3c2412-i2s.c 2009-08-24 15:02:32.000000000 +0800 @@ -44,11 +44,16 @@ #define S3C2412_I2S_DEBUG 0
static struct s3c2410_dma_client s3c2412_dma_client_out = { - .name = "I2S PCM Stereo out" + .name = "I2S PCM Stereo out", + .channel = DMACH_I2S_OUT, + /* callback functions will be set in s3c_i2sv2_probe */ + };
static struct s3c2410_dma_client s3c2412_dma_client_in = { - .name = "I2S PCM Stereo in" + .name = "I2S PCM Stereo in", + .channel = DMACH_I2S_IN, + /* callback functions will be set in s3c_i2sv2_probe */ };
static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_out = { @@ -112,13 +117,14 @@
pr_debug("Entered %s\n", __func__);
+ /* s3c_i2sv2_probe will setup dma callback functions for them */ + s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; + s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; + ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); if (ret) return ret;
- s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; - s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; - s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); if (s3c2412_i2s.iis_cclk == NULL) { pr_err("failed to get i2sclk clock\n"); --- a/sound/soc/s3c24xx/s3c64xx-i2s.c 2009-08-24 13:28:58.000000000 +0800 +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c 2009-08-24 15:00:24.000000000 +0800 @@ -39,24 +39,42 @@ #include "s3c24xx-pcm.h" #include "s3c64xx-i2s.h"
-static struct s3c2410_dma_client s3c64xx_dma_client_out = { - .name = "I2S PCM Stereo out" +static struct s3c2410_dma_client s3c64xx_dma_client_out_0 = { + .name = "I2S PCM Stereo out #0", + .channel = DMACH_I2S0_OUT, + /* callback functions will be set in s3c_i2sv2_probe */ };
-static struct s3c2410_dma_client s3c64xx_dma_client_in = { - .name = "I2S PCM Stereo in" +static struct s3c2410_dma_client s3c64xx_dma_client_out_1 = { + .name = "I2S PCM Stereo out #1", + .channel = DMACH_I2S1_OUT, + /* callback functions will be set in s3c_i2sv2_probe */ +}; + +static struct s3c2410_dma_client s3c64xx_dma_client_in_0 = { + .name = "I2S PCM Stereo in #0", + .channel = DMACH_I2S0_IN, + /* callback functions will be set in s3c_i2sv2_probe */ + +}; + +static struct s3c2410_dma_client s3c64xx_dma_client_in_1 = { + .name = "I2S PCM Stereo in #1", + .channel = DMACH_I2S1_IN, + /* callback functions will be set in s3c_i2sv2_probe */ + };
static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = { [0] = { .channel = DMACH_I2S0_OUT, - .client = &s3c64xx_dma_client_out, + .client = &s3c64xx_dma_client_out_0, .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD, .dma_size = 4, }, [1] = { .channel = DMACH_I2S1_OUT, - .client = &s3c64xx_dma_client_out, + .client = &s3c64xx_dma_client_out_1, .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD, .dma_size = 4, }, @@ -65,13 +83,13 @@ static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = { [0] = { .channel = DMACH_I2S0_IN, - .client = &s3c64xx_dma_client_in, + .client = &s3c64xx_dma_client_in_0, .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD, .dma_size = 4, }, [1] = { .channel = DMACH_I2S1_IN, - .client = &s3c64xx_dma_client_in, + .client = &s3c64xx_dma_client_in_1, .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD, .dma_size = 4, },