11245b700SNamarta Kohli /* 21245b700SNamarta Kohli * soc-compress.c -- ALSA SoC Compress 31245b700SNamarta Kohli * 41245b700SNamarta Kohli * Copyright (C) 2012 Intel Corp. 51245b700SNamarta Kohli * 61245b700SNamarta Kohli * Authors: Namarta Kohli <namartax.kohli@intel.com> 71245b700SNamarta Kohli * Ramesh Babu K V <ramesh.babu@linux.intel.com> 81245b700SNamarta Kohli * Vinod Koul <vinod.koul@linux.intel.com> 91245b700SNamarta Kohli * 101245b700SNamarta Kohli * This program is free software; you can redistribute it and/or modify it 111245b700SNamarta Kohli * under the terms of the GNU General Public License as published by the 121245b700SNamarta Kohli * Free Software Foundation; either version 2 of the License, or (at your 131245b700SNamarta Kohli * option) any later version. 141245b700SNamarta Kohli * 151245b700SNamarta Kohli */ 161245b700SNamarta Kohli 171245b700SNamarta Kohli #include <linux/kernel.h> 181245b700SNamarta Kohli #include <linux/init.h> 191245b700SNamarta Kohli #include <linux/delay.h> 201245b700SNamarta Kohli #include <linux/slab.h> 211245b700SNamarta Kohli #include <linux/workqueue.h> 221245b700SNamarta Kohli #include <sound/core.h> 231245b700SNamarta Kohli #include <sound/compress_params.h> 241245b700SNamarta Kohli #include <sound/compress_driver.h> 251245b700SNamarta Kohli #include <sound/soc.h> 261245b700SNamarta Kohli #include <sound/initval.h> 272a99ef0fSLiam Girdwood #include <sound/soc-dpcm.h> 281245b700SNamarta Kohli 291245b700SNamarta Kohli static int soc_compr_open(struct snd_compr_stream *cstream) 301245b700SNamarta Kohli { 311245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 321245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 331245b700SNamarta Kohli int ret = 0; 341245b700SNamarta Kohli 3515e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 3615e2e619SCharles Keepax 371245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->open) { 381245b700SNamarta Kohli ret = platform->driver->compr_ops->open(cstream); 391245b700SNamarta Kohli if (ret < 0) { 40f4333203SLars-Peter Clausen pr_err("compress asoc: can't open platform %s\n", 41f4333203SLars-Peter Clausen platform->component.name); 421245b700SNamarta Kohli goto out; 431245b700SNamarta Kohli } 441245b700SNamarta Kohli } 451245b700SNamarta Kohli 461245b700SNamarta Kohli if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { 471245b700SNamarta Kohli ret = rtd->dai_link->compr_ops->startup(cstream); 481245b700SNamarta Kohli if (ret < 0) { 491245b700SNamarta Kohli pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); 501245b700SNamarta Kohli goto machine_err; 511245b700SNamarta Kohli } 521245b700SNamarta Kohli } 531245b700SNamarta Kohli 5424894b76SLars-Peter Clausen snd_soc_runtime_activate(rtd, cstream->direction); 551245b700SNamarta Kohli 5615e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5715e2e619SCharles Keepax 581245b700SNamarta Kohli return 0; 591245b700SNamarta Kohli 601245b700SNamarta Kohli machine_err: 611245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->free) 621245b700SNamarta Kohli platform->driver->compr_ops->free(cstream); 631245b700SNamarta Kohli out: 6415e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 651245b700SNamarta Kohli return ret; 661245b700SNamarta Kohli } 671245b700SNamarta Kohli 682a99ef0fSLiam Girdwood static int soc_compr_open_fe(struct snd_compr_stream *cstream) 692a99ef0fSLiam Girdwood { 702a99ef0fSLiam Girdwood struct snd_soc_pcm_runtime *fe = cstream->private_data; 712a99ef0fSLiam Girdwood struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; 722a99ef0fSLiam Girdwood struct snd_soc_platform *platform = fe->platform; 732a99ef0fSLiam Girdwood struct snd_soc_dpcm *dpcm; 742a99ef0fSLiam Girdwood struct snd_soc_dapm_widget_list *list; 752a99ef0fSLiam Girdwood int stream; 762a99ef0fSLiam Girdwood int ret = 0; 772a99ef0fSLiam Girdwood 782a99ef0fSLiam Girdwood if (cstream->direction == SND_COMPRESS_PLAYBACK) 792a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_PLAYBACK; 802a99ef0fSLiam Girdwood else 812a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_CAPTURE; 822a99ef0fSLiam Girdwood 832a99ef0fSLiam Girdwood mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 842a99ef0fSLiam Girdwood 852a99ef0fSLiam Girdwood if (platform->driver->compr_ops && platform->driver->compr_ops->open) { 862a99ef0fSLiam Girdwood ret = platform->driver->compr_ops->open(cstream); 872a99ef0fSLiam Girdwood if (ret < 0) { 88f4333203SLars-Peter Clausen pr_err("compress asoc: can't open platform %s\n", 89f4333203SLars-Peter Clausen platform->component.name); 902a99ef0fSLiam Girdwood goto out; 912a99ef0fSLiam Girdwood } 922a99ef0fSLiam Girdwood } 932a99ef0fSLiam Girdwood 942a99ef0fSLiam Girdwood if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) { 952a99ef0fSLiam Girdwood ret = fe->dai_link->compr_ops->startup(cstream); 962a99ef0fSLiam Girdwood if (ret < 0) { 972a99ef0fSLiam Girdwood pr_err("compress asoc: %s startup failed\n", fe->dai_link->name); 982a99ef0fSLiam Girdwood goto machine_err; 992a99ef0fSLiam Girdwood } 1002a99ef0fSLiam Girdwood } 1012a99ef0fSLiam Girdwood 1022a99ef0fSLiam Girdwood fe->dpcm[stream].runtime = fe_substream->runtime; 1032a99ef0fSLiam Girdwood 1048f70e515SQiao Zhou ret = dpcm_path_get(fe, stream, &list); 1058f70e515SQiao Zhou if (ret < 0) { 1068f70e515SQiao Zhou mutex_unlock(&fe->card->mutex); 1078f70e515SQiao Zhou goto fe_err; 1088f70e515SQiao Zhou } else if (ret == 0) { 1092a99ef0fSLiam Girdwood dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", 1102a99ef0fSLiam Girdwood fe->dai_link->name, stream ? "capture" : "playback"); 1112a99ef0fSLiam Girdwood } 1122a99ef0fSLiam Girdwood 1132a99ef0fSLiam Girdwood /* calculate valid and active FE <-> BE dpcms */ 1142a99ef0fSLiam Girdwood dpcm_process_paths(fe, stream, &list, 1); 1152a99ef0fSLiam Girdwood 1162a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 1172a99ef0fSLiam Girdwood 1182a99ef0fSLiam Girdwood ret = dpcm_be_dai_startup(fe, stream); 1192a99ef0fSLiam Girdwood if (ret < 0) { 1202a99ef0fSLiam Girdwood /* clean up all links */ 1212a99ef0fSLiam Girdwood list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) 1222a99ef0fSLiam Girdwood dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 1232a99ef0fSLiam Girdwood 1242a99ef0fSLiam Girdwood dpcm_be_disconnect(fe, stream); 1252a99ef0fSLiam Girdwood fe->dpcm[stream].runtime = NULL; 1262a99ef0fSLiam Girdwood goto fe_err; 1272a99ef0fSLiam Girdwood } 1282a99ef0fSLiam Girdwood 1292a99ef0fSLiam Girdwood dpcm_clear_pending_state(fe, stream); 1302a99ef0fSLiam Girdwood dpcm_path_put(&list); 1312a99ef0fSLiam Girdwood 1322a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; 1332a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 1342a99ef0fSLiam Girdwood 13524894b76SLars-Peter Clausen snd_soc_runtime_activate(fe, stream); 1362a99ef0fSLiam Girdwood 1372a99ef0fSLiam Girdwood mutex_unlock(&fe->card->mutex); 1382a99ef0fSLiam Girdwood 1392a99ef0fSLiam Girdwood return 0; 1402a99ef0fSLiam Girdwood 1412a99ef0fSLiam Girdwood fe_err: 1422a99ef0fSLiam Girdwood if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) 1432a99ef0fSLiam Girdwood fe->dai_link->compr_ops->shutdown(cstream); 1442a99ef0fSLiam Girdwood machine_err: 1452a99ef0fSLiam Girdwood if (platform->driver->compr_ops && platform->driver->compr_ops->free) 1462a99ef0fSLiam Girdwood platform->driver->compr_ops->free(cstream); 1472a99ef0fSLiam Girdwood out: 1482a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 1492a99ef0fSLiam Girdwood mutex_unlock(&fe->card->mutex); 1502a99ef0fSLiam Girdwood return ret; 1512a99ef0fSLiam Girdwood } 1522a99ef0fSLiam Girdwood 153202c8f70SCharles Keepax /* 154202c8f70SCharles Keepax * Power down the audio subsystem pmdown_time msecs after close is called. 155202c8f70SCharles Keepax * This is to ensure there are no pops or clicks in between any music tracks 156202c8f70SCharles Keepax * due to DAPM power cycling. 157202c8f70SCharles Keepax */ 158202c8f70SCharles Keepax static void close_delayed_work(struct work_struct *work) 159202c8f70SCharles Keepax { 160202c8f70SCharles Keepax struct snd_soc_pcm_runtime *rtd = 161202c8f70SCharles Keepax container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); 162202c8f70SCharles Keepax struct snd_soc_dai *codec_dai = rtd->codec_dai; 163202c8f70SCharles Keepax 164202c8f70SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 165202c8f70SCharles Keepax 166202c8f70SCharles Keepax dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", 167202c8f70SCharles Keepax codec_dai->driver->playback.stream_name, 168202c8f70SCharles Keepax codec_dai->playback_active ? "active" : "inactive", 169202c8f70SCharles Keepax rtd->pop_wait ? "yes" : "no"); 170202c8f70SCharles Keepax 171202c8f70SCharles Keepax /* are we waiting on this codec DAI stream */ 172202c8f70SCharles Keepax if (rtd->pop_wait == 1) { 173202c8f70SCharles Keepax rtd->pop_wait = 0; 174202c8f70SCharles Keepax snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, 175202c8f70SCharles Keepax SND_SOC_DAPM_STREAM_STOP); 176202c8f70SCharles Keepax } 177202c8f70SCharles Keepax 178202c8f70SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 179202c8f70SCharles Keepax } 180202c8f70SCharles Keepax 1811245b700SNamarta Kohli static int soc_compr_free(struct snd_compr_stream *cstream) 1821245b700SNamarta Kohli { 1831245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1841245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 1851245b700SNamarta Kohli struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 1861245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 18724894b76SLars-Peter Clausen int stream; 1881245b700SNamarta Kohli 18915e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 19015e2e619SCharles Keepax 19124894b76SLars-Peter Clausen if (cstream->direction == SND_COMPRESS_PLAYBACK) 19224894b76SLars-Peter Clausen stream = SNDRV_PCM_STREAM_PLAYBACK; 19324894b76SLars-Peter Clausen else 19424894b76SLars-Peter Clausen stream = SNDRV_PCM_STREAM_CAPTURE; 19524894b76SLars-Peter Clausen 19624894b76SLars-Peter Clausen snd_soc_runtime_deactivate(rtd, stream); 1971245b700SNamarta Kohli 198da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 199da18396fSMark Brown 2001245b700SNamarta Kohli if (!cpu_dai->active) 2011245b700SNamarta Kohli cpu_dai->rate = 0; 2021245b700SNamarta Kohli 2031245b700SNamarta Kohli if (!codec_dai->active) 2041245b700SNamarta Kohli codec_dai->rate = 0; 2051245b700SNamarta Kohli 2061245b700SNamarta Kohli 2071245b700SNamarta Kohli if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) 2081245b700SNamarta Kohli rtd->dai_link->compr_ops->shutdown(cstream); 2091245b700SNamarta Kohli 2101245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->free) 2111245b700SNamarta Kohli platform->driver->compr_ops->free(cstream); 2121245b700SNamarta Kohli 2131245b700SNamarta Kohli if (cstream->direction == SND_COMPRESS_PLAYBACK) { 214208a1589SLars-Peter Clausen if (snd_soc_runtime_ignore_pmdown_time(rtd)) { 2151245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, 2161245b700SNamarta Kohli SNDRV_PCM_STREAM_PLAYBACK, 2171245b700SNamarta Kohli SND_SOC_DAPM_STREAM_STOP); 2188c3d2aa4SCharles Keepax } else { 2199bffb1fbSMisael Lopez Cruz rtd->pop_wait = 1; 2203d24cfe4SMark Brown queue_delayed_work(system_power_efficient_wq, 2213d24cfe4SMark Brown &rtd->delayed_work, 2221245b700SNamarta Kohli msecs_to_jiffies(rtd->pmdown_time)); 2238c3d2aa4SCharles Keepax } 2241245b700SNamarta Kohli } else { 2251245b700SNamarta Kohli /* capture streams can be powered down now */ 2261245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, 2271245b700SNamarta Kohli SNDRV_PCM_STREAM_CAPTURE, 2281245b700SNamarta Kohli SND_SOC_DAPM_STREAM_STOP); 2291245b700SNamarta Kohli } 2301245b700SNamarta Kohli 23115e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2321245b700SNamarta Kohli return 0; 2331245b700SNamarta Kohli } 2341245b700SNamarta Kohli 2352a99ef0fSLiam Girdwood static int soc_compr_free_fe(struct snd_compr_stream *cstream) 2362a99ef0fSLiam Girdwood { 2372a99ef0fSLiam Girdwood struct snd_soc_pcm_runtime *fe = cstream->private_data; 2382a99ef0fSLiam Girdwood struct snd_soc_platform *platform = fe->platform; 2392a99ef0fSLiam Girdwood struct snd_soc_dpcm *dpcm; 2402a99ef0fSLiam Girdwood int stream, ret; 2412a99ef0fSLiam Girdwood 2422a99ef0fSLiam Girdwood mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 2432a99ef0fSLiam Girdwood 24424894b76SLars-Peter Clausen if (cstream->direction == SND_COMPRESS_PLAYBACK) 2452a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_PLAYBACK; 24624894b76SLars-Peter Clausen else 2472a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_CAPTURE; 2482a99ef0fSLiam Girdwood 24924894b76SLars-Peter Clausen snd_soc_runtime_deactivate(fe, stream); 2502a99ef0fSLiam Girdwood 2512a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 2522a99ef0fSLiam Girdwood 2532a99ef0fSLiam Girdwood ret = dpcm_be_dai_hw_free(fe, stream); 2542a99ef0fSLiam Girdwood if (ret < 0) 2552a99ef0fSLiam Girdwood dev_err(fe->dev, "compressed hw_free failed %d\n", ret); 2562a99ef0fSLiam Girdwood 2572a99ef0fSLiam Girdwood ret = dpcm_be_dai_shutdown(fe, stream); 2582a99ef0fSLiam Girdwood 2592a99ef0fSLiam Girdwood /* mark FE's links ready to prune */ 2602a99ef0fSLiam Girdwood list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) 2612a99ef0fSLiam Girdwood dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 2622a99ef0fSLiam Girdwood 2632a99ef0fSLiam Girdwood if (stream == SNDRV_PCM_STREAM_PLAYBACK) 2642a99ef0fSLiam Girdwood dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 2652a99ef0fSLiam Girdwood else 2662a99ef0fSLiam Girdwood dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 2672a99ef0fSLiam Girdwood 2682a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; 2692a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 2702a99ef0fSLiam Girdwood 2712a99ef0fSLiam Girdwood dpcm_be_disconnect(fe, stream); 2722a99ef0fSLiam Girdwood 2732a99ef0fSLiam Girdwood fe->dpcm[stream].runtime = NULL; 2742a99ef0fSLiam Girdwood 2752a99ef0fSLiam Girdwood if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown) 2762a99ef0fSLiam Girdwood fe->dai_link->compr_ops->shutdown(cstream); 2772a99ef0fSLiam Girdwood 2782a99ef0fSLiam Girdwood if (platform->driver->compr_ops && platform->driver->compr_ops->free) 2792a99ef0fSLiam Girdwood platform->driver->compr_ops->free(cstream); 2802a99ef0fSLiam Girdwood 2812a99ef0fSLiam Girdwood mutex_unlock(&fe->card->mutex); 2822a99ef0fSLiam Girdwood return 0; 2832a99ef0fSLiam Girdwood } 2842a99ef0fSLiam Girdwood 2851245b700SNamarta Kohli static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 2861245b700SNamarta Kohli { 2871245b700SNamarta Kohli 2881245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2891245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 2901245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 2911245b700SNamarta Kohli int ret = 0; 2921245b700SNamarta Kohli 29315e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 29415e2e619SCharles Keepax 2951245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { 2961245b700SNamarta Kohli ret = platform->driver->compr_ops->trigger(cstream, cmd); 2971245b700SNamarta Kohli if (ret < 0) 29815e2e619SCharles Keepax goto out; 2991245b700SNamarta Kohli } 3001245b700SNamarta Kohli 301e38b9b74SMark Brown switch (cmd) { 302e38b9b74SMark Brown case SNDRV_PCM_TRIGGER_START: 303da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction); 304e38b9b74SMark Brown break; 305e38b9b74SMark Brown case SNDRV_PCM_TRIGGER_STOP: 306da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 307e38b9b74SMark Brown break; 308e38b9b74SMark Brown } 3091245b700SNamarta Kohli 31015e2e619SCharles Keepax out: 31115e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 3121245b700SNamarta Kohli return ret; 3131245b700SNamarta Kohli } 3141245b700SNamarta Kohli 3152a99ef0fSLiam Girdwood static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 3162a99ef0fSLiam Girdwood { 3172a99ef0fSLiam Girdwood struct snd_soc_pcm_runtime *fe = cstream->private_data; 3182a99ef0fSLiam Girdwood struct snd_soc_platform *platform = fe->platform; 3192a99ef0fSLiam Girdwood int ret = 0, stream; 3202a99ef0fSLiam Girdwood 3212a99ef0fSLiam Girdwood if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || 3222a99ef0fSLiam Girdwood cmd == SND_COMPR_TRIGGER_DRAIN) { 3232a99ef0fSLiam Girdwood 3242a99ef0fSLiam Girdwood if (platform->driver->compr_ops && 3252a99ef0fSLiam Girdwood platform->driver->compr_ops->trigger) 32615b8e94fSDan Carpenter return platform->driver->compr_ops->trigger(cstream, 32715b8e94fSDan Carpenter cmd); 3282a99ef0fSLiam Girdwood } 3292a99ef0fSLiam Girdwood 3302a99ef0fSLiam Girdwood if (cstream->direction == SND_COMPRESS_PLAYBACK) 3312a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_PLAYBACK; 3322a99ef0fSLiam Girdwood else 3332a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_CAPTURE; 3342a99ef0fSLiam Girdwood 3352a99ef0fSLiam Girdwood 3362a99ef0fSLiam Girdwood mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 3372a99ef0fSLiam Girdwood 3382a99ef0fSLiam Girdwood if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { 3392a99ef0fSLiam Girdwood ret = platform->driver->compr_ops->trigger(cstream, cmd); 3402a99ef0fSLiam Girdwood if (ret < 0) 3412a99ef0fSLiam Girdwood goto out; 3422a99ef0fSLiam Girdwood } 3432a99ef0fSLiam Girdwood 3442a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 3452a99ef0fSLiam Girdwood 3462a99ef0fSLiam Girdwood ret = dpcm_be_dai_trigger(fe, stream, cmd); 3472a99ef0fSLiam Girdwood 3482a99ef0fSLiam Girdwood switch (cmd) { 3492a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_START: 3502a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_RESUME: 3512a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 3522a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; 3532a99ef0fSLiam Girdwood break; 3542a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_STOP: 3552a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_SUSPEND: 3562a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; 3572a99ef0fSLiam Girdwood break; 3582a99ef0fSLiam Girdwood case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 3592a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; 3602a99ef0fSLiam Girdwood break; 3612a99ef0fSLiam Girdwood } 3622a99ef0fSLiam Girdwood 3632a99ef0fSLiam Girdwood out: 3642a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 3652a99ef0fSLiam Girdwood mutex_unlock(&fe->card->mutex); 3662a99ef0fSLiam Girdwood return ret; 3672a99ef0fSLiam Girdwood } 3682a99ef0fSLiam Girdwood 3691245b700SNamarta Kohli static int soc_compr_set_params(struct snd_compr_stream *cstream, 3701245b700SNamarta Kohli struct snd_compr_params *params) 3711245b700SNamarta Kohli { 3721245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 3731245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 3741245b700SNamarta Kohli int ret = 0; 3751245b700SNamarta Kohli 37615e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 37715e2e619SCharles Keepax 3781245b700SNamarta Kohli /* first we call set_params for the platform driver 3791245b700SNamarta Kohli * this should configure the soc side 3801245b700SNamarta Kohli * if the machine has compressed ops then we call that as well 3811245b700SNamarta Kohli * expectation is that platform and machine will configure everything 3821245b700SNamarta Kohli * for this compress path, like configuring pcm port for codec 3831245b700SNamarta Kohli */ 3841245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { 3851245b700SNamarta Kohli ret = platform->driver->compr_ops->set_params(cstream, params); 3861245b700SNamarta Kohli if (ret < 0) 387fa40ef20SCharles Keepax goto err; 3881245b700SNamarta Kohli } 3891245b700SNamarta Kohli 3901245b700SNamarta Kohli if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { 3911245b700SNamarta Kohli ret = rtd->dai_link->compr_ops->set_params(cstream); 3921245b700SNamarta Kohli if (ret < 0) 393fa40ef20SCharles Keepax goto err; 3941245b700SNamarta Kohli } 3951245b700SNamarta Kohli 3962c071ed7SCharles Keepax if (cstream->direction == SND_COMPRESS_PLAYBACK) 3971245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, 3981245b700SNamarta Kohli SND_SOC_DAPM_STREAM_START); 3992c071ed7SCharles Keepax else 4002c071ed7SCharles Keepax snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE, 4012c071ed7SCharles Keepax SND_SOC_DAPM_STREAM_START); 4021245b700SNamarta Kohli 403fa40ef20SCharles Keepax /* cancel any delayed stream shutdown that is pending */ 404fa40ef20SCharles Keepax rtd->pop_wait = 0; 405fa40ef20SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 406fa40ef20SCharles Keepax 407fa40ef20SCharles Keepax cancel_delayed_work_sync(&rtd->delayed_work); 408fa40ef20SCharles Keepax 409fa40ef20SCharles Keepax return ret; 410fa40ef20SCharles Keepax 411fa40ef20SCharles Keepax err: 41215e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 4131245b700SNamarta Kohli return ret; 4141245b700SNamarta Kohli } 4151245b700SNamarta Kohli 4162a99ef0fSLiam Girdwood static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 4172a99ef0fSLiam Girdwood struct snd_compr_params *params) 4182a99ef0fSLiam Girdwood { 4192a99ef0fSLiam Girdwood struct snd_soc_pcm_runtime *fe = cstream->private_data; 4202a99ef0fSLiam Girdwood struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; 4212a99ef0fSLiam Girdwood struct snd_soc_platform *platform = fe->platform; 4222a99ef0fSLiam Girdwood int ret = 0, stream; 4232a99ef0fSLiam Girdwood 4242a99ef0fSLiam Girdwood if (cstream->direction == SND_COMPRESS_PLAYBACK) 4252a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_PLAYBACK; 4262a99ef0fSLiam Girdwood else 4272a99ef0fSLiam Girdwood stream = SNDRV_PCM_STREAM_CAPTURE; 4282a99ef0fSLiam Girdwood 4292a99ef0fSLiam Girdwood mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 4302a99ef0fSLiam Girdwood 4312a99ef0fSLiam Girdwood if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { 4322a99ef0fSLiam Girdwood ret = platform->driver->compr_ops->set_params(cstream, params); 4332a99ef0fSLiam Girdwood if (ret < 0) 4342a99ef0fSLiam Girdwood goto out; 4352a99ef0fSLiam Girdwood } 4362a99ef0fSLiam Girdwood 4372a99ef0fSLiam Girdwood if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) { 4382a99ef0fSLiam Girdwood ret = fe->dai_link->compr_ops->set_params(cstream); 4392a99ef0fSLiam Girdwood if (ret < 0) 4402a99ef0fSLiam Girdwood goto out; 4412a99ef0fSLiam Girdwood } 4422a99ef0fSLiam Girdwood 4432a99ef0fSLiam Girdwood /* 4442a99ef0fSLiam Girdwood * Create an empty hw_params for the BE as the machine driver must 4452a99ef0fSLiam Girdwood * fix this up to match DSP decoder and ASRC configuration. 4462a99ef0fSLiam Girdwood * I.e. machine driver fixup for compressed BE is mandatory. 4472a99ef0fSLiam Girdwood */ 4482a99ef0fSLiam Girdwood memset(&fe->dpcm[fe_substream->stream].hw_params, 0, 4492a99ef0fSLiam Girdwood sizeof(struct snd_pcm_hw_params)); 4502a99ef0fSLiam Girdwood 4512a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 4522a99ef0fSLiam Girdwood 4532a99ef0fSLiam Girdwood ret = dpcm_be_dai_hw_params(fe, stream); 4542a99ef0fSLiam Girdwood if (ret < 0) 4552a99ef0fSLiam Girdwood goto out; 4562a99ef0fSLiam Girdwood 4572a99ef0fSLiam Girdwood ret = dpcm_be_dai_prepare(fe, stream); 4582a99ef0fSLiam Girdwood if (ret < 0) 4592a99ef0fSLiam Girdwood goto out; 4602a99ef0fSLiam Girdwood 4612a99ef0fSLiam Girdwood if (stream == SNDRV_PCM_STREAM_PLAYBACK) 4622a99ef0fSLiam Girdwood dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 4632a99ef0fSLiam Girdwood else 4642a99ef0fSLiam Girdwood dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 4652a99ef0fSLiam Girdwood 4662a99ef0fSLiam Girdwood fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 4672a99ef0fSLiam Girdwood 4682a99ef0fSLiam Girdwood out: 4692a99ef0fSLiam Girdwood fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 4702a99ef0fSLiam Girdwood mutex_unlock(&fe->card->mutex); 4712a99ef0fSLiam Girdwood return ret; 4722a99ef0fSLiam Girdwood } 4732a99ef0fSLiam Girdwood 4741245b700SNamarta Kohli static int soc_compr_get_params(struct snd_compr_stream *cstream, 4751245b700SNamarta Kohli struct snd_codec *params) 4761245b700SNamarta Kohli { 4771245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 4781245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 4791245b700SNamarta Kohli int ret = 0; 4801245b700SNamarta Kohli 48115e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 48215e2e619SCharles Keepax 4831245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) 4841245b700SNamarta Kohli ret = platform->driver->compr_ops->get_params(cstream, params); 4851245b700SNamarta Kohli 48615e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 4871245b700SNamarta Kohli return ret; 4881245b700SNamarta Kohli } 4891245b700SNamarta Kohli 4901245b700SNamarta Kohli static int soc_compr_get_caps(struct snd_compr_stream *cstream, 4911245b700SNamarta Kohli struct snd_compr_caps *caps) 4921245b700SNamarta Kohli { 4931245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 4941245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 4951245b700SNamarta Kohli int ret = 0; 4961245b700SNamarta Kohli 49715e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 49815e2e619SCharles Keepax 4991245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) 5001245b700SNamarta Kohli ret = platform->driver->compr_ops->get_caps(cstream, caps); 5011245b700SNamarta Kohli 50215e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5031245b700SNamarta Kohli return ret; 5041245b700SNamarta Kohli } 5051245b700SNamarta Kohli 5061245b700SNamarta Kohli static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, 5071245b700SNamarta Kohli struct snd_compr_codec_caps *codec) 5081245b700SNamarta Kohli { 5091245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5101245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 5111245b700SNamarta Kohli int ret = 0; 5121245b700SNamarta Kohli 51315e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 51415e2e619SCharles Keepax 5151245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) 5161245b700SNamarta Kohli ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); 5171245b700SNamarta Kohli 51815e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5191245b700SNamarta Kohli return ret; 5201245b700SNamarta Kohli } 5211245b700SNamarta Kohli 5221245b700SNamarta Kohli static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 5231245b700SNamarta Kohli { 5241245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5251245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 5261245b700SNamarta Kohli int ret = 0; 5271245b700SNamarta Kohli 52815e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 52915e2e619SCharles Keepax 5301245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->ack) 5311245b700SNamarta Kohli ret = platform->driver->compr_ops->ack(cstream, bytes); 5321245b700SNamarta Kohli 53315e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5341245b700SNamarta Kohli return ret; 5351245b700SNamarta Kohli } 5361245b700SNamarta Kohli 5371245b700SNamarta Kohli static int soc_compr_pointer(struct snd_compr_stream *cstream, 5381245b700SNamarta Kohli struct snd_compr_tstamp *tstamp) 5391245b700SNamarta Kohli { 5401245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5411245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 5421245b700SNamarta Kohli 54315e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 54415e2e619SCharles Keepax 5451245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) 5461245b700SNamarta Kohli platform->driver->compr_ops->pointer(cstream, tstamp); 5471245b700SNamarta Kohli 54815e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5491245b700SNamarta Kohli return 0; 5501245b700SNamarta Kohli } 5511245b700SNamarta Kohli 5521f88eb0fSCharles Keepax static int soc_compr_copy(struct snd_compr_stream *cstream, 5534daf891cSCharles Keepax char __user *buf, size_t count) 5541f88eb0fSCharles Keepax { 5551f88eb0fSCharles Keepax struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5561f88eb0fSCharles Keepax struct snd_soc_platform *platform = rtd->platform; 5571f88eb0fSCharles Keepax int ret = 0; 5581f88eb0fSCharles Keepax 5591f88eb0fSCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 5601f88eb0fSCharles Keepax 5611f88eb0fSCharles Keepax if (platform->driver->compr_ops && platform->driver->compr_ops->copy) 5621f88eb0fSCharles Keepax ret = platform->driver->compr_ops->copy(cstream, buf, count); 5631f88eb0fSCharles Keepax 5641f88eb0fSCharles Keepax mutex_unlock(&rtd->pcm_mutex); 5651f88eb0fSCharles Keepax return ret; 5661f88eb0fSCharles Keepax } 5671f88eb0fSCharles Keepax 56802bd90e8SVinod Koul static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 56936953d98SJeeja KP struct snd_compr_metadata *metadata) 57036953d98SJeeja KP { 57136953d98SJeeja KP struct snd_soc_pcm_runtime *rtd = cstream->private_data; 57236953d98SJeeja KP struct snd_soc_platform *platform = rtd->platform; 57336953d98SJeeja KP int ret = 0; 57436953d98SJeeja KP 57536953d98SJeeja KP if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) 57636953d98SJeeja KP ret = platform->driver->compr_ops->set_metadata(cstream, metadata); 57736953d98SJeeja KP 57836953d98SJeeja KP return ret; 57936953d98SJeeja KP } 58036953d98SJeeja KP 58102bd90e8SVinod Koul static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 58236953d98SJeeja KP struct snd_compr_metadata *metadata) 58336953d98SJeeja KP { 58436953d98SJeeja KP struct snd_soc_pcm_runtime *rtd = cstream->private_data; 58536953d98SJeeja KP struct snd_soc_platform *platform = rtd->platform; 58636953d98SJeeja KP int ret = 0; 58736953d98SJeeja KP 58836953d98SJeeja KP if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) 58936953d98SJeeja KP ret = platform->driver->compr_ops->get_metadata(cstream, metadata); 59036953d98SJeeja KP 59136953d98SJeeja KP return ret; 59236953d98SJeeja KP } 5932a99ef0fSLiam Girdwood 5941245b700SNamarta Kohli /* ASoC Compress operations */ 5951245b700SNamarta Kohli static struct snd_compr_ops soc_compr_ops = { 5961245b700SNamarta Kohli .open = soc_compr_open, 5971245b700SNamarta Kohli .free = soc_compr_free, 5981245b700SNamarta Kohli .set_params = soc_compr_set_params, 59902bd90e8SVinod Koul .set_metadata = soc_compr_set_metadata, 60002bd90e8SVinod Koul .get_metadata = soc_compr_get_metadata, 6011245b700SNamarta Kohli .get_params = soc_compr_get_params, 6021245b700SNamarta Kohli .trigger = soc_compr_trigger, 6031245b700SNamarta Kohli .pointer = soc_compr_pointer, 6041245b700SNamarta Kohli .ack = soc_compr_ack, 6051245b700SNamarta Kohli .get_caps = soc_compr_get_caps, 6061245b700SNamarta Kohli .get_codec_caps = soc_compr_get_codec_caps 6071245b700SNamarta Kohli }; 6081245b700SNamarta Kohli 6092a99ef0fSLiam Girdwood /* ASoC Dynamic Compress operations */ 6102a99ef0fSLiam Girdwood static struct snd_compr_ops soc_compr_dyn_ops = { 6112a99ef0fSLiam Girdwood .open = soc_compr_open_fe, 6122a99ef0fSLiam Girdwood .free = soc_compr_free_fe, 6132a99ef0fSLiam Girdwood .set_params = soc_compr_set_params_fe, 6142a99ef0fSLiam Girdwood .get_params = soc_compr_get_params, 6152a99ef0fSLiam Girdwood .set_metadata = soc_compr_set_metadata, 6162a99ef0fSLiam Girdwood .get_metadata = soc_compr_get_metadata, 6172a99ef0fSLiam Girdwood .trigger = soc_compr_trigger_fe, 6182a99ef0fSLiam Girdwood .pointer = soc_compr_pointer, 6192a99ef0fSLiam Girdwood .ack = soc_compr_ack, 6202a99ef0fSLiam Girdwood .get_caps = soc_compr_get_caps, 6212a99ef0fSLiam Girdwood .get_codec_caps = soc_compr_get_codec_caps 6222a99ef0fSLiam Girdwood }; 6232a99ef0fSLiam Girdwood 6241245b700SNamarta Kohli /* create a new compress */ 6251245b700SNamarta Kohli int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 6261245b700SNamarta Kohli { 6271245b700SNamarta Kohli struct snd_soc_codec *codec = rtd->codec; 6281f88eb0fSCharles Keepax struct snd_soc_platform *platform = rtd->platform; 6291245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 6301245b700SNamarta Kohli struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 6311245b700SNamarta Kohli struct snd_compr *compr; 6322a99ef0fSLiam Girdwood struct snd_pcm *be_pcm; 6331245b700SNamarta Kohli char new_name[64]; 6341245b700SNamarta Kohli int ret = 0, direction = 0; 6351245b700SNamarta Kohli 6368151d5e6SBenoit Cousson if (rtd->num_codecs > 1) { 6378151d5e6SBenoit Cousson dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n"); 6388151d5e6SBenoit Cousson return -EINVAL; 6398151d5e6SBenoit Cousson } 6408151d5e6SBenoit Cousson 6411245b700SNamarta Kohli /* check client and interface hw capabilities */ 6421245b700SNamarta Kohli snprintf(new_name, sizeof(new_name), "%s %s-%d", 6431245b700SNamarta Kohli rtd->dai_link->stream_name, codec_dai->name, num); 644daa2db59SCharles Keepax 645daa2db59SCharles Keepax if (codec_dai->driver->playback.channels_min) 6461245b700SNamarta Kohli direction = SND_COMPRESS_PLAYBACK; 647daa2db59SCharles Keepax else if (codec_dai->driver->capture.channels_min) 648daa2db59SCharles Keepax direction = SND_COMPRESS_CAPTURE; 649daa2db59SCharles Keepax else 650daa2db59SCharles Keepax return -EINVAL; 651daa2db59SCharles Keepax 6521245b700SNamarta Kohli compr = kzalloc(sizeof(*compr), GFP_KERNEL); 6531245b700SNamarta Kohli if (compr == NULL) { 6541245b700SNamarta Kohli snd_printk(KERN_ERR "Cannot allocate compr\n"); 6551245b700SNamarta Kohli return -ENOMEM; 6561245b700SNamarta Kohli } 6571245b700SNamarta Kohli 6581f88eb0fSCharles Keepax compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 6591f88eb0fSCharles Keepax GFP_KERNEL); 6601f88eb0fSCharles Keepax if (compr->ops == NULL) { 6611f88eb0fSCharles Keepax dev_err(rtd->card->dev, "Cannot allocate compressed ops\n"); 6621f88eb0fSCharles Keepax ret = -ENOMEM; 6631f88eb0fSCharles Keepax goto compr_err; 6641f88eb0fSCharles Keepax } 6652a99ef0fSLiam Girdwood 6662a99ef0fSLiam Girdwood if (rtd->dai_link->dynamic) { 6672a99ef0fSLiam Girdwood snprintf(new_name, sizeof(new_name), "(%s)", 6682a99ef0fSLiam Girdwood rtd->dai_link->stream_name); 6692a99ef0fSLiam Girdwood 6702a99ef0fSLiam Girdwood ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 6712a99ef0fSLiam Girdwood 1, 0, &be_pcm); 6722a99ef0fSLiam Girdwood if (ret < 0) { 6732a99ef0fSLiam Girdwood dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n", 6742a99ef0fSLiam Girdwood rtd->dai_link->name); 6752a99ef0fSLiam Girdwood goto compr_err; 6762a99ef0fSLiam Girdwood } 6772a99ef0fSLiam Girdwood 6782a99ef0fSLiam Girdwood rtd->pcm = be_pcm; 6792a99ef0fSLiam Girdwood rtd->fe_compr = 1; 6802a99ef0fSLiam Girdwood be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 6812a99ef0fSLiam Girdwood be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 6822a99ef0fSLiam Girdwood memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 6832a99ef0fSLiam Girdwood } else 6841f88eb0fSCharles Keepax memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 6851f88eb0fSCharles Keepax 6861f88eb0fSCharles Keepax /* Add copy callback for not memory mapped DSPs */ 6871f88eb0fSCharles Keepax if (platform->driver->compr_ops && platform->driver->compr_ops->copy) 6881f88eb0fSCharles Keepax compr->ops->copy = soc_compr_copy; 6891f88eb0fSCharles Keepax 6901245b700SNamarta Kohli mutex_init(&compr->lock); 6911245b700SNamarta Kohli ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); 6921245b700SNamarta Kohli if (ret < 0) { 6931245b700SNamarta Kohli pr_err("compress asoc: can't create compress for codec %s\n", 694f4333203SLars-Peter Clausen codec->component.name); 6951f88eb0fSCharles Keepax goto compr_err; 6961245b700SNamarta Kohli } 6971245b700SNamarta Kohli 698202c8f70SCharles Keepax /* DAPM dai link stream work */ 699202c8f70SCharles Keepax INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); 700202c8f70SCharles Keepax 7011245b700SNamarta Kohli rtd->compr = compr; 7021245b700SNamarta Kohli compr->private_data = rtd; 7031245b700SNamarta Kohli 7041245b700SNamarta Kohli printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, 7051245b700SNamarta Kohli cpu_dai->name); 7061245b700SNamarta Kohli return ret; 7071f88eb0fSCharles Keepax 7081f88eb0fSCharles Keepax compr_err: 7091f88eb0fSCharles Keepax kfree(compr); 7101f88eb0fSCharles Keepax return ret; 7111245b700SNamarta Kohli } 712