diff options
Diffstat (limited to 'sound/soc/qcom')
| -rw-r--r-- | sound/soc/qcom/qdsp6/audioreach.c | 234 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6adm.c | 179 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6afe.c | 49 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6apm-dai.c | 25 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6apm.c | 57 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6asm-dai.c | 87 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6asm.c | 203 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6asm.h | 1 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6prm.c | 27 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6routing.c | 6 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/q6usb.c | 3 | ||||
| -rw-r--r-- | sound/soc/qcom/qdsp6/topology.c | 12 | ||||
| -rw-r--r-- | sound/soc/qcom/sc7180.c | 10 | ||||
| -rw-r--r-- | sound/soc/qcom/sc7280.c | 67 | ||||
| -rw-r--r-- | sound/soc/qcom/sc8280xp.c | 34 | ||||
| -rw-r--r-- | sound/soc/qcom/sdm845.c | 53 | ||||
| -rw-r--r-- | sound/soc/qcom/sdw.c | 128 | ||||
| -rw-r--r-- | sound/soc/qcom/sdw.h | 7 | ||||
| -rw-r--r-- | sound/soc/qcom/sm8250.c | 34 | ||||
| -rw-r--r-- | sound/soc/qcom/x1e80100.c | 33 |
20 files changed, 413 insertions, 836 deletions
diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index 2365424a9b42..ded49124581b 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -612,19 +612,12 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, struct apm_module_frame_size_factor_cfg *fs_cfg; struct apm_module_param_data *param_data; struct apm_module_hw_ep_mf_cfg *hw_cfg; - int ic_sz, ep_sz, fs_sz, dl_sz; - int rc, payload_size; - struct gpr_pkt *pkt; + int ic_sz = APM_DP_INTF_CFG_PSIZE; + int ep_sz = APM_HW_EP_CFG_PSIZE; + int fs_sz = APM_FS_CFG_PSIZE; + int size = ic_sz + ep_sz + fs_sz; void *p; - - ic_sz = APM_DP_INTF_CFG_PSIZE; - ep_sz = APM_HW_EP_CFG_PSIZE; - fs_sz = APM_FS_CFG_PSIZE; - dl_sz = 0; - - payload_size = ic_sz + ep_sz + fs_sz + dl_sz; - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -663,11 +656,7 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, intf_cfg->cfg.mst_idx = 0; intf_cfg->cfg.dptx_idx = cfg->dp_idx; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } /* LPASS Codec DMA port Module Media Format Setup */ @@ -680,20 +669,13 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, struct apm_module_hw_ep_power_mode_cfg *pm_cfg; struct apm_module_param_data *param_data; struct apm_module_hw_ep_mf_cfg *hw_cfg; - int ic_sz, ep_sz, fs_sz, pm_sz, dl_sz; - int rc, payload_size; - struct gpr_pkt *pkt; + int ic_sz = APM_CDMA_INTF_CFG_PSIZE; + int ep_sz = APM_HW_EP_CFG_PSIZE; + int fs_sz = APM_FS_CFG_PSIZE; + int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE; + int size = ic_sz + ep_sz + fs_sz + pm_sz; void *p; - - ic_sz = APM_CDMA_INTF_CFG_PSIZE; - ep_sz = APM_HW_EP_CFG_PSIZE; - fs_sz = APM_FS_CFG_PSIZE; - pm_sz = APM_HW_EP_PMODE_CFG_PSIZE; - dl_sz = 0; - - payload_size = ic_sz + ep_sz + fs_sz + pm_sz + dl_sz; - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -741,24 +723,17 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph, param_data->param_size = pm_sz - APM_MODULE_PARAM_DATA_SIZE; pm_cfg->power_mode.power_mode = 0; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_module *module, uint32_t param_id, uint32_t param_val) { struct apm_module_param_data *param_data; - struct gpr_pkt *pkt; + struct gpr_pkt *pkt __free(kfree) = NULL; uint32_t *param; - int rc, payload_size; - void *p; - - payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE; - p = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + int payload_size = sizeof(uint32_t) + APM_MODULE_PARAM_DATA_SIZE; + void *p = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); if (IS_ERR(p)) return -ENOMEM; @@ -775,11 +750,7 @@ int audioreach_send_u32_param(struct q6apm_graph *graph, struct audioreach_modul param = p; *param = param_val; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } EXPORT_SYMBOL_GPL(audioreach_send_u32_param); @@ -815,24 +786,17 @@ static int audioreach_set_module_config(struct q6apm_graph *graph, struct audioreach_module *module, struct audioreach_module_config *cfg) { - int payload_size = le32_to_cpu(module->data->size); - struct gpr_pkt *pkt; - int rc; + int size = le32_to_cpu(module->data->size); void *p; - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; - memcpy(p, module->data->data, payload_size); - - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); + memcpy(p, module->data->data, size); - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, @@ -842,15 +806,11 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, struct apm_module_param_data *param_data; struct param_id_mfc_media_format *media_format; uint32_t num_channels = cfg->num_channels; - int payload_size; - struct gpr_pkt *pkt; - int rc, i; + int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) + + APM_MODULE_PARAM_DATA_SIZE; + int i; void *p; - - payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) + - APM_MODULE_PARAM_DATA_SIZE; - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -870,11 +830,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph, for (i = 0; i < num_channels; i++) media_format->channel_mapping[i] = cfg->channel_map[i]; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr, @@ -962,31 +918,24 @@ static int audioreach_set_compr_media_format(struct media_format *media_fmt_hdr, int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg) { struct media_format *header; - struct gpr_pkt *pkt; - int iid, payload_size, rc; + int rc; void *p; - - payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); - - iid = q6apm_graph_get_rx_shmem_module_iid(graph); - pkt = audioreach_alloc_cmd_pkt(payload_size, DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, - 0, graph->port->id, iid); - + int iid = q6apm_graph_get_rx_shmem_module_iid(graph); + int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, + DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT, + 0, graph->port->id, iid); if (IS_ERR(pkt)) return -ENOMEM; + p = (void *)pkt + GPR_HDR_SIZE; header = p; rc = audioreach_set_compr_media_format(header, p, mcfg); - if (rc) { - kfree(pkt); + if (rc) return rc; - } - - rc = gpr_send_port_pkt(graph->port, pkt); - kfree(pkt); - return rc; + return gpr_send_port_pkt(graph->port, pkt); } EXPORT_SYMBOL_GPL(audioreach_compr_set_param); @@ -998,18 +947,12 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, struct apm_module_param_data *param_data; struct apm_i2s_module_intf_cfg *intf_cfg; struct apm_module_hw_ep_mf_cfg *hw_cfg; - int ic_sz, ep_sz, fs_sz; - int rc, payload_size; - struct gpr_pkt *pkt; + int ic_sz = APM_I2S_INTF_CFG_PSIZE; + int ep_sz = APM_HW_EP_CFG_PSIZE; + int fs_sz = APM_FS_CFG_PSIZE; + int size = ic_sz + ep_sz + fs_sz; void *p; - - ic_sz = APM_I2S_INTF_CFG_PSIZE; - ep_sz = APM_HW_EP_CFG_PSIZE; - fs_sz = APM_FS_CFG_PSIZE; - - payload_size = ic_sz + ep_sz + fs_sz; - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1060,11 +1003,7 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, param_data->param_size = fs_sz - APM_MODULE_PARAM_DATA_SIZE; fs_cfg->frame_size_factor = 1; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } static int audioreach_logging_set_media_format(struct q6apm_graph *graph, @@ -1072,12 +1011,9 @@ static int audioreach_logging_set_media_format(struct q6apm_graph *graph, { struct apm_module_param_data *param_data; struct data_logging_config *cfg; - int rc, payload_size; - struct gpr_pkt *pkt; + int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - - payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1087,7 +1023,7 @@ static int audioreach_logging_set_media_format(struct q6apm_graph *graph, param_data->module_instance_id = module->instance_id; param_data->error_code = 0; param_data->param_id = PARAM_ID_DATA_LOGGING_CONFIG; - param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE; + param_data->param_size = size - APM_MODULE_PARAM_DATA_SIZE; p = p + APM_MODULE_PARAM_DATA_SIZE; cfg = p; @@ -1095,11 +1031,7 @@ static int audioreach_logging_set_media_format(struct q6apm_graph *graph, cfg->log_tap_point_id = module->log_tap_point_id; cfg->mode = module->log_mode; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, @@ -1110,8 +1042,8 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, uint32_t num_channels = mcfg->num_channels; struct apm_pcm_module_media_fmt_cmd *cfg; struct apm_module_param_data *param_data; - int rc, payload_size; - struct gpr_pkt *pkt; + int payload_size; + struct gpr_pkt *pkt __free(kfree) = NULL; if (num_channels > 4) { dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels); @@ -1146,11 +1078,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, media_cfg->bits_per_sample = mcfg->bit_width; memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, @@ -1162,7 +1090,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, struct payload_media_fmt_pcm *cfg; struct media_format *header; int rc, payload_size; - struct gpr_pkt *pkt; + struct gpr_pkt *pkt __free(kfree) = NULL; void *p; if (num_channels > 4) { @@ -1204,29 +1132,20 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); } else { rc = audioreach_set_compr_media_format(header, p, mcfg); - if (rc) { - kfree(pkt); + if (rc) return rc; - } } - rc = audioreach_graph_send_cmd_sync(graph, pkt, 0); - - kfree(pkt); - - return rc; + return audioreach_graph_send_cmd_sync(graph, pkt, 0); } int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct audioreach_module *module, int vol) { struct param_id_vol_ctrl_master_gain *cfg; struct apm_module_param_data *param_data; - int rc, payload_size; - struct gpr_pkt *pkt; + int size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; void *p; - - payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1236,16 +1155,12 @@ int audioreach_gain_set_vol_ctrl(struct q6apm *apm, struct audioreach_module *mo param_data->module_instance_id = module->instance_id; param_data->error_code = 0; param_data->param_id = PARAM_ID_VOL_CTRL_MASTER_GAIN; - param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE; + param_data->param_size = size - APM_MODULE_PARAM_DATA_SIZE; p = p + APM_MODULE_PARAM_DATA_SIZE; cfg = p; cfg->master_gain = vol; - rc = q6apm_send_cmd_sync(apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(apm, pkt, 0); } EXPORT_SYMBOL_GPL(audioreach_gain_set_vol_ctrl); @@ -1253,11 +1168,8 @@ static int audioreach_gain_set(struct q6apm_graph *graph, struct audioreach_modu { struct apm_module_param_data *param_data; struct apm_gain_module_cfg *cfg; - int rc, payload_size; - struct gpr_pkt *pkt; - - payload_size = APM_GAIN_CFG_PSIZE; - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + int size = APM_GAIN_CFG_PSIZE; + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1267,15 +1179,11 @@ static int audioreach_gain_set(struct q6apm_graph *graph, struct audioreach_modu param_data->module_instance_id = module->instance_id; param_data->error_code = 0; param_data->param_id = APM_PARAM_ID_GAIN; - param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE; + param_data->param_size = size - APM_MODULE_PARAM_DATA_SIZE; cfg->gain_cfg.gain = module->gain; - rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(graph->apm, pkt, 0); } int audioreach_set_media_format(struct q6apm_graph *graph, struct audioreach_module *module, @@ -1360,9 +1268,9 @@ int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, s struct apm_cmd_shared_mem_map_regions *cmd; uint32_t num_regions, buf_sz, payload_size; struct audioreach_graph_data *data; - struct gpr_pkt *pkt; + struct gpr_pkt *pkt __free(kfree) = NULL; void *p; - int rc, i; + int i; if (dir == SNDRV_PCM_STREAM_PLAYBACK) data = &graph->rx_data; @@ -1409,23 +1317,16 @@ int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, s } mutex_unlock(&graph->lock); - rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS); - - kfree(pkt); - - return rc; + return audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS); } EXPORT_SYMBOL_GPL(audioreach_map_memory_regions); int audioreach_shared_memory_send_eos(struct q6apm_graph *graph) { struct data_cmd_wr_sh_mem_ep_eos *eos; - struct gpr_pkt *pkt; - int rc = 0, iid; - - iid = q6apm_graph_get_rx_shmem_module_iid(graph); - pkt = audioreach_alloc_cmd_pkt(sizeof(*eos), DATA_CMD_WR_SH_MEM_EP_EOS, 0, - graph->port->id, iid); + int iid = q6apm_graph_get_rx_shmem_module_iid(graph); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos), + DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -1433,9 +1334,6 @@ int audioreach_shared_memory_send_eos(struct q6apm_graph *graph) eos->policy = WR_SH_MEM_EP_EOS_POLICY_LAST; - rc = gpr_send_port_pkt(graph->port, pkt); - kfree(pkt); - - return rc; + return gpr_send_port_pkt(graph->port, pkt); } EXPORT_SYMBOL_GPL(audioreach_shared_memory_send_eos); diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index 1530e98df165..0b8d06ec8b26 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -109,11 +109,75 @@ static struct q6copp *q6adm_find_copp(struct q6adm *adm, int port_idx, } +static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp, + struct apr_pkt *pkt, uint32_t rsp_opcode) +{ + struct device *dev = adm->dev; + uint32_t opcode = pkt->hdr.opcode; + int ret; + + mutex_lock(&adm->lock); + copp->result.opcode = 0; + copp->result.status = 0; + ret = apr_send_pkt(adm->apr, pkt); + if (ret < 0) { + dev_err(dev, "Failed to send APR packet\n"); + ret = -EINVAL; + goto err; + } + + /* Wait for the callback with copp id */ + if (rsp_opcode) + ret = wait_event_timeout(copp->wait, + (copp->result.opcode == opcode) || + (copp->result.opcode == rsp_opcode), + msecs_to_jiffies(TIMEOUT_MS)); + else + ret = wait_event_timeout(copp->wait, + (copp->result.opcode == opcode), + msecs_to_jiffies(TIMEOUT_MS)); + + if (!ret) { + dev_err(dev, "ADM copp cmd timedout\n"); + ret = -ETIMEDOUT; + } else if (copp->result.status > 0) { + dev_err(dev, "DSP returned error[%d]\n", + copp->result.status); + ret = -EINVAL; + } + +err: + mutex_unlock(&adm->lock); + return ret; +} + +static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp, + int port_id, int copp_idx) +{ + struct apr_pkt close; + + close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + close.hdr.pkt_size = sizeof(close); + close.hdr.src_port = port_id; + close.hdr.dest_port = copp->id; + close.hdr.token = port_id << 16 | copp_idx; + close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5; + + return q6adm_apr_send_copp_pkt(adm, copp, &close, 0); +} + static void q6adm_free_copp(struct kref *ref) { struct q6copp *c = container_of(ref, struct q6copp, refcount); struct q6adm *adm = c->adm; unsigned long flags; + int ret; + + ret = q6adm_device_close(adm, c, c->afe_port, c->copp_idx); + if (ret < 0) + dev_err(adm->dev, "Failed to close copp %d\n", ret); spin_lock_irqsave(&adm->copps_list_lock, flags); clear_bit(c->copp_idx, &adm->copp_bitmap[c->afe_port]); @@ -155,13 +219,13 @@ static int q6adm_callback(struct apr_device *adev, struct apr_resp_pkt *data) switch (result->opcode) { case ADM_CMD_DEVICE_OPEN_V5: case ADM_CMD_DEVICE_CLOSE_V5: - copp = q6adm_find_copp(adm, port_idx, copp_idx); - if (!copp) - return 0; - - copp->result = *result; - wake_up(&copp->wait); - kref_put(&copp->refcount, q6adm_free_copp); + list_for_each_entry(copp, &adm->copps_list, node) { + if ((port_idx == copp->afe_port) && (copp_idx == copp->copp_idx)) { + copp->result = *result; + wake_up(&copp->wait); + break; + } + } break; case ADM_CMD_MATRIX_MAP_ROUTINGS_V5: adm->result = *result; @@ -234,65 +298,6 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx) return c; } -static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp, - struct apr_pkt *pkt, uint32_t rsp_opcode) -{ - struct device *dev = adm->dev; - uint32_t opcode = pkt->hdr.opcode; - int ret; - - mutex_lock(&adm->lock); - copp->result.opcode = 0; - copp->result.status = 0; - ret = apr_send_pkt(adm->apr, pkt); - if (ret < 0) { - dev_err(dev, "Failed to send APR packet\n"); - ret = -EINVAL; - goto err; - } - - /* Wait for the callback with copp id */ - if (rsp_opcode) - ret = wait_event_timeout(copp->wait, - (copp->result.opcode == opcode) || - (copp->result.opcode == rsp_opcode), - msecs_to_jiffies(TIMEOUT_MS)); - else - ret = wait_event_timeout(copp->wait, - (copp->result.opcode == opcode), - msecs_to_jiffies(TIMEOUT_MS)); - - if (!ret) { - dev_err(dev, "ADM copp cmd timedout\n"); - ret = -ETIMEDOUT; - } else if (copp->result.status > 0) { - dev_err(dev, "DSP returned error[%d]\n", - copp->result.status); - ret = -EINVAL; - } - -err: - mutex_unlock(&adm->lock); - return ret; -} - -static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp, - int port_id, int copp_idx) -{ - struct apr_pkt close; - - close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, - APR_HDR_LEN(APR_HDR_SIZE), - APR_PKT_VER); - close.hdr.pkt_size = sizeof(close); - close.hdr.src_port = port_id; - close.hdr.dest_port = copp->id; - close.hdr.token = port_id << 16 | copp_idx; - close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5; - - return q6adm_apr_send_copp_pkt(adm, copp, &close, 0); -} - static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm, int port_id, int topology, int mode, int rate, @@ -325,11 +330,8 @@ static int q6adm_device_open(struct q6adm *adm, struct q6copp *copp, struct q6adm_cmd_device_open_v5 *open; int afe_port = q6afe_get_port_id(port_id); struct apr_pkt *pkt; - void *p; - int ret, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*open); - p = kzalloc(pkt_size, GFP_KERNEL); + int ret, pkt_size = APR_HDR_SIZE + sizeof(*open); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -354,14 +356,9 @@ static int q6adm_device_open(struct q6adm *adm, struct q6copp *copp, ret = q6dsp_map_channels(&open->dev_channel_mapping[0], channel_mode); if (ret) - goto err; - - ret = q6adm_apr_send_copp_pkt(adm, copp, pkt, - ADM_CMDRSP_DEVICE_OPEN_V5); + return ret; -err: - kfree(pkt); - return ret; + return q6adm_apr_send_copp_pkt(adm, copp, pkt, ADM_CMDRSP_DEVICE_OPEN_V5); } /** @@ -464,15 +461,12 @@ int q6adm_matrix_map(struct device *dev, int path, struct q6adm_session_map_node_v5 *node; struct apr_pkt *pkt; uint16_t *copps_list; - int pkt_size, ret, i, copp_idx; - void *matrix_map; - struct q6copp *copp; - + int ret, i, copp_idx; /* Assumes port_ids have already been validated during adm_open */ - pkt_size = (APR_HDR_SIZE + sizeof(*route) + sizeof(*node) + + struct q6copp *copp; + int pkt_size = (APR_HDR_SIZE + sizeof(*route) + sizeof(*node) + (sizeof(uint32_t) * payload_map.num_copps)); - - matrix_map = kzalloc(pkt_size, GFP_KERNEL); + void *matrix_map __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!matrix_map) return -ENOMEM; @@ -510,16 +504,13 @@ int q6adm_matrix_map(struct device *dev, int path, if (port_idx < 0) { dev_err(dev, "Invalid port_id %d\n", payload_map.port_id[i]); - kfree(pkt); return -EINVAL; } copp_idx = payload_map.copp_idx[i]; copp = q6adm_find_copp(adm, port_idx, copp_idx); - if (!copp) { - kfree(pkt); + if (!copp) return -EINVAL; - } copps_list[i] = copp->id; kref_put(&copp->refcount, q6adm_free_copp); @@ -552,7 +543,6 @@ int q6adm_matrix_map(struct device *dev, int path, fail_cmd: mutex_unlock(&adm->lock); - kfree(pkt); return ret; } EXPORT_SYMBOL_GPL(q6adm_matrix_map); @@ -567,15 +557,6 @@ EXPORT_SYMBOL_GPL(q6adm_matrix_map); */ int q6adm_close(struct device *dev, struct q6copp *copp) { - struct q6adm *adm = dev_get_drvdata(dev->parent); - int ret = 0; - - ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx); - if (ret < 0) { - dev_err(adm->dev, "Failed to close copp %d\n", ret); - return ret; - } - kref_put(&copp->refcount, q6adm_free_copp); return 0; diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 7b59d514b432..980851a12976 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -946,9 +946,8 @@ static struct q6afe_port *q6afe_find_port(struct q6afe *afe, int token) { struct q6afe_port *p; struct q6afe_port *ret = NULL; - unsigned long flags; - spin_lock_irqsave(&afe->port_list_lock, flags); + guard(spinlock)(&afe->port_list_lock); list_for_each_entry(p, &afe->port_list, node) if (p->token == token) { ret = p; @@ -956,7 +955,6 @@ static struct q6afe_port *q6afe_find_port(struct q6afe *afe, int token) break; } - spin_unlock_irqrestore(&afe->port_list_lock, flags); return ret; } @@ -1077,11 +1075,9 @@ static int q6afe_set_param(struct q6afe *afe, struct q6afe_port *port, struct afe_svc_cmd_set_param *param; struct afe_port_param_data_v2 *pdata; struct apr_pkt *pkt; - int ret, pkt_size; - void *p, *pl; - - pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize; - p = kzalloc(pkt_size, GFP_KERNEL); + int ret, pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize; + void *pl; + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1112,7 +1108,6 @@ static int q6afe_set_param(struct q6afe *afe, struct q6afe_port *port, if (ret) dev_err(afe->dev, "AFE set params failed %d\n", ret); - kfree(pkt); return ret; } @@ -1131,11 +1126,9 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, struct q6afe *afe = port->afe; struct apr_pkt *pkt; u16 port_id = port->id; - int ret, pkt_size; - void *p, *pl; - - pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize; - p = kzalloc(pkt_size, GFP_KERNEL); + int ret, pkt_size = APR_HDR_SIZE + sizeof(*param) + sizeof(*pdata) + psize; + void *pl; + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1168,7 +1161,6 @@ static int q6afe_port_set_param_v2(struct q6afe_port *port, void *data, dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", port_id, ret); - kfree(pkt); return ret; } @@ -1285,7 +1277,7 @@ int q6afe_port_stop(struct q6afe_port *port) int port_id = port->id; int ret = 0; int index, pkt_size; - void *p; + void *p __free(kfree) = NULL; index = port->token; if (index < 0 || index >= AFE_PORT_MAX) { @@ -1316,7 +1308,6 @@ int q6afe_port_stop(struct q6afe_port *port) if (ret) dev_err(afe->dev, "AFE close failed %d\n", ret); - kfree(pkt); return ret; } EXPORT_SYMBOL_GPL(q6afe_port_stop); @@ -1676,7 +1667,7 @@ int q6afe_port_start(struct q6afe_port *port) int ret, param_id = port->cfg_type; struct apr_pkt *pkt; int pkt_size; - void *p; + void *p __free(kfree) = NULL; ret = q6afe_port_set_param_v2(port, &port->port_cfg, param_id, AFE_MODULE_AUDIO_DEV_INTERFACE, @@ -1722,7 +1713,6 @@ int q6afe_port_start(struct q6afe_port *port) dev_err(afe->dev, "AFE enable for port 0x%x failed %d\n", port_id, ret); - kfree(pkt); return ret; } EXPORT_SYMBOL_GPL(q6afe_port_start); @@ -1741,7 +1731,6 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) int port_id; struct q6afe *afe = dev_get_drvdata(dev->parent); struct q6afe_port *port; - unsigned long flags; int cfg_type; if (id < 0 || id >= AFE_PORT_MAX) { @@ -1818,9 +1807,8 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id) port->cfg_type = cfg_type; kref_init(&port->refcount); - spin_lock_irqsave(&afe->port_list_lock, flags); + guard(spinlock)(&afe->port_list_lock); list_add_tail(&port->node, &afe->port_list); - spin_unlock_irqrestore(&afe->port_list_lock, flags); return port; @@ -1845,11 +1833,8 @@ int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, struct afe_cmd_remote_lpass_core_hw_devote_request *vote_cfg; struct apr_pkt *pkt; int ret = 0; - int pkt_size; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1871,7 +1856,6 @@ int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, if (ret < 0) dev_err(afe->dev, "AFE failed to unvote (%d)\n", hw_block_id); - kfree(pkt); return ret; } EXPORT_SYMBOL(q6afe_unvote_lpass_core_hw); @@ -1883,11 +1867,8 @@ int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, struct afe_cmd_remote_lpass_core_hw_vote_request *vote_cfg; struct apr_pkt *pkt; int ret = 0; - int pkt_size; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*vote_cfg); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1911,8 +1892,6 @@ int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, if (ret) dev_err(afe->dev, "AFE failed to vote (%d)\n", hw_block_id); - - kfree(pkt); return ret; } EXPORT_SYMBOL(q6afe_vote_lpass_core_hw); diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 4ecaff45c518..aaeeadded7aa 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -86,6 +86,7 @@ static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_BATCH), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .rates = SNDRV_PCM_RATE_8000_48000, @@ -105,6 +106,7 @@ static const struct snd_pcm_hardware q6apm_dai_hardware_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_BATCH), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE), .rates = SNDRV_PCM_RATE_8000_192000, @@ -149,33 +151,28 @@ static void event_handler_compr(uint32_t opcode, uint32_t token, { struct q6apm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; - unsigned long flags; uint32_t wflags = 0; uint64_t avail; uint32_t bytes_written, bytes_to_write; bool is_last_buffer = false; + guard(spinlock_irqsave)(&prtd->lock); switch (opcode) { case APM_CLIENT_EVENT_CMD_EOS_DONE: - spin_lock_irqsave(&prtd->lock, flags); if (prtd->notify_on_drain) { snd_compr_drain_notify(prtd->cstream); prtd->notify_on_drain = false; } else { prtd->state = Q6APM_STREAM_STOPPED; } - spin_unlock_irqrestore(&prtd->lock, flags); break; case APM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); bytes_written = token >> APM_WRITE_TOKEN_LEN_SHIFT; prtd->copied_total += bytes_written; snd_compr_fragment_elapsed(substream); - if (prtd->state != Q6APM_STREAM_RUNNING) { - spin_unlock_irqrestore(&prtd->lock, flags); + if (prtd->state != Q6APM_STREAM_RUNNING) break; - } avail = prtd->bytes_received - prtd->bytes_sent; @@ -200,7 +197,6 @@ static void event_handler_compr(uint32_t opcode, uint32_t token, audioreach_shared_memory_send_eos(prtd->graph); } - spin_unlock_irqrestore(&prtd->lock, flags); break; default: break; @@ -581,14 +577,12 @@ static int q6apm_dai_compr_pointer(struct snd_soc_component *component, { struct snd_compr_runtime *runtime = stream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; - unsigned long flags; uint64_t temp_copied_total; - spin_lock_irqsave(&prtd->lock, flags); + guard(spinlock_irqsave)(&prtd->lock); tstamp->copied_total = prtd->copied_total; temp_copied_total = tstamp->copied_total; tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); - spin_unlock_irqrestore(&prtd->lock, flags); return 0; } @@ -631,11 +625,9 @@ static int q6apm_dai_compr_ack(struct snd_soc_component *component, struct snd_c { struct snd_compr_runtime *runtime = stream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; - unsigned long flags; - spin_lock_irqsave(&prtd->lock, flags); + guard(spinlock_irqsave)(&prtd->lock); prtd->bytes_received += count; - spin_unlock_irqrestore(&prtd->lock, flags); return count; } @@ -760,7 +752,6 @@ static int q6apm_compr_copy(struct snd_soc_component *component, struct snd_compr_runtime *runtime = stream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; void *dstn; - unsigned long flags; size_t copy; u32 wflags = 0; u32 app_pointer; @@ -795,7 +786,7 @@ static int q6apm_compr_copy(struct snd_soc_component *component, return -EFAULT; } - spin_lock_irqsave(&prtd->lock, flags); + guard(spinlock_irqsave)(&prtd->lock); bytes_in_flight = prtd->bytes_received - prtd->copied_total; if (prtd->next_track) { @@ -818,8 +809,6 @@ static int q6apm_compr_copy(struct snd_soc_component *component, prtd->bytes_sent += bytes_to_write; } - spin_unlock_irqrestore(&prtd->lock, flags); - return count; } diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 0e667a7eb546..94cc6376a367 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -99,12 +99,8 @@ static int audioreach_graph_mgmt_cmd(struct audioreach_graph *graph, uint32_t op struct apm_graph_mgmt_cmd *mgmt_cmd; struct audioreach_sub_graph *sg; struct q6apm *apm = graph->apm; - int i = 0, rc, payload_size; - struct gpr_pkt *pkt; - - payload_size = APM_GRAPH_MGMT_PSIZE(mgmt_cmd, num_sub_graphs); - - pkt = audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0); + int i = 0, payload_size = APM_GRAPH_MGMT_PSIZE(mgmt_cmd, num_sub_graphs); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, opcode, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -120,11 +116,7 @@ static int audioreach_graph_mgmt_cmd(struct audioreach_graph *graph, uint32_t op list_for_each_entry(sg, &info->sg_list, node) mgmt_cmd->sub_graph_id_list[i++] = sg->sub_graph_id; - rc = q6apm_send_cmd_sync(apm, pkt, 0); - - kfree(pkt); - - return rc; + return q6apm_send_cmd_sync(apm, pkt, 0); } static void q6apm_put_audioreach_graph(struct kref *ref) @@ -148,16 +140,13 @@ static void q6apm_put_audioreach_graph(struct kref *ref) static int q6apm_get_apm_state(struct q6apm *apm) { - struct gpr_pkt *pkt; - - pkt = audioreach_alloc_apm_cmd_pkt(0, APM_CMD_GET_SPF_STATE, 0); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(0, + APM_CMD_GET_SPF_STATE, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_GET_SPF_STATE); - kfree(pkt); - return apm->state; } @@ -270,7 +259,7 @@ int q6apm_unmap_memory_regions(struct q6apm_graph *graph, unsigned int dir) { struct apm_cmd_shared_mem_unmap_regions *cmd; struct audioreach_graph_data *data; - struct gpr_pkt *pkt; + struct gpr_pkt *pkt __free(kfree) = NULL; int rc; if (dir == SNDRV_PCM_STREAM_PLAYBACK) @@ -290,7 +279,6 @@ int q6apm_unmap_memory_regions(struct q6apm_graph *graph, unsigned int dir) cmd->mem_map_handle = data->mem_map_handle; rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS); - kfree(pkt); audioreach_graph_free_buf(graph); @@ -420,13 +408,11 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, { struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2 *write_buffer; struct audio_buffer *ab; - struct gpr_pkt *pkt; - int rc, iid; - - iid = q6apm_graph_get_rx_shmem_module_iid(graph); - pkt = audioreach_alloc_pkt(sizeof(*write_buffer), DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, - graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT), - graph->port->id, iid); + int iid = q6apm_graph_get_rx_shmem_module_iid(graph); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*write_buffer), + DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2, + graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT), + graph->port->id, iid); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -450,11 +436,7 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, mutex_unlock(&graph->lock); - rc = gpr_send_port_pkt(graph->port, pkt); - - kfree(pkt); - - return rc; + return gpr_send_port_pkt(graph->port, pkt); } EXPORT_SYMBOL_GPL(q6apm_write_async); @@ -463,12 +445,10 @@ int q6apm_read(struct q6apm_graph *graph) struct data_cmd_rd_sh_mem_ep_data_buffer_v2 *read_buffer; struct audioreach_graph_data *port; struct audio_buffer *ab; - struct gpr_pkt *pkt; - int rc, iid; - - iid = q6apm_graph_get_tx_shmem_module_iid(graph); - pkt = audioreach_alloc_pkt(sizeof(*read_buffer), DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, - graph->tx_data.dsp_buf, graph->port->id, iid); + int iid = q6apm_graph_get_tx_shmem_module_iid(graph); + struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*read_buffer), + DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2, + graph->tx_data.dsp_buf, graph->port->id, iid); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -490,10 +470,7 @@ int q6apm_read(struct q6apm_graph *graph) mutex_unlock(&graph->lock); - rc = gpr_send_port_pkt(graph->port, pkt); - kfree(pkt); - - return rc; + return gpr_send_port_pkt(graph->port, pkt); } EXPORT_SYMBOL_GPL(q6apm_read); diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index b616ce316d2f..709b4f3318ff 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -58,12 +58,12 @@ struct q6asm_dai_rtd { phys_addr_t phys; unsigned int pcm_size; unsigned int pcm_count; - unsigned int pcm_irq_pos; /* IRQ position */ unsigned int periods; uint64_t bytes_sent; uint64_t bytes_received; uint64_t copied_total; uint16_t bits_per_sample; + snd_pcm_uframes_t queue_ptr; uint16_t source; /* Encoding source bit mask */ struct audio_client *audio_client; uint32_t next_track_stream_id; @@ -85,6 +85,7 @@ struct q6asm_dai_data { static const struct snd_pcm_hardware q6asm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), @@ -108,6 +109,7 @@ static const struct snd_pcm_hardware q6asm_dai_hardware_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -182,24 +184,15 @@ static void event_handler(uint32_t opcode, uint32_t token, switch (opcode) { case ASM_CLIENT_EVENT_CMD_RUN_DONE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - q6asm_write_async(prtd->audio_client, prtd->stream_id, - prtd->pcm_count, 0, 0, 0); break; case ASM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6ASM_STREAM_STOPPED; break; case ASM_CLIENT_EVENT_DATA_WRITE_DONE: { - prtd->pcm_irq_pos += prtd->pcm_count; snd_pcm_period_elapsed(substream); - if (prtd->state == Q6ASM_STREAM_RUNNING) - q6asm_write_async(prtd->audio_client, prtd->stream_id, - prtd->pcm_count, 0, 0, 0); - break; } case ASM_CLIENT_EVENT_DATA_READ_DONE: - prtd->pcm_irq_pos += prtd->pcm_count; snd_pcm_period_elapsed(substream); if (prtd->state == Q6ASM_STREAM_RUNNING) q6asm_read(prtd->audio_client, prtd->stream_id); @@ -231,15 +224,15 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } prtd->pcm_count = snd_pcm_lib_period_bytes(substream); - prtd->pcm_irq_pos = 0; /* rate and channels are sent to audio driver */ - if (prtd->state) { + if (prtd->state == Q6ASM_STREAM_RUNNING) { /* clear the previous setup if any */ q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); q6routing_stream_close(soc_prtd->dai_link->id, substream->stream); + prtd->state = Q6ASM_STREAM_STOPPED; } ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client, @@ -310,6 +303,29 @@ open_err: return ret; } +static int q6asm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + int i, ret = 0, avail_periods; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && prtd->state == Q6ASM_STREAM_RUNNING) { + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; + for (i = 0; i < avail_periods; i++) { + ret = q6asm_write_async(prtd->audio_client, prtd->stream_id, + prtd->pcm_count, 0, 0, 0); + + if (ret < 0) { + dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + return ret; + } + prtd->queue_ptr += runtime->period_size; + } + } + + return ret; +} + static int q6asm_dai_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { @@ -403,13 +419,13 @@ static int q6asm_dai_open(struct snd_soc_component *component, } ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for period bytes step ret = %d\n", ret); } ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); @@ -417,10 +433,13 @@ static int q6asm_dai_open(struct snd_soc_component *component, runtime->private_data = prtd; - snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); - - runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; - + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback); + runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max; + } else { + snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_capture); + runtime->dma_bytes = q6asm_dai_hardware_capture.buffer_bytes_max; + } if (pdata->sid < 0) prtd->phys = substream->dma_buffer.addr; @@ -459,11 +478,13 @@ static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; + snd_pcm_uframes_t ptr; - if (prtd->pcm_irq_pos >= prtd->pcm_size) - prtd->pcm_irq_pos = 0; + ptr = q6asm_get_hw_pointer(prtd->audio_client, substream->stream) * runtime->period_size; + if (ptr) + return ptr - 1; - return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); + return 0; } static int q6asm_dai_hw_params(struct snd_soc_component *component, @@ -493,15 +514,15 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, { struct q6asm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; - unsigned long flags; u32 wflags = 0; uint64_t avail; uint32_t bytes_written, bytes_to_write; bool is_last_buffer = false; + guard(spinlock_irqsave)(&prtd->lock); + switch (opcode) { case ASM_CLIENT_EVENT_CMD_RUN_DONE: - spin_lock_irqsave(&prtd->lock, flags); if (!prtd->bytes_sent) { q6asm_stream_remove_initial_silence(prtd->audio_client, prtd->stream_id, @@ -512,11 +533,9 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, prtd->bytes_sent += prtd->pcm_count; } - spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_CLIENT_EVENT_CMD_EOS_DONE: - spin_lock_irqsave(&prtd->lock, flags); if (prtd->notify_on_drain) { if (substream->partial_drain) { /* @@ -539,20 +558,16 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, } else { prtd->state = Q6ASM_STREAM_STOPPED; } - spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT; prtd->copied_total += bytes_written; snd_compr_fragment_elapsed(substream); - if (prtd->state != Q6ASM_STREAM_RUNNING) { - spin_unlock_irqrestore(&prtd->lock, flags); + if (prtd->state != Q6ASM_STREAM_RUNNING) break; - } avail = prtd->bytes_received - prtd->bytes_sent; if (avail > prtd->pcm_count) { @@ -581,7 +596,6 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, CMD_EOS); - spin_unlock_irqrestore(&prtd->lock, flags); break; default: @@ -1031,17 +1045,14 @@ static int q6asm_dai_compr_pointer(struct snd_soc_component *component, { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; - unsigned long flags; uint64_t temp_copied_total; - spin_lock_irqsave(&prtd->lock, flags); + guard(spinlock_irqsave)(&prtd->lock); tstamp->copied_total = prtd->copied_total; temp_copied_total = tstamp->copied_total; tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size); - spin_unlock_irqrestore(&prtd->lock, flags); - return 0; } @@ -1051,7 +1062,6 @@ static int q6asm_compr_copy(struct snd_soc_component *component, { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; - unsigned long flags; u32 wflags = 0; uint64_t avail, bytes_in_flight = 0; void *dstn; @@ -1087,7 +1097,7 @@ static int q6asm_compr_copy(struct snd_soc_component *component, return -EFAULT; } - spin_lock_irqsave(&prtd->lock, flags); + guard(spinlock_irqsave)(&prtd->lock); bytes_in_flight = prtd->bytes_received - prtd->copied_total; @@ -1113,8 +1123,6 @@ static int q6asm_compr_copy(struct snd_soc_component *component, prtd->bytes_sent += bytes_to_write; } - spin_unlock_irqrestore(&prtd->lock, flags); - return count; } @@ -1214,6 +1222,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .close = q6asm_dai_close, .prepare = q6asm_dai_prepare, .trigger = q6asm_dai_trigger, + .ack = q6asm_dai_ack, .pointer = q6asm_dai_pointer, .pcm_construct = q6asm_dai_pcm_new, .compress_ops = &q6asm_dai_compress_ops, diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 67e9ca18883c..e7295b7b2461 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -6,6 +6,7 @@ #include <linux/mutex.h> #include <linux/wait.h> #include <linux/module.h> +#include <linux/atomic.h> #include <linux/soc/qcom/apr.h> #include <linux/device.h> #include <linux/of_platform.h> @@ -248,6 +249,7 @@ struct audio_port_data { uint32_t num_periods; uint32_t dsp_buf; uint32_t mem_map_handle; + atomic_t hw_ptr; }; struct q6asm { @@ -333,7 +335,7 @@ static int __q6asm_memory_unmap(struct audio_client *ac, struct q6asm *a = dev_get_drvdata(ac->dev->parent); struct apr_pkt *pkt; int rc, pkt_size; - void *p; + void *p __free(kfree) = NULL; if (ac->port[dir].mem_map_handle == 0) { dev_err(ac->dev, "invalid mem handle\n"); @@ -358,14 +360,11 @@ static int __q6asm_memory_unmap(struct audio_client *ac, mem_unmap->mem_map_handle = ac->port[dir].mem_map_handle; rc = q6asm_apr_send_session_pkt(a, ac, pkt, 0); - if (rc < 0) { - kfree(pkt); + if (rc < 0) return rc; - } ac->port[dir].mem_map_handle = 0; - kfree(pkt); return 0; } @@ -429,10 +428,10 @@ static int __q6asm_memory_map_regions(struct audio_client *ac, int dir, struct audio_port_data *port = NULL; struct audio_buffer *ab = NULL; struct apr_pkt *pkt; - void *p; + void *p __free(kfree) = NULL; unsigned long flags; uint32_t num_regions, buf_sz; - int rc, i, pkt_size; + int i, pkt_size; if (is_contiguous) { num_regions = 1; @@ -479,12 +478,7 @@ static int __q6asm_memory_map_regions(struct audio_client *ac, int dir, } spin_unlock_irqrestore(&ac->lock, flags); - rc = q6asm_apr_send_session_pkt(a, ac, pkt, - ASM_CMDRSP_SHARED_MEM_MAP_REGIONS); - - kfree(pkt); - - return rc; + return q6asm_apr_send_session_pkt(a, ac, pkt, ASM_CMDRSP_SHARED_MEM_MAP_REGIONS); } /** @@ -577,9 +571,8 @@ static struct audio_client *q6asm_get_audio_client(struct q6asm *a, int session_id) { struct audio_client *ac = NULL; - unsigned long flags; - spin_lock_irqsave(&a->slock, flags); + guard(spinlock_irqsave)(&a->slock); if ((session_id <= 0) || (session_id > MAX_SESSIONS)) { dev_err(a->dev, "invalid session: %d\n", session_id); goto err; @@ -594,10 +587,17 @@ static struct audio_client *q6asm_get_audio_client(struct q6asm *a, ac = a->session[session_id]; kref_get(&ac->refcount); err: - spin_unlock_irqrestore(&a->slock, flags); return ac; } +int q6asm_get_hw_pointer(struct audio_client *ac, unsigned int dir) +{ + struct audio_port_data *data = &ac->port[dir]; + + return (int)atomic_read(&data->hw_ptr); +} +EXPORT_SYMBOL_GPL(q6asm_get_hw_pointer); + static int32_t q6asm_stream_callback(struct apr_device *adev, struct apr_resp_pkt *data, int session_id) @@ -638,6 +638,7 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, client_event = ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE; break; case ASM_STREAM_CMD_OPEN_WRITE_V3: + case ASM_DATA_CMD_WRITE_V2: case ASM_STREAM_CMD_OPEN_READ_V3: case ASM_STREAM_CMD_OPEN_READWRITE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: @@ -654,6 +655,10 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, goto done; } break; + case ASM_DATA_CMD_EOS: + case ASM_DATA_CMD_READ_V2: + /* response as result of close stream */ + break; default: dev_err(ac->dev, "command[0x%x] not expecting rsp\n", result->opcode); @@ -674,15 +679,13 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, client_event = ASM_CLIENT_EVENT_DATA_WRITE_DONE; if (ac->io_mode & ASM_SYNC_IO_MODE) { phys_addr_t phys; - unsigned long flags; int token = hdr->token & ASM_WRITE_TOKEN_MASK; - spin_lock_irqsave(&ac->lock, flags); + guard(spinlock_irqsave)(&ac->lock); port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; if (!port->buf) { - spin_unlock_irqrestore(&ac->lock, flags); ret = 0; goto done; } @@ -693,29 +696,27 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, upper_32_bits(phys) != result->status) { dev_err(ac->dev, "Expected addr %pa\n", &port->buf[token].phys); - spin_unlock_irqrestore(&ac->lock, flags); ret = -EINVAL; goto done; } - spin_unlock_irqrestore(&ac->lock, flags); + atomic_set(&port->hw_ptr, token + 1); } break; case ASM_DATA_EVENT_READ_DONE_V2: client_event = ASM_CLIENT_EVENT_DATA_READ_DONE; if (ac->io_mode & ASM_SYNC_IO_MODE) { struct asm_data_cmd_read_v2_done *done = data->payload; - unsigned long flags; phys_addr_t phys; - spin_lock_irqsave(&ac->lock, flags); + guard(spinlock_irqsave)(&ac->lock); port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; if (!port->buf) { - spin_unlock_irqrestore(&ac->lock, flags); ret = 0; goto done; } phys = port->buf[hdr->token].phys; + atomic_set(&port->hw_ptr, hdr->token + 1); if (upper_32_bits(phys) != done->buf_addr_msw || lower_32_bits(phys) != done->buf_addr_lsw) { @@ -723,11 +724,9 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, &port->buf[hdr->token].phys, done->buf_addr_lsw, done->buf_addr_msw); - spin_unlock_irqrestore(&ac->lock, flags); ret = -EINVAL; goto done; } - spin_unlock_irqrestore(&ac->lock, flags); } break; @@ -930,12 +929,8 @@ int q6asm_open_write(struct audio_client *ac, uint32_t stream_id, { struct asm_stream_cmd_open_write_v3 *open; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*open); - - p = kzalloc(pkt_size, GFP_KERNEL); + int rc, pkt_size = APR_HDR_SIZE + sizeof(*open); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1001,7 +996,6 @@ int q6asm_open_write(struct audio_client *ac, uint32_t stream_id, ac->io_mode |= ASM_TUN_WRITE_IO_MODE; err: - kfree(pkt); return rc; } EXPORT_SYMBOL_GPL(q6asm_open_write); @@ -1012,11 +1006,8 @@ static int __q6asm_run(struct audio_client *ac, uint32_t stream_id, { struct asm_session_cmd_run_v2 *run; struct apr_pkt *pkt; - int pkt_size, rc; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*run); - p = kzalloc(pkt_size, GFP_ATOMIC); + int rc, pkt_size = APR_HDR_SIZE + sizeof(*run); + void *p __free(kfree) = kzalloc(pkt_size, GFP_ATOMIC); if (!p) return -ENOMEM; @@ -1037,7 +1028,6 @@ static int __q6asm_run(struct audio_client *ac, uint32_t stream_id, rc = 0; } - kfree(pkt); return rc; } @@ -1098,11 +1088,8 @@ int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, struct asm_multi_channel_pcm_fmt_blk_v2 *fmt; struct apr_pkt *pkt; u8 *channel_mapping; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1125,16 +1112,11 @@ int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, } else { if (q6dsp_map_channels(channel_mapping, channels)) { dev_err(ac->dev, " map channels failed %d\n", channels); - rc = -EINVAL; - goto err; + return -EINVAL; } } - rc = q6asm_ac_send_cmd_sync(ac, pkt); - -err: - kfree(pkt); - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm); @@ -1144,11 +1126,8 @@ int q6asm_stream_media_format_block_flac(struct audio_client *ac, { struct asm_flac_fmt_blk_v2 *fmt; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1168,10 +1147,7 @@ int q6asm_stream_media_format_block_flac(struct audio_client *ac, fmt->max_frame_size = cfg->max_frame_size; fmt->sample_size = cfg->sample_size; - rc = q6asm_ac_send_cmd_sync(ac, pkt); - kfree(pkt); - - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_flac); @@ -1181,11 +1157,8 @@ int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, { struct asm_wmastdv9_fmt_blk_v2 *fmt; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1206,10 +1179,7 @@ int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, fmt->enc_options = cfg->enc_options; fmt->reserved = 0; - rc = q6asm_ac_send_cmd_sync(ac, pkt); - kfree(pkt); - - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v9); @@ -1219,11 +1189,8 @@ int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, { struct asm_wmaprov10_fmt_blk_v2 *fmt; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1245,10 +1212,7 @@ int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, fmt->advanced_enc_options1 = cfg->adv_enc_options; fmt->advanced_enc_options2 = cfg->adv_enc_options2; - rc = q6asm_ac_send_cmd_sync(ac, pkt); - kfree(pkt); - - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v10); @@ -1258,11 +1222,8 @@ int q6asm_stream_media_format_block_alac(struct audio_client *ac, { struct asm_alac_fmt_blk_v2 *fmt; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1287,10 +1248,7 @@ int q6asm_stream_media_format_block_alac(struct audio_client *ac, fmt->mb = cfg->mb; fmt->kb = cfg->kb; - rc = q6asm_ac_send_cmd_sync(ac, pkt); - kfree(pkt); - - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_alac); @@ -1300,11 +1258,8 @@ int q6asm_stream_media_format_block_ape(struct audio_client *ac, { struct asm_ape_fmt_blk_v2 *fmt; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(*fmt); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*fmt); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1327,10 +1282,7 @@ int q6asm_stream_media_format_block_ape(struct audio_client *ac, fmt->sample_rate = cfg->sample_rate; fmt->seek_table_present = cfg->seek_table_present; - rc = q6asm_ac_send_cmd_sync(ac, pkt); - kfree(pkt); - - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape); @@ -1340,11 +1292,8 @@ static int q6asm_stream_remove_silence(struct audio_client *ac, uint32_t stream_ { uint32_t *samples; struct apr_pkt *pkt; - void *p; - int rc, pkt_size; - - pkt_size = APR_HDR_SIZE + sizeof(uint32_t); - p = kzalloc(pkt_size, GFP_ATOMIC); + int rc, pkt_size = APR_HDR_SIZE + sizeof(uint32_t); + void *p __free(kfree) = kzalloc(pkt_size, GFP_ATOMIC); if (!p) return -ENOMEM; @@ -1359,8 +1308,6 @@ static int q6asm_stream_remove_silence(struct audio_client *ac, uint32_t stream_ if (rc == pkt_size) rc = 0; - kfree(pkt); - return rc; } @@ -1403,11 +1350,8 @@ int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, struct apr_pkt *pkt; u8 *channel_mapping; u32 frames_per_buf = 0; - int pkt_size, rc; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*enc_cfg); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*enc_cfg); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1428,15 +1372,10 @@ int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, enc_cfg->is_signed = 1; channel_mapping = enc_cfg->channel_mapping; - if (q6dsp_map_channels(channel_mapping, channels)) { - rc = -EINVAL; - goto err; - } + if (q6dsp_map_channels(channel_mapping, channels)) + return -EINVAL; - rc = q6asm_ac_send_cmd_sync(ac, pkt); -err: - kfree(pkt); - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support); @@ -1456,12 +1395,9 @@ int q6asm_read(struct audio_client *ac, uint32_t stream_id) struct audio_buffer *ab; struct apr_pkt *pkt; unsigned long flags; - int pkt_size; + int pkt_size = APR_HDR_SIZE + sizeof(*read); int rc = 0; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*read); - p = kzalloc(pkt_size, GFP_ATOMIC); + void *p __free(kfree) = kzalloc(pkt_size, GFP_ATOMIC); if (!p) return -ENOMEM; @@ -1493,7 +1429,6 @@ int q6asm_read(struct audio_client *ac, uint32_t stream_id) else pr_err("read op[0x%x]rc[%d]\n", pkt->hdr.opcode, rc); - kfree(pkt); return rc; } EXPORT_SYMBOL_GPL(q6asm_read); @@ -1503,11 +1438,8 @@ static int __q6asm_open_read(struct audio_client *ac, uint32_t stream_id, { struct asm_stream_cmd_open_read_v3 *open; struct apr_pkt *pkt; - int pkt_size, rc; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*open); - p = kzalloc(pkt_size, GFP_KERNEL); + int pkt_size = APR_HDR_SIZE + sizeof(*open); + void *p __free(kfree) = kzalloc(pkt_size, GFP_KERNEL); if (!p) return -ENOMEM; @@ -1535,10 +1467,7 @@ static int __q6asm_open_read(struct audio_client *ac, uint32_t stream_id, pr_err("Invalid format[%d]\n", format); } - rc = q6asm_ac_send_cmd_sync(ac, pkt); - - kfree(pkt); - return rc; + return q6asm_ac_send_cmd_sync(ac, pkt); } /** @@ -1578,12 +1507,9 @@ int q6asm_write_async(struct audio_client *ac, uint32_t stream_id, uint32_t len, struct audio_buffer *ab; unsigned long flags; struct apr_pkt *pkt; - int pkt_size; + int pkt_size = APR_HDR_SIZE + sizeof(*write); int rc = 0; - void *p; - - pkt_size = APR_HDR_SIZE + sizeof(*write); - p = kzalloc(pkt_size, GFP_ATOMIC); + void *p __free(kfree) = kzalloc(pkt_size, GFP_ATOMIC); if (!p) return -ENOMEM; @@ -1618,7 +1544,6 @@ int q6asm_write_async(struct audio_client *ac, uint32_t stream_id, uint32_t len, if (rc == pkt_size) rc = 0; - kfree(pkt); return rc; } EXPORT_SYMBOL_GPL(q6asm_write_async); @@ -1626,14 +1551,12 @@ EXPORT_SYMBOL_GPL(q6asm_write_async); static void q6asm_reset_buf_state(struct audio_client *ac) { struct audio_port_data *port; - unsigned long flags; - spin_lock_irqsave(&ac->lock, flags); + guard(spinlock_irqsave)(&ac->lock); port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; port->dsp_buf = 0; port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; port->dsp_buf = 0; - spin_unlock_irqrestore(&ac->lock, flags); } static int __q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd, diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index 519e1b3a3f7c..6fafda5bd849 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -148,4 +148,5 @@ int q6asm_map_memory_regions(unsigned int dir, phys_addr_t phys, size_t period_sz, unsigned int periods); int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac); +int q6asm_get_hw_pointer(struct audio_client *ac, unsigned int dir); #endif /* __Q6_ASM_H__ */ diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c index 81554d202658..0b8fad0bc832 100644 --- a/sound/soc/qcom/qdsp6/q6prm.c +++ b/sound/soc/qcom/qdsp6/q6prm.c @@ -62,8 +62,7 @@ static int q6prm_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool struct prm_cmd_request_hw_core *req; gpr_device_t *gdev = prm->gdev; uint32_t opcode, rsp_opcode; - struct gpr_pkt *pkt; - int rc; + struct gpr_pkt *pkt __free(kfree) = NULL; if (enable) { opcode = PRM_CMD_REQUEST_HW_RSC; @@ -88,11 +87,7 @@ static int q6prm_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool req->hw_clk_id = hw_block_id; - rc = q6prm_send_cmd_sync(prm, pkt, rsp_opcode); - - kfree(pkt); - - return rc; + return q6prm_send_cmd_sync(prm, pkt, rsp_opcode); } int q6prm_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, @@ -116,8 +111,7 @@ static int q6prm_request_lpass_clock(struct device *dev, int clk_id, int clk_att struct apm_module_param_data *param_data; struct prm_cmd_request_rsc *req; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt; - int rc; + struct gpr_pkt *pkt __free(kfree) = NULL; pkt = audioreach_alloc_cmd_pkt(sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, GPR_PRM_MODULE_IID); @@ -139,11 +133,7 @@ static int q6prm_request_lpass_clock(struct device *dev, int clk_id, int clk_att req->clock_id.clock_attri = clk_attr; req->clock_id.clock_root = clk_root; - rc = q6prm_send_cmd_sync(prm, pkt, PRM_CMD_RSP_REQUEST_HW_RSC); - - kfree(pkt); - - return rc; + return q6prm_send_cmd_sync(prm, pkt, PRM_CMD_RSP_REQUEST_HW_RSC); } static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root, @@ -153,8 +143,7 @@ static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_att struct apm_module_param_data *param_data; struct prm_cmd_release_rsc *rel; gpr_device_t *gdev = prm->gdev; - struct gpr_pkt *pkt; - int rc; + struct gpr_pkt *pkt __free(kfree) = NULL; pkt = audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, GPR_PRM_MODULE_IID); @@ -173,11 +162,7 @@ static int q6prm_release_lpass_clock(struct device *dev, int clk_id, int clk_att rel->num_clk_id = 1; rel->clock_id.clock_id = clk_id; - rc = q6prm_send_cmd_sync(prm, pkt, PRM_CMD_RSP_RELEASE_HW_RSC); - - kfree(pkt); - - return rc; + return q6prm_send_cmd_sync(prm, pkt, PRM_CMD_RSP_RELEASE_HW_RSC); } int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_root, diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index f49243daa517..aaa3af9f1993 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -468,8 +468,7 @@ EXPORT_SYMBOL_GPL(q6routing_stream_close); static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_context *dapm = - snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int session_id = mc->shift; @@ -488,8 +487,7 @@ static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol, static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_context *dapm = - snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); struct msm_routing_data *data = dev_get_drvdata(c->dev); struct soc_mixer_control *mc = diff --git a/sound/soc/qcom/qdsp6/q6usb.c b/sound/soc/qcom/qdsp6/q6usb.c index ebe0c2425927..6381b289c55c 100644 --- a/sound/soc/qcom/qdsp6/q6usb.c +++ b/sound/soc/qcom/qdsp6/q6usb.c @@ -138,10 +138,11 @@ static int q6usb_audio_ports_of_xlate_dai_name(struct snd_soc_component *compone static int q6usb_get_pcm_id_from_widget(struct snd_soc_dapm_widget *w) { + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *dai; - for_each_card_rtds(w->dapm->card, rtd) { + for_each_card_rtds(card, rtd) { dai = snd_soc_rtd_to_cpu(rtd, 0); /* * Only look for playback widget. RTD number carries the assigned diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index f61285e7dcf2..5ce6edf3305e 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -1143,8 +1143,8 @@ static int audioreach_get_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); + struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); struct snd_ar_control *dapm_scontrol = dw->dobj.private; struct snd_ar_control *scontrol = mc->dobj.private; @@ -1164,8 +1164,8 @@ static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); + struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct snd_soc_component *c = snd_soc_dapm_to_component(dapm); struct snd_ar_control *dapm_scontrol = dw->dobj.private; struct snd_ar_control *scontrol = mc->dobj.private; @@ -1184,7 +1184,7 @@ static int audioreach_put_audio_mixer(struct snd_kcontrol *kcontrol, static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct audioreach_module *mod = dw->dobj.private; ucontrol->value.integer.value[0] = mod->gain; @@ -1195,7 +1195,7 @@ static int audioreach_get_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, static int audioreach_put_vol_ctrl_audio_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_widget *dw = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct audioreach_module *mod = dw->dobj.private; mod->gain = ucontrol->value.integer.value[0]; diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c index 84b6ac5d2a20..bc5a18883479 100644 --- a/sound/soc/qcom/sc7180.c +++ b/sound/soc/qcom/sc7180.c @@ -287,8 +287,9 @@ static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream) static int dmic_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct sc7180_snd_data *data = snd_soc_card_get_drvdata(dapm->card); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); + struct snd_soc_card *card = snd_soc_dapm_to_card(dapm); + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); ucontrol->value.integer.value[0] = data->dmic_switch; return 0; @@ -297,8 +298,9 @@ static int dmic_get(struct snd_kcontrol *kcontrol, static int dmic_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct sc7180_snd_data *data = snd_soc_card_get_drvdata(dapm->card); + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); + struct snd_soc_card *card = snd_soc_dapm_to_card(dapm); + struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); data->dmic_switch = ucontrol->value.integer.value[0]; gpiod_set_value(data->dmic_sel, data->dmic_switch); diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c index af412bd0c89f..abdd58c1d0a4 100644 --- a/sound/soc/qcom/sc7280.c +++ b/sound/soc/qcom/sc7280.c @@ -31,7 +31,6 @@ struct sc7280_snd_data { struct snd_soc_card card; - struct sdw_stream_runtime *sruntime[LPASS_MAX_PORTS]; u32 pri_mi2s_clk_count; struct snd_soc_jack hs_jack; struct snd_soc_jack hdmi_jack; @@ -207,32 +206,12 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime; - int i; if (!rtd->dai_link->no_pcm) { snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000); } - switch (cpu_dai->id) { - case LPASS_CDC_DMA_TX3: - case LPASS_CDC_DMA_RX0: - case RX_CODEC_DMA_RX_0: - case SECONDARY_MI2S_RX: - case TX_CODEC_DMA_TX_3: - case VA_CODEC_DMA_TX_0: - for_each_rtd_codec_dais(rtd, i, codec_dai) { - sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); - if (sruntime != ERR_PTR(-ENOTSUPP)) - pdata->sruntime[cpu_dai->id] = sruntime; - } - break; - } - return 0; } @@ -241,30 +220,8 @@ static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - int ret; - if (!sruntime) - return 0; - - if (data->stream_prepared[cpu_dai->id]) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - data->stream_prepared[cpu_dai->id] = false; - } - - ret = sdw_prepare_stream(sruntime); - if (ret) - return ret; - - ret = sdw_enable_stream(sruntime); - if (ret) { - sdw_deprepare_stream(sruntime); - return ret; - } - data->stream_prepared[cpu_dai->id] = true; - - return ret; + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int sc7280_snd_prepare(struct snd_pcm_substream *substream) @@ -291,24 +248,8 @@ static int sc7280_snd_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - switch (cpu_dai->id) { - case LPASS_CDC_DMA_RX0: - case LPASS_CDC_DMA_TX3: - case RX_CODEC_DMA_RX_0: - case TX_CODEC_DMA_TX_3: - case VA_CODEC_DMA_TX_0: - if (sruntime && data->stream_prepared[cpu_dai->id]) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - data->stream_prepared[cpu_dai->id] = false; - } - break; - default: - break; - } - return 0; + return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); } static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) @@ -317,7 +258,6 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; switch (cpu_dai->id) { case MI2S_PRIMARY: @@ -336,8 +276,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) break; } - data->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); + qcom_snd_sdw_shutdown(substream); } static int sc7280_snd_startup(struct snd_pcm_substream *substream) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 187f37ffe328..7925aa3f63ba 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -18,7 +18,6 @@ struct sc8280xp_snd_data { bool stream_prepared[AFE_PORT_MAX]; struct snd_soc_card *card; - struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; bool jack_setup; @@ -68,17 +67,6 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } -static void sc8280xp_snd_shutdown(struct snd_pcm_substream *substream) -{ - 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 sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = pdata->sruntime[cpu_dai->id]; - - pdata->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); -} - static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -108,25 +96,13 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int sc8280xp_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 sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); - - return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); -} - static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) { 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 sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - return qcom_snd_sdw_prepare(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) @@ -134,16 +110,13 @@ static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - return qcom_snd_sdw_hw_free(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); } static const struct snd_soc_ops sc8280xp_be_ops = { .startup = qcom_snd_sdw_startup, - .shutdown = sc8280xp_snd_shutdown, - .hw_params = sc8280xp_snd_hw_params, + .shutdown = qcom_snd_sdw_shutdown, .hw_free = sc8280xp_snd_hw_free, .prepare = sc8280xp_snd_prepare, }; @@ -191,6 +164,7 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) } static const struct of_device_id snd_sc8280xp_dt_match[] = { + {.compatible = "qcom,kaanapali-sndcard", "kaanapali"}, {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, {.compatible = "qcom,qcs615-sndcard", "qcs615"}, {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index a233b80049ee..e18a8e44f2db 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -40,7 +40,6 @@ struct sdm845_snd_data { uint32_t pri_mi2s_clk_count; uint32_t sec_mi2s_clk_count; uint32_t quat_tdm_clk_count; - struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; }; static struct snd_soc_jack_pin sdm845_jack_pins[] = { @@ -62,18 +61,11 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream, 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 snd_soc_dai *codec_dai; - struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS]; - struct sdw_stream_runtime *sruntime; u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret = 0, i; for_each_rtd_codec_dais(rtd, i, codec_dai) { - sruntime = snd_soc_dai_get_stream(codec_dai, - substream->stream); - if (sruntime != ERR_PTR(-ENOTSUPP)) - pdata->sruntime[cpu_dai->id] = sruntime; - ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch); @@ -430,7 +422,6 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; switch (cpu_dai->id) { case PRIMARY_MI2S_RX: @@ -471,8 +462,7 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) break; } - data->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); + qcom_snd_sdw_shutdown(substream); } static int sdm845_snd_prepare(struct snd_pcm_substream *substream) @@ -480,38 +470,8 @@ static int sdm845_snd_prepare(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - int ret; - - if (!sruntime) - return 0; - - if (data->stream_prepared[cpu_dai->id]) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - data->stream_prepared[cpu_dai->id] = false; - } - ret = sdw_prepare_stream(sruntime); - if (ret) - return ret; - - /** - * NOTE: there is a strict hw requirement about the ordering of port - * enables and actual WSA881x PA enable. PA enable should only happen - * after soundwire ports are enabled if not DC on the line is - * accumulated resulting in Click/Pop Noise - * PA enable/mute are handled as part of codec DAPM and digital mute. - */ - - ret = sdw_enable_stream(sruntime); - if (ret) { - sdw_deprepare_stream(sruntime); - return ret; - } - data->stream_prepared[cpu_dai->id] = true; - - return ret; + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int sdm845_snd_hw_free(struct snd_pcm_substream *substream) @@ -519,15 +479,8 @@ static int sdm845_snd_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - - if (sruntime && data->stream_prepared[cpu_dai->id]) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - data->stream_prepared[cpu_dai->id] = false; - } - return 0; + return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); } static const struct snd_soc_ops sdm845_be_ops = { diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 7d7981d4295b..6576b47a4c8c 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -2,11 +2,53 @@ // Copyright (c) 2018-2023, Linaro Limited. // Copyright (c) 2018, The Linux Foundation. All rights reserved. +#include <dt-bindings/sound/qcom,lpass.h> #include <dt-bindings/sound/qcom,q6afe.h> #include <linux/module.h> #include <sound/soc.h> #include "sdw.h" +static bool qcom_snd_is_sdw_dai(int id) +{ + switch (id) { + case WSA_CODEC_DMA_RX_0: + case WSA_CODEC_DMA_TX_0: + case WSA_CODEC_DMA_RX_1: + case WSA_CODEC_DMA_TX_1: + case WSA_CODEC_DMA_TX_2: + case RX_CODEC_DMA_RX_0: + case TX_CODEC_DMA_TX_0: + case RX_CODEC_DMA_RX_1: + case TX_CODEC_DMA_TX_1: + case RX_CODEC_DMA_RX_2: + case TX_CODEC_DMA_TX_2: + case RX_CODEC_DMA_RX_3: + case TX_CODEC_DMA_TX_3: + case RX_CODEC_DMA_RX_4: + case TX_CODEC_DMA_TX_4: + case RX_CODEC_DMA_RX_5: + case TX_CODEC_DMA_TX_5: + case RX_CODEC_DMA_RX_6: + case RX_CODEC_DMA_RX_7: + case SLIMBUS_0_RX...SLIMBUS_6_TX: + return true; + default: + break; + } + + /* DSP Bypass usecase, cpu dai index overlaps with DSP dai ids, + * DO NOT MERGE into top switch case */ + switch (id) { + case LPASS_CDC_DMA_TX3: + case LPASS_CDC_DMA_RX0: + return true; + default: + break; + } + + return false; +} + /** * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup() @@ -29,6 +71,9 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream) u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret, i, j; + if (!qcom_snd_is_sdw_dai(cpu_dai->id)) + return 0; + sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM); if (!sruntime) return -ENOMEM; @@ -79,29 +124,20 @@ err_set_stream: EXPORT_SYMBOL_GPL(qcom_snd_sdw_startup); int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, - struct sdw_stream_runtime *sruntime, bool *stream_prepared) { 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 sdw_stream_runtime *sruntime; int ret; - if (!sruntime) + + if (!qcom_snd_is_sdw_dai(cpu_dai->id)) return 0; - switch (cpu_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: - break; - default: + sruntime = qcom_snd_sdw_get_stream(substream); + if (!sruntime) return 0; - } if (*stream_prepared) return 0; @@ -129,9 +165,7 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, } EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); -int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct sdw_stream_runtime **psruntime) +struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; @@ -139,50 +173,40 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, struct sdw_stream_runtime *sruntime; int i; - switch (cpu_dai->id) { - case WSA_CODEC_DMA_RX_0: - 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: - for_each_rtd_codec_dais(rtd, i, codec_dai) { - sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); - if (sruntime != ERR_PTR(-ENOTSUPP)) - *psruntime = sruntime; - } - break; + if (!qcom_snd_is_sdw_dai(cpu_dai->id)) + return NULL; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); + if (sruntime != ERR_PTR(-ENOTSUPP)) + return sruntime; } + return NULL; +} +EXPORT_SYMBOL_GPL(qcom_snd_sdw_get_stream); - return 0; +void qcom_snd_sdw_shutdown(struct snd_pcm_substream *substream) +{ + struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream); + sdw_release_stream(sruntime); } -EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); +EXPORT_SYMBOL_GPL(qcom_snd_sdw_shutdown); -int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, - struct sdw_stream_runtime *sruntime, bool *stream_prepared) +int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, bool *stream_prepared) { 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 sdw_stream_runtime *sruntime; - switch (cpu_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: - if (sruntime && *stream_prepared) { - sdw_disable_stream(sruntime); - sdw_deprepare_stream(sruntime); - *stream_prepared = false; - } - break; - default: - break; + if (!qcom_snd_is_sdw_dai(cpu_dai->id)) + return 0; + + sruntime = qcom_snd_sdw_get_stream(substream); + if (sruntime && *stream_prepared) { + sdw_disable_stream(sruntime); + sdw_deprepare_stream(sruntime); + *stream_prepared = false; } return 0; diff --git a/sound/soc/qcom/sdw.h b/sound/soc/qcom/sdw.h index 392e3455f1b1..061a63f1ac52 100644 --- a/sound/soc/qcom/sdw.h +++ b/sound/soc/qcom/sdw.h @@ -7,13 +7,10 @@ #include <linux/soundwire/sdw.h> int qcom_snd_sdw_startup(struct snd_pcm_substream *substream); +void qcom_snd_sdw_shutdown(struct snd_pcm_substream *substream); int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, - struct sdw_stream_runtime *runtime, bool *stream_prepared); -int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct sdw_stream_runtime **psruntime); +struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *stream); int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, - struct sdw_stream_runtime *sruntime, bool *stream_prepared); #endif diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index f5b75a06e5bd..05a8b04e50e0 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -21,7 +21,6 @@ struct sm8250_snd_data { bool stream_prepared[AFE_PORT_MAX]; struct snd_soc_card *card; - struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; struct snd_soc_jack jack; struct snd_soc_jack usb_offload_jack; bool usb_offload_jack_setup; @@ -112,36 +111,13 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) return qcom_snd_sdw_startup(substream); } -static void sm8250_snd_shutdown(struct snd_pcm_substream *substream) -{ - 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 sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - - data->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); -} - -static int sm8250_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 sm8250_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); - - return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]); -} - static int sm8250_snd_prepare(struct snd_pcm_substream *substream) { 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 sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - return qcom_snd_sdw_prepare(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) @@ -149,16 +125,13 @@ static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - return qcom_snd_sdw_hw_free(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); } static const struct snd_soc_ops sm8250_be_ops = { .startup = sm8250_snd_startup, - .shutdown = sm8250_snd_shutdown, - .hw_params = sm8250_snd_hw_params, + .shutdown = qcom_snd_sdw_shutdown, .hw_free = sm8250_snd_hw_free, .prepare = sm8250_snd_prepare, }; @@ -210,6 +183,7 @@ static int sm8250_platform_probe(struct platform_device *pdev) static const struct of_device_id snd_sm8250_dt_match[] = { { .compatible = "fairphone,fp4-sndcard", .data = "sm7225" }, { .compatible = "fairphone,fp5-sndcard", .data = "qcm6490" }, + { .compatible = "qcom,qrb2210-sndcard", .data = "qcm2290" }, { .compatible = "qcom,qrb4210-rb2-sndcard", .data = "sm4250" }, { .compatible = "qcom,qrb5165-rb5-sndcard", .data = "sm8250" }, { .compatible = "qcom,sm8250-sndcard", .data = "sm8250" }, diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c index 444f2162889f..a3f4785c4bbe 100644 --- a/sound/soc/qcom/x1e80100.c +++ b/sound/soc/qcom/x1e80100.c @@ -18,7 +18,6 @@ struct x1e80100_snd_data { bool stream_prepared[AFE_PORT_MAX]; struct snd_soc_card *card; - struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; struct snd_soc_jack jack; struct snd_soc_jack dp_jack[8]; bool jack_setup; @@ -50,17 +49,6 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd) return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); } -static void x1e80100_snd_shutdown(struct snd_pcm_substream *substream) -{ - 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 x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - - data->sruntime[cpu_dai->id] = NULL; - sdw_release_stream(sruntime); -} - static int x1e80100_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -85,16 +73,6 @@ static int x1e80100_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int x1e80100_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 x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - - return qcom_snd_sdw_hw_params(substream, params, &data->sruntime[cpu_dai->id]); -} - static int x1e80100_snd_hw_map_channels(unsigned int *ch_map, int num) { switch (num) { @@ -128,7 +106,6 @@ static int x1e80100_snd_prepare(struct snd_pcm_substream *substream) 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 x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; unsigned int channels = substream->runtime->channels; unsigned int rx_slot[4]; int ret; @@ -149,8 +126,7 @@ static int x1e80100_snd_prepare(struct snd_pcm_substream *substream) break; } - return qcom_snd_sdw_prepare(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]); } static int x1e80100_snd_hw_free(struct snd_pcm_substream *substream) @@ -158,16 +134,13 @@ static int x1e80100_snd_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; - return qcom_snd_sdw_hw_free(substream, sruntime, - &data->stream_prepared[cpu_dai->id]); + return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]); } static const struct snd_soc_ops x1e80100_be_ops = { .startup = qcom_snd_sdw_startup, - .shutdown = x1e80100_snd_shutdown, - .hw_params = x1e80100_snd_hw_params, + .shutdown = qcom_snd_sdw_shutdown, .hw_free = x1e80100_snd_hw_free, .prepare = x1e80100_snd_prepare, }; |
