diff options
Diffstat (limited to 'sound/soc/soc-pcm.c')
| -rw-r--r-- | sound/soc/soc-pcm.c | 430 |
1 files changed, 397 insertions, 33 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b773d61cd5bc..5845a3d53010 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -25,6 +25,7 @@ #include <linux/workqueue.h> #include <linux/export.h> #include <linux/debugfs.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -52,6 +53,26 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) return codec_stream->channels_min; } +static const struct snd_pcm_hardware no_host_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = PAGE_SIZE >> 2, + .period_bytes_max = PAGE_SIZE >> 1, + .periods_min = 2, + .periods_max = 4, + /* + * Increase the max buffer bytes as PAGE_SIZE bytes is + * not enough to encompass all the scenarios sent by + * userspapce. + */ + .buffer_bytes_max = PAGE_SIZE * 4, +}; + /** * snd_soc_runtime_activate() - Increment active count for PCM runtime components * @rtd: ASoC PCM runtime that is activated @@ -156,6 +177,8 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw) { struct snd_pcm_runtime *runtime = substream->runtime; + if (!runtime) + return 0; runtime->hw.info = hw->info; runtime->hw.formats = hw->formats; runtime->hw.period_bytes_min = hw->period_bytes_min; @@ -182,8 +205,10 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, be->dai_link->name, event, dir); if ((event == SND_SOC_DAPM_STREAM_STOP) && - (be->dpcm[dir].users >= 1)) + (be->dpcm[dir].users >= 1)) { + pr_debug("%s Don't close BE \n", __func__); continue; + } snd_soc_dapm_stream_event(be, dir, event); } @@ -468,6 +493,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) pm_runtime_get_sync(platform->dev); mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) + snd_soc_set_runtime_hwparams(substream, &no_host_hardware); /* startup the audio subsystem */ if (cpu_dai->driver->ops && cpu_dai->driver->ops->startup) { @@ -598,7 +625,7 @@ codec_dai_err: platform->driver->ops->close(substream); platform_err: - if (cpu_dai->driver->ops->shutdown) + if (cpu_dai->driver->ops && cpu_dai->driver->ops->shutdown) cpu_dai->driver->ops->shutdown(substream, cpu_dai); out: mutex_unlock(&rtd->pcm_mutex); @@ -674,6 +701,20 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { + /* powered down playback stream now */ + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_STOP); + } else { + /* start delayed pop wq here for playback streams */ + rtd->pop_wait = 1; + queue_delayed_work(system_power_efficient_wq, + &rtd->delayed_work, + msecs_to_jiffies(rtd->pmdown_time)); + } + } if (cpu_dai->driver->ops->shutdown) cpu_dai->driver->ops->shutdown(substream, cpu_dai); @@ -689,20 +730,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) if (platform->driver->ops && platform->driver->ops->close) platform->driver->ops->close(substream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (snd_soc_runtime_ignore_pmdown_time(rtd)) { - /* powered down playback stream now */ - snd_soc_dapm_stream_event(rtd, - SNDRV_PCM_STREAM_PLAYBACK, - SND_SOC_DAPM_STREAM_STOP); - } else { - /* start delayed pop wq here for playback streams */ - rtd->pop_wait = 1; - queue_delayed_work(system_power_efficient_wq, - &rtd->delayed_work, - msecs_to_jiffies(rtd->pmdown_time)); - } - } else { + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { /* capture streams can be powered down now */ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE, SND_SOC_DAPM_STREAM_STOP); @@ -739,6 +767,11 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_START); + if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) { ret = rtd->dai_link->ops->prepare(substream); if (ret < 0) { @@ -787,8 +820,15 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) cancel_delayed_work(&rtd->delayed_work); } - snd_soc_dapm_stream_event(rtd, substream->stream, - SND_SOC_DAPM_STREAM_START); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + for (i = 0; i < rtd->num_codecs; i++) { + codec_dai = rtd->codec_dais[i]; + if (codec_dai->capture_active == 1) + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_CAPTURE, + SND_SOC_DAPM_STREAM_START); + } + } for (i = 0; i < rtd->num_codecs; i++) snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, @@ -796,6 +836,13 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); out: + if (ret < 0 && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pr_err("%s: Issue stop stream for codec_dai due to op failure %d = ret\n", + __func__, ret); + snd_soc_dapm_stream_event(rtd, + SNDRV_PCM_STREAM_PLAYBACK, + SND_SOC_DAPM_STREAM_STOP); + } mutex_unlock(&rtd->pcm_mutex); return ret; } @@ -844,10 +891,31 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + /* perform any hw_params fixups */ + if ((rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) && + rtd->dai_link->be_hw_params_fixup) { + ret = rtd->dai_link->be_hw_params_fixup(rtd, + params); + if (ret < 0) + dev_err(rtd->card->dev, "ASoC: fixup failed for %s\n", + rtd->dai_link->name); + } + ret = soc_pcm_params_symmetry(substream, params); if (ret) goto out; + /* perform any hw_params fixups */ + if ((rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) && + rtd->dai_link->be_hw_params_fixup) { + ret = rtd->dai_link->be_hw_params_fixup(rtd, + params); + if (ret < 0) { + dev_err(rtd->card->dev, "ASoC: fixup failed for %s\n", + rtd->dai_link->name); + } + } + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { ret = rtd->dai_link->ops->hw_params(substream, params); if (ret < 0) { @@ -920,6 +988,22 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, cpu_dai->channels = params_channels(params); cpu_dai->sample_bits = snd_pcm_format_physical_width(params_format(params)); + /* malloc a page for hostless IO. + * FIXME: rework with alsa-lib changes so that this malloc is not required. + */ + if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) { + substream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV; + substream->dma_buffer.dev.dev = rtd->dev; + substream->dma_buffer.dev.dev->coherent_dma_mask = + DMA_BIT_MASK(sizeof(dma_addr_t) * 8); + substream->dma_buffer.private_data = NULL; + + arch_setup_dma_ops(substream->dma_buffer.dev.dev, + 0, 0, NULL, 0); + ret = snd_pcm_lib_malloc_pages(substream, PAGE_SIZE); + if (ret < 0) + goto platform_err; + } out: mutex_unlock(&rtd->pcm_mutex); @@ -1003,6 +1087,9 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free) cpu_dai->driver->ops->hw_free(substream, cpu_dai); + if (rtd->dai_link->no_host_mode == SND_SOC_DAI_LINK_NO_HOST) + snd_pcm_lib_free_pages(substream); + mutex_unlock(&rtd->pcm_mutex); return 0; } @@ -1099,6 +1186,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) if (platform->driver->ops && platform->driver->ops->pointer) offset = platform->driver->ops->pointer(substream); + if (platform->driver->delay_blk) + return offset; + if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay) delay += cpu_dai->driver->ops->delay(substream, cpu_dai); @@ -1123,6 +1213,22 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) return offset; } +static int soc_pcm_delay_blk(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_platform *platform = rtd->platform; + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_sframes_t delay = 0; + + if (platform->driver->delay_blk) + delay = platform->driver->delay_blk(substream, + rtd->codec_dais[0]); + + runtime->delay = delay; + + return 0; +} + /* connect a FE and BE */ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be, int stream) @@ -1229,7 +1335,11 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; - if (be->cpu_dai->playback_widget == widget) + if ((be->cpu_dai->playback_widget == widget && + (be->dai_link->stream_name && + !strcmp(be->dai_link->stream_name, + be->cpu_dai->playback_widget->sname))) || + be->codec_dai->playback_widget == widget) return be; for (j = 0; j < be->num_codecs; j++) { @@ -1246,7 +1356,11 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, if (!be->dai_link->no_pcm) continue; - if (be->cpu_dai->capture_widget == widget) + if ((be->cpu_dai->capture_widget == widget && + (be->dai_link->stream_name && + !strcmp(be->dai_link->stream_name, + be->cpu_dai->capture_widget->sname))) || + be->codec_dai->capture_widget == widget) return be; for (j = 0; j < be->num_codecs; j++) { @@ -1716,14 +1830,14 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); - /* shutdown the BEs */ - dpcm_be_dai_shutdown(fe, substream->stream); - dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name); /* now shutdown the frontend */ soc_pcm_close(substream); + /* shutdown the BEs */ + dpcm_be_dai_shutdown(fe, substream->stream); + /* run the stream event for each BE */ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); @@ -1802,6 +1916,81 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) return 0; } +int dpcm_fe_dai_hw_params_be(struct snd_soc_pcm_runtime *fe, + struct snd_soc_pcm_runtime *be, + struct snd_pcm_hw_params *params, int stream) +{ + int ret; + struct snd_soc_dpcm *dpcm; + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, stream); + + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + return 0; + + /* only allow hw_params() if no connected FEs are running */ + if (!snd_soc_dpcm_can_be_params(fe, be, stream)) + return 0; + + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && + (be->dpcm[stream].state != + SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE)) + return 0; + + dev_dbg(be->dev, "ASoC: hw_params BE %s\n", + fe->dai_link->name); + + /* perform any hw_params fixups */ + if (be->dai_link->be_hw_params_fixup) { + ret = be->dai_link->be_hw_params_fixup(be, + params); + if (ret < 0) { + dev_err(be->dev, + "ASoC: hw_params BE fixup failed %d\n", + ret); + goto unwind; + } + } + + ret = soc_pcm_hw_params(be_substream, params); + if (ret < 0) { + dev_err(be->dev, "ASoC: hw_params BE failed %d\n", ret); + goto unwind; + } + + be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; + return 0; + +unwind: + /* disable any enabled and non active backends */ + list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { + struct snd_soc_pcm_runtime *be = dpcm->be; + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, stream); + + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + continue; + + /* only allow hw_free() if no connected FEs are running */ + if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) + continue; + + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && + (be->dpcm[stream].state + != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state + != SND_SOC_DPCM_STATE_HW_FREE) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + continue; + + soc_pcm_hw_free(be_substream); + } + + return ret; +} + int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -2147,6 +2336,35 @@ out: return ret; } +int dpcm_fe_dai_prepare_be(struct snd_soc_pcm_runtime *fe, + struct snd_soc_pcm_runtime *be, int stream) +{ + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, stream); + int ret = 0; + + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + return 0; + + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + return 0; + + dev_dbg(be->dev, "ASoC: prepare BE %s\n", + fe->dai_link->name); + + ret = soc_pcm_prepare(be_substream); + if (ret < 0) { + dev_err(be->dev, "ASoC: backend prepare failed %d\n", + ret); + return ret; + } + + be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; + return ret; +} + static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *fe = substream->private_data; @@ -2198,13 +2416,94 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) return ret; } +static void dpcm_be_async_prepare(void *data, async_cookie_t cookie) +{ + struct snd_soc_dpcm *dpcm = data; + struct snd_soc_pcm_runtime *be = dpcm->be; + int stream = dpcm->stream; + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, stream); + int ret; + + dev_dbg(be->dev, "%s ASoC: prepare BE %s\n", __func__, + dpcm->fe->dai_link->name); + ret = soc_pcm_prepare(be_substream); + if (ret < 0) { + be->err_ops = ret; + dev_err(be->dev, "ASoC: backend prepare failed %d\n", + ret); + return; + } + be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; +} + +void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream, + struct async_domain *domain) +{ + struct snd_soc_dpcm *dpcm; + struct snd_soc_dpcm *dpcm_async[DPCM_MAX_BE_USERS]; + int i = 0, j; + + list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { + struct snd_soc_pcm_runtime *be = dpcm->be; + + be->err_ops = 0; + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + continue; + + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + continue; + + /* does this BE support async op ?*/ + if ((fe->dai_link->async_ops & ASYNC_DPCM_SND_SOC_PREPARE) && + (be->dai_link->async_ops & ASYNC_DPCM_SND_SOC_PREPARE)) { + dpcm->stream = stream; + async_schedule_domain(dpcm_be_async_prepare, + dpcm, domain); + } else { + dpcm_async[i++] = dpcm; + if (i == DPCM_MAX_BE_USERS) { + dev_dbg(fe->dev, "ASoC: MAX backend users!\n"); + break; + } + } + } + + for (j = 0; j < i; j++) { + struct snd_soc_dpcm *dpcm = dpcm_async[j]; + struct snd_soc_pcm_runtime *be = dpcm->be; + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, stream); + int ret; + + dev_dbg(be->dev, "ASoC: prepare BE %s\n", + dpcm->fe->dai_link->name); + + ret = soc_pcm_prepare(be_substream); + if (ret < 0) { + dev_err(be->dev, "ASoC: backend prepare failed %d\n", + ret); + be->err_ops = ret; + return; + } + + be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; + } +} + static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = substream->private_data; + struct snd_soc_dpcm *dpcm; int stream = substream->stream, ret = 0; + ASYNC_DOMAIN_EXCLUSIVE(async_domain); mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + fe->err_ops = 0; + dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); @@ -2217,16 +2516,47 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) goto out; } - ret = dpcm_be_dai_prepare(fe, substream->stream); - if (ret < 0) - goto out; + if (!(fe->dai_link->async_ops & ASYNC_DPCM_SND_SOC_PREPARE)) { + ret = dpcm_be_dai_prepare(fe, substream->stream); + if (ret < 0) + goto out; + /* call prepare on the frontend */ + ret = soc_pcm_prepare(substream); + if (ret < 0) { + dev_err(fe->dev, "ASoC: prepare FE %s failed\n", + fe->dai_link->name); + goto out; + } + } else { + dpcm_be_dai_prepare_async(fe, substream->stream, + &async_domain); - /* call prepare on the frontend */ - ret = soc_pcm_prepare(substream); - if (ret < 0) { - dev_err(fe->dev,"ASoC: prepare FE %s failed\n", - fe->dai_link->name); - goto out; + /* call prepare on the frontend */ + ret = soc_pcm_prepare(substream); + if (ret < 0) { + fe->err_ops = ret; + dev_err(fe->dev, "ASoC: prepare FE %s failed\n", + fe->dai_link->name); + } + + async_synchronize_full_domain(&async_domain); + + /* check if any BE failed */ + list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, + list_be) { + struct snd_soc_pcm_runtime *be = dpcm->be; + + if (be->err_ops < 0) { + ret = be->err_ops; + goto out; + } + } + + /* check if FE failed */ + if (fe->err_ops < 0) { + ret = fe->err_ops; + goto out; + } } /* run the stream event for each BE */ @@ -2240,6 +2570,18 @@ out: return ret; } +static int soc_pcm_compat_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_platform *platform = rtd->platform; + + if (platform->driver->ops->compat_ioctl) + return platform->driver->ops->compat_ioctl(substream, + cmd, arg); + return snd_pcm_lib_ioctl(substream, cmd, arg); +} + static int soc_pcm_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { @@ -2668,9 +3010,27 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; if (capture) pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; + if (platform->driver->pcm_new) + rtd->platform->driver->pcm_new(rtd); goto out; } + /* setup any hostless PCMs - i.e. no host IO is performed */ + if (rtd->dai_link->no_host_mode) { + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->hw_no_buffer = 1; + snd_soc_set_runtime_hwparams( + pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, + &no_host_hardware); + } + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->hw_no_buffer = 1; + snd_soc_set_runtime_hwparams( + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, + &no_host_hardware); + } + } + /* ASoC PCM operations */ if (rtd->dai_link->dynamic) { rtd->ops.open = dpcm_fe_dai_open; @@ -2680,7 +3040,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.hw_free = dpcm_fe_dai_hw_free; rtd->ops.close = dpcm_fe_dai_close; rtd->ops.pointer = soc_pcm_pointer; + rtd->ops.delay_blk = soc_pcm_delay_blk; rtd->ops.ioctl = soc_pcm_ioctl; + rtd->ops.compat_ioctl = soc_pcm_compat_ioctl; } else { rtd->ops.open = soc_pcm_open; rtd->ops.hw_params = soc_pcm_hw_params; @@ -2689,7 +3051,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.hw_free = soc_pcm_hw_free; rtd->ops.close = soc_pcm_close; rtd->ops.pointer = soc_pcm_pointer; + rtd->ops.delay_blk = soc_pcm_delay_blk; rtd->ops.ioctl = soc_pcm_ioctl; + rtd->ops.compat_ioctl = soc_pcm_compat_ioctl; } if (platform->driver->ops) { @@ -2718,7 +3082,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->private_free = platform->driver->pcm_free; out: - dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", + dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, cpu_dai->name); return ret; |
