Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 148 additions & 16 deletions audioreach-driver/audioreach_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

#include <dt-bindings/sound/qcom,q6afe.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
Expand All @@ -25,6 +27,9 @@
#define I2S_BIT_RATE(rate, channels, format) \
((rate) * (channels) * (format))

#define SHIKRA_IQS_MCLK_RATE 12288000
#define SHIKRA_CQS_BCLK_RATE 3072000

struct snd_soc_common {
const char *driver_name;
const struct snd_soc_dapm_widget *dapm_widgets;
Expand All @@ -34,11 +39,21 @@ struct snd_soc_common {
const struct snd_kcontrol_new *controls;
int num_controls;
unsigned int codec_dai_fmt;
unsigned int codec_sysclk_rate;
int num_wsa_spkr;
bool codec_sysclk_set;
bool mi2s_mclk_enable;
bool mi2s_bclk_enable;
bool qaif_backend_names;
const char *primary_mi2s_rx_backend_name;
bool wcd_jack;
/* Shikra-style: stereo channel fixup in be_hw_params_fixup */
bool stereo_fixup;
/* bclk derived from params and set as CLOCK_IN on cpu dai */
bool bclk_from_params;
/* fixed bclk rate for TDM cpu dai + codec sysclk */
unsigned int tdm_bclk_rate;

};

struct qcs6490_snd_data {
Expand Down Expand Up @@ -165,6 +180,25 @@ static const struct snd_soc_dapm_route qcs6490_dapm_routes[] = {
{ "SpkrRight Speaker", NULL, "SpkrRight SPKR" },
};

static const struct snd_soc_dapm_widget shikra_cqs_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Mic Jack", NULL),
};

static const struct snd_soc_dapm_widget shikra_iqs_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
};

static const struct snd_kcontrol_new shikra_iqs_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
SOC_DAPM_PIN_SWITCH("Speaker"),
};

static struct snd_soc_dapm_widget glymur_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Mic Jack", NULL),
Expand Down Expand Up @@ -481,14 +515,18 @@ static int qcs6490_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
}


static void audioreach_get_link_name(const char **link_name, int dai_id)
static void audioreach_get_link_name(const char **link_name, int dai_id,
const struct snd_soc_common *common)
{
switch (dai_id) {
case WSA_CODEC_DMA_RX_0:
*link_name = "CODEC_DMA-LPAIF_WSA-RX-0";
break;
case VA_CODEC_DMA_TX_0:
*link_name = "CODEC_DMA-LPAIF_VA-TX-0";
if (common && common->qaif_backend_names)
*link_name = "CODEC_DMA-QAIF-TX-0";
else
*link_name = "CODEC_DMA-LPAIF_VA-TX-0";
break;
case RX_CODEC_DMA_RX_0:
*link_name = "CODEC_DMA-LPAIF_RXTX-RX-0";
Expand All @@ -500,7 +538,11 @@ static void audioreach_get_link_name(const char **link_name, int dai_id)
*link_name = "CODEC_DMA-LPAIF_RXTX-TX-3";
break;
case PRIMARY_MI2S_RX:
if (strstr(*link_name, "HS") != NULL)
if (common && common->primary_mi2s_rx_backend_name)
*link_name = common->primary_mi2s_rx_backend_name;
else if (common && common->qaif_backend_names)
*link_name = "QAIF-QAIF_AUD-RX-2";
else if (strstr(*link_name, "HS") != NULL)
*link_name = "MI2S-LPAIF_SDR-RX-PRIMARY";
else
*link_name = "MI2S-LPAIF-RX-PRIMARY";
Expand Down Expand Up @@ -550,6 +592,8 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card)
struct snd_soc_dai_link *link;
struct of_phandle_args args;
struct snd_soc_dai_link_component *dlc;
struct qcs6490_snd_data *data = snd_soc_card_get_drvdata(card);
const struct snd_soc_common *common = data ? data->snd_soc_common_priv : NULL;
int ret, num_links;

ret = snd_soc_of_parse_card_name(card, "model");
Expand Down Expand Up @@ -634,7 +678,7 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card)
goto err;
}

link->id = args.args[0];
link->id = args.args[0];
link->platforms->of_node = link->cpus->of_node;

if (codec) {
Expand Down Expand Up @@ -663,7 +707,7 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card)
link->nonatomic = 1;
}

audioreach_get_link_name(&link->name, link->id);
audioreach_get_link_name(&link->name, link->id, common);
link->stream_name = link->name;
link++;

Expand Down Expand Up @@ -747,13 +791,19 @@ static int qcs6490_snd_init(struct snd_soc_pcm_runtime *rtd)
static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);

rate->min = rate->max = 48000;
if (pdata->snd_soc_common_priv->stereo_fixup) {
channels->min = 2;
channels->max = 2;
}

switch (cpu_dai->id) {
case TX_CODEC_DMA_TX_0:
case TX_CODEC_DMA_TX_1:
Expand All @@ -769,13 +819,46 @@ static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}

static int qcs6490_snd_set_codecs_fmt(struct snd_soc_pcm_runtime *rtd,
unsigned int fmt)
{
struct snd_soc_dai *codec_dai;
int ret;
int i;

for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_fmt(codec_dai, fmt);
if (ret && ret != -ENOTSUPP)
return ret;
}

return 0;
}

static int qcs6490_snd_set_codecs_sysclk(struct snd_soc_pcm_runtime *rtd,
unsigned int freq)
{
struct snd_soc_dai *codec_dai;
int ret;
int i;

for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_sysclk(codec_dai, 0, freq,
SND_SOC_CLOCK_IN);
if (ret)
return ret;
}

return 0;
}

static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
const struct snd_soc_common *common = pdata->snd_soc_common_priv;
int mclk_freq = qcs6490_get_mclk_freq(params);
int bclk_freq = qcs6490_get_bclk_freq(params);
int ret = 0;
Expand All @@ -787,35 +870,55 @@ static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream,
if (ret && ret != -ENOTSUPP)
return ret;

if (pdata->snd_soc_common_priv->codec_dai_fmt) {
ret = snd_soc_dai_set_fmt(codec_dai,
pdata->snd_soc_common_priv->codec_dai_fmt);
if (ret && ret != -ENOTSUPP)
if (common->codec_dai_fmt) {
ret = qcs6490_snd_set_codecs_fmt(rtd, common->codec_dai_fmt);
if (ret)
return ret;
}

if (pdata->snd_soc_common_priv->mi2s_mclk_enable) {
if (common->mi2s_mclk_enable) {
ret = snd_soc_dai_set_sysclk(cpu_dai,
LPAIF_MI2S_MCLK, mclk_freq,
SND_SOC_CLOCK_OUT);
if (ret)
return ret;
}

if (pdata->snd_soc_common_priv->mi2s_bclk_enable) {
if (common->bclk_from_params) {
int bclk = snd_soc_params_to_bclk(params);

if (bclk <= 0)
return -EINVAL;
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK,
bclk, SND_SOC_CLOCK_IN);
if (ret)
return ret;
} else if (common->mi2s_bclk_enable) {
ret = snd_soc_dai_set_sysclk(cpu_dai,
LPAIF_MI2S_BCLK, bclk_freq,
SND_SOC_CLOCK_OUT);
if (ret)
return ret;
}

if (pdata->snd_soc_common_priv->codec_sysclk_set) {
ret = snd_soc_dai_set_sysclk(codec_dai,
0, mclk_freq,
if (common->codec_sysclk_set || common->codec_sysclk_rate) {
ret = qcs6490_snd_set_codecs_sysclk(rtd,
common->codec_sysclk_rate ?: mclk_freq);
if (ret)
return ret;
}
break;
case SECONDARY_TDM_RX_0:
if (common->tdm_bclk_rate) {
ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK,
common->tdm_bclk_rate,
SND_SOC_CLOCK_IN);
if (ret)
return ret;
ret = qcs6490_snd_set_codecs_sysclk(rtd,
common->tdm_bclk_rate);
if (ret)
return ret;
}
break;
default:
Expand Down Expand Up @@ -867,6 +970,29 @@ static void qcs6490_add_be_ops(struct snd_soc_card *card)
}
}

static struct snd_soc_common shikra_cqs_priv_data = {
.driver_name = "shikra-cqs",
.dapm_widgets = shikra_cqs_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(shikra_cqs_dapm_widgets),
.qaif_backend_names = true,
.stereo_fixup = true,
.tdm_bclk_rate = SHIKRA_CQS_BCLK_RATE,
};

static struct snd_soc_common shikra_iqs_priv_data = {
.driver_name = "shikra-iqs",
.dapm_widgets = shikra_iqs_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(shikra_iqs_dapm_widgets),
.controls = shikra_iqs_controls,
.num_controls = ARRAY_SIZE(shikra_iqs_controls),
.qaif_backend_names = true,
.primary_mi2s_rx_backend_name = "QAIF-QAIF_AUD-RX-0",
.codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S,
.codec_sysclk_rate = SHIKRA_IQS_MCLK_RATE,
.bclk_from_params = true,
.stereo_fixup = true,
};

static int qcs6490_platform_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
Expand Down Expand Up @@ -903,7 +1029,11 @@ static int qcs6490_platform_probe(struct platform_device *pdev)

card->driver_name = data->snd_soc_common_priv->driver_name;
qcs6490_add_be_ops(card);
return devm_snd_soc_register_card(dev, card);
ret = devm_snd_soc_register_card(dev, card);
if (ret)
return dev_err_probe(dev, ret, "sound card registration failed\n");

return 0;
}

static struct snd_soc_common glymur_priv_data = {
Expand Down Expand Up @@ -1039,6 +1169,8 @@ static const struct of_device_id snd_qcs6490_dt_match[] = {
{.compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data},
{.compatible = "qcom,sm8750-sndcard", .data = &sm8750_priv_data},
{.compatible = "qcom,x1e80100-sndcard", .data = &x1e80100_priv_data},
{.compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data},
{.compatible = "qcom,shikra-iqs-sndcard", .data = &shikra_iqs_priv_data},
{}
};

Expand Down
Loading