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> 271245b700SNamarta Kohli 281245b700SNamarta Kohli static int soc_compr_open(struct snd_compr_stream *cstream) 291245b700SNamarta Kohli { 301245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 311245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 321245b700SNamarta Kohli struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 331245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 341245b700SNamarta Kohli int ret = 0; 351245b700SNamarta Kohli 3615e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 3715e2e619SCharles Keepax 381245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->open) { 391245b700SNamarta Kohli ret = platform->driver->compr_ops->open(cstream); 401245b700SNamarta Kohli if (ret < 0) { 411245b700SNamarta Kohli pr_err("compress asoc: can't open platform %s\n", platform->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 541245b700SNamarta Kohli if (cstream->direction == SND_COMPRESS_PLAYBACK) { 551245b700SNamarta Kohli cpu_dai->playback_active++; 561245b700SNamarta Kohli codec_dai->playback_active++; 571245b700SNamarta Kohli } else { 581245b700SNamarta Kohli cpu_dai->capture_active++; 591245b700SNamarta Kohli codec_dai->capture_active++; 601245b700SNamarta Kohli } 611245b700SNamarta Kohli 621245b700SNamarta Kohli cpu_dai->active++; 631245b700SNamarta Kohli codec_dai->active++; 641245b700SNamarta Kohli rtd->codec->active++; 651245b700SNamarta Kohli 6615e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 6715e2e619SCharles Keepax 681245b700SNamarta Kohli return 0; 691245b700SNamarta Kohli 701245b700SNamarta Kohli machine_err: 711245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->free) 721245b700SNamarta Kohli platform->driver->compr_ops->free(cstream); 731245b700SNamarta Kohli out: 7415e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 751245b700SNamarta Kohli return ret; 761245b700SNamarta Kohli } 771245b700SNamarta Kohli 78202c8f70SCharles Keepax /* 79202c8f70SCharles Keepax * Power down the audio subsystem pmdown_time msecs after close is called. 80202c8f70SCharles Keepax * This is to ensure there are no pops or clicks in between any music tracks 81202c8f70SCharles Keepax * due to DAPM power cycling. 82202c8f70SCharles Keepax */ 83202c8f70SCharles Keepax static void close_delayed_work(struct work_struct *work) 84202c8f70SCharles Keepax { 85202c8f70SCharles Keepax struct snd_soc_pcm_runtime *rtd = 86202c8f70SCharles Keepax container_of(work, struct snd_soc_pcm_runtime, delayed_work.work); 87202c8f70SCharles Keepax struct snd_soc_dai *codec_dai = rtd->codec_dai; 88202c8f70SCharles Keepax 89202c8f70SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 90202c8f70SCharles Keepax 91202c8f70SCharles Keepax dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n", 92202c8f70SCharles Keepax codec_dai->driver->playback.stream_name, 93202c8f70SCharles Keepax codec_dai->playback_active ? "active" : "inactive", 94202c8f70SCharles Keepax rtd->pop_wait ? "yes" : "no"); 95202c8f70SCharles Keepax 96202c8f70SCharles Keepax /* are we waiting on this codec DAI stream */ 97202c8f70SCharles Keepax if (rtd->pop_wait == 1) { 98202c8f70SCharles Keepax rtd->pop_wait = 0; 99202c8f70SCharles Keepax snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, 100202c8f70SCharles Keepax SND_SOC_DAPM_STREAM_STOP); 101202c8f70SCharles Keepax } 102202c8f70SCharles Keepax 103202c8f70SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 104202c8f70SCharles Keepax } 105202c8f70SCharles Keepax 1061245b700SNamarta Kohli static int soc_compr_free(struct snd_compr_stream *cstream) 1071245b700SNamarta Kohli { 1081245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1091245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 1101245b700SNamarta Kohli struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 1111245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 1121245b700SNamarta Kohli struct snd_soc_codec *codec = rtd->codec; 1131245b700SNamarta Kohli 11415e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 11515e2e619SCharles Keepax 1161245b700SNamarta Kohli if (cstream->direction == SND_COMPRESS_PLAYBACK) { 1171245b700SNamarta Kohli cpu_dai->playback_active--; 1181245b700SNamarta Kohli codec_dai->playback_active--; 1191245b700SNamarta Kohli } else { 1201245b700SNamarta Kohli cpu_dai->capture_active--; 1211245b700SNamarta Kohli codec_dai->capture_active--; 1221245b700SNamarta Kohli } 1231245b700SNamarta Kohli 124da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 125da18396fSMark Brown 1261245b700SNamarta Kohli cpu_dai->active--; 1271245b700SNamarta Kohli codec_dai->active--; 1281245b700SNamarta Kohli codec->active--; 1291245b700SNamarta Kohli 1301245b700SNamarta Kohli if (!cpu_dai->active) 1311245b700SNamarta Kohli cpu_dai->rate = 0; 1321245b700SNamarta Kohli 1331245b700SNamarta Kohli if (!codec_dai->active) 1341245b700SNamarta Kohli codec_dai->rate = 0; 1351245b700SNamarta Kohli 1361245b700SNamarta Kohli 1371245b700SNamarta Kohli if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) 1381245b700SNamarta Kohli rtd->dai_link->compr_ops->shutdown(cstream); 1391245b700SNamarta Kohli 1401245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->free) 1411245b700SNamarta Kohli platform->driver->compr_ops->free(cstream); 1421245b700SNamarta Kohli cpu_dai->runtime = NULL; 1431245b700SNamarta Kohli 1441245b700SNamarta Kohli if (cstream->direction == SND_COMPRESS_PLAYBACK) { 1451245b700SNamarta Kohli if (!rtd->pmdown_time || codec->ignore_pmdown_time || 1461245b700SNamarta Kohli rtd->dai_link->ignore_pmdown_time) { 1471245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, 1481245b700SNamarta Kohli SNDRV_PCM_STREAM_PLAYBACK, 1491245b700SNamarta Kohli SND_SOC_DAPM_STREAM_STOP); 1508c3d2aa4SCharles Keepax } else { 1519bffb1fbSMisael Lopez Cruz rtd->pop_wait = 1; 1521245b700SNamarta Kohli schedule_delayed_work(&rtd->delayed_work, 1531245b700SNamarta Kohli msecs_to_jiffies(rtd->pmdown_time)); 1548c3d2aa4SCharles Keepax } 1551245b700SNamarta Kohli } else { 1561245b700SNamarta Kohli /* capture streams can be powered down now */ 1571245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, 1581245b700SNamarta Kohli SNDRV_PCM_STREAM_CAPTURE, 1591245b700SNamarta Kohli SND_SOC_DAPM_STREAM_STOP); 1601245b700SNamarta Kohli } 1611245b700SNamarta Kohli 16215e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 1631245b700SNamarta Kohli return 0; 1641245b700SNamarta Kohli } 1651245b700SNamarta Kohli 1661245b700SNamarta Kohli static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 1671245b700SNamarta Kohli { 1681245b700SNamarta Kohli 1691245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 1701245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 1711245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 1721245b700SNamarta Kohli int ret = 0; 1731245b700SNamarta Kohli 17415e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 17515e2e619SCharles Keepax 1761245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { 1771245b700SNamarta Kohli ret = platform->driver->compr_ops->trigger(cstream, cmd); 1781245b700SNamarta Kohli if (ret < 0) 17915e2e619SCharles Keepax goto out; 1801245b700SNamarta Kohli } 1811245b700SNamarta Kohli 182e38b9b74SMark Brown switch (cmd) { 183e38b9b74SMark Brown case SNDRV_PCM_TRIGGER_START: 184da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction); 185e38b9b74SMark Brown break; 186e38b9b74SMark Brown case SNDRV_PCM_TRIGGER_STOP: 187da18396fSMark Brown snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 188e38b9b74SMark Brown break; 189e38b9b74SMark Brown } 1901245b700SNamarta Kohli 19115e2e619SCharles Keepax out: 19215e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 1931245b700SNamarta Kohli return ret; 1941245b700SNamarta Kohli } 1951245b700SNamarta Kohli 1961245b700SNamarta Kohli static int soc_compr_set_params(struct snd_compr_stream *cstream, 1971245b700SNamarta Kohli struct snd_compr_params *params) 1981245b700SNamarta Kohli { 1991245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2001245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 2011245b700SNamarta Kohli int ret = 0; 2021245b700SNamarta Kohli 20315e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 20415e2e619SCharles Keepax 2051245b700SNamarta Kohli /* first we call set_params for the platform driver 2061245b700SNamarta Kohli * this should configure the soc side 2071245b700SNamarta Kohli * if the machine has compressed ops then we call that as well 2081245b700SNamarta Kohli * expectation is that platform and machine will configure everything 2091245b700SNamarta Kohli * for this compress path, like configuring pcm port for codec 2101245b700SNamarta Kohli */ 2111245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { 2121245b700SNamarta Kohli ret = platform->driver->compr_ops->set_params(cstream, params); 2131245b700SNamarta Kohli if (ret < 0) 214fa40ef20SCharles Keepax goto err; 2151245b700SNamarta Kohli } 2161245b700SNamarta Kohli 2171245b700SNamarta Kohli if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { 2181245b700SNamarta Kohli ret = rtd->dai_link->compr_ops->set_params(cstream); 2191245b700SNamarta Kohli if (ret < 0) 220fa40ef20SCharles Keepax goto err; 2211245b700SNamarta Kohli } 2221245b700SNamarta Kohli 2231245b700SNamarta Kohli snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, 2241245b700SNamarta Kohli SND_SOC_DAPM_STREAM_START); 2251245b700SNamarta Kohli 226fa40ef20SCharles Keepax /* cancel any delayed stream shutdown that is pending */ 227fa40ef20SCharles Keepax rtd->pop_wait = 0; 228fa40ef20SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 229fa40ef20SCharles Keepax 230fa40ef20SCharles Keepax cancel_delayed_work_sync(&rtd->delayed_work); 231fa40ef20SCharles Keepax 232fa40ef20SCharles Keepax return ret; 233fa40ef20SCharles Keepax 234fa40ef20SCharles Keepax err: 23515e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2361245b700SNamarta Kohli return ret; 2371245b700SNamarta Kohli } 2381245b700SNamarta Kohli 2391245b700SNamarta Kohli static int soc_compr_get_params(struct snd_compr_stream *cstream, 2401245b700SNamarta Kohli struct snd_codec *params) 2411245b700SNamarta Kohli { 2421245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2431245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 2441245b700SNamarta Kohli int ret = 0; 2451245b700SNamarta Kohli 24615e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 24715e2e619SCharles Keepax 2481245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) 2491245b700SNamarta Kohli ret = platform->driver->compr_ops->get_params(cstream, params); 2501245b700SNamarta Kohli 25115e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2521245b700SNamarta Kohli return ret; 2531245b700SNamarta Kohli } 2541245b700SNamarta Kohli 2551245b700SNamarta Kohli static int soc_compr_get_caps(struct snd_compr_stream *cstream, 2561245b700SNamarta Kohli struct snd_compr_caps *caps) 2571245b700SNamarta Kohli { 2581245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2591245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 2601245b700SNamarta Kohli int ret = 0; 2611245b700SNamarta Kohli 26215e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 26315e2e619SCharles Keepax 2641245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) 2651245b700SNamarta Kohli ret = platform->driver->compr_ops->get_caps(cstream, caps); 2661245b700SNamarta Kohli 26715e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2681245b700SNamarta Kohli return ret; 2691245b700SNamarta Kohli } 2701245b700SNamarta Kohli 2711245b700SNamarta Kohli static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, 2721245b700SNamarta Kohli struct snd_compr_codec_caps *codec) 2731245b700SNamarta Kohli { 2741245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2751245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 2761245b700SNamarta Kohli int ret = 0; 2771245b700SNamarta Kohli 27815e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 27915e2e619SCharles Keepax 2801245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) 2811245b700SNamarta Kohli ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); 2821245b700SNamarta Kohli 28315e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2841245b700SNamarta Kohli return ret; 2851245b700SNamarta Kohli } 2861245b700SNamarta Kohli 2871245b700SNamarta Kohli static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 2881245b700SNamarta Kohli { 2891245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 2901245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 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->ack) 2961245b700SNamarta Kohli ret = platform->driver->compr_ops->ack(cstream, bytes); 2971245b700SNamarta Kohli 29815e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 2991245b700SNamarta Kohli return ret; 3001245b700SNamarta Kohli } 3011245b700SNamarta Kohli 3021245b700SNamarta Kohli static int soc_compr_pointer(struct snd_compr_stream *cstream, 3031245b700SNamarta Kohli struct snd_compr_tstamp *tstamp) 3041245b700SNamarta Kohli { 3051245b700SNamarta Kohli struct snd_soc_pcm_runtime *rtd = cstream->private_data; 3061245b700SNamarta Kohli struct snd_soc_platform *platform = rtd->platform; 3071245b700SNamarta Kohli 30815e2e619SCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 30915e2e619SCharles Keepax 3101245b700SNamarta Kohli if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) 3111245b700SNamarta Kohli platform->driver->compr_ops->pointer(cstream, tstamp); 3121245b700SNamarta Kohli 31315e2e619SCharles Keepax mutex_unlock(&rtd->pcm_mutex); 3141245b700SNamarta Kohli return 0; 3151245b700SNamarta Kohli } 3161245b700SNamarta Kohli 3171f88eb0fSCharles Keepax static int soc_compr_copy(struct snd_compr_stream *cstream, 3184daf891cSCharles Keepax char __user *buf, size_t count) 3191f88eb0fSCharles Keepax { 3201f88eb0fSCharles Keepax struct snd_soc_pcm_runtime *rtd = cstream->private_data; 3211f88eb0fSCharles Keepax struct snd_soc_platform *platform = rtd->platform; 3221f88eb0fSCharles Keepax int ret = 0; 3231f88eb0fSCharles Keepax 3241f88eb0fSCharles Keepax mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); 3251f88eb0fSCharles Keepax 3261f88eb0fSCharles Keepax if (platform->driver->compr_ops && platform->driver->compr_ops->copy) 3271f88eb0fSCharles Keepax ret = platform->driver->compr_ops->copy(cstream, buf, count); 3281f88eb0fSCharles Keepax 3291f88eb0fSCharles Keepax mutex_unlock(&rtd->pcm_mutex); 3301f88eb0fSCharles Keepax return ret; 3311f88eb0fSCharles Keepax } 3321f88eb0fSCharles Keepax 33336953d98SJeeja KP static int sst_compr_set_metadata(struct snd_compr_stream *cstream, 33436953d98SJeeja KP struct snd_compr_metadata *metadata) 33536953d98SJeeja KP { 33636953d98SJeeja KP struct snd_soc_pcm_runtime *rtd = cstream->private_data; 33736953d98SJeeja KP struct snd_soc_platform *platform = rtd->platform; 33836953d98SJeeja KP int ret = 0; 33936953d98SJeeja KP 34036953d98SJeeja KP if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) 34136953d98SJeeja KP ret = platform->driver->compr_ops->set_metadata(cstream, metadata); 34236953d98SJeeja KP 34336953d98SJeeja KP return ret; 34436953d98SJeeja KP } 34536953d98SJeeja KP 34636953d98SJeeja KP static int sst_compr_get_metadata(struct snd_compr_stream *cstream, 34736953d98SJeeja KP struct snd_compr_metadata *metadata) 34836953d98SJeeja KP { 34936953d98SJeeja KP struct snd_soc_pcm_runtime *rtd = cstream->private_data; 35036953d98SJeeja KP struct snd_soc_platform *platform = rtd->platform; 35136953d98SJeeja KP int ret = 0; 35236953d98SJeeja KP 35336953d98SJeeja KP if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) 35436953d98SJeeja KP ret = platform->driver->compr_ops->get_metadata(cstream, metadata); 35536953d98SJeeja KP 35636953d98SJeeja KP return ret; 35736953d98SJeeja KP } 3581245b700SNamarta Kohli /* ASoC Compress operations */ 3591245b700SNamarta Kohli static struct snd_compr_ops soc_compr_ops = { 3601245b700SNamarta Kohli .open = soc_compr_open, 3611245b700SNamarta Kohli .free = soc_compr_free, 3621245b700SNamarta Kohli .set_params = soc_compr_set_params, 36336953d98SJeeja KP .set_metadata = sst_compr_set_metadata, 36436953d98SJeeja KP .get_metadata = sst_compr_get_metadata, 3651245b700SNamarta Kohli .get_params = soc_compr_get_params, 3661245b700SNamarta Kohli .trigger = soc_compr_trigger, 3671245b700SNamarta Kohli .pointer = soc_compr_pointer, 3681245b700SNamarta Kohli .ack = soc_compr_ack, 3691245b700SNamarta Kohli .get_caps = soc_compr_get_caps, 3701245b700SNamarta Kohli .get_codec_caps = soc_compr_get_codec_caps 3711245b700SNamarta Kohli }; 3721245b700SNamarta Kohli 3731245b700SNamarta Kohli /* create a new compress */ 3741245b700SNamarta Kohli int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 3751245b700SNamarta Kohli { 3761245b700SNamarta Kohli struct snd_soc_codec *codec = rtd->codec; 3771f88eb0fSCharles Keepax struct snd_soc_platform *platform = rtd->platform; 3781245b700SNamarta Kohli struct snd_soc_dai *codec_dai = rtd->codec_dai; 3791245b700SNamarta Kohli struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 3801245b700SNamarta Kohli struct snd_compr *compr; 3811245b700SNamarta Kohli char new_name[64]; 3821245b700SNamarta Kohli int ret = 0, direction = 0; 3831245b700SNamarta Kohli 3841245b700SNamarta Kohli /* check client and interface hw capabilities */ 3851245b700SNamarta Kohli snprintf(new_name, sizeof(new_name), "%s %s-%d", 3861245b700SNamarta Kohli rtd->dai_link->stream_name, codec_dai->name, num); 387daa2db59SCharles Keepax 388daa2db59SCharles Keepax if (codec_dai->driver->playback.channels_min) 3891245b700SNamarta Kohli direction = SND_COMPRESS_PLAYBACK; 390daa2db59SCharles Keepax else if (codec_dai->driver->capture.channels_min) 391daa2db59SCharles Keepax direction = SND_COMPRESS_CAPTURE; 392daa2db59SCharles Keepax else 393daa2db59SCharles Keepax return -EINVAL; 394daa2db59SCharles Keepax 3951245b700SNamarta Kohli compr = kzalloc(sizeof(*compr), GFP_KERNEL); 3961245b700SNamarta Kohli if (compr == NULL) { 3971245b700SNamarta Kohli snd_printk(KERN_ERR "Cannot allocate compr\n"); 3981245b700SNamarta Kohli return -ENOMEM; 3991245b700SNamarta Kohli } 4001245b700SNamarta Kohli 4011f88eb0fSCharles Keepax compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 4021f88eb0fSCharles Keepax GFP_KERNEL); 4031f88eb0fSCharles Keepax if (compr->ops == NULL) { 4041f88eb0fSCharles Keepax dev_err(rtd->card->dev, "Cannot allocate compressed ops\n"); 4051f88eb0fSCharles Keepax ret = -ENOMEM; 4061f88eb0fSCharles Keepax goto compr_err; 4071f88eb0fSCharles Keepax } 4081f88eb0fSCharles Keepax memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 4091f88eb0fSCharles Keepax 4101f88eb0fSCharles Keepax /* Add copy callback for not memory mapped DSPs */ 4111f88eb0fSCharles Keepax if (platform->driver->compr_ops && platform->driver->compr_ops->copy) 4121f88eb0fSCharles Keepax compr->ops->copy = soc_compr_copy; 4131f88eb0fSCharles Keepax 4141245b700SNamarta Kohli mutex_init(&compr->lock); 4151245b700SNamarta Kohli ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); 4161245b700SNamarta Kohli if (ret < 0) { 4171245b700SNamarta Kohli pr_err("compress asoc: can't create compress for codec %s\n", 4181245b700SNamarta Kohli codec->name); 4191f88eb0fSCharles Keepax goto compr_err; 4201245b700SNamarta Kohli } 4211245b700SNamarta Kohli 422202c8f70SCharles Keepax /* DAPM dai link stream work */ 423202c8f70SCharles Keepax INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); 424202c8f70SCharles Keepax 4251245b700SNamarta Kohli rtd->compr = compr; 4261245b700SNamarta Kohli compr->private_data = rtd; 4271245b700SNamarta Kohli 4281245b700SNamarta Kohli printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, 4291245b700SNamarta Kohli cpu_dai->name); 4301245b700SNamarta Kohli return ret; 4311f88eb0fSCharles Keepax 4321f88eb0fSCharles Keepax compr_err: 4331f88eb0fSCharles Keepax kfree(compr); 4341f88eb0fSCharles Keepax return ret; 4351245b700SNamarta Kohli } 436