diff options
| -rw-r--r-- | sound/soc/msm/sdm660-common.c | 60 | ||||
| -rw-r--r-- | sound/soc/msm/sdm660-ext-dai-links.c | 30 | ||||
| -rw-r--r-- | sound/soc/msm/sdm660-internal.c | 27 |
3 files changed, 116 insertions, 1 deletions
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c index 271697747dd2..a9aa9a9d82e8 100644 --- a/sound/soc/msm/sdm660-common.c +++ b/sound/soc/msm/sdm660-common.c @@ -22,6 +22,8 @@ #include "../codecs/sdm660_cdc/msm-analog-cdc.h" #include "../codecs/wsa881x.h" +#define __CHIPSET__ "SDM660 " +#define MSM_DAILINK_NAME(name) (__CHIPSET__#name) #define DRV_NAME "sdm660-asoc-snd" #define MSM_INT_DIGITAL_CODEC "msm-dig-codec" @@ -29,6 +31,7 @@ #define DEV_NAME_STR_LEN 32 #define DEFAULT_MCLK_RATE 9600000 +#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */ struct dev_config { u32 sample_rate; @@ -278,6 +281,7 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025", static char const *ext_disp_bit_format_text[] = {"S16_LE", "S24_LE"}; static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96", "KHZ_192"}; +static const char *const qos_text[] = {"Disable", "Enable"}; static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text); @@ -328,6 +332,9 @@ static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_sample_rate, tdm_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_chs, tdm_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_format, tdm_bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_sample_rate, tdm_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(qos_vote, qos_text); + +static int qos_vote_status; static struct afe_clk_set mi2s_clk[MI2S_MAX] = { { @@ -1816,6 +1823,55 @@ static int ext_disp_rx_sample_rate_put(struct snd_kcontrol *kcontrol, return 0; } +static int msm_qos_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.enumerated.item[0] = qos_vote_status; + return 0; +} + +static int msm_qos_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct snd_soc_card *card = codec->component.card; + const char *fe_name = MSM_DAILINK_NAME(LowLatency); + struct snd_soc_pcm_runtime *rtd; + struct snd_pcm_substream *substream; + s32 usecs; + + rtd = snd_soc_get_pcm_runtime(card, fe_name); + if (!rtd) { + pr_err("%s: fail to get pcm runtime for %s\n", + __func__, fe_name); + return -EINVAL; + } + + substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s: substream is null\n", __func__); + return -EINVAL; + } + + qos_vote_status = ucontrol->value.enumerated.item[0]; + if (qos_vote_status) { + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); + if (!substream->runtime) { + pr_err("%s: runtime is null\n", __func__); + return -EINVAL; + } + usecs = MSM_LL_QOS_VALUE; + if (usecs >= 0) + pm_qos_add_request(&substream->latency_pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, usecs); + } else { + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); + } + return 0; +} + const struct snd_kcontrol_new msm_common_snd_controls[] = { SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs, proxy_rx_ch_get, proxy_rx_ch_put), @@ -2000,6 +2056,10 @@ const struct snd_kcontrol_new msm_common_snd_controls[] = { SOC_ENUM_EXT("QUAT_TDM_TX_0 Channels", tdm_tx_chs, tdm_tx_ch_get, tdm_tx_ch_put), + + SOC_ENUM_EXT("MultiMedia5_RX QOS Vote", qos_vote, msm_qos_ctl_get, + msm_qos_ctl_put), + }; /** diff --git a/sound/soc/msm/sdm660-ext-dai-links.c b/sound/soc/msm/sdm660-ext-dai-links.c index 30c3ffe2347d..9a3e8e2fad51 100644 --- a/sound/soc/msm/sdm660-ext-dai-links.c +++ b/sound/soc/msm/sdm660-ext-dai-links.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ #include "../codecs/wcd9335.h" #include "sdm660-common.h" #include "sdm660-external.h" +#include <linux/pm_qos.h> #define DEV_NAME_STR_LEN 32 #define __CHIPSET__ "SDM660 " @@ -28,6 +29,7 @@ #define WCN_CDC_SLIM_RX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX 3 +#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */ static struct snd_soc_card snd_soc_card_msm_card_tavil; static struct snd_soc_card snd_soc_card_msm_card_tasha; @@ -270,6 +272,30 @@ static struct snd_soc_ops msm_tdm_be_ops = { .hw_params = msm_tdm_snd_hw_params }; +static int msm_fe_qos_prepare(struct snd_pcm_substream *substream) +{ + cpumask_t mask; + + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); + + cpumask_clear(&mask); + cpumask_set_cpu(1, &mask); /* affine to core 1 */ + cpumask_set_cpu(2, &mask); /* affine to core 2 */ + cpumask_copy(&substream->latency_pm_qos_req.cpus_affine, &mask); + + substream->latency_pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; + + pm_qos_add_request(&substream->latency_pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, + MSM_LL_QOS_VALUE); + return 0; +} + +static struct snd_soc_ops msm_fe_qos_ops = { + .prepare = msm_fe_qos_prepare, +}; + static struct snd_soc_dai_link msm_ext_tasha_fe_dai[] = { /* tasha_vifeedback for speaker protection */ { @@ -954,6 +980,7 @@ static struct snd_soc_dai_link msm_ext_common_fe_dai[] = { /* this dai link has playback support */ .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, + .ops = &msm_fe_qos_ops, }, /* LSM FE */ {/* hw:x,14 */ @@ -1022,6 +1049,7 @@ static struct snd_soc_dai_link msm_ext_common_fe_dai[] = { .ignore_pmdown_time = 1, /* this dai link has playback support */ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8, + .ops = &msm_fe_qos_ops, }, {/* hw:x,18 */ .name = "HDMI_RX_HOSTLESS", diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c index 072d586da818..e4a6d86e908d 100644 --- a/sound/soc/msm/sdm660-internal.c +++ b/sound/soc/msm/sdm660-internal.c @@ -20,6 +20,7 @@ #include "../codecs/sdm660_cdc/msm-digital-cdc.h" #include "../codecs/sdm660_cdc/msm-analog-cdc.h" #include "../codecs/msm_sdw/msm_sdw.h" +#include <linux/pm_qos.h> #define __CHIPSET__ "SDM660 " #define MSM_DAILINK_NAME(name) (__CHIPSET__#name) @@ -31,6 +32,7 @@ #define WSA8810_NAME_1 "wsa881x.20170211" #define WSA8810_NAME_2 "wsa881x.20170212" +#define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */ enum { INT0_MI2S = 0, @@ -1718,6 +1720,29 @@ static struct snd_soc_ops msm_sdw_mi2s_be_ops = { .shutdown = msm_sdw_mi2s_snd_shutdown, }; +static int msm_fe_qos_prepare(struct snd_pcm_substream *substream) +{ + cpumask_t mask; + + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); + + cpumask_clear(&mask); + cpumask_set_cpu(1, &mask); /* affine to core 1 */ + cpumask_set_cpu(2, &mask); /* affine to core 2 */ + cpumask_copy(&substream->latency_pm_qos_req.cpus_affine, &mask); + substream->latency_pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; + + pm_qos_add_request(&substream->latency_pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, + MSM_LL_QOS_VALUE); + return 0; +} + +static struct snd_soc_ops msm_fe_qos_ops = { + .prepare = msm_fe_qos_prepare, +}; + struct snd_soc_dai_link_component dlc_rx1[] = { { .of_node = NULL, @@ -1974,6 +1999,7 @@ static struct snd_soc_dai_link msm_int_dai[] = { /* this dai link has playback support */ .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5, + .ops = &msm_fe_qos_ops, }, /* LSM FE */ {/* hw:x,14 */ @@ -2040,6 +2066,7 @@ static struct snd_soc_dai_link msm_int_dai[] = { .ignore_pmdown_time = 1, /* this dai link has playback support */ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8, + .ops = &msm_fe_qos_ops, }, {/* hw:x,18 */ .name = "HDMI_RX_HOSTLESS", |
