···294294 Say Y if you want to add support for SoC audio on an i.MX board with295295 a sgtl5000 codec.296296297297+ Note that this is an old driver. Consider enabling298298+ SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer299299+ driver.300300+297301config SND_SOC_IMX_SPDIF298302 tristate "SoC Audio support for i.MX boards with S/PDIF"299303 select SND_SOC_IMX_PCM_DMA
···559559 {560560 .comp_ids = &essx_83x6,561561 .drv_name = "sof-essx8336",562562- .sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */562562+ .sof_tplg_filename = "sof-adl-es8336", /* the tplg suffix is added at run time */563563 .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |564564 SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |565565 SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
···392392 snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset,393393 SOF_HDA_VS_D0I3C_I3, value);394394395395+ /*396396+ * The value written to the D0I3C::I3 bit may not be taken into account immediately.397397+ * A delay is recommended before checking if D0I3C::CIP is cleared398398+ */399399+ usleep_range(30, 40);400400+395401 /* Wait for cmd in progress to be cleared before exiting the function */396402 ret = hda_dsp_wait_d0i3c_done(sdev);397403 if (ret < 0) {···406400 }407401408402 reg = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset);403403+ /* Confirm d0i3 state changed with paranoia check */404404+ if ((reg ^ value) & SOF_HDA_VS_D0I3C_I3) {405405+ dev_err(sdev->dev, "failed to update D0I3C!\n");406406+ return -EIO;407407+ }408408+409409 trace_sof_intel_D0I3C_updated(sdev, reg);410410411411 return 0;
···75757676 /* LPE base */7777 base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;7878- size = pci_resource_len(pci, desc->resindex_lpe_base);7979- if (size < PCI_BAR_SIZE) {8080- dev_err(sdev->dev, "error: I/O region is too small.\n");8181- return -ENODEV;8282- }7878+ size = PCI_BAR_SIZE;83798480 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);8581 sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+30-2
sound/soc/sof/ipc3-topology.c
···20812081 break;20822082 case SOF_DAI_INTEL_ALH:20832083 if (data) {20842084- config->dai_index = data->dai_index;20842084+ /* save the dai_index during hw_params and reuse it for hw_free */20852085+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)20862086+ config->dai_index = data->dai_index;20852087 config->alh.stream_id = data->dai_data;20862088 }20872089 break;···20912089 break;20922090 }2093209120942094- config->flags = flags;20922092+ /*20932093+ * The dai_config op is invoked several times and the flags argument varies as below:20942094+ * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains20952095+ * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks20962096+ * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has20972097+ * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no20982098+ * quirks20992099+ * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to21002100+ * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks21012101+ * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to21022102+ * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks21032103+ * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to21042104+ * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks21052105+ *21062106+ * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE21072107+ * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks21082108+ * need to be preserved when assigning the flags before sending the IPC.21092109+ * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.21102110+ */21112111+21122112+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)21132113+ config->flags |= flags;21142114+ else21152115+ config->flags = flags;2095211620962117 /* only send the IPC if the widget is set up in the DSP */20972118 if (swidget->use_count > 0) {···21222097 &reply, sizeof(reply));21232098 if (ret < 0)21242099 dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);21002100+21012101+ /* clear the flags once the IPC has been sent even if it fails */21022102+ config->flags = SOF_DAI_CONFIG_FLAGS_NONE;21252103 }2126210421272105 return ret;
+3-2
sound/soc/sof/ipc3.c
···970970 return;971971 }972972973973- if (hdr.size < sizeof(hdr)) {974974- dev_err(sdev->dev, "The received message size is invalid\n");973973+ if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) {974974+ dev_err(sdev->dev, "The received message size is invalid: %u\n",975975+ hdr.size);975976 return;976977 }977978
+2-1
sound/soc/sof/ipc4-control.c
···9797 }98989999 /* set curve type and duration from topology */100100- data.curve_duration = gain->data.curve_duration;100100+ data.curve_duration_l = gain->data.curve_duration_l;101101+ data.curve_duration_h = gain->data.curve_duration_h;101102 data.curve_type = gain->data.curve_type;102103103104 msg->data_ptr = &data;
+16-5
sound/soc/sof/ipc4-topology.c
···107107 get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)},108108 {SOF_TKN_GAIN_RAMP_DURATION,109109 SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,110110- offsetof(struct sof_ipc4_gain_data, curve_duration)},110110+ offsetof(struct sof_ipc4_gain_data, curve_duration_l)},111111 {SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD,112112 get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},113113};···155155 for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) {156156 fmt = ptr;157157 dev_dbg(dev,158158- " #%d: %uKHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n",158158+ " #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n",159159 i, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map,160160 fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg);161161 }···692692693693 dev_dbg(scomp->dev,694694 "pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x, cpc %d\n",695695- swidget->widget->name, gain->data.curve_type, gain->data.curve_duration,695695+ swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l,696696 gain->data.init_val, gain->base_config.cpc);697697698698 ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg);···980980981981 ipc4_copier = dai->private;982982 if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {983983+ struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data;983984 struct sof_ipc4_alh_configuration_blob *blob;984985 unsigned int group_id;985986···990989 ALH_MULTI_GTW_BASE;991990 ida_free(&alh_group_ida, group_id);992991 }992992+993993+ /* clear the node ID */994994+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;993995 }994996 }995997···19441940 pipeline->skip_during_fe_trigger = true;19451941 fallthrough;19461942 case SOF_DAI_INTEL_ALH:19471947- copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;19481948- copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);19431943+ /*19441944+ * Do not clear the node ID when this op is invoked with19451945+ * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during19461946+ * unprepare.19471947+ */19481948+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {19491949+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;19501950+ copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);19511951+ }19491952 break;19501953 case SOF_DAI_INTEL_DMIC:19511954 case SOF_DAI_INTEL_SSP:
···5050 /* reset route setup status for all routes that contain this widget */5151 sof_reset_route_setup_status(sdev, swidget);52525353+ /* free DAI config and continue to free widget even if it fails */5454+ if (WIDGET_IS_DAI(swidget->id)) {5555+ struct snd_sof_dai_config_data data;5656+ unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE;5757+5858+ data.dai_data = DMA_CHAN_INVALID;5959+6060+ if (tplg_ops && tplg_ops->dai_config) {6161+ err = tplg_ops->dai_config(sdev, swidget, flags, &data);6262+ if (err < 0)6363+ dev_err(sdev->dev, "failed to free config for widget %s\n",6464+ swidget->widget->name);6565+ }6666+ }6767+5368 /* continue to disable core even if IPC fails */5454- if (tplg_ops && tplg_ops->widget_free)5555- err = tplg_ops->widget_free(sdev, swidget);6969+ if (tplg_ops && tplg_ops->widget_free) {7070+ ret = tplg_ops->widget_free(sdev, swidget);7171+ if (ret < 0 && !err)7272+ err = ret;7373+ }56745775 /*5876 * disable widget core. continue to route setup status and complete flag···169151170152 /* send config for DAI components */171153 if (WIDGET_IS_DAI(swidget->id)) {172172- unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE;154154+ unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;173155156156+ /*157157+ * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does158158+ * not use the flags argument.159159+ */174160 if (tplg_ops && tplg_ops->dai_config) {175161 ret = tplg_ops->dai_config(sdev, swidget, flags, NULL);176162 if (ret < 0)···610588 ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,611589 dir, SOF_WIDGET_SETUP);612590 if (ret < 0) {613613- ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,614614- dir, SOF_WIDGET_UNPREPARE);591591+ sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,592592+ dir, SOF_WIDGET_UNPREPARE);615593 return ret;616594 }617595
+17-17
sound/soc/sof/topology.c
···13881388 if (ret < 0) {13891389 dev_err(scomp->dev, "failed to parse component pin tokens for %s\n",13901390 w->name);13911391- return ret;13911391+ goto widget_free;13921392 }1393139313941394 if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS ||13951395 swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) {13961396 dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n",13971397 swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins);13981398- return -EINVAL;13981398+ ret = -EINVAL;13991399+ goto widget_free;13991400 }1400140114011402 if (swidget->num_sink_pins > 1) {···14051404 if (ret < 0) {14061405 dev_err(scomp->dev, "failed to parse sink pin binding for %s\n",14071406 w->name);14081408- return ret;14071407+ goto widget_free;14091408 }14101409 }14111410···14151414 if (ret < 0) {14161415 dev_err(scomp->dev, "failed to parse source pin binding for %s\n",14171416 w->name);14181418- return ret;14171417+ goto widget_free;14191418 }14201419 }14211420···14371436 case snd_soc_dapm_dai_out:14381437 dai = kzalloc(sizeof(*dai), GFP_KERNEL);14391438 if (!dai) {14401440- kfree(swidget);14411441- return -ENOMEM;14421442-14391439+ ret = -ENOMEM;14401440+ goto widget_free;14431441 }1444144214451443 ret = sof_widget_parse_tokens(scomp, swidget, tw, token_list, token_list_size);···14961496 tw->shift, swidget->id, tw->name,14971497 strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 014981498 ? tw->sname : "none");14991499- kfree(swidget);15001500- return ret;14991499+ goto widget_free;15011500 }1502150115031502 if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) {···15171518 if (ret) {15181519 dev_err(scomp->dev, "widget event binding failed for %s\n",15191520 swidget->widget->name);15201520- kfree(swidget->private);15211521- kfree(swidget->tuples);15221522- kfree(swidget);15231523- return ret;15211521+ goto free;15241522 }15251523 }15261524 }···1528153215291533 spipe = kzalloc(sizeof(*spipe), GFP_KERNEL);15301534 if (!spipe) {15311531- kfree(swidget->private);15321532- kfree(swidget->tuples);15331533- kfree(swidget);15341534- return -ENOMEM;15351535+ ret = -ENOMEM;15361536+ goto free;15351537 }1536153815371539 spipe->pipe_widget = swidget;···1539154515401546 w->dobj.private = swidget;15411547 list_add(&swidget->list, &sdev->widget_list);15481548+ return ret;15491549+free:15501550+ kfree(swidget->private);15511551+ kfree(swidget->tuples);15521552+widget_free:15531553+ kfree(swidget);15421554 return ret;15431555}15441556
+14-8
sound/usb/endpoint.c
···455455 * This function is used both for implicit feedback endpoints and in low-456456 * latency playback mode.457457 */458458-void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,459459- bool in_stream_lock)458458+int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,459459+ bool in_stream_lock)460460{461461 bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep);462462···480480 spin_unlock_irqrestore(&ep->lock, flags);481481482482 if (ctx == NULL)483483- return;483483+ break;484484485485 /* copy over the length information */486486 if (implicit_fb) {···495495 break;496496 if (err < 0) {497497 /* push back to ready list again for -EAGAIN */498498- if (err == -EAGAIN)498498+ if (err == -EAGAIN) {499499 push_back_to_ready_list(ep, ctx);500500- else500500+ break;501501+ }502502+503503+ if (!in_stream_lock)501504 notify_xrun(ep);502502- return;505505+ return -EPIPE;503506 }504507505508 err = usb_submit_urb(ctx->urb, GFP_ATOMIC);···510507 usb_audio_err(ep->chip,511508 "Unable to submit urb #%d: %d at %s\n",512509 ctx->index, err, __func__);513513- notify_xrun(ep);514514- return;510510+ if (!in_stream_lock)511511+ notify_xrun(ep);512512+ return -EPIPE;515513 }516514517515 set_bit(ctx->index, &ep->active_mask);518516 atomic_inc(&ep->submitted_urbs);519517 }518518+519519+ return 0;520520}521521522522/*