diff --git a/audioreach-driver/audioreach_common.c b/audioreach-driver/audioreach_common.c index 523b8bd..2fb9f32 100644 --- a/audioreach-driver/audioreach_common.c +++ b/audioreach-driver/audioreach_common.c @@ -4,10 +4,13 @@ #include #include +#include #include +#include #include #include #include +#include #include #include #include @@ -16,6 +19,8 @@ #define AFE_PORT_MAX 137 #define NAME_SIZE 32 +#define SHIKRA_IQS_MCLK_RATE 12288000 +#define SHIKRA_CQS_BCLK_RATE 3072000 struct qcs6490_snd_data { bool stream_prepared[AFE_PORT_MAX]; @@ -36,6 +41,34 @@ struct qcom_snd_common_data { struct qcom_snd_dailink_data *link_data; }; +static bool qcs6490_snd_model_is(struct snd_soc_card *card, const char *model) +{ + const char *card_model; + + if (of_property_read_string(card->dev->of_node, "model", &card_model)) + return false; + + return !strcmp(card_model, model); +} + +static bool qcs6490_snd_is_shikra_cqm(struct snd_soc_card *card) +{ + return of_device_is_compatible(card->dev->of_node, "qcom,shikra-cqm-sndcard") || + qcs6490_snd_model_is(card, "shikra-cqm-evk"); +} + +static bool qcs6490_snd_is_shikra_cqs(struct snd_soc_card *card) +{ + return of_device_is_compatible(card->dev->of_node, "qcom,shikra-cqs-sndcard") || + qcs6490_snd_model_is(card, "shikra-cqs-evk"); +} + +static bool qcs6490_snd_is_shikra_iqs(struct snd_soc_card *card) +{ + return of_device_is_compatible(card->dev->of_node, "qcom,shikra-iqs-sndcard") || + qcs6490_snd_model_is(card, "shikra-iqs-evk"); +} + static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), @@ -49,6 +82,24 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { SND_SOC_DAPM_SPK("DP7 Jack", NULL), }; +static struct snd_soc_dapm_widget shikra_cqm_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_jack_pin qcs6490_headset_jack_pins[] = { /* Headset */ @@ -62,6 +113,23 @@ static struct snd_soc_jack_pin qcs6490_headset_jack_pins[] = { }, }; +static bool qcs6490_snd_is_sdw_dai(int dai_id) +{ + switch (dai_id) { + case WSA_CODEC_DMA_RX_0: + case WSA_CODEC_DMA_RX_1: + case RX_CODEC_DMA_RX_0: + case RX_CODEC_DMA_RX_1: + case TX_CODEC_DMA_TX_0: + case TX_CODEC_DMA_TX_1: + case TX_CODEC_DMA_TX_2: + case TX_CODEC_DMA_TX_3: + return true; + default: + return false; + } +} + static int qcs6490_snd_sdw_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -72,6 +140,9 @@ static int qcs6490_snd_sdw_startup(struct snd_pcm_substream *substream) u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret, i, j; + if (!qcs6490_snd_is_sdw_dai(cpu_dai->id)) + return 0; + sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM); if (!sruntime) return -ENOMEM; @@ -260,8 +331,12 @@ static void qcs6490_snd_shutdown(struct snd_pcm_substream *substream) break; } + if (!qcs6490_snd_is_sdw_dai(cpu_dai->id)) + return; + pdata->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); + if (sruntime) + sdw_release_stream(sruntime); } static int qcs6490_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, @@ -480,6 +555,7 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card) } cpu = of_get_child_by_name(np, "cpu"); + platform = of_get_child_by_name(np, "platform"); codec = of_get_child_by_name(np, "codec"); if (!cpu) { @@ -496,7 +572,18 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card) } link->id = args.args[0]; - link->platforms->of_node = link->cpus->of_node; + if (platform) { + link->platforms->of_node = of_parse_phandle(platform, + "sound-dai", 0); + if (!link->platforms->of_node) { + dev_err(card->dev, "%s: platform dai not found\n", + link->name); + ret = -EINVAL; + goto err; + } + } else { + link->platforms->of_node = link->cpus->of_node; + } if (codec) { ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); @@ -585,6 +672,9 @@ static int qcs6490_snd_init(struct snd_soc_pcm_runtime *rtd) if (dp_jack) return qcs6490_snd_dp_jack_setup(rtd, dp_jack, dp_pcm_id); + if (qcs6490_snd_is_shikra_cqs(card) || qcs6490_snd_is_shikra_iqs(card)) + return 0; + return qcs6490_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } @@ -615,12 +705,81 @@ static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int qcs6490_snd_set_codec_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_set_iqs_codec_fmt(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *codec_dai; + unsigned int fmt = SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S; + int ret; + int i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + 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 *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); + int bclk_freq; + int ret; + + if (qcs6490_snd_is_shikra_iqs(rtd->card) && + (cpu_dai->id == PRIMARY_MI2S_RX || cpu_dai->id == PRIMARY_MI2S_TX)) { + ret = qcs6490_snd_set_iqs_codec_fmt(rtd); + if (ret) + return ret; + + ret = qcs6490_snd_set_codec_sysclk(rtd, SHIKRA_IQS_MCLK_RATE); + if (ret) + return ret; + + bclk_freq = snd_soc_params_to_bclk(params); + if (bclk_freq <= 0) + return -EINVAL; + + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, + bclk_freq, SND_SOC_CLOCK_IN); + if (ret) + return ret; + } + + if (qcs6490_snd_is_shikra_cqs(rtd->card) && + cpu_dai->id == SECONDARY_TDM_RX_0) { + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, + SHIKRA_CQS_BCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret) + return ret; + + ret = qcs6490_snd_set_codec_sysclk(rtd, SHIKRA_CQS_BCLK_RATE); + if (ret) + return ret; + } return qcs6490_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); } @@ -667,6 +826,19 @@ static void qcs6490_add_be_ops(struct snd_soc_card *card) } } +static void qcs6490_add_shikra_card_data(struct snd_soc_card *card) +{ + if (qcs6490_snd_is_shikra_cqm(card) || qcs6490_snd_is_shikra_cqs(card)) { + card->dapm_widgets = shikra_cqm_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(shikra_cqm_dapm_widgets); + } else if (qcs6490_snd_is_shikra_iqs(card)) { + card->dapm_widgets = shikra_iqs_dapm_widgets; + card->num_dapm_widgets = ARRAY_SIZE(shikra_iqs_dapm_widgets); + card->controls = shikra_iqs_controls; + card->num_controls = ARRAY_SIZE(shikra_iqs_controls); + } +} + static int qcs6490_platform_probe(struct platform_device *pdev) { struct snd_soc_card *card; @@ -686,6 +858,7 @@ static int qcs6490_platform_probe(struct platform_device *pdev) card->dev = dev; dev_set_drvdata(dev, card); snd_soc_card_set_drvdata(card, data); + qcs6490_add_shikra_card_data(card); ret = qcs6490_snd_parse_of(card); if (ret) return ret; @@ -699,6 +872,10 @@ static const struct of_device_id snd_qcs6490_dt_match[] = { {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, {.compatible = "qcom,qcs615-sndcard", "qcs615"}, {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, + {.compatible = "qcom,shikra-sndcard", "shikra"}, + {.compatible = "qcom,shikra-cqm-sndcard", "shikra"}, + {.compatible = "qcom,shikra-cqs-sndcard", "shikra"}, + {.compatible = "qcom,shikra-iqs-sndcard", "shikra"}, {.compatible = "qcom,qcs8275-sndcard", "qcs8275"}, {.compatible = "qcom,qcs8300-sndcard", "qcs8300"}, {.compatible = "qcom,qcs9075-sndcard", "qcs9075"}, diff --git a/audioreach-driver/q6apm_audio_pkt.c b/audioreach-driver/q6apm_audio_pkt.c index 768e8aa..b308ac1 100644 --- a/audioreach-driver/q6apm_audio_pkt.c +++ b/audioreach-driver/q6apm_audio_pkt.c @@ -181,7 +181,8 @@ static int q6apm_audio_send_cmd(struct q6apm_audio_pkt *apm, struct gpr_pkt *pkt } static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) + uint32_t src_port, uint32_t dest_port, + uint16_t dest_domain, bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -201,7 +202,7 @@ static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt->hdr.dest_domain = dest_domain ?: GPR_DOMAIN_ID_ADSP; pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -217,17 +218,21 @@ static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t return pkt; } -static void *q6apm_audio_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token) +static void *q6apm_audio_alloc_apm_cmd_pkt(struct q6apm_audio_pkt *apm, + int pkt_size, uint32_t opcode, + uint32_t token) { return __q6apm_audio_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID, - APM_MODULE_INSTANCE_ID, true); + APM_MODULE_INSTANCE_ID, + audioreach_gpr_dest_domain(apm ? apm->adev : NULL), + true); } static int q6apm_audio_get_apm_state(struct q6apm_audio_pkt *apm) { struct gpr_pkt *pkt; - pkt = q6apm_audio_alloc_apm_cmd_pkt(0, APM_CMD_GET_SPF_STATE, 0); + pkt = q6apm_audio_alloc_apm_cmd_pkt(apm, 0, APM_CMD_GET_SPF_STATE, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -250,7 +255,7 @@ static void q6apm_audio_close_all(void) { struct gpr_pkt *pkt; - pkt = q6apm_audio_alloc_apm_cmd_pkt(0, APM_CMD_CLOSE_ALL, 0); + pkt = q6apm_audio_alloc_apm_cmd_pkt(g_apm, 0, APM_CMD_CLOSE_ALL, 0); if (IS_ERR(pkt)) return; diff --git a/audioreach-driver/q6apm_lpass_dummy_dais.c b/audioreach-driver/q6apm_lpass_dummy_dais.c index 0bd7292..424a885 100644 --- a/audioreach-driver/q6apm_lpass_dummy_dais.c +++ b/audioreach-driver/q6apm_lpass_dummy_dais.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,15 @@ #define APM_PORT_MAX 127 #define AUDIOREACH_BE_PCM_BASE 16 +struct q6apm_dai_priv_data { + struct clk *mclk; + struct clk *bclk; + struct clk *eclk; + bool mclk_enabled; + bool bclk_enabled; + bool eclk_enabled; +}; + #define Q6AFE_TDM_PB_DAI(pre, num, did) { \ .playback = { \ .stream_name = pre" TDM"#num" Playback", \ @@ -613,6 +623,7 @@ struct q6apm_lpass_dai_data { struct q6apm_graph *graph[APM_PORT_MAX]; bool is_port_started[APM_PORT_MAX]; struct audioreach_module_config module_config[APM_PORT_MAX]; + struct q6apm_dai_priv_data priv[APM_PORT_MAX]; }; static const struct snd_pcm_hardware q6apm_dummy_dma_hardware = { @@ -692,16 +703,121 @@ static int q6apm_lpass_dai_dummy_startup(struct snd_pcm_substream *substream, return 0; } +static void q6apm_lpass_dai_dummy_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6apm_dai_priv_data *priv; + + if (dai->id >= APM_PORT_MAX) + return; + + priv = &dai_data->priv[dai->id]; + + if (priv->mclk_enabled) { + clk_disable_unprepare(priv->mclk); + priv->mclk_enabled = false; + } + + if (priv->bclk_enabled) { + clk_disable_unprepare(priv->bclk); + priv->bclk_enabled = false; + } + + if (priv->eclk_enabled) { + clk_disable_unprepare(priv->eclk); + priv->eclk_enabled = false; + } +} + +static int q6apm_lpass_dai_dummy_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, + int dir) +{ + struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct q6apm_dai_priv_data *priv; + struct clk *sysclk; + bool *enabled; + int ret; + + if (dai->id >= APM_PORT_MAX) + return -EINVAL; + + priv = &dai_data->priv[dai->id]; + + switch (clk_id) { + case LPAIF_MI2S_MCLK: + sysclk = priv->mclk; + enabled = &priv->mclk_enabled; + break; + case LPAIF_MI2S_BCLK: + sysclk = priv->bclk; + enabled = &priv->bclk_enabled; + break; + case LPAIF_MI2S_ECLK: + sysclk = priv->eclk; + enabled = &priv->eclk_enabled; + break; + default: + return 0; + } + + if (!sysclk) + return 0; + + if (!freq) { + if (*enabled) { + clk_disable_unprepare(sysclk); + *enabled = false; + } + return 0; + } + + ret = clk_set_rate(sysclk, freq); + if (ret) + return ret; + + if (*enabled) + return 0; + + ret = clk_prepare_enable(sysclk); + if (ret) + return ret; + + *enabled = true; + + return 0; +} + +static int q6apm_lpass_dai_get_clk(struct device *dev, struct device_node *np, + const char *name, struct clk **clk) +{ + *clk = devm_get_clk_from_child(dev, np, name); + if (IS_ERR(*clk)) { + if (PTR_ERR(*clk) == -EPROBE_DEFER) + return dev_err_probe(dev, PTR_ERR(*clk), + "unable to get %s\n", name); + + *clk = NULL; + } + + return 0; +} + static const struct snd_soc_dai_ops q6dummy_ops = { .startup = q6apm_lpass_dai_dummy_startup, }; static const struct snd_soc_dai_ops q6i2sdummy_ops = { .startup = q6apm_lpass_dai_dummy_startup, + .shutdown = q6apm_lpass_dai_dummy_shutdown, + .set_sysclk = q6apm_lpass_dai_dummy_set_sysclk, }; static const struct snd_soc_dai_ops q6tdmdummy_ops = { .startup = q6apm_lpass_dai_dummy_startup, + .shutdown = q6apm_lpass_dai_dummy_shutdown, + .set_sysclk = q6apm_lpass_dai_dummy_set_sysclk, }; static const struct snd_soc_component_driver q6apm_lpass_dummy_dai_component = { @@ -718,12 +834,46 @@ static int q6apm_lpass_dummy_dai_dev_probe(struct platform_device *pdev) struct q6apm_lpass_dai_data *dai_data; struct snd_soc_dai_driver *dais; struct device *dev = &pdev->dev; + struct device_node *np; int num_dais; + int ret; dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); if (!dai_data) return -ENOMEM; + for_each_available_child_of_node(dev->of_node, np) { + struct q6apm_dai_priv_data *priv; + u32 id; + + ret = of_property_read_u32(np, "reg", &id); + if (ret || id >= APM_PORT_MAX) + continue; + + switch (id) { + case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: + case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: + break; + default: + continue; + } + + priv = &dai_data->priv[id]; + + ret = q6apm_lpass_dai_get_clk(dev, np, "mclk", &priv->mclk); + if (ret) + goto err_put_np; + + ret = q6apm_lpass_dai_get_clk(dev, np, "bclk", &priv->bclk); + if (ret) + goto err_put_np; + + ret = q6apm_lpass_dai_get_clk(dev, np, "eclk", &priv->eclk); + if (ret) + goto err_put_np; + } + dev_set_drvdata(dev, dai_data); memset(&cfg, 0, sizeof(cfg)); @@ -739,6 +889,10 @@ static int q6apm_lpass_dummy_dai_dev_probe(struct platform_device *pdev) dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais); return devm_snd_soc_register_component(dev, q6apm_lpass_component, dais, num_dais); + +err_put_np: + of_node_put(np); + return ret; } #ifdef CONFIG_OF diff --git a/audioreach-driver/q6prm_audioreach.c b/audioreach-driver/q6prm_audioreach.c index d06326e..57961da 100644 --- a/audioreach-driver/q6prm_audioreach.c +++ b/audioreach-driver/q6prm_audioreach.c @@ -106,7 +106,8 @@ static int q6prm_audioreach_send_cmd_sync(struct q6prm *prm, struct gpr_pkt *pkt } static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) + uint32_t src_port, uint32_t dest_port, + uint16_t dest_domain, bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -126,7 +127,7 @@ static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uin pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt->hdr.dest_domain = dest_domain ?: GPR_DOMAIN_ID_ADSP; pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -142,10 +143,12 @@ static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uin return pkt; } -static void *q6prm_audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port) +static void *q6prm_audioreach_alloc_cmd_pkt(gpr_device_t *gdev, int payload_size, + uint32_t opcode, uint32_t token, uint32_t src_port, + uint32_t dest_port) { - return __q6prm_audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true); + return __q6prm_audioreach_alloc_pkt(payload_size, opcode, token, src_port, + dest_port, audioreach_gpr_dest_domain(gdev), true); } static int q6prm_audioreach_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool enable) @@ -166,7 +169,8 @@ static int q6prm_audioreach_set_hw_core_req(struct device *dev, uint32_t hw_bloc rsp_opcode = PRM_CMD_RSP_RELEASE_HW_RSC; } - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*req), opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID); + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*req), opcode, 0, + gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -214,7 +218,7 @@ static int q6prm_audioreach_request_lpass_clock(struct device *dev, int clk_id, struct gpr_pkt *pkt; int rc; - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -251,7 +255,7 @@ static int q6prm_audioreach_release_lpass_clock(struct device *dev, int clk_id, struct gpr_pkt *pkt; int rc; - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); diff --git a/audioreach-driver/q6prm_audioreach.h b/audioreach-driver/q6prm_audioreach.h index 51fb155..ffd5841 100644 --- a/audioreach-driver/q6prm_audioreach.h +++ b/audioreach-driver/q6prm_audioreach.h @@ -4,7 +4,9 @@ #ifndef __Q6PRM_AUDIOREACH_H__ #define __Q6PRM_AUDIOREACH_H__ +#include #include +#include /* Clock ID for Primary I2S IBIT */ #define Q6PRM_LPASS_CLK_ID_PRI_MI2S_IBIT 0x100 @@ -97,11 +99,75 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define Q6PRM_LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 0x318 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_IBIT 0x500 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_EBIT 0x501 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_IBIT 0x502 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_EBIT 0x503 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_IBIT 0x504 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_EBIT 0x505 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_IBIT 0x506 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_EBIT 0x507 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_IBIT 0x508 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_EBIT 0x509 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_IBIT 0x50A +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_EBIT 0x50B +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_IBIT 0x50C +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_EBIT 0x50D +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_IBIT 0x50E +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_EBIT 0x50F +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_IBIT 0x510 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_EBIT 0x511 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_IBIT 0x512 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_EBIT 0x513 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_IBIT 0x514 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_EBIT 0x515 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_IBIT 0x516 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_EBIT 0x517 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_IBIT 0x518 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_EBIT 0x519 +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_IBIT 0x550 +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_EBIT 0x551 + +#ifndef LPASS_CLK_ID_AUD_INTF0_IBIT +#define LPASS_CLK_ID_AUD_INTF0_IBIT 71 +#define LPASS_CLK_ID_AUD_INTF0_EBIT 72 +#define LPASS_CLK_ID_AUD_INTF1_IBIT 73 +#define LPASS_CLK_ID_AUD_INTF1_EBIT 74 +#define LPASS_CLK_ID_AUD_INTF2_IBIT 75 +#define LPASS_CLK_ID_AUD_INTF2_EBIT 76 +#define LPASS_CLK_ID_AUD_INTF3_IBIT 77 +#define LPASS_CLK_ID_AUD_INTF3_EBIT 78 +#define LPASS_CLK_ID_AUD_INTF4_IBIT 79 +#define LPASS_CLK_ID_AUD_INTF4_EBIT 80 +#define LPASS_CLK_ID_AUD_INTF5_IBIT 81 +#define LPASS_CLK_ID_AUD_INTF5_EBIT 82 +#define LPASS_CLK_ID_AUD_INTF6_IBIT 83 +#define LPASS_CLK_ID_AUD_INTF6_EBIT 84 +#define LPASS_CLK_ID_AUD_INTF7_IBIT 85 +#define LPASS_CLK_ID_AUD_INTF7_EBIT 86 +#define LPASS_CLK_ID_AUD_INTF8_IBIT 87 +#define LPASS_CLK_ID_AUD_INTF8_EBIT 88 +#define LPASS_CLK_ID_AUD_INTF9_IBIT 89 +#define LPASS_CLK_ID_AUD_INTF9_EBIT 90 +#define LPASS_CLK_ID_AUD_INTF10_IBIT 91 +#define LPASS_CLK_ID_AUD_INTF10_EBIT 92 +#define LPASS_CLK_ID_AUD_INTF11_IBIT 93 +#define LPASS_CLK_ID_AUD_INTF11_EBIT 94 +#define LPASS_CLK_ID_AUD_INTF12_IBIT 95 +#define LPASS_CLK_ID_AUD_INTF12_EBIT 96 +#define LPASS_CLK_ID_AUD_VA_INTF0_IBIT 97 +#define LPASS_CLK_ID_AUD_VA_INTF0_EBIT 98 +#endif + #define Q6PRM_LPASS_CLK_SRC_INTERNAL 1 #define Q6PRM_LPASS_CLK_ROOT_DEFAULT 0 #define Q6PRM_HW_CORE_ID_LPASS 1 #define Q6PRM_HW_CORE_ID_DCODEC 2 +#define LPAIF_MI2S_MCLK 1 +#define LPAIF_MI2S_BCLK 2 +#define LPAIF_MI2S_ECLK 3 + struct audio_hw_clk_cfg { uint32_t clock_id; uint32_t clock_freq; @@ -131,6 +197,11 @@ struct q6dsp_clk_desc { int (*lpass_unvote_clk)(struct device *dev, uint32_t hid, uint32_t h); }; +static inline u16 audioreach_gpr_dest_domain(gpr_device_t *gdev) +{ + return gdev && gdev->domain_id ? gdev->domain_id : GPR_DOMAIN_ID_ADSP; +} + int q6dsp_clock_dev_probe(struct platform_device *pdev); int q6prm_audioreach_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, diff --git a/audioreach-driver/q6prm_audioreach_clock.c b/audioreach-driver/q6prm_audioreach_clock.c index 1ac5e01..87e60bb 100644 --- a/audioreach-driver/q6prm_audioreach_clock.c +++ b/audioreach-driver/q6prm_audioreach_clock.c @@ -65,6 +65,34 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK), Q6PRM_CLK(LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_EBIT), Q6DSP_VOTE_CLK(LPASS_HW_MACRO_VOTE, Q6PRM_HW_CORE_ID_LPASS, "LPASS_HW_MACRO"), Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6PRM_HW_CORE_ID_DCODEC, diff --git a/dsp/spf-core.c b/dsp/spf-core.c index 28ad3c1..68c1811 100644 --- a/dsp/spf-core.c +++ b/dsp/spf-core.c @@ -36,6 +36,11 @@ struct spf_core_private { struct work_struct add_chld_dev_work; }; +static inline u16 spf_core_gpr_dest_domain(gpr_device_t *gdev) +{ + return gdev && gdev->domain_id ? gdev->domain_id : GPR_DOMAIN_ID_ADSP; +} + static struct spf_core_private *spf_core_priv; struct apm_cmd_rsp_get_spf_status_t @@ -93,7 +98,7 @@ static bool __spf_core_is_apm_ready(struct spf_core *core) pkt.hdr.opcode = APM_CMD_GET_SPF_STATE; pkt.hdr.dest_port = APM_MODULE_INSTANCE_ID; pkt.hdr.src_port = adev->svc_id; //1 - pkt.hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt.hdr.dest_domain = spf_core_gpr_dest_domain(adev); pkt.hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt.hdr.opcode = APM_CMD_GET_SPF_STATE;