diff options
author | Wilson Sung <wilsonsung@google.com> | 2021-05-18 15:42:58 +0800 |
---|---|---|
committer | Wilson Sung <wilsonsung@google.com> | 2021-05-18 15:43:17 +0800 |
commit | a115064da70841274c1a8024c3b73bd4c635fcc5 (patch) | |
tree | f354e71345dd5b59bd7433ab7b13264e8054d284 | |
parent | e4ec5db336f06b9cd8d94a9e3af527b60dfa3973 (diff) | |
parent | 3da6272ea2fdf0e8990de49fd37ff736b3a43ead (diff) | |
download | msm-extra-a115064da70841274c1a8024c3b73bd4c635fcc5.tar.gz |
Merge branch 'LA.UM.9.12.C10.11.00.00.840.010' into qcom-msm-4.19-7250-audio-drivers.lnx.4.0.r3
Change-Id: I5401782d473b0b04922bd526d2b69e40565d7b51
-rw-r--r-- | asoc/codecs/bolero/bolero-cdc.c | 2 | ||||
-rw-r--r-- | asoc/codecs/bolero/rx-macro.c | 27 | ||||
-rw-r--r-- | asoc/codecs/bolero/tx-macro.c | 17 | ||||
-rw-r--r-- | asoc/codecs/bolero/va-macro.c | 17 | ||||
-rw-r--r-- | asoc/codecs/bolero/wsa-macro.c | 15 | ||||
-rw-r--r-- | asoc/msm-pcm-routing-v2.c | 15 | ||||
-rw-r--r-- | dsp/q6adm.c | 211 | ||||
-rw-r--r-- | dsp/q6afe.c | 7 | ||||
-rw-r--r-- | dsp/rtac.c | 32 | ||||
-rw-r--r-- | include/dsp/q6adm-v2.h | 4 | ||||
-rw-r--r-- | soc/swr-mstr-ctrl.c | 45 |
11 files changed, 216 insertions, 176 deletions
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index 53c70fab..e80a8239 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -1379,7 +1379,6 @@ static int bolero_probe(struct platform_device *pdev) mutex_init(&priv->vote_lock); INIT_WORK(&priv->bolero_add_child_devices_work, bolero_add_child_devices); - schedule_work(&priv->bolero_add_child_devices_work); /* Register LPASS core hw vote */ lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote"); @@ -1403,6 +1402,7 @@ static int bolero_probe(struct platform_device *pdev) } priv->lpass_audio_hw_vote = lpass_audio_hw_vote; + schedule_work(&priv->bolero_add_child_devices_work); return 0; } diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 07dd8ada..9934a865 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -350,6 +350,7 @@ struct rx_macro_bcl_pmic_params { u8 ppid; }; +static int rx_macro_core_vote(void *handle, bool enable); static int rx_macro_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); @@ -1230,10 +1231,12 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, if (rx_priv->rx_mclk_users == 0) { if (rx_priv->is_native_on) rx_priv->clk_id = RX_CORE_CLK; + rx_macro_core_vote(rx_priv, true); ret = bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, rx_priv->clk_id, true); + rx_macro_core_vote(rx_priv, false); if (ret < 0) { dev_err(rx_priv->dev, "%s: rx request clock enable failed\n", @@ -1283,10 +1286,12 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, 0x01, 0x00); bolero_clk_rsc_fs_gen_request(rx_priv->dev, false); + rx_macro_core_vote(rx_priv, true); bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, rx_priv->clk_id, false); + rx_macro_core_vote(rx_priv, false); rx_priv->clk_id = rx_priv->default_clk_id; } } @@ -1396,18 +1401,21 @@ static int rx_macro_event_handler(struct snd_soc_component *component, } break; case BOLERO_MACRO_EVT_PRE_SSR_UP: + rx_macro_core_vote(rx_priv, true); /* enable&disable RX_CORE_CLK to reset GFMUX reg */ ret = bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, RX_CORE_CLK, true); - if (ret < 0) + if (ret < 0) { dev_err_ratelimited(rx_priv->dev, "%s, failed to enable clk, ret:%d\n", __func__, ret); - else + } else { bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, RX_CORE_CLK, false); + } + rx_macro_core_vote(rx_priv, false); break; case BOLERO_MACRO_EVT_SSR_UP: trace_printk("%s, enter SSR up\n", __func__); @@ -3672,22 +3680,25 @@ static const struct snd_soc_dapm_route rx_audio_map[] = { static int rx_macro_core_vote(void *handle, bool enable) { + int rc = 0; struct rx_macro_priv *rx_priv = (struct rx_macro_priv *) handle; if (rx_priv == NULL) { pr_err("%s: rx priv data is NULL\n", __func__); return -EINVAL; } + if (enable) { pm_runtime_get_sync(rx_priv->dev); + if (bolero_check_core_votes(rx_priv->dev)) + rc = 0; + else + rc = -ENOTSYNC; + } else { pm_runtime_put_autosuspend(rx_priv->dev); pm_runtime_mark_last_busy(rx_priv->dev); } - - if (bolero_check_core_votes(rx_priv->dev)) - return 0; - else - return -EINVAL; + return rc; } static int rx_swrm_clock(void *handle, bool enable) @@ -4165,12 +4176,12 @@ static int rx_macro_probe(struct platform_device *pdev) "%s: register macro failed\n", __func__); goto err_reg_macro; } - schedule_work(&rx_priv->rx_macro_add_child_devices_work); pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); + schedule_work(&rx_priv->rx_macro_add_child_devices_work); return 0; diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index de04e1e9..7f0e758b 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -2678,22 +2678,25 @@ static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src) static int tx_macro_core_vote(void *handle, bool enable) { + int rc = 0; struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; if (tx_priv == NULL) { pr_err("%s: tx priv data is NULL\n", __func__); return -EINVAL; } + if (enable) { pm_runtime_get_sync(tx_priv->dev); + if (bolero_check_core_votes(tx_priv->dev)) + rc = 0; + else + rc = -ENOTSYNC; + } else { pm_runtime_put_autosuspend(tx_priv->dev); pm_runtime_mark_last_busy(tx_priv->dev); } - - if (bolero_check_core_votes(tx_priv->dev)) - return 0; - else - return -EINVAL; + return rc; } static int tx_macro_swrm_clock(void *handle, bool enable) @@ -3280,13 +3283,13 @@ static int tx_macro_probe(struct platform_device *pdev) "%s: register macro failed\n", __func__); goto err_reg_macro; } - if (is_used_tx_swr_gpio) - schedule_work(&tx_priv->tx_macro_add_child_devices_work); pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); + if (is_used_tx_swr_gpio) + schedule_work(&tx_priv->tx_macro_add_child_devices_work); return 0; err_reg_macro: diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 2e369952..93fc0fc9 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -671,22 +671,25 @@ done: static int va_macro_core_vote(void *handle, bool enable) { + int rc = 0; struct va_macro_priv *va_priv = (struct va_macro_priv *) handle; if (va_priv == NULL) { pr_err("%s: va priv data is NULL\n", __func__); return -EINVAL; } + if (enable) { pm_runtime_get_sync(va_priv->dev); + if (bolero_check_core_votes(va_priv->dev)) + rc = 0; + else + rc = -ENOTSYNC; + } else { pm_runtime_put_autosuspend(va_priv->dev); pm_runtime_mark_last_busy(va_priv->dev); } - - if (bolero_check_core_votes(va_priv->dev)) - return 0; - else - return -EINVAL; + return rc; } static int va_macro_swrm_clock(void *handle, bool enable) @@ -3143,13 +3146,13 @@ static int va_macro_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: register macro failed\n", __func__); goto reg_macro_fail; } - if (is_used_va_swr_gpio) - schedule_work(&va_priv->va_macro_add_child_devices_work); pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); + if (is_used_va_swr_gpio) + schedule_work(&va_priv->va_macro_add_child_devices_work); return ret; reg_macro_fail: diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 5ace96db..4e06d12b 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -2828,22 +2828,25 @@ static void wsa_macro_init_reg(struct snd_soc_component *component) static int wsa_macro_core_vote(void *handle, bool enable) { + int rc = 0; struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle; if (wsa_priv == NULL) { pr_err("%s: wsa priv data is NULL\n", __func__); return -EINVAL; } + if (enable) { pm_runtime_get_sync(wsa_priv->dev); + if (bolero_check_core_votes(wsa_priv->dev)) + rc = 0; + else + rc = -ENOTSYNC; + } else { pm_runtime_put_autosuspend(wsa_priv->dev); pm_runtime_mark_last_busy(wsa_priv->dev); } - - if (bolero_check_core_votes(wsa_priv->dev)) - return 0; - else - return -EINVAL; + return rc; } static int wsa_swrm_clock(void *handle, bool enable) @@ -3237,12 +3240,12 @@ static int wsa_macro_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s: register macro failed\n", __func__); goto reg_macro_fail; } - schedule_work(&wsa_priv->wsa_macro_add_child_devices_work); pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); + schedule_work(&wsa_priv->wsa_macro_add_child_devices_work); return ret; reg_macro_fail: diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 7aafe2b9..99e93c39 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -1729,6 +1729,11 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode, for (i = 0; i < ADM_MAX_CHANNELS && channel_input[fe_id][i] > 0; ++i) { be_id = channel_input[fe_id][i] - 1; + if (be_id < 0 || be_id >= MSM_BACKEND_DAI_MAX) { + pr_err("%s: Received out of bounds be_id %d\n", + __func__, be_id); + return -EINVAL; + } channel_mixer[fe_id].input_channels[i] = msm_bedais[be_id].channel; @@ -3470,10 +3475,10 @@ static int msm_pcm_get_out_chs(struct snd_kcontrol *kcontrol, static int msm_pcm_put_out_chs(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - u16 fe_id = 0; - + u16 fe_id = 0, out_ch = 0; fe_id = ((struct soc_multi_mixer_control *) kcontrol->private_value)->shift; + out_ch = ucontrol->value.integer.value[0]; if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) { pr_err("%s: invalid FE %d\n", __func__, fe_id); return -EINVAL; @@ -3482,6 +3487,12 @@ static int msm_pcm_put_out_chs(struct snd_kcontrol *kcontrol, pr_debug("%s: fe_id is %d, output channels = %d\n", __func__, fe_id, (unsigned int)(ucontrol->value.integer.value[0])); + if (out_ch < 0 || + out_ch > ADM_MAX_CHANNELS) { + pr_err("%s: invalid output channel %d\n", __func__, + out_ch); + return -EINVAL; + } channel_mixer[fe_id].output_channel = (unsigned int)(ucontrol->value.integer.value[0]); diff --git a/dsp/q6adm.c b/dsp/q6adm.c index 51ca185b..e63547d8 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -95,6 +95,7 @@ struct adm_ctl { struct param_outband outband_memmap; struct source_tracking_data sourceTrackingData; + struct mutex adm_apr_lock; int set_custom_topology; int ec_ref_rx; int num_ec_ref_rx_chans; @@ -870,6 +871,71 @@ exit: EXPORT_SYMBOL(adm_set_custom_chmix_cfg); /* + * adm_apr_send_pkt : returns 0 on success, negative otherwise. + */ +int adm_apr_send_pkt(void *data, wait_queue_head_t *wait, + int port_idx, int copp_idx, int opcode) +{ + int ret = 0; + atomic_t *copp_stat = NULL; + int32_t time_out = msecs_to_jiffies(TIMEOUT_MS); + wait = &this_adm.copp.wait[port_idx][copp_idx]; + + if (!wait) + return -EINVAL; + + mutex_lock(&this_adm.adm_apr_lock); + pr_debug("%s: port idx %d copp idx %d\n", __func__, + port_idx, copp_idx); + copp_stat = &this_adm.copp.stat[port_idx][copp_idx]; + atomic_set(copp_stat, -1); + + if (opcode != ADM_CMD_DEVICE_OPEN_V8 && + opcode != ADM_CMD_DEVICE_OPEN_V6 && + opcode != ADM_CMD_DEVICE_OPEN_V5 && + opcode != ADM_CMD_DEVICE_CLOSE_V5) { + if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) + == 0) { + pr_err("%s: port[0x%x] copp[0x%x] inactive\n", + __func__, port_idx, copp_idx); + mutex_unlock(&this_adm.adm_apr_lock); + return -EINVAL; + } + } + + if (opcode == ADM_CMD_DEVICE_OPEN_V8 || + opcode == ADM_CMD_DEVICE_OPEN_V6 || + opcode == ADM_CMD_DEVICE_OPEN_V5) { + time_out = msecs_to_jiffies(2 * TIMEOUT_MS); + } + + ret = apr_send_pkt(this_adm.apr, data); + if (ret > 0) { + ret = wait_event_timeout(*wait, + atomic_read(copp_stat) >= 0, + time_out); + if (atomic_read(copp_stat) > 0) { + pr_err("%s: DSP returned error[%s]\n", __func__, + adsp_err_get_err_str(atomic_read(copp_stat))); + ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat)); + } else if (!ret) { + pr_err_ratelimited("%s: request timedout\n", + __func__); + ret = -ETIMEDOUT; + } else { + ret = 0; + } + } else if (ret == 0) { + pr_err("%s: packet not transmitted\n", __func__); + /* apr_send_pkt can return 0 when nothing is transmitted */ + ret = -EINVAL; + } + + mutex_unlock(&this_adm.adm_apr_lock); + return ret; +} + +/* * With pre-packed data, only the opcode differes from V5 and V6. * Use q6common_pack_pp_params to pack the data correctly. */ @@ -880,7 +946,6 @@ int adm_set_pp_params(int port_id, int copp_idx, struct adm_cmd_set_pp_params *adm_set_params = NULL; int size = 0; int port_idx = 0; - atomic_t *copp_stat = NULL; int ret = 0; port_id = afe_convert_virtual_to_portid(port_id); @@ -938,32 +1003,9 @@ int adm_set_pp_params(int port_id, int copp_idx, ret = -EINVAL; goto done; } - - copp_stat = &this_adm.copp.stat[port_idx][copp_idx]; - atomic_set(copp_stat, -1); - ret = apr_send_pkt(this_adm.apr, (uint32_t *) adm_set_params); - if (ret < 0) { - pr_err("%s: Set params APR send failed port = 0x%x ret %d\n", - __func__, port_id, ret); - goto done; - } - ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], - atomic_read(copp_stat) >= 0, - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("%s: Set params timed out port = 0x%x\n", __func__, - port_id); - ret = -ETIMEDOUT; - goto done; - } - if (atomic_read(copp_stat) > 0) { - pr_err("%s: DSP returned error[%s]\n", __func__, - adsp_err_get_err_str(atomic_read(copp_stat))); - ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat)); - goto done; - } - - ret = 0; + ret = adm_apr_send_pkt((uint32_t *) adm_set_params, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, adm_set_params->apr_hdr.opcode); done: kfree(adm_set_params); return ret; @@ -1016,7 +1058,6 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id, int returned_param_size_in_bytes = 0; int port_idx = 0; int idx = 0; - atomic_t *copp_stat = NULL; int ret = 0; if (param_hdr == NULL) { @@ -1064,33 +1105,9 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id, else adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5; - copp_stat = &this_adm.copp.stat[port_idx][copp_idx]; - atomic_set(copp_stat, -1); - - ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params); - if (ret < 0) { - pr_err("%s: Get params APR send failed port = 0x%x ret %d\n", - __func__, port_id, ret); - ret = -EINVAL; - goto done; - } - ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], - atomic_read(copp_stat) >= 0, - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("%s: Get params timed out port = 0x%x\n", __func__, - port_id); - ret = -ETIMEDOUT; - goto done; - } - if (atomic_read(copp_stat) > 0) { - pr_err("%s: DSP returned error[%s]\n", __func__, - adsp_err_get_err_str(atomic_read(copp_stat))); - ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat)); - goto done; - } - - ret = 0; + ret = adm_apr_send_pkt((uint32_t *) &adm_get_params, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, adm_get_params.apr_hdr.opcode); /* Copy data to caller if sent in band */ if (!returned_param_data) { @@ -1118,7 +1135,6 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id, memcpy(returned_param_data, &adm_get_parameters[idx + 1], returned_param_size_in_bytes); -done: return ret; } EXPORT_SYMBOL(adm_get_pp_params); @@ -1601,8 +1617,15 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) this_adm.sourceTrackingData. apr_cmd_status = payload[1]; else if (rtac_make_adm_callback(payload, - data->payload_size)) - break; + data->payload_size)) { + pr_debug("%s: rtac cmd response\n", + __func__); + } + atomic_set(&this_adm.copp.stat[port_idx] + [copp_idx], payload[1]); + wake_up( + &this_adm.copp.wait[port_idx][copp_idx]); + break; /* * if soft volume is called and already * interrupted break out of the sequence here @@ -1611,8 +1634,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMD_DEVICE_CLOSE_V5: case ADM_CMD_DEVICE_OPEN_V6: case ADM_CMD_DEVICE_OPEN_V8: - pr_debug("%s: Basic callback received, wake up.\n", - __func__); + pr_debug("%s: Basic callback received for 0x%x, wake up.\n", + __func__, payload[0]); atomic_set(&this_adm.copp.stat[port_idx] [copp_idx], payload[1]); wake_up( @@ -1745,8 +1768,13 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) this_adm.sourceTrackingData.apr_cmd_status = payload[0]; else if (rtac_make_adm_callback(payload, - data->payload_size)) + data->payload_size)) { + pr_debug("%s: rtac cmd response\n", __func__); + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], + payload[0]); + wake_up(&this_adm.copp.wait[port_idx][copp_idx]); break; + } idx = ADM_GET_PARAMETER_LENGTH * copp_idx; if (payload[0] == 0 && data->payload_size > 0) { @@ -3287,8 +3315,9 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, ep2_payload_size); } - ret = apr_send_pkt(this_adm.apr, - (uint32_t *)adm_params); + ret = adm_apr_send_pkt((uint32_t *) adm_params, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, open_v8.hdr.opcode); if (ret < 0) { pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n", __func__, tmp_port, port_id, ret); @@ -3374,11 +3403,13 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, if (ret) return ret; - ret = apr_send_pkt(this_adm.apr, - (uint32_t *)&open_v6); + ret = adm_apr_send_pkt((uint32_t *) &open_v6, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, open_v6.hdr.opcode); } else { - ret = apr_send_pkt(this_adm.apr, - (uint32_t *)&open); + ret = adm_apr_send_pkt((uint32_t *) &open, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, open.hdr.opcode); } if (ret < 0) { pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n", @@ -3386,26 +3417,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, return -EINVAL; } } - - /* Wait for the callback with copp id */ - ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]) >= 0, - msecs_to_jiffies(2 * TIMEOUT_MS)); - if (!ret) { - pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n", - __func__, tmp_port, port_id); - return -EINVAL; - } else if (atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]))); - return adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx])); - } } atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]); @@ -3910,31 +3921,13 @@ int adm_close(int port_id, int perf_mode, int copp_idx) clear_bit(ADM_STATUS_CALIBRATION_REQUIRED, (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); - - ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close); + ret = adm_apr_send_pkt((uint32_t *) &close, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx, close.opcode); if (ret < 0) { pr_err("%s: ADM close failed %d\n", __func__, ret); return -EINVAL; } - - ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]) >= 0, - msecs_to_jiffies(TIMEOUT_MS)); - if (!ret) { - pr_err("%s: ADM cmd Route timedout for port 0x%x\n", - __func__, port_id); - return -EINVAL; - } else if (atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]) > 0) { - pr_err("%s: DSP returned error[%s]\n", - __func__, adsp_err_get_err_str( - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx]))); - return adsp_err_get_lnx_err_code( - atomic_read(&this_adm.copp.stat - [port_idx][copp_idx])); - } } if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) { @@ -5504,6 +5497,7 @@ int __init adm_init(void) this_adm.ffecns_port_id = -1; init_waitqueue_head(&this_adm.matrix_map_wait); init_waitqueue_head(&this_adm.adm_wait); + mutex_init(&this_adm.adm_apr_lock); for (i = 0; i < AFE_MAX_PORTS; i++) { for (j = 0; j < MAX_COPPS_PER_PORT; j++) { @@ -5528,6 +5522,7 @@ int __init adm_init(void) void adm_exit(void) { + mutex_destroy(&this_adm.adm_apr_lock); if (this_adm.apr) adm_reset_data(); adm_delete_cal_data(); diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 88124df9..7f594f29 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -10160,6 +10160,7 @@ static int afe_get_cal_sp_th_vi_param(int32_t cal_type, size_t data_size, if (cal_data == NULL || data_size > sizeof(*cal_data) || + data_size < sizeof(cal_data->cal_hdr) || this_afe.cal_data[AFE_FB_SPKR_PROT_TH_VI_CAL] == NULL) return 0; @@ -10188,7 +10189,8 @@ static int afe_get_cal_spv4_ex_vi_ftm_param(int32_t cal_type, size_t data_size, pr_debug("%s: cal_type = %d\n", __func__, cal_type); if (this_afe.cal_data[AFE_FB_SPKR_PROT_V4_EX_VI_CAL] == NULL || cal_data == NULL || - data_size != sizeof(*cal_data)) + data_size > sizeof(*cal_data) || + data_size < sizeof(cal_data->cal_hdr)) goto done; mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_V4_EX_VI_CAL]->lock); @@ -10255,7 +10257,8 @@ static int afe_get_cal_sp_ex_vi_ftm_param(int32_t cal_type, size_t data_size, pr_debug("%s: cal_type = %d\n", __func__, cal_type); if (this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL] == NULL || cal_data == NULL || - data_size != sizeof(*cal_data)) + data_size > sizeof(*cal_data) || + data_size < sizeof(cal_data->cal_hdr)) goto done; mutex_lock(&this_afe.cal_data[AFE_FB_SPKR_PROT_EX_VI_CAL]->lock); @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include <linux/fs.h> @@ -728,7 +728,6 @@ bool rtac_make_adm_callback(uint32_t *payload, u32 payload_size) atomic_set(&rtac_common.apr_err_code, payload[1]); atomic_set(&rtac_adm_apr_data.cmd_state, 0); - wake_up(&rtac_adm_apr_data.cmd_wait); return true; } @@ -880,33 +879,12 @@ int send_adm_apr(void *buf, u32 opcode) pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", __func__, opcode, &rtac_cal[ADM_RTAC_CAL].cal_data.paddr); + mutex_unlock(&rtac_adm_apr_mutex); - result = apr_send_pkt(rtac_adm_apr_data.apr_handle, - (uint32_t *)rtac_adm_buffer); - if (result < 0) { - pr_err("%s: Set params failed copp = %d\n", __func__, copp_id); - goto err; - } - /* Wait for the callback */ - result = wait_event_timeout(rtac_adm_apr_data.cmd_wait, - (atomic_read(&rtac_adm_apr_data.cmd_state) == 0), - msecs_to_jiffies(TIMEOUT_MS)); - if (!result) { - pr_err("%s: Set params timed out copp = %d\n", __func__, - copp_id); - goto err; - } - if (atomic_read(&rtac_common.apr_err_code)) { - pr_err("%s: DSP returned error code = [%s], opcode = 0x%x\n", - __func__, adsp_err_get_err_str(atomic_read( - &rtac_common.apr_err_code)), - opcode); - result = adsp_err_get_lnx_err_code( - atomic_read( - &rtac_common.apr_err_code)); - goto err; - } + result = adm_apr_send_pkt((uint32_t *)rtac_adm_buffer, + NULL, port_idx, copp_idx, adm_params.opcode); + mutex_lock(&rtac_adm_apr_mutex); if (opcode == ADM_CMD_GET_PP_PARAMS_V5) { bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h index 644855d0..84fc1e01 100644 --- a/include/dsp/q6adm-v2.h +++ b/include/dsp/q6adm-v2.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #ifndef __Q6_ADM_V2_H__ #define __Q6_ADM_V2_H__ @@ -229,4 +229,6 @@ void msm_dts_srs_acquire_lock(void); void msm_dts_srs_release_lock(void); void adm_set_native_mode(int mode); int adm_set_ffecns_freeze_event(bool ffecns_freeze_event); +int adm_apr_send_pkt(void *data, wait_queue_head_t *wait, + int port_idx, int copp_idx, int opcode); #endif /* __Q6_ADM_V2_H__ */ diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 385e59fa..4cdb3f50 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -457,7 +457,7 @@ static int swrm_get_ssp_period(struct swr_mstr_ctrl *swrm, return ((swrm->bus_clk * 2) / ((row * col) * frame_sync)); } -static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm) +static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm, bool enable) { int ret = 0; @@ -470,7 +470,7 @@ static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm) goto exit; } if (swrm->core_vote) { - ret = swrm->core_vote(swrm->handle, true); + ret = swrm->core_vote(swrm->handle, enable); if (ret) dev_err_ratelimited(swrm->dev, "%s: core vote request failed\n", __func__); @@ -501,8 +501,10 @@ static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable) dev_err_ratelimited(swrm->dev, "%s: core vote request failed\n", __func__); + swrm->core_vote(swrm->handle, false); goto exit; } + ret = swrm->core_vote(swrm->handle, false); } } swrm->clk_ref_count++; @@ -538,6 +540,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm, { u32 temp = (u32)(*value); int ret = 0; + int vote_ret = 0; mutex_lock(&swrm->devlock); if (!swrm->dev_up) @@ -551,13 +554,20 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm, __func__); goto err; } - } else if (swrm_core_vote_request(swrm)) { - goto err; + } else { + vote_ret = swrm_core_vote_request(swrm, true); + if (vote_ret == -ENOTSYNC) + goto err_vote; + else if (vote_ret) + goto err; } iowrite32(temp, swrm->swrm_dig_base + reg); if (is_swr_clk_needed(swrm)) swrm_clk_request(swrm, FALSE); +err_vote: + if (!is_swr_clk_needed(swrm)) + swrm_core_vote_request(swrm, false); err: mutex_unlock(&swrm->devlock); return ret; @@ -568,6 +578,7 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm, { u32 temp = 0; int ret = 0; + int vote_ret = 0; mutex_lock(&swrm->devlock); if (!swrm->dev_up) @@ -580,14 +591,21 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm, __func__); goto err; } - } else if (swrm_core_vote_request(swrm)) { - goto err; + } else { + vote_ret = swrm_core_vote_request(swrm, true); + if (vote_ret == -ENOTSYNC) + goto err_vote; + else if (vote_ret) + goto err; } temp = ioread32(swrm->swrm_dig_base + reg); *value = temp; if (is_swr_clk_needed(swrm)) swrm_clk_request(swrm, FALSE); +err_vote: + if (!is_swr_clk_needed(swrm)) + swrm_core_vote_request(swrm, false); err: mutex_unlock(&swrm->devlock); return ret; @@ -2577,6 +2595,7 @@ static int swrm_probe(struct platform_device *pdev) int ret = 0; struct clk *lpass_core_hw_vote = NULL; struct clk *lpass_core_audio = NULL; + u32 swrm_hw_ver = 0; /* Allocate soundwire master driver structure */ swrm = devm_kzalloc(&pdev->dev, sizeof(struct swr_mstr_ctrl), @@ -2603,6 +2622,14 @@ static int swrm_probe(struct platform_device *pdev) ret = -EINVAL; goto err_pdata_fail; } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,swr-master-version", + &swrm->version); + if (ret) { + dev_dbg(&pdev->dev, "%s: swrm version not defined, use default\n", + __func__); + swrm->version = SWRM_VERSION_1_6; + } ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr_master_id", &swrm->master_id); if (ret) { @@ -2850,7 +2877,11 @@ static int swrm_probe(struct platform_device *pdev) swr_master_add_boarddevices(&swrm->master); mutex_lock(&swrm->mlock); swrm_clk_request(swrm, true); - swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION); + swrm_hw_ver = swr_master_read(swrm, SWRM_COMP_HW_VERSION); + if (swrm->version != swrm_hw_ver) + dev_info(&pdev->dev, + "%s: version specified in dtsi: 0x%x not match with HW read version 0x%x\n", + __func__, swrm->version, swrm_hw_ver); ret = swrm_master_init(swrm); if (ret < 0) { dev_err(&pdev->dev, |