1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2022 Intel Corporation. All rights reserved. 7 // 8 9 #include <sound/pcm_params.h> 10 #include <sound/sof/ipc4/header.h> 11 #include "sof-audio.h" 12 #include "sof-priv.h" 13 #include "ipc4-priv.h" 14 #include "ipc4-topology.h" 15 16 static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state, 17 struct ipc4_pipeline_set_state_data *trigger_list) 18 { 19 struct sof_ipc4_msg msg = {{ 0 }}; 20 u32 primary, ipc_size; 21 22 /* trigger a single pipeline */ 23 if (trigger_list->count == 1) 24 return sof_ipc4_set_pipeline_state(sdev, trigger_list->pipeline_ids[0], state); 25 26 primary = state; 27 primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_SET_PIPELINE_STATE); 28 primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 29 primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); 30 msg.primary = primary; 31 32 /* trigger multiple pipelines with a single IPC */ 33 msg.extension = SOF_IPC4_GLB_PIPE_STATE_EXT_MULTI; 34 35 /* ipc_size includes the count and the pipeline IDs for the number of pipelines */ 36 ipc_size = sizeof(u32) * (trigger_list->count + 1); 37 msg.data_size = ipc_size; 38 msg.data_ptr = trigger_list; 39 40 return sof_ipc_tx_message(sdev->ipc, &msg, ipc_size, NULL, 0); 41 } 42 43 int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state) 44 { 45 struct sof_ipc4_msg msg = {{ 0 }}; 46 u32 primary; 47 48 dev_dbg(sdev->dev, "ipc4 set pipeline %d state %d", id, state); 49 50 primary = state; 51 primary |= SOF_IPC4_GLB_PIPE_STATE_ID(id); 52 primary |= SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_GLB_SET_PIPELINE_STATE); 53 primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 54 primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_FW_GEN_MSG); 55 56 msg.primary = primary; 57 58 return sof_ipc_tx_message(sdev->ipc, &msg, 0, NULL, 0); 59 } 60 EXPORT_SYMBOL(sof_ipc4_set_pipeline_state); 61 62 static void 63 sof_ipc4_add_pipeline_to_trigger_list(struct snd_sof_dev *sdev, int state, 64 struct snd_sof_pipeline *spipe, 65 struct ipc4_pipeline_set_state_data *trigger_list) 66 { 67 struct snd_sof_widget *pipe_widget = spipe->pipe_widget; 68 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 69 70 if (pipeline->skip_during_fe_trigger) 71 return; 72 73 switch (state) { 74 case SOF_IPC4_PIPE_RUNNING: 75 /* 76 * Trigger pipeline if all PCMs containing it are paused or if it is RUNNING 77 * for the first time 78 */ 79 if (spipe->started_count == spipe->paused_count) 80 trigger_list->pipeline_ids[trigger_list->count++] = 81 pipe_widget->instance_id; 82 break; 83 case SOF_IPC4_PIPE_RESET: 84 /* RESET if the pipeline is neither running nor paused */ 85 if (!spipe->started_count && !spipe->paused_count) 86 trigger_list->pipeline_ids[trigger_list->count++] = 87 pipe_widget->instance_id; 88 break; 89 case SOF_IPC4_PIPE_PAUSED: 90 /* Pause the pipeline only when its started_count is 1 more than paused_count */ 91 if (spipe->paused_count == (spipe->started_count - 1)) 92 trigger_list->pipeline_ids[trigger_list->count++] = 93 pipe_widget->instance_id; 94 break; 95 default: 96 break; 97 } 98 } 99 100 static void 101 sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd, 102 struct snd_sof_pipeline *spipe, 103 struct ipc4_pipeline_set_state_data *trigger_list) 104 { 105 struct snd_sof_widget *pipe_widget = spipe->pipe_widget; 106 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 107 int i; 108 109 if (pipeline->skip_during_fe_trigger) 110 return; 111 112 /* set state for pipeline if it was just triggered */ 113 for (i = 0; i < trigger_list->count; i++) { 114 if (trigger_list->pipeline_ids[i] == pipe_widget->instance_id) { 115 pipeline->state = state; 116 break; 117 } 118 } 119 120 switch (state) { 121 case SOF_IPC4_PIPE_PAUSED: 122 switch (cmd) { 123 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 124 /* 125 * increment paused_count if the PAUSED is the final state during 126 * the PAUSE trigger 127 */ 128 spipe->paused_count++; 129 break; 130 case SNDRV_PCM_TRIGGER_STOP: 131 case SNDRV_PCM_TRIGGER_SUSPEND: 132 /* 133 * decrement started_count if PAUSED is the final state during the 134 * STOP trigger 135 */ 136 spipe->started_count--; 137 break; 138 default: 139 break; 140 } 141 break; 142 case SOF_IPC4_PIPE_RUNNING: 143 switch (cmd) { 144 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 145 /* decrement paused_count for RELEASE */ 146 spipe->paused_count--; 147 break; 148 case SNDRV_PCM_TRIGGER_START: 149 case SNDRV_PCM_TRIGGER_RESUME: 150 /* increment started_count for START/RESUME */ 151 spipe->started_count++; 152 break; 153 default: 154 break; 155 } 156 break; 157 default: 158 break; 159 } 160 } 161 162 /* 163 * The picture below represents the pipeline state machine wrt PCM actions corresponding to the 164 * triggers and ioctls 165 * +---------------+ 166 * | | 167 * | INIT | 168 * | | 169 * +-------+-------+ 170 * | 171 * | 172 * | START 173 * | 174 * | 175 * +----------------+ +------v-------+ +-------------+ 176 * | | START | | HW_FREE | | 177 * | RUNNING <-------------+ PAUSED +--------------> + RESET | 178 * | | PAUSE | | | | 179 * +------+---------+ RELEASE +---------+----+ +-------------+ 180 * | ^ 181 * | | 182 * | | 183 * | | 184 * | PAUSE | 185 * +---------------------------------+ 186 * STOP/SUSPEND 187 * 188 * Note that during system suspend, the suspend trigger is followed by a hw_free in 189 * sof_pcm_trigger(). So, the final state during suspend would be RESET. 190 * Also, since the SOF driver doesn't support full resume, streams would be restarted with the 191 * prepare ioctl before the START trigger. 192 */ 193 194 static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, 195 struct snd_pcm_substream *substream, int state, int cmd) 196 { 197 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 198 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 199 struct snd_sof_pcm_stream_pipeline_list *pipeline_list; 200 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 201 struct ipc4_pipeline_set_state_data *trigger_list; 202 struct snd_sof_pipeline *spipe; 203 struct snd_sof_pcm *spcm; 204 int ret; 205 int i; 206 207 dev_dbg(sdev->dev, "trigger cmd: %d state: %d\n", cmd, state); 208 209 spcm = snd_sof_find_spcm_dai(component, rtd); 210 if (!spcm) 211 return -EINVAL; 212 213 pipeline_list = &spcm->stream[substream->stream].pipeline_list; 214 215 /* nothing to trigger if the list is empty */ 216 if (!pipeline_list->pipelines || !pipeline_list->count) 217 return 0; 218 219 /* allocate memory for the pipeline data */ 220 trigger_list = kzalloc(struct_size(trigger_list, pipeline_ids, pipeline_list->count), 221 GFP_KERNEL); 222 if (!trigger_list) 223 return -ENOMEM; 224 225 mutex_lock(&ipc4_data->pipeline_state_mutex); 226 227 /* 228 * IPC4 requires pipelines to be triggered in order starting at the sink and 229 * walking all the way to the source. So traverse the pipeline_list in the order 230 * sink->source when starting PCM's and in the reverse order to pause/stop PCM's. 231 * Skip the pipelines that have their skip_during_fe_trigger flag set. If there is a fork 232 * in the pipeline, the order of triggering between the left/right paths will be 233 * indeterministic. But the sink->source trigger order sink->source would still be 234 * guaranteed for each fork independently. 235 */ 236 if (state == SOF_IPC4_PIPE_RUNNING || state == SOF_IPC4_PIPE_RESET) 237 for (i = pipeline_list->count - 1; i >= 0; i--) { 238 spipe = pipeline_list->pipelines[i]; 239 sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list); 240 } 241 else 242 for (i = 0; i < pipeline_list->count; i++) { 243 spipe = pipeline_list->pipelines[i]; 244 sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list); 245 } 246 247 /* return if all pipelines are in the requested state already */ 248 if (!trigger_list->count) { 249 ret = 0; 250 goto free; 251 } 252 253 /* no need to pause before reset or before pause release */ 254 if (state == SOF_IPC4_PIPE_RESET || cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) 255 goto skip_pause_transition; 256 257 /* 258 * set paused state for pipelines if the final state is PAUSED or when the pipeline 259 * is set to RUNNING for the first time after the PCM is started. 260 */ 261 ret = sof_ipc4_set_multi_pipeline_state(sdev, SOF_IPC4_PIPE_PAUSED, trigger_list); 262 if (ret < 0) { 263 dev_err(sdev->dev, "failed to pause all pipelines\n"); 264 goto free; 265 } 266 267 /* update PAUSED state for all pipelines just triggered */ 268 for (i = 0; i < pipeline_list->count ; i++) { 269 spipe = pipeline_list->pipelines[i]; 270 sof_ipc4_update_pipeline_state(sdev, SOF_IPC4_PIPE_PAUSED, cmd, spipe, 271 trigger_list); 272 } 273 274 /* return if this is the final state */ 275 if (state == SOF_IPC4_PIPE_PAUSED) 276 goto free; 277 skip_pause_transition: 278 /* else set the RUNNING/RESET state in the DSP */ 279 ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list); 280 if (ret < 0) { 281 dev_err(sdev->dev, "failed to set final state %d for all pipelines\n", state); 282 goto free; 283 } 284 285 /* update RUNNING/RESET state for all pipelines that were just triggered */ 286 for (i = 0; i < pipeline_list->count; i++) { 287 spipe = pipeline_list->pipelines[i]; 288 sof_ipc4_update_pipeline_state(sdev, state, cmd, spipe, trigger_list); 289 } 290 291 free: 292 mutex_unlock(&ipc4_data->pipeline_state_mutex); 293 kfree(trigger_list); 294 return ret; 295 } 296 297 static int sof_ipc4_pcm_trigger(struct snd_soc_component *component, 298 struct snd_pcm_substream *substream, int cmd) 299 { 300 int state; 301 302 /* determine the pipeline state */ 303 switch (cmd) { 304 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 305 state = SOF_IPC4_PIPE_PAUSED; 306 break; 307 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 308 case SNDRV_PCM_TRIGGER_RESUME: 309 case SNDRV_PCM_TRIGGER_START: 310 state = SOF_IPC4_PIPE_RUNNING; 311 break; 312 case SNDRV_PCM_TRIGGER_SUSPEND: 313 case SNDRV_PCM_TRIGGER_STOP: 314 state = SOF_IPC4_PIPE_PAUSED; 315 break; 316 default: 317 dev_err(component->dev, "%s: unhandled trigger cmd %d\n", __func__, cmd); 318 return -EINVAL; 319 } 320 321 /* set the pipeline state */ 322 return sof_ipc4_trigger_pipelines(component, substream, state, cmd); 323 } 324 325 static int sof_ipc4_pcm_hw_free(struct snd_soc_component *component, 326 struct snd_pcm_substream *substream) 327 { 328 /* command is not relevant with RESET, so just pass 0 */ 329 return sof_ipc4_trigger_pipelines(component, substream, SOF_IPC4_PIPE_RESET, 0); 330 } 331 332 static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, 333 struct snd_pcm_hw_params *params) 334 { 335 struct snd_sof_dai_link *slink; 336 struct snd_sof_dai *dai; 337 bool dai_link_found = false; 338 int i; 339 340 list_for_each_entry(slink, &sdev->dai_link_list, list) { 341 if (!strcmp(slink->link->name, link_name)) { 342 dai_link_found = true; 343 break; 344 } 345 } 346 347 if (!dai_link_found) 348 return; 349 350 for (i = 0; i < slink->num_hw_configs; i++) { 351 struct snd_soc_tplg_hw_config *hw_config = &slink->hw_configs[i]; 352 353 if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate)) { 354 /* set current config for all DAI's with matching name */ 355 list_for_each_entry(dai, &sdev->dai_list, list) 356 if (!strcmp(slink->link->name, dai->name)) 357 dai->current_config = le32_to_cpu(hw_config->id); 358 break; 359 } 360 } 361 } 362 363 static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, 364 struct snd_pcm_hw_params *params) 365 { 366 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 367 struct snd_sof_dai *dai = snd_sof_find_dai(component, rtd->dai_link->name); 368 struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 369 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 370 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 371 struct sof_ipc4_copier *ipc4_copier; 372 373 if (!dai) { 374 dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, 375 rtd->dai_link->name); 376 return -EINVAL; 377 } 378 379 ipc4_copier = dai->private; 380 if (!ipc4_copier) { 381 dev_err(component->dev, "%s: No private data found for DAI %s\n", 382 __func__, rtd->dai_link->name); 383 return -EINVAL; 384 } 385 386 /* always set BE format to 32-bits for both playback and capture */ 387 snd_mask_none(fmt); 388 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 389 390 rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency; 391 rate->max = rate->min; 392 393 switch (ipc4_copier->dai_type) { 394 case SOF_DAI_INTEL_SSP: 395 ipc4_ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params); 396 break; 397 default: 398 break; 399 } 400 401 return 0; 402 } 403 404 static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm) 405 { 406 struct snd_sof_pcm_stream_pipeline_list *pipeline_list; 407 int stream; 408 409 for_each_pcm_streams(stream) { 410 pipeline_list = &spcm->stream[stream].pipeline_list; 411 kfree(pipeline_list->pipelines); 412 pipeline_list->pipelines = NULL; 413 } 414 } 415 416 static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm) 417 { 418 struct snd_sof_pcm_stream_pipeline_list *pipeline_list; 419 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 420 int stream; 421 422 for_each_pcm_streams(stream) { 423 pipeline_list = &spcm->stream[stream].pipeline_list; 424 425 /* allocate memory for max number of pipeline IDs */ 426 pipeline_list->pipelines = kcalloc(ipc4_data->max_num_pipelines, 427 sizeof(struct snd_sof_widget *), GFP_KERNEL); 428 if (!pipeline_list->pipelines) { 429 sof_ipc4_pcm_free(sdev, spcm); 430 return -ENOMEM; 431 } 432 } 433 434 return 0; 435 } 436 437 const struct sof_ipc_pcm_ops ipc4_pcm_ops = { 438 .trigger = sof_ipc4_pcm_trigger, 439 .hw_free = sof_ipc4_pcm_hw_free, 440 .dai_link_fixup = sof_ipc4_pcm_dai_link_fixup, 441 .pcm_setup = sof_ipc4_pcm_setup, 442 .pcm_free = sof_ipc4_pcm_free, 443 }; 444