0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <sound/hdaudio_ext.h>
0010 #include "avs.h"
0011 #include "registers.h"
0012 #include "trace.h"
0013
0014 #define AVS_ADSPCS_INTERVAL_US 500
0015 #define AVS_ADSPCS_TIMEOUT_US 50000
0016 #define AVS_ADSPCS_DELAY_US 1000
0017
0018 int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
0019 {
0020 u32 value, mask, reg;
0021 int ret;
0022
0023 value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
0024 trace_avs_dsp_core_op(value, core_mask, "power", power);
0025
0026 mask = AVS_ADSPCS_SPA_MASK(core_mask);
0027 value = power ? mask : 0;
0028
0029 snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
0030
0031 usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);
0032
0033 mask = AVS_ADSPCS_CPA_MASK(core_mask);
0034 value = power ? mask : 0;
0035
0036 ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
0037 reg, (reg & mask) == value,
0038 AVS_ADSPCS_INTERVAL_US,
0039 AVS_ADSPCS_TIMEOUT_US);
0040 if (ret)
0041 dev_err(adev->dev, "core_mask %d power %s failed: %d\n",
0042 core_mask, power ? "on" : "off", ret);
0043
0044 return ret;
0045 }
0046
0047 int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
0048 {
0049 u32 value, mask, reg;
0050 int ret;
0051
0052 value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
0053 trace_avs_dsp_core_op(value, core_mask, "reset", reset);
0054
0055 mask = AVS_ADSPCS_CRST_MASK(core_mask);
0056 value = reset ? mask : 0;
0057
0058 snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
0059
0060 ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
0061 reg, (reg & mask) == value,
0062 AVS_ADSPCS_INTERVAL_US,
0063 AVS_ADSPCS_TIMEOUT_US);
0064 if (ret)
0065 dev_err(adev->dev, "core_mask %d %s reset failed: %d\n",
0066 core_mask, reset ? "enter" : "exit", ret);
0067
0068 return ret;
0069 }
0070
0071 int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall)
0072 {
0073 u32 value, mask, reg;
0074 int ret;
0075
0076 value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
0077 trace_avs_dsp_core_op(value, core_mask, "stall", stall);
0078
0079 mask = AVS_ADSPCS_CSTALL_MASK(core_mask);
0080 value = stall ? mask : 0;
0081
0082 snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
0083
0084 ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
0085 reg, (reg & mask) == value,
0086 AVS_ADSPCS_INTERVAL_US,
0087 AVS_ADSPCS_TIMEOUT_US);
0088 if (ret) {
0089 dev_err(adev->dev, "core_mask %d %sstall failed: %d\n",
0090 core_mask, stall ? "" : "un", ret);
0091 return ret;
0092 }
0093
0094
0095 usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);
0096 return 0;
0097 }
0098
0099 int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask)
0100 {
0101 int ret;
0102
0103 ret = avs_dsp_op(adev, power, core_mask, true);
0104 if (ret)
0105 return ret;
0106
0107 ret = avs_dsp_op(adev, reset, core_mask, false);
0108 if (ret)
0109 return ret;
0110
0111 return avs_dsp_op(adev, stall, core_mask, false);
0112 }
0113
0114 int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask)
0115 {
0116
0117 avs_dsp_op(adev, stall, core_mask, true);
0118 avs_dsp_op(adev, reset, core_mask, true);
0119
0120 return avs_dsp_op(adev, power, core_mask, false);
0121 }
0122
0123 static int avs_dsp_enable(struct avs_dev *adev, u32 core_mask)
0124 {
0125 u32 mask;
0126 int ret;
0127
0128 ret = avs_dsp_core_enable(adev, core_mask);
0129 if (ret < 0)
0130 return ret;
0131
0132 mask = core_mask & ~AVS_MAIN_CORE_MASK;
0133 if (!mask)
0134
0135
0136
0137
0138 return 0;
0139
0140 ret = avs_ipc_set_dx(adev, mask, true);
0141 return AVS_IPC_RET(ret);
0142 }
0143
0144 static int avs_dsp_disable(struct avs_dev *adev, u32 core_mask)
0145 {
0146 int ret;
0147
0148 ret = avs_ipc_set_dx(adev, core_mask, false);
0149 if (ret)
0150 return AVS_IPC_RET(ret);
0151
0152 return avs_dsp_core_disable(adev, core_mask);
0153 }
0154
0155 static int avs_dsp_get_core(struct avs_dev *adev, u32 core_id)
0156 {
0157 u32 mask;
0158 int ret;
0159
0160 mask = BIT_MASK(core_id);
0161 if (mask == AVS_MAIN_CORE_MASK)
0162
0163 return 0;
0164 if (core_id >= adev->hw_cfg.dsp_cores) {
0165 ret = -EINVAL;
0166 goto err;
0167 }
0168
0169 adev->core_refs[core_id]++;
0170 if (adev->core_refs[core_id] == 1) {
0171
0172
0173
0174
0175
0176 ret = avs_dsp_disable_d0ix(adev);
0177 if (ret && ret != -AVS_EIPC)
0178 goto err_disable_d0ix;
0179
0180 ret = avs_dsp_enable(adev, mask);
0181 if (ret)
0182 goto err_enable_dsp;
0183 }
0184
0185 return 0;
0186
0187 err_enable_dsp:
0188 avs_dsp_enable_d0ix(adev);
0189 err_disable_d0ix:
0190 adev->core_refs[core_id]--;
0191 err:
0192 dev_err(adev->dev, "get core %d failed: %d\n", core_id, ret);
0193 return ret;
0194 }
0195
0196 static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id)
0197 {
0198 u32 mask;
0199 int ret;
0200
0201 mask = BIT_MASK(core_id);
0202 if (mask == AVS_MAIN_CORE_MASK)
0203
0204 return 0;
0205 if (core_id >= adev->hw_cfg.dsp_cores) {
0206 ret = -EINVAL;
0207 goto err;
0208 }
0209
0210 adev->core_refs[core_id]--;
0211 if (!adev->core_refs[core_id]) {
0212 ret = avs_dsp_disable(adev, mask);
0213 if (ret)
0214 goto err;
0215
0216
0217 avs_dsp_enable_d0ix(adev);
0218 }
0219
0220 return 0;
0221 err:
0222 dev_err(adev->dev, "put core %d failed: %d\n", core_id, ret);
0223 return ret;
0224 }
0225
0226 int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
0227 u8 core_id, u8 domain, void *param, u32 param_size,
0228 u16 *instance_id)
0229 {
0230 struct avs_module_entry mentry;
0231 bool was_loaded = false;
0232 int ret, id;
0233
0234 id = avs_module_id_alloc(adev, module_id);
0235 if (id < 0)
0236 return id;
0237
0238 ret = avs_get_module_id_entry(adev, module_id, &mentry);
0239 if (ret)
0240 goto err_mod_entry;
0241
0242 ret = avs_dsp_get_core(adev, core_id);
0243 if (ret)
0244 goto err_mod_entry;
0245
0246
0247 if (!id && !avs_module_entry_is_loaded(&mentry)) {
0248 ret = avs_dsp_op(adev, transfer_mods, true, &mentry, 1);
0249 if (ret) {
0250 dev_err(adev->dev, "load modules failed: %d\n", ret);
0251 goto err_mod_entry;
0252 }
0253 was_loaded = true;
0254 }
0255
0256 ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id,
0257 core_id, domain, param, param_size);
0258 if (ret) {
0259 ret = AVS_IPC_RET(ret);
0260 goto err_ipc;
0261 }
0262
0263 *instance_id = id;
0264 return 0;
0265
0266 err_ipc:
0267 if (was_loaded)
0268 avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
0269 avs_dsp_put_core(adev, core_id);
0270 err_mod_entry:
0271 avs_module_id_free(adev, module_id, id);
0272 return ret;
0273 }
0274
0275 void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
0276 u8 ppl_instance_id, u8 core_id)
0277 {
0278 struct avs_module_entry mentry;
0279 int ret;
0280
0281
0282 if (ppl_instance_id == INVALID_PIPELINE_ID)
0283 avs_ipc_delete_instance(adev, module_id, instance_id);
0284
0285 avs_module_id_free(adev, module_id, instance_id);
0286
0287 ret = avs_get_module_id_entry(adev, module_id, &mentry);
0288
0289 if (!ret && mentry.type.load_type == AVS_MODULE_LOAD_TYPE_LOADABLE) {
0290 if (avs_is_module_ida_empty(adev, module_id)) {
0291 ret = avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
0292 if (ret)
0293 dev_err(adev->dev, "unload modules failed: %d\n", ret);
0294 }
0295 }
0296
0297 avs_dsp_put_core(adev, core_id);
0298 }
0299
0300 int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
0301 bool lp, u16 attributes, u8 *instance_id)
0302 {
0303 struct avs_fw_cfg *fw_cfg = &adev->fw_cfg;
0304 int ret, id;
0305
0306 id = ida_alloc_max(&adev->ppl_ida, fw_cfg->max_ppl_count - 1, GFP_KERNEL);
0307 if (id < 0)
0308 return id;
0309
0310 ret = avs_ipc_create_pipeline(adev, req_size, priority, id, lp, attributes);
0311 if (ret) {
0312 ida_free(&adev->ppl_ida, id);
0313 return AVS_IPC_RET(ret);
0314 }
0315
0316 *instance_id = id;
0317 return 0;
0318 }
0319
0320 int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id)
0321 {
0322 int ret;
0323
0324 ret = avs_ipc_delete_pipeline(adev, instance_id);
0325 if (ret)
0326 ret = AVS_IPC_RET(ret);
0327
0328 ida_free(&adev->ppl_ida, instance_id);
0329 return ret;
0330 }