diff options
Diffstat (limited to 'sound')
49 files changed, 532 insertions, 269 deletions
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 6a384b922e4f..d1f6cdcf1866 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -557,9 +557,32 @@ static const struct config_entry *snd_intel_dsp_find_config if (table->codec_hid) { int i; - for (i = 0; i < table->codec_hid->num_codecs; i++) - if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) + for (i = 0; i < table->codec_hid->num_codecs; i++) { + struct nhlt_acpi_table *nhlt; + bool ssp_found = false; + + if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1)) + continue; + + nhlt = intel_nhlt_init(&pci->dev); + if (!nhlt) { + dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n", + __func__, table->codec_hid->codecs[i]); + continue; + } + + if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) && + intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S)) + ssp_found = true; + + intel_nhlt_free(nhlt); + + if (ssp_found) break; + + dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n", + __func__, table->codec_hid->codecs[i]); + } if (i == table->codec_hid->num_codecs) continue; } diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c index 5f60658c6051..d7417a40392b 100644 --- a/sound/hda/intel-sdw-acpi.c +++ b/sound/hda/intel-sdw-acpi.c @@ -45,6 +45,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx) "intel-quirk-mask", &quirk_mask); + fwnode_handle_put(link); + if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE) return false; diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c index 1a3f84599cb5..558c1f38fe97 100644 --- a/sound/pci/hda/cs35l56_hda.c +++ b/sound/pci/hda/cs35l56_hda.c @@ -644,6 +644,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); if (ret) goto err_powered_up; + + regcache_cache_only(cs35l56->base.regmap, false); } /* Disable auto-hibernate so that runtime_pm has control */ @@ -1002,6 +1004,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) if (ret) goto err; + regcache_cache_only(cs35l56->base.regmap, false); + ret = cs35l56_set_patch(&cs35l56->base); if (ret) goto err; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2cac337f5263..325e8f0b99a8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -616,7 +616,6 @@ void snd_hda_shutup_pins(struct hda_codec *codec) } EXPORT_SYMBOL_GPL(snd_hda_shutup_pins); -#ifdef CONFIG_PM /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ static void restore_shutup_pins(struct hda_codec *codec) { @@ -634,7 +633,6 @@ static void restore_shutup_pins(struct hda_codec *codec) } codec->pins_shutup = 0; } -#endif static void hda_jackpoll_work(struct work_struct *work) { @@ -1001,9 +999,7 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, codec->card = card; codec->addr = codec_addr; -#ifdef CONFIG_PM codec->power_jiffies = jiffies; -#endif snd_hda_sysfs_init(codec); @@ -1238,7 +1234,6 @@ static void purify_inactive_streams(struct hda_codec *codec) } } -#ifdef CONFIG_PM /* clean up all streams; called from suspend */ static void hda_cleanup_all_streams(struct hda_codec *codec) { @@ -1250,7 +1245,6 @@ static void hda_cleanup_all_streams(struct hda_codec *codec) really_cleanup_stream(codec, p); } } -#endif /* * amp access functions @@ -2858,7 +2852,6 @@ static void hda_exec_init_verbs(struct hda_codec *codec) static inline void hda_exec_init_verbs(struct hda_codec *codec) {} #endif -#ifdef CONFIG_PM /* update the power on/off account with the current jiffies */ static void update_power_acct(struct hda_codec *codec, bool on) { @@ -2966,9 +2959,6 @@ static int hda_codec_runtime_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM */ - -#ifdef CONFIG_PM_SLEEP static int hda_codec_pm_prepare(struct device *dev) { struct hda_codec *codec = dev_to_hda_codec(dev); @@ -3023,22 +3013,19 @@ static int hda_codec_pm_restore(struct device *dev) dev->power.power_state = PMSG_RESTORE; return pm_runtime_force_resume(dev); } -#endif /* CONFIG_PM_SLEEP */ /* referred in hda_bind.c */ const struct dev_pm_ops hda_codec_driver_pm = { -#ifdef CONFIG_PM_SLEEP - .prepare = hda_codec_pm_prepare, - .complete = hda_codec_pm_complete, - .suspend = hda_codec_pm_suspend, - .resume = hda_codec_pm_resume, - .freeze = hda_codec_pm_freeze, - .thaw = hda_codec_pm_thaw, - .poweroff = hda_codec_pm_suspend, - .restore = hda_codec_pm_restore, -#endif /* CONFIG_PM_SLEEP */ - SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume, - NULL) + .prepare = pm_sleep_ptr(hda_codec_pm_prepare), + .complete = pm_sleep_ptr(hda_codec_pm_complete), + .suspend = pm_sleep_ptr(hda_codec_pm_suspend), + .resume = pm_sleep_ptr(hda_codec_pm_resume), + .freeze = pm_sleep_ptr(hda_codec_pm_freeze), + .thaw = pm_sleep_ptr(hda_codec_pm_thaw), + .poweroff = pm_sleep_ptr(hda_codec_pm_suspend), + .restore = pm_sleep_ptr(hda_codec_pm_restore), + .runtime_suspend = pm_ptr(hda_codec_runtime_suspend), + .runtime_resume = pm_ptr(hda_codec_runtime_resume), }; /* suspend the codec at shutdown; called from driver's shutdown callback */ @@ -3425,7 +3412,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, } EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls); -#ifdef CONFIG_PM /** * snd_hda_codec_set_power_save - Configure codec's runtime PM * @codec: codec device to configure @@ -3516,7 +3502,6 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, return 0; } EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power); -#endif /* * input MUX helper @@ -4060,12 +4045,10 @@ void snd_hda_bus_reset_codecs(struct hda_bus *bus) /* FIXME: maybe a better way needed for forced reset */ if (current_work() != &codec->jackpoll_work.work) cancel_delayed_work_sync(&codec->jackpoll_work); -#ifdef CONFIG_PM if (hda_codec_is_power_on(codec)) { hda_call_codec_suspend(codec); hda_call_codec_resume(codec); } -#endif } } diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 8af5ee1b0ea8..1030a8bfb3cd 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1075,11 +1075,9 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) bool active, handled = false; int repeat = 0; /* count for avoiding endless loop */ -#ifdef CONFIG_PM if (azx_has_pm_runtime(chip)) if (!pm_runtime_active(chip->card->dev)) return IRQ_NONE; -#endif spin_lock(&bus->reg_lock); diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index de2a3d08c73c..f64d9dc197a3 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -6021,7 +6021,6 @@ void snd_hda_gen_free(struct hda_codec *codec) } EXPORT_SYMBOL_GPL(snd_hda_gen_free); -#ifdef CONFIG_PM /** * snd_hda_gen_check_power_status - check the loopback power save state * @codec: the HDA codec @@ -6035,7 +6034,6 @@ int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid) return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); } EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status); -#endif /* @@ -6048,9 +6046,7 @@ static const struct hda_codec_ops generic_patch_ops = { .init = snd_hda_gen_init, .free = snd_hda_gen_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .check_power_status = snd_hda_gen_check_power_status, -#endif }; /* diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index a8eea8367629..8f5ecf740c49 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -340,9 +340,7 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_callback *jack); void snd_hda_gen_update_outputs(struct hda_codec *codec); -#ifdef CONFIG_PM int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid); -#endif unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec, hda_nid_t nid, unsigned int power_state); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a03f17f1328f..2bd652dcb5b3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -186,8 +186,10 @@ MODULE_PARM_DESC(pm_blacklist, "Enable power-management denylist"); static bool power_save_controller = 1; module_param(power_save_controller, bool, 0644); MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); -#else +#else /* CONFIG_PM */ #define power_save 0 +#define pm_blacklist false +#define power_save_controller false #endif /* CONFIG_PM */ static int align_buffer_size = -1; @@ -893,7 +895,6 @@ static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset) display_power(chip, false); } -#ifdef CONFIG_PM static DEFINE_MUTEX(card_list_lock); static LIST_HEAD(card_list); @@ -919,7 +920,7 @@ static void azx_del_card_list(struct azx *chip) } /* trigger power-save check at writing parameter */ -static int param_set_xint(const char *val, const struct kernel_param *kp) +static int __maybe_unused param_set_xint(const char *val, const struct kernel_param *kp) { struct hda_intel *hda; struct azx *chip; @@ -990,7 +991,6 @@ static void __azx_runtime_resume(struct azx *chip) display_power(chip, false); } -#ifdef CONFIG_PM_SLEEP static int azx_prepare(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); @@ -1049,7 +1049,7 @@ static int azx_suspend(struct device *dev) return 0; } -static int azx_resume(struct device *dev) +static int __maybe_unused azx_resume(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; @@ -1100,9 +1100,8 @@ static int azx_thaw_noirq(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ -static int azx_runtime_suspend(struct device *dev) +static int __maybe_unused azx_runtime_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; @@ -1119,7 +1118,7 @@ static int azx_runtime_suspend(struct device *dev) return 0; } -static int azx_runtime_resume(struct device *dev) +static int __maybe_unused azx_runtime_resume(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; @@ -1136,7 +1135,7 @@ static int azx_runtime_resume(struct device *dev) return 0; } -static int azx_runtime_idle(struct device *dev) +static int __maybe_unused azx_runtime_idle(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; @@ -1162,23 +1161,14 @@ static int azx_runtime_idle(struct device *dev) } static const struct dev_pm_ops azx_pm = { - SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume) -#ifdef CONFIG_PM_SLEEP - .prepare = azx_prepare, - .complete = azx_complete, - .freeze_noirq = azx_freeze_noirq, - .thaw_noirq = azx_thaw_noirq, -#endif + SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume) + .prepare = pm_sleep_ptr(azx_prepare), + .complete = pm_sleep_ptr(azx_complete), + .freeze_noirq = pm_sleep_ptr(azx_freeze_noirq), + .thaw_noirq = pm_sleep_ptr(azx_thaw_noirq), SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle) }; -#define AZX_PM_OPS &azx_pm -#else -#define azx_add_card_list(chip) /* NOP */ -#define azx_del_card_list(chip) /* NOP */ -#define AZX_PM_OPS NULL -#endif /* CONFIG_PM */ - static int azx_probe_continue(struct azx *chip); @@ -2209,7 +2199,6 @@ out_free: return err; } -#ifdef CONFIG_PM /* On some boards setting power_save to a non 0 value leads to clicking / * popping sounds when ever we enter/leave powersaving mode. Ideally we would * figure out how to avoid these sounds, but that is not always feasible. @@ -2251,13 +2240,11 @@ static const struct snd_pci_quirk power_save_denylist[] = { SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0), {} }; -#endif /* CONFIG_PM */ static void set_default_power_save(struct azx *chip) { int val = power_save; -#ifdef CONFIG_PM if (pm_blacklist) { const struct snd_pci_quirk *q; @@ -2268,7 +2255,6 @@ static void set_default_power_save(struct azx *chip) val = 0; } } -#endif /* CONFIG_PM */ snd_hda_set_power_save(&chip->bus, val * 1000); } @@ -2324,10 +2310,6 @@ static int azx_probe_continue(struct azx *chip) chip->fw->data); if (err < 0) goto out_free; -#ifndef CONFIG_PM - release_firmware(chip->fw); /* no longer needed */ - chip->fw = NULL; -#endif } #endif @@ -2770,7 +2752,7 @@ static struct pci_driver azx_driver = { .remove = azx_remove, .shutdown = azx_shutdown, .driver = { - .pm = AZX_PM_OPS, + .pm = &azx_pm, }, }; diff --git a/sound/pci/hda/hda_intel_trace.h b/sound/pci/hda/hda_intel_trace.h index 73a7adfa192d..2775fa81a500 100644 --- a/sound/pci/hda/hda_intel_trace.h +++ b/sound/pci/hda/hda_intel_trace.h @@ -34,7 +34,6 @@ DEFINE_EVENT(hda_pm, azx_resume, TP_ARGS(chip) ); -#ifdef CONFIG_PM DEFINE_EVENT(hda_pm, azx_runtime_suspend, TP_PROTO(struct azx *chip), TP_ARGS(chip) @@ -44,7 +43,6 @@ DEFINE_EVENT(hda_pm, azx_runtime_resume, TP_PROTO(struct azx *chip), TP_ARGS(chip) ); -#endif #endif /* _TRACE_HDA_INTEL_H */ diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 69ebc37a4d6f..265fd4737893 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -26,7 +26,6 @@ struct hda_hint { const char *val; /* contained in the same alloc as key */ }; -#ifdef CONFIG_PM static ssize_t power_on_acct_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -47,7 +46,6 @@ static ssize_t power_off_acct_show(struct device *dev, static DEVICE_ATTR_RO(power_on_acct); static DEVICE_ATTR_RO(power_off_acct); -#endif /* CONFIG_PM */ #define CODEC_INFO_SHOW(type, field) \ static ssize_t type##_show(struct device *dev, \ @@ -745,10 +743,8 @@ static struct attribute *hda_dev_attrs[] = { &dev_attr_modelname.attr, &dev_attr_init_pin_configs.attr, &dev_attr_driver_pin_configs.attr, -#ifdef CONFIG_PM &dev_attr_power_on_acct.attr, &dev_attr_power_off_acct.attr, -#endif #ifdef CONFIG_SND_HDA_RECONFIG &dev_attr_init_verbs.attr, &dev_attr_hints.attr, diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 8afe6000f7da..1e9dadcdc51b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -72,7 +72,6 @@ static int create_beep_ctls(struct hda_codec *codec) #define create_beep_ctls(codec) 0 #endif -#ifdef CONFIG_PM static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, hda_nid_t hp) { @@ -118,7 +117,6 @@ static int ad198x_suspend(struct hda_codec *codec) ad198x_power_eapd(codec); return 0; } -#endif /* follow EAPD via vmaster hook */ static void ad_vmaster_eapd_hook(void *private_data, int enabled) @@ -158,10 +156,8 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = { .init = snd_hda_gen_init, .free = snd_hda_gen_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .check_power_status = snd_hda_gen_check_power_status, .suspend = ad198x_suspend, -#endif }; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index aa312441604f..e4673a71551a 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -9682,7 +9682,6 @@ static void dbpro_free(struct hda_codec *codec) kfree(codec->spec); } -#ifdef CONFIG_PM static int ca0132_suspend(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; @@ -9690,7 +9689,6 @@ static int ca0132_suspend(struct hda_codec *codec) cancel_delayed_work_sync(&spec->unsol_hp_work); return 0; } -#endif static const struct hda_codec_ops ca0132_patch_ops = { .build_controls = ca0132_build_controls, @@ -9698,9 +9696,7 @@ static const struct hda_codec_ops ca0132_patch_ops = { .init = ca0132_init, .free = ca0132_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .suspend = ca0132_suspend, -#endif }; static const struct hda_codec_ops dbpro_patch_ops = { diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 6807b4708a17..654724559355 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1128,7 +1128,6 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) return 0; } -#ifdef CONFIG_PM /* * Manage PDREF, when transitioning to D3hot * (DAC,ADC) -> D3, PDREF=1, AFG->D3 @@ -1153,7 +1152,6 @@ static int cs421x_suspend(struct hda_codec *codec) return 0; } -#endif static const struct hda_codec_ops cs421x_patch_ops = { .build_controls = snd_hda_gen_build_controls, @@ -1161,9 +1159,7 @@ static const struct hda_codec_ops cs421x_patch_ops = { .init = cs421x_init, .free = cs_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .suspend = cs421x_suspend, -#endif }; static int patch_cs4210(struct hda_codec *codec) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index e8209178d87b..17389a3801bd 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -294,13 +294,11 @@ static void cx_jack_unsol_event(struct hda_codec *codec, unsigned int res) snd_hda_jack_unsol_event(codec, res); } -#ifdef CONFIG_PM static int cx_auto_suspend(struct hda_codec *codec) { cx_auto_shutdown(codec); return 0; } -#endif static const struct hda_codec_ops cx_auto_patch_ops = { .build_controls = snd_hda_gen_build_controls, @@ -308,10 +306,8 @@ static const struct hda_codec_ops cx_auto_patch_ops = { .init = cx_auto_init, .free = cx_auto_free, .unsol_event = cx_jack_unsol_event, -#ifdef CONFIG_PM .suspend = cx_auto_suspend, .check_power_status = snd_hda_gen_check_power_status, -#endif }; /* diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c index e41316e2e983..26f3c31600d7 100644 --- a/sound/pci/hda/patch_cs8409.c +++ b/sound/pci/hda/patch_cs8409.c @@ -909,7 +909,6 @@ static void cs42l42_resume(struct sub_codec *cs42l42) cs42l42_enable_jack_detect(cs42l42); } -#ifdef CONFIG_PM static void cs42l42_suspend(struct sub_codec *cs42l42) { struct hda_codec *codec = cs42l42->codec; @@ -948,7 +947,6 @@ static void cs42l42_suspend(struct sub_codec *cs42l42) spec->gpio_data &= ~cs42l42->reset_gpio; snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_data); } -#endif static void cs8409_free(struct hda_codec *codec) { @@ -1003,7 +1001,6 @@ static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned in } } -#ifdef CONFIG_PM /* Manage PDREF, when transition to D3hot */ static int cs8409_cs42l42_suspend(struct hda_codec *codec) { @@ -1025,7 +1022,6 @@ static int cs8409_cs42l42_suspend(struct hda_codec *codec) return 0; } -#endif /* Vendor specific HW configuration * PLL, ASP, I2C, SPI, GPIOs, DMIC etc... @@ -1080,9 +1076,7 @@ static const struct hda_codec_ops cs8409_cs42l42_patch_ops = { .init = cs8409_init, .free = cs8409_free, .unsol_event = cs8409_cs42l42_jack_unsol_event, -#ifdef CONFIG_PM .suspend = cs8409_cs42l42_suspend, -#endif }; static int cs8409_cs42l42_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags, @@ -1310,9 +1304,7 @@ static const struct hda_codec_ops cs8409_dolphin_patch_ops = { .init = cs8409_init, .free = cs8409_free, .unsol_event = dolphin_jack_unsol_event, -#ifdef CONFIG_PM .suspend = cs8409_cs42l42_suspend, -#endif }; static int dolphin_exec_verb(struct hdac_device *dev, unsigned int cmd, unsigned int flags, diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 0a00c5ea42e0..db24c8fc7cd0 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2513,7 +2513,6 @@ static void generic_hdmi_free(struct hda_codec *codec) generic_spec_free(codec); } -#ifdef CONFIG_PM static int generic_hdmi_suspend(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2540,7 +2539,6 @@ static int generic_hdmi_resume(struct hda_codec *codec) } return 0; } -#endif static const struct hda_codec_ops generic_hdmi_patch_ops = { .init = generic_hdmi_init, @@ -2548,10 +2546,8 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = { .build_pcms = generic_hdmi_build_pcms, .build_controls = generic_hdmi_build_controls, .unsol_event = hdmi_unsol_event, -#ifdef CONFIG_PM .suspend = generic_hdmi_suspend, .resume = generic_hdmi_resume, -#endif }; static const struct hdmi_ops generic_standard_hdmi_ops = { @@ -2952,7 +2948,6 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec, } } -#ifdef CONFIG_PM static int i915_adlp_hdmi_suspend(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -3032,7 +3027,6 @@ static int i915_adlp_hdmi_resume(struct hda_codec *codec) return res; } -#endif /* precondition and allocation for Intel codecs */ static int alloc_intel_hdmi(struct hda_codec *codec) @@ -3167,10 +3161,8 @@ static int patch_i915_adlp_hdmi(struct hda_codec *codec) if (spec->silent_stream_type) { spec->silent_stream_type = SILENT_STREAM_KAE; -#ifdef CONFIG_PM codec->patch_ops.resume = i915_adlp_hdmi_resume; codec->patch_ops.suspend = i915_adlp_hdmi_suspend; -#endif } } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 38a9b4872f1e..2eb419c814f6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -109,9 +109,7 @@ struct alc_spec { /* hooks */ void (*init_hook)(struct hda_codec *codec); -#ifdef CONFIG_PM void (*power_hook)(struct hda_codec *codec); -#endif void (*shutup)(struct hda_codec *codec); int init_amp; @@ -920,6 +918,8 @@ static void alc_pre_init(struct hda_codec *codec) ((codec)->core.dev.power.power_state.event == PM_EVENT_RESUME) #define is_s4_resume(codec) \ ((codec)->core.dev.power.power_state.event == PM_EVENT_RESTORE) +#define is_s4_suspend(codec) \ + ((codec)->core.dev.power.power_state.event == PM_EVENT_FREEZE) static int alc_init(struct hda_codec *codec) { @@ -945,7 +945,6 @@ static int alc_init(struct hda_codec *codec) #define alc_free snd_hda_gen_free -#ifdef CONFIG_PM static inline void alc_shutup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -984,7 +983,6 @@ static int alc_resume(struct hda_codec *codec) hda_call_check_power_status(codec, 0x01); return 0; } -#endif /* */ @@ -994,11 +992,9 @@ static const struct hda_codec_ops alc_patch_ops = { .init = alc_init, .free = alc_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .resume = alc_resume, .suspend = alc_suspend, .check_power_status = snd_hda_gen_check_power_status, -#endif }; @@ -4039,7 +4035,6 @@ static void alc5505_dsp_init(struct hda_codec *codec) #define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec) #endif -#ifdef CONFIG_PM static int alc269_suspend(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -4085,7 +4080,6 @@ static int alc269_resume(struct hda_codec *codec) return 0; } -#endif /* CONFIG_PM */ static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -7183,6 +7177,44 @@ static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec, alc245_fixup_hp_gpio_led(codec, fix, action); } +/* + * ALC287 PCM hooks + */ +static void alc287_alc1318_playback_pcm_hook(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream, + int action) +{ + alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */ + switch (action) { + case HDA_GEN_PCM_ACT_OPEN: + alc_write_coefex_idx(codec, 0x5a, 0x00, 0x954f); /* write gpio3 to high */ + break; + case HDA_GEN_PCM_ACT_CLOSE: + alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */ + break; + } +} + +static void alc287_s4_power_gpio3_default(struct hda_codec *codec) +{ + if (is_s4_suspend(codec)) { + alc_write_coef_idx(codec, 0x10, 0x8806); /* Change MLK to GPIO3 */ + alc_write_coefex_idx(codec, 0x5a, 0x00, 0x554f); /* write gpio3 as default value */ + } +} + +static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + spec->power_hook = alc287_s4_power_gpio3_default; + spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook; +} + enum { ALC269_FIXUP_GPIO2, @@ -7426,6 +7458,7 @@ enum { ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, ALC298_FIXUP_LENOVO_C940_DUET7, ALC287_FIXUP_LENOVO_14IRP8_DUETITL, + ALC287_FIXUP_LENOVO_LEGION_7, ALC287_FIXUP_13S_GEN2_SPEAKERS, ALC256_FIXUP_SET_COEF_DEFAULTS, ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, @@ -7470,7 +7503,8 @@ enum { ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC, ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1, ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC, - ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1 + ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1, + ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -7510,6 +7544,23 @@ static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec, __snd_hda_apply_fixup(codec, id, action, 0); } +/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with + * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec); + * we apply a corresponding fixup depending on the codec SSID instead + */ +static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + int id; + + if (codec->core.subsystem_id == 0x17aa38a8) + id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */ + else + id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */ + __snd_hda_apply_fixup(codec, id, action, 0); +} + static const struct hda_fixup alc269_fixups[] = { [ALC269_FIXUP_GPIO2] = { .type = HDA_FIXUP_FUNC, @@ -9404,6 +9455,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc287_fixup_lenovo_14irp8_duetitl, }, + [ALC287_FIXUP_LENOVO_LEGION_7] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_lenovo_legion_7, + }, [ALC287_FIXUP_13S_GEN2_SPEAKERS] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -9726,6 +9781,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_ASUS_GA403U, }, + [ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_lenovo_thinkpad_with_alc1318, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -9937,6 +9998,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), @@ -10397,6 +10459,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), + SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318), + SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), @@ -10428,7 +10492,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), - SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7), SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), @@ -11219,10 +11283,8 @@ static int patch_alc269(struct hda_codec *codec) codec->power_save_node = 0; spec->en_3kpull_low = true; -#ifdef CONFIG_PM codec->patch_ops.suspend = alc269_suspend; codec->patch_ops.resume = alc269_resume; -#endif spec->shutup = alc_default_shutup; spec->init_hook = alc_default_init; @@ -11520,9 +11582,7 @@ static int patch_alc861(struct hda_codec *codec) if (has_cdefine_beep(codec)) spec->gen.beep_nid = 0x23; -#ifdef CONFIG_PM spec->power_hook = alc_power_eapd; -#endif alc_pre_init(codec); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 61258b0aac8d..ae1a34c68c61 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -2154,10 +2154,8 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec, if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ -#ifdef CONFIG_PM /* resetting controller clears GPIO, so we need to keep on */ codec->core.power_caps &= ~AC_PWRST_CLKSTOP; -#endif } } @@ -4442,7 +4440,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, #define stac927x_proc_hook NULL #endif -#ifdef CONFIG_PM static int stac_suspend(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -4456,9 +4453,6 @@ static int stac_suspend(struct hda_codec *codec) return 0; } -#else -#define stac_suspend NULL -#endif /* CONFIG_PM */ static const struct hda_codec_ops stac_patch_ops = { .build_controls = snd_hda_gen_build_controls, @@ -4466,9 +4460,7 @@ static const struct hda_codec_ops stac_patch_ops = { .init = stac_init, .free = stac_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .suspend = stac_suspend, -#endif }; static int alloc_stac_spec(struct hda_codec *codec) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 2994f85bc1b9..a8ef4bb70dd0 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -379,7 +379,6 @@ static void via_free(struct hda_codec *codec) snd_hda_gen_free(codec); } -#ifdef CONFIG_PM static int via_suspend(struct hda_codec *codec) { struct via_spec *spec = codec->spec; @@ -400,9 +399,7 @@ static int via_resume(struct hda_codec *codec) snd_hda_regmap_sync(codec); return 0; } -#endif -#ifdef CONFIG_PM static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) { struct via_spec *spec = codec->spec; @@ -410,7 +407,6 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) vt1708_update_hp_work(codec); return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid); } -#endif /* */ @@ -423,11 +419,9 @@ static const struct hda_codec_ops via_patch_ops = { .init = via_init, .free = via_free, .unsol_event = snd_hda_jack_unsol_event, -#ifdef CONFIG_PM .suspend = via_suspend, .resume = via_resume, .check_power_status = via_check_power_status, -#endif }; diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 69c68d8e7a6b..1760b5d42460 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -433,6 +433,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { { .driver_data = &acp6x_card, .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MDC"), + DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "System76"), DMI_MATCH(DMI_PRODUCT_VERSION, "pang12"), } diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index dfb4ce53491b..f8e57a2fc3e3 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1094,6 +1094,7 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf static int cs35l41_dsp_init(struct cs35l41_private *cs35l41) { struct wm_adsp *dsp; + uint32_t dsp1rx5_src; int ret; dsp = &cs35l41->dsp; @@ -1113,16 +1114,29 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41) return ret; } - ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, - CS35L41_INPUT_SRC_VPMON); + switch (cs35l41->hw_cfg.bst_type) { + case CS35L41_INT_BOOST: + case CS35L41_SHD_BOOST_ACTV: + dsp1rx5_src = CS35L41_INPUT_SRC_VPMON; + break; + case CS35L41_EXT_BOOST: + case CS35L41_SHD_BOOST_PASS: + dsp1rx5_src = CS35L41_INPUT_SRC_VBSTMON; + break; + default: + dev_err(cs35l41->dev, "wm_halo_init failed - Invalid Boost Type: %d\n", + cs35l41->hw_cfg.bst_type); + goto err_dsp; + } + + ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, dsp1rx5_src); if (ret < 0) { - dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret); + dev_err(cs35l41->dev, "Write DSP1RX5_SRC: %d failed: %d\n", dsp1rx5_src, ret); goto err_dsp; } - ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, - CS35L41_INPUT_SRC_CLASSH); + ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, CS35L41_INPUT_SRC_VBSTMON); if (ret < 0) { - dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret); + dev_err(cs35l41->dev, "Write CS35L41_INPUT_SRC_VBSTMON failed: %d\n", ret); goto err_dsp; } ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC, diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 14a5f86019aa..70ff55c1517f 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -188,8 +188,6 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) goto out; } - regcache_cache_only(cs35l56->base.regmap, false); - ret = cs35l56_init(cs35l56); if (ret < 0) { regcache_cache_only(cs35l56->base.regmap, true); diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 08cac58e3ab2..fd02b621da52 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -40,16 +40,11 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED); static const struct reg_default cs35l56_reg_defaults[] = { /* no defaults for OTP_MEM - first read populates cache */ - { CS35L56_ASP1_ENABLES1, 0x00000000 }, - { CS35L56_ASP1_CONTROL1, 0x00000028 }, - { CS35L56_ASP1_CONTROL2, 0x18180200 }, - { CS35L56_ASP1_CONTROL3, 0x00000002 }, - { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, - { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, - { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, - { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, - - /* no defaults for ASP1TX mixer */ + /* + * No defaults for ASP1 control or ASP1TX mixer. See + * cs35l56_populate_asp1_register_defaults() and + * cs35l56_sync_asp1_mixer_widgets_with_firmware(). + */ { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, @@ -210,6 +205,36 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) } } +static const struct reg_sequence cs35l56_asp1_defaults[] = { + REG_SEQ0(CS35L56_ASP1_ENABLES1, 0x00000000), + REG_SEQ0(CS35L56_ASP1_CONTROL1, 0x00000028), + REG_SEQ0(CS35L56_ASP1_CONTROL2, 0x18180200), + REG_SEQ0(CS35L56_ASP1_CONTROL3, 0x00000002), + REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1, 0x03020100), + REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5, 0x00020100), + REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1, 0x00000018), + REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5, 0x00000018), +}; + +/* + * The firmware can have control of the ASP so we don't provide regmap + * with defaults for these registers, to prevent a regcache_sync() from + * overwriting the firmware settings. But if the machine driver hooks up + * the ASP it means the driver is taking control of the ASP, so then the + * registers are populated with the defaults. + */ +int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base) +{ + if (!cs35l56_base->fw_owns_asp1) + return 0; + + cs35l56_base->fw_owns_asp1 = false; + + return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults, + ARRAY_SIZE(cs35l56_asp1_defaults)); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED); + /* * The firmware boot sequence can overwrite the ASP1 config registers so that * they don't match regmap's view of their values. Rewrite the values from the @@ -217,19 +242,15 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg) */ int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base) { - struct reg_sequence asp1_regs[] = { - { .reg = CS35L56_ASP1_ENABLES1 }, - { .reg = CS35L56_ASP1_CONTROL1 }, - { .reg = CS35L56_ASP1_CONTROL2 }, - { .reg = CS35L56_ASP1_CONTROL3 }, - { .reg = CS35L56_ASP1_FRAME_CONTROL1 }, - { .reg = CS35L56_ASP1_FRAME_CONTROL5 }, - { .reg = CS35L56_ASP1_DATA_CONTROL1 }, - { .reg = CS35L56_ASP1_DATA_CONTROL5 }, - }; + struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)]; int i, ret; - /* Read values from regmap cache into a write sequence */ + if (cs35l56_base->fw_owns_asp1) + return 0; + + memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs)); + + /* Read current values from regmap cache into the write sequence */ for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) { ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def); if (ret) @@ -307,10 +328,10 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) reg = CS35L56_DSP1_HALO_STATE; /* - * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK - * I2C until it has booted which would terminate the poll + * The regmap must remain in cache-only until the chip has + * booted, so use a bypassed read of the status register. */ - poll_ret = read_poll_timeout(regmap_read, read_ret, + poll_ret = read_poll_timeout(regmap_read_bypassed, read_ret, (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE), CS35L56_HALO_STATE_POLL_US, CS35L56_HALO_STATE_TIMEOUT_US, @@ -362,7 +383,8 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire) return; cs35l56_wait_control_port_ready(); - regcache_cache_only(cs35l56_base->regmap, false); + + /* Leave in cache-only. This will be revoked when the chip has rebooted. */ } EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED); @@ -577,14 +599,14 @@ int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_sou cs35l56_issue_wake_event(cs35l56_base); out_sync: - regcache_cache_only(cs35l56_base->regmap, false); - ret = cs35l56_wait_for_firmware_boot(cs35l56_base); if (ret) { dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret); goto err; } + regcache_cache_only(cs35l56_base->regmap, false); + ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE); if (ret) goto err; @@ -684,7 +706,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED); int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base) { - u64 silicon_uid; + u64 silicon_uid = 0; int ret; /* Driver can't apply calibration to a secured part, so skip */ @@ -757,7 +779,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) * devices so the REVID needs to be determined before waiting for the * firmware to boot. */ - ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid); + ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid); if (ret < 0) { dev_err(cs35l56_base->dev, "Get Revision ID failed\n"); return ret; @@ -768,7 +790,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) if (ret) return ret; - ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid); + ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_DEVID, &devid); if (ret < 0) { dev_err(cs35l56_base->dev, "Get Device ID failed\n"); return ret; @@ -787,6 +809,9 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) cs35l56_base->type = devid & 0xFF; + /* Silicon is now identified and booted so exit cache-only */ + regcache_cache_only(cs35l56_base->regmap, false); + ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); if (ret) { dev_err(cs35l56_base->dev, "Get Secure status failed\n"); diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 8d2f021fb362..4986e78105da 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -454,9 +454,14 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); unsigned int val; + int ret; dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt); + ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); + if (ret) + return ret; + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { case SND_SOC_DAIFMT_CBC_CFC: break; @@ -530,6 +535,11 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx unsigned int rx_mask, int slots, int slot_width) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); + int ret; + + ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); + if (ret) + return ret; if ((slots == 0) || (slot_width == 0)) { dev_dbg(cs35l56->base.dev, "tdm config cleared\n"); @@ -578,6 +588,11 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream, struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); unsigned int rate = params_rate(params); u8 asp_width, asp_wl; + int ret; + + ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); + if (ret) + return ret; asp_wl = params_width(params); if (cs35l56->asp_slot_width) @@ -634,7 +649,11 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); - int freq_id; + int freq_id, ret; + + ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); + if (ret) + return ret; if (freq == 0) { cs35l56->sysclk_set = false; @@ -1341,6 +1360,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5 "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj); if (ret) { dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret); + fwnode_handle_put(af01_fwnode); return -ENOENT; } @@ -1348,6 +1368,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5 if (obj->package.count != 4) { dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n", obj->package.count); + fwnode_handle_put(af01_fwnode); return -ENOENT; } @@ -1362,6 +1383,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5 */ ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping); if (ret) { + fwnode_handle_put(af01_fwnode); return dev_err_probe(cs35l56->base.dev, ret, "Failed to add gpio mapping to AF01\n"); } @@ -1369,14 +1391,17 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5 ret = devm_add_action_or_reset(cs35l56->base.dev, cs35l56_acpi_dev_release_driver_gpios, adev); - if (ret) + if (ret) { + fwnode_handle_put(af01_fwnode); return ret; + } dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n"); } desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL); if (IS_ERR(desc)) { + fwnode_handle_put(af01_fwnode); ret = PTR_ERR(desc); return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n"); } @@ -1385,9 +1410,12 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5 gpiod_put(desc); if (ret < 0) { + fwnode_handle_put(af01_fwnode); dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n"); return ret; - } + } + + fwnode_handle_put(af01_fwnode); dev_info(cs35l56->base.dev, "Got spk-id from AF01\n"); @@ -1403,6 +1431,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) cs35l56->base.cal_index = -1; cs35l56->speaker_id = -ENOENT; + /* Assume that the firmware owns ASP1 until we know different */ + cs35l56->base.fw_owns_asp1 = true; + dev_set_drvdata(cs35l56->base.dev, cs35l56); cs35l56_fill_supply_names(cs35l56->supplies); @@ -1531,6 +1562,8 @@ post_soft_reset: return ret; dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n"); + + regcache_cache_only(cs35l56->base.regmap, false); } /* Disable auto-hibernate so that runtime_pm has control */ diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 6bc068cdcbe2..15e5e3eb592b 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -671,8 +671,10 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev) return NULL; aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL); - if (!aad_pdata) + if (!aad_pdata) { + fwnode_handle_put(aad_np); return NULL; + } aad_pdata->irq = i2c->irq; @@ -753,6 +755,8 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev) else aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1; + fwnode_handle_put(aad_np); + return aad_pdata; } diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index e3ba04484813..d0d24a53df74 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -444,6 +444,7 @@ struct rt5645_priv { struct regmap *regmap; struct i2c_client *i2c; struct gpio_desc *gpiod_hp_det; + struct gpio_desc *gpiod_cbj_sleeve; struct snd_soc_jack *hp_jack; struct snd_soc_jack *mic_jack; struct snd_soc_jack *btn_jack; @@ -3186,6 +3187,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2, RT5645_CBJ_MN_JD, 0); + if (rt5645->gpiod_cbj_sleeve) + gpiod_set_value(rt5645->gpiod_cbj_sleeve, 1); + msleep(600); regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val); val &= 0x7; @@ -3202,6 +3206,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); snd_soc_dapm_sync(dapm); rt5645->jack_type = SND_JACK_HEADPHONE; + if (rt5645->gpiod_cbj_sleeve) + gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0); } if (rt5645->pdata.level_trigger_irq) regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, @@ -3229,6 +3235,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse if (rt5645->pdata.level_trigger_irq) regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); + + if (rt5645->gpiod_cbj_sleeve) + gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0); } return rt5645->jack_type; @@ -4012,6 +4021,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c) return ret; } + rt5645->gpiod_cbj_sleeve = devm_gpiod_get_optional(&i2c->dev, "cbj-sleeve", + GPIOD_OUT_LOW); + + if (IS_ERR(rt5645->gpiod_cbj_sleeve)) { + ret = PTR_ERR(rt5645->gpiod_cbj_sleeve); + dev_info(&i2c->dev, "failed to initialize gpiod, ret=%d\n", ret); + if (ret != -ENOENT) + return ret; + } + for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++) rt5645->supplies[i].supply = rt5645_supply_names[i]; @@ -4259,6 +4278,9 @@ static void rt5645_i2c_remove(struct i2c_client *i2c) cancel_delayed_work_sync(&rt5645->jack_detect_work); cancel_delayed_work_sync(&rt5645->rcclock_work); + if (rt5645->gpiod_cbj_sleeve) + gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0); + regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); } @@ -4274,6 +4296,9 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c) 0); msleep(20); regmap_write(rt5645->regmap, RT5645_RESET, 0); + + if (rt5645->gpiod_cbj_sleeve) + gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0); } static int __maybe_unused rt5645_sys_suspend(struct device *dev) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 3fb7b9adb61d..bc3579203c7a 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -316,7 +316,7 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol, return 0; } -static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol, @@ -477,7 +477,7 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = { RT715_SDCA_FU_VOL_CTRL, CH_01), SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, RT715_SDCA_FU_VOL_CTRL, CH_02), - 0x2f, 0x7f, 0, + 0x2f, 0x3f, 0, rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put, in_vol_tlv), RT715_SDCA_EXT_TLV("FU02 Capture Volume", @@ -485,13 +485,13 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = { RT715_SDCA_FU_VOL_CTRL, CH_01), rt715_sdca_set_amp_gain_4ch_get, rt715_sdca_set_amp_gain_4ch_put, - in_vol_tlv, 4, 0x7f), + in_vol_tlv, 4, 0x3f), RT715_SDCA_EXT_TLV("FU06 Capture Volume", SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, RT715_SDCA_FU_VOL_CTRL, CH_01), rt715_sdca_set_amp_gain_4ch_get, rt715_sdca_set_amp_gain_4ch_put, - in_vol_tlv, 4, 0x7f), + in_vol_tlv, 4, 0x3f), /* MIC Boost Control */ RT715_SDCA_BOOST_EXT_TLV("FU0E Boost", SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 7e13868ff99f..f012fe0ded6d 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -111,6 +111,7 @@ static bool rt715_readable_register(struct device *dev, unsigned int reg) case 0x839d: case 0x83a7: case 0x83a9: + case 0x752001: case 0x752039: return true; default: diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index e0ea3a23f7cc..e5bd9ef812de 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -1330,7 +1330,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = { .capture = { .stream_name = "DP6 DMic Capture", .channels_min = 1, - .channels_max = 2, + .channels_max = 4, .rates = RT722_STEREO_RATES, .formats = RT722_FORMATS, }, @@ -1439,9 +1439,12 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722) int loop_check, chk_cnt = 100, ret; unsigned int calib_status = 0; - /* Read eFuse */ - rt722_sdca_index_write(rt722, RT722_VENDOR_SPK_EFUSE, RT722_DC_CALIB_CTRL, - 0x4808); + /* Config analog bias */ + rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3, + 0xa081); + /* GE related settings */ + rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2, + 0xa009); /* Button A, B, C, D bypass mode */ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4, 0xcf00); @@ -1475,9 +1478,6 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722) if ((calib_status & 0x0040) == 0x0) break; } - /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */ - rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4, - 0x0010); /* Set ADC09 power entity floating control */ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL, 0x2a12); @@ -1490,8 +1490,21 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722) /* Set DAC03 and HP power entity floating control */ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL, 0x4040); + rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1, + 0x4141); + rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1, + 0x0101); /* Fine tune PDE40 latency */ regmap_write(rt722->regmap, 0x2f58, 0x07); + regmap_write(rt722->regmap, 0x2f03, 0x06); + /* MIC VRefo */ + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG, + RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200); + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG, + RT722_VREFO_GAT, 0x4000, 0x4000); + /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */ + rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4, + 0x0010); } int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave) diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h index 44af8901352e..2464361a7958 100644 --- a/sound/soc/codecs/rt722-sdca.h +++ b/sound/soc/codecs/rt722-sdca.h @@ -69,6 +69,7 @@ struct rt722_sdca_dmic_kctrl_priv { #define RT722_COMBO_JACK_AUTO_CTL2 0x46 #define RT722_COMBO_JACK_AUTO_CTL3 0x47 #define RT722_DIGITAL_MISC_CTRL4 0x4a +#define RT722_VREFO_GAT 0x63 #define RT722_FSM_CTL 0x67 #define RT722_SDCA_INTR_REC 0x82 #define RT722_SW_CONFIG1 0x8a @@ -127,6 +128,8 @@ struct rt722_sdca_dmic_kctrl_priv { #define RT722_UMP_HID_CTL6 0x66 #define RT722_UMP_HID_CTL7 0x67 #define RT722_UMP_HID_CTL8 0x68 +#define RT722_FLOAT_CTRL_1 0x70 +#define RT722_ENT_FLOAT_CTRL_1 0x76 /* Parameter & Verb control 01 (0x1a)(NID:20h) */ #define RT722_HIDDEN_REG_SW_RESET (0x1 << 14) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 3c025dabaf7a..1253695bebd8 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + pdev->prop.clk_stop_mode1 = true; gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val); wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config); diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index 9d9921e1cd4d..d2554c857732 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -64,7 +64,7 @@ struct avs_icl_memwnd2_desc { struct avs_icl_memwnd2 { union { struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT]; - u8 rsvd[PAGE_SIZE]; + u8 rsvd[SZ_4K]; }; u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE]; } __packed; diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 13061bd1488b..42b42903ae9d 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1582,6 +1582,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, if (!le32_to_cpu(dw->priv.size)) return 0; + w->no_wname_in_kcontrol_name = true; + if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) { dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n"); w->ignore_suspend = false; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 05f38d1f7d82..b41a1147f1c3 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -636,28 +636,30 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_USE_AMCR0F28), }, { + /* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), }, .driver_data = (void *)(BYT_RT5640_IN1_MAP | BYT_RT5640_JD_SRC_JD2_IN4N | BYT_RT5640_OVCD_TH_2000UA | BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF2 | BYT_RT5640_MCLK_EN), }, { + /* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */ .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"), }, .driver_data = (void *)(BYT_RT5640_IN1_MAP | BYT_RT5640_JD_SRC_JD2_IN4N | BYT_RT5640_OVCD_TH_2000UA | BYT_RT5640_OVCD_SF_0P75 | - BYT_RT5640_MONO_SPEAKER | - BYT_RT5640_DIFF_MIC | - BYT_RT5640_SSP0_AIF2 | BYT_RT5640_MCLK_EN), }, { diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index b93ea33739f2..6458d5dc4902 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM config SND_MESON_CARD_UTILS tristate + select SND_DYNAMIC_MINORS config SND_MESON_CODEC_GLUE tristate diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 3180aa4d3a15..8c5605c1e34e 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c @@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, dai_link->cpus = cpu; dai_link->num_cpus = 1; + dai_link->nonatomic = true; ret = meson_card_parse_dai(card, np, dai_link->cpus); if (ret) diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index bebee0ca8e38..ecb3eb7a9723 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -204,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) unsigned int status; regmap_read(fifo->map, FIFO_STATUS1, &status); - status = FIELD_GET(STATUS1_INT_STS, status); + axg_fifo_ack_irq(fifo, status); + + /* Use the thread to call period elapsed on nonatomic links */ if (status & FIFO_INT_COUNT_REPEAT) - snd_pcm_period_elapsed(ss); - else - dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", - status); + return IRQ_WAKE_THREAD; - /* Ack irqs */ - axg_fifo_ack_irq(fifo, status); + dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", + status); + + return IRQ_NONE; +} + +static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id) +{ + struct snd_pcm_substream *ss = dev_id; + + snd_pcm_period_elapsed(ss); - return IRQ_RETVAL(status); + return IRQ_HANDLED; } int axg_fifo_pcm_open(struct snd_soc_component *component, @@ -243,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, if (ret) return ret; - ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, - dev_name(dev), ss); + ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block, + axg_fifo_pcm_irq_block_thread, + IRQF_ONESHOT, dev_name(dev), ss); if (ret) return ret; diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index 63333a2b0a9c..a6579efd3775 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -392,6 +392,46 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts) } EXPORT_SYMBOL_GPL(axg_tdm_stream_free); +int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts, + unsigned int fmt) +{ + int ret = 0; + + if (fmt & SND_SOC_DAIFMT_CONT) { + /* Clock are already enabled - skipping */ + if (ts->clk_enabled) + return 0; + + ret = clk_prepare_enable(ts->iface->mclk); + if (ret) + return ret; + + ret = clk_prepare_enable(ts->iface->sclk); + if (ret) + goto err_sclk; + + ret = clk_prepare_enable(ts->iface->lrclk); + if (ret) + goto err_lrclk; + + ts->clk_enabled = true; + return 0; + } + + /* Clocks are already disabled - skipping */ + if (!ts->clk_enabled) + return 0; + + clk_disable_unprepare(ts->iface->lrclk); +err_lrclk: + clk_disable_unprepare(ts->iface->sclk); +err_sclk: + clk_disable_unprepare(ts->iface->mclk); + ts->clk_enabled = false; + return ret; +} +EXPORT_SYMBOL_GPL(axg_tdm_stream_set_cont_clocks); + MODULE_DESCRIPTION("Amlogic AXG TDM formatter driver"); MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index bf708717635b..62057c71f742 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -309,6 +309,7 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); + struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); int ret; switch (iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -346,7 +347,11 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, return ret; } - return 0; + ret = axg_tdm_stream_set_cont_clocks(ts, iface->fmt); + if (ret) + dev_err(dai->dev, "failed to apply continuous clock setting\n"); + + return ret; } static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream, @@ -354,19 +359,32 @@ static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream, { struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); - /* Stop all attached formatters */ - axg_tdm_stream_stop(ts); - - return 0; + return axg_tdm_stream_set_cont_clocks(ts, 0); } -static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream, +static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) { - struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); + struct axg_tdm_stream *ts = + snd_soc_dai_get_dma_data(dai, substream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + axg_tdm_stream_start(ts); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_STOP: + axg_tdm_stream_stop(ts); + break; + default: + return -EINVAL; + } - /* Force all attached formatters to update */ - return axg_tdm_stream_reset(ts); + return 0; } static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai) @@ -412,8 +430,8 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = { .set_fmt = axg_tdm_iface_set_fmt, .startup = axg_tdm_iface_startup, .hw_params = axg_tdm_iface_hw_params, - .prepare = axg_tdm_iface_prepare, .hw_free = axg_tdm_iface_hw_free, + .trigger = axg_tdm_iface_trigger, }; /* TDM Backend DAIs */ diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h index 42f7470b9a7f..daaca10fec9e 100644 --- a/sound/soc/meson/axg-tdm.h +++ b/sound/soc/meson/axg-tdm.h @@ -58,12 +58,17 @@ struct axg_tdm_stream { unsigned int physical_width; u32 *mask; bool ready; + + /* For continuous clock tracking */ + bool clk_enabled; }; struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface); void axg_tdm_stream_free(struct axg_tdm_stream *ts); int axg_tdm_stream_start(struct axg_tdm_stream *ts); void axg_tdm_stream_stop(struct axg_tdm_stream *ts); +int axg_tdm_stream_set_cont_clocks(struct axg_tdm_stream *ts, + unsigned int fmt); static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts) { diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index cc84d4c81be9..238bda5f6b76 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -350,7 +350,9 @@ static int sof_init_environment(struct snd_sof_dev *sdev) } ret = sof_select_ipc_and_paths(sdev); - if (!ret && plat_data->ipc_type != base_profile->ipc_type) { + if (ret) { + goto err_machine_check; + } else if (plat_data->ipc_type != base_profile->ipc_type) { /* IPC type changed, re-initialize the ops */ sof_ops_free(sdev); diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 7c8aafca8fde..7275437ea8d8 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -330,14 +330,32 @@ EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init); int snd_sof_dbg_init(struct snd_sof_dev *sdev) { + struct snd_sof_pdata *plat_data = sdev->pdata; struct snd_sof_dsp_ops *ops = sof_ops(sdev); const struct snd_sof_debugfs_map *map; + struct dentry *fw_profile; int i; int err; /* use "sof" as top level debugFS dir */ sdev->debugfs_root = debugfs_create_dir("sof", NULL); + /* expose firmware/topology prefix/names for test purposes */ + fw_profile = debugfs_create_dir("fw_profile", sdev->debugfs_root); + + debugfs_create_str("fw_path", 0444, fw_profile, + (char **)&plat_data->fw_filename_prefix); + debugfs_create_str("fw_lib_path", 0444, fw_profile, + (char **)&plat_data->fw_lib_prefix); + debugfs_create_str("tplg_path", 0444, fw_profile, + (char **)&plat_data->tplg_filename_prefix); + debugfs_create_str("fw_name", 0444, fw_profile, + (char **)&plat_data->fw_filename); + debugfs_create_str("tplg_name", 0444, fw_profile, + (char **)&plat_data->tplg_filename); + debugfs_create_u32("ipc_type", 0444, fw_profile, + (u32 *)&plat_data->ipc_type); + /* init dfsentry list */ INIT_LIST_HEAD(&sdev->dfsentry_list); diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index b26ffe767fab..b14e508f1f31 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = { .default_fw_path = { [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl", }, + .default_lib_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl", + }, .default_tplg_path = { [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", }, diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index 35769dd7905e..af0bf354cb20 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -434,4 +434,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = { .trigger = sof_ipc3_pcm_trigger, .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup, .reset_hw_params_during_stop = true, + .d0i3_supported_in_s0ix = true, }; diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index e915f9f87a6c..4594470ed08b 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -37,6 +37,25 @@ struct sof_ipc4_timestamp_info { snd_pcm_sframes_t delay; }; +/** + * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data + * @time_info: pointer to time info struct if it is supported, otherwise NULL + * @chain_dma_allocated: indicates the ChainDMA allocation state + */ +struct sof_ipc4_pcm_stream_priv { + struct sof_ipc4_timestamp_info *time_info; + + bool chain_dma_allocated; +}; + +static inline struct sof_ipc4_timestamp_info * +sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps) +{ + struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private; + + return stream_priv->time_info; +} + static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state, struct ipc4_pipeline_set_state_data *trigger_list) { @@ -253,14 +272,17 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd, */ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, - int direction, + struct snd_sof_pcm *spcm, int direction, struct snd_sof_pcm_stream_pipeline_list *pipeline_list, int state, int cmd) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; + struct sof_ipc4_pcm_stream_priv *stream_priv; bool allocate, enable, set_fifo_size; struct sof_ipc4_msg msg = {{ 0 }}; - int i; + int ret, i; + + stream_priv = spcm->stream[direction].private; switch (state) { case SOF_IPC4_PIPE_RUNNING: /* Allocate and start chained dma */ @@ -281,6 +303,11 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, set_fifo_size = false; break; case SOF_IPC4_PIPE_RESET: /* Disable and free chained DMA. */ + + /* ChainDMA can only be reset if it has been allocated */ + if (!stream_priv->chain_dma_allocated) + return 0; + allocate = false; enable = false; set_fifo_size = false; @@ -338,7 +365,12 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev, if (enable) msg.primary |= SOF_IPC4_GLB_CHAIN_DMA_ENABLE_MASK; - return sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); + ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); + /* Update the ChainDMA allocation state */ + if (!ret) + stream_priv->chain_dma_allocated = allocate; + + return ret; } static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, @@ -378,7 +410,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, * trigger function that handles the rest for the substream. */ if (pipeline->use_chain_dma) - return sof_ipc4_chain_dma_trigger(sdev, substream->stream, + return sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream, pipeline_list, state, cmd); /* allocate memory for the pipeline data */ @@ -452,7 +484,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, * Invalidate the stream_start_offset to make sure that it is * going to be updated if the stream resumes */ - time_info = spcm->stream[substream->stream].private; + time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); if (time_info) time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION; @@ -706,12 +738,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm) { struct snd_sof_pcm_stream_pipeline_list *pipeline_list; + struct sof_ipc4_pcm_stream_priv *stream_priv; int stream; for_each_pcm_streams(stream) { pipeline_list = &spcm->stream[stream].pipeline_list; kfree(pipeline_list->pipelines); pipeline_list->pipelines = NULL; + + stream_priv = spcm->stream[stream].private; + kfree(stream_priv->time_info); kfree(spcm->stream[stream].private); spcm->stream[stream].private = NULL; } @@ -721,7 +757,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm { struct snd_sof_pcm_stream_pipeline_list *pipeline_list; struct sof_ipc4_fw_data *ipc4_data = sdev->private; - struct sof_ipc4_timestamp_info *stream_info; + struct sof_ipc4_pcm_stream_priv *stream_priv; + struct sof_ipc4_timestamp_info *time_info; bool support_info = true; u32 abi_version; u32 abi_offset; @@ -749,33 +786,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm return -ENOMEM; } + stream_priv = kzalloc(sizeof(*stream_priv), GFP_KERNEL); + if (!stream_priv) { + sof_ipc4_pcm_free(sdev, spcm); + return -ENOMEM; + } + + spcm->stream[stream].private = stream_priv; + if (!support_info) continue; - stream_info = kzalloc(sizeof(*stream_info), GFP_KERNEL); - if (!stream_info) { + time_info = kzalloc(sizeof(*time_info), GFP_KERNEL); + if (!time_info) { sof_ipc4_pcm_free(sdev, spcm); return -ENOMEM; } - spcm->stream[stream].private = stream_info; + stream_priv->time_info = time_info; } return 0; } -static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *spcm) +static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps) { struct sof_ipc4_copier *host_copier = NULL; struct sof_ipc4_copier *dai_copier = NULL; struct sof_ipc4_llp_reading_slot llp_slot; - struct sof_ipc4_timestamp_info *info; + struct sof_ipc4_timestamp_info *time_info; struct snd_soc_dapm_widget *widget; struct snd_sof_dai *dai; int i; /* find host & dai to locate info in memory window */ - for_each_dapm_widgets(spcm->list, i, widget) { + for_each_dapm_widgets(sps->list, i, widget) { struct snd_sof_widget *swidget = widget->dobj.private; if (!swidget) @@ -795,44 +840,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc return; } - info = spcm->private; - info->host_copier = host_copier; - info->dai_copier = dai_copier; - info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_gpdma_reading_slots) + - sdev->fw_info_box.offset; + time_info = sof_ipc4_sps_to_time_info(sps); + time_info->host_copier = host_copier; + time_info->dai_copier = dai_copier; + time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, + llp_gpdma_reading_slots) + sdev->fw_info_box.offset; /* find llp slot used by current dai */ for (i = 0; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS; i++) { - sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot)); + sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id) break; - info->llp_offset += sizeof(llp_slot); + time_info->llp_offset += sizeof(llp_slot); } if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS) return; /* if no llp gpdma slot is used, check aggregated sdw slot */ - info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_sndw_reading_slots) + - sdev->fw_info_box.offset; + time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, + llp_sndw_reading_slots) + sdev->fw_info_box.offset; for (i = 0; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS; i++) { - sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot)); + sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id) break; - info->llp_offset += sizeof(llp_slot); + time_info->llp_offset += sizeof(llp_slot); } if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS) return; /* check EVAD slot */ - info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_evad_reading_slot) + - sdev->fw_info_box.offset; - sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot)); + time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers, + llp_evad_reading_slot) + sdev->fw_info_box.offset; + sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot)); if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id) - info->llp_offset = 0; + time_info->llp_offset = 0; } static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component, @@ -849,7 +894,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component, if (!spcm) return -EINVAL; - time_info = spcm->stream[substream->stream].private; + time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); /* delay calculation is not supported by current fw_reg ABI */ if (!time_info) return 0; @@ -864,7 +909,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component, static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, - struct snd_sof_pcm_stream *stream, + struct snd_sof_pcm_stream *sps, struct sof_ipc4_timestamp_info *time_info) { struct sof_ipc4_copier *host_copier = time_info->host_copier; @@ -918,7 +963,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component, struct sof_ipc4_timestamp_info *time_info; struct sof_ipc4_llp_reading_slot llp; snd_pcm_uframes_t head_cnt, tail_cnt; - struct snd_sof_pcm_stream *stream; + struct snd_sof_pcm_stream *sps; u64 dai_cnt, host_cnt, host_ptr; struct snd_sof_pcm *spcm; int ret; @@ -927,8 +972,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component, if (!spcm) return -EOPNOTSUPP; - stream = &spcm->stream[substream->stream]; - time_info = stream->private; + sps = &spcm->stream[substream->stream]; + time_info = sof_ipc4_sps_to_time_info(sps); if (!time_info) return -EOPNOTSUPP; @@ -938,7 +983,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component, * the statistics is complete. And it will not change after the first initiailization. */ if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) { - ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info); + ret = sof_ipc4_get_stream_start_offset(sdev, substream, sps, time_info); if (ret < 0) return -EOPNOTSUPP; } @@ -1030,15 +1075,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sof_ipc4_timestamp_info *time_info; - struct snd_sof_pcm_stream *stream; struct snd_sof_pcm *spcm; spcm = snd_sof_find_spcm_dai(component, rtd); if (!spcm) return 0; - stream = &spcm->stream[substream->stream]; - time_info = stream->private; + time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]); /* * Report the stored delay value calculated in the pointer callback. * In the unlikely event that the calculation was skipped/aborted, the diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index f03cee94bce6..8804e00e7251 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -325,14 +325,13 @@ static int sof_pcm_trigger(struct snd_soc_component *component, ipc_first = true; break; case SNDRV_PCM_TRIGGER_SUSPEND: - if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && + /* + * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for + * D0I3-compatible streams to keep the firmware pipeline running + */ + if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix && + sdev->system_suspend_target == SOF_SUSPEND_S0IX && spcm->stream[substream->stream].d0i3_compatible) { - /* - * trap the event, not sending trigger stop to - * prevent the FW pipelines from being stopped, - * and mark the flag to ignore the upcoming DAPM - * PM events. - */ spcm->stream[substream->stream].suspend_ignored = true; return 0; } diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 86bbb531e142..499b6084b526 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -116,6 +116,7 @@ struct snd_sof_dai_config_data { * triggers. The FW keeps the host DMA running in this case and * therefore the host must do the same and should stop the DMA during * hw_free. + * @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX */ struct sof_ipc_pcm_ops { int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, @@ -135,6 +136,7 @@ struct sof_ipc_pcm_ops { bool reset_hw_params_during_stop; bool ipc_first_on_start; bool platform_stop_during_hw_free; + bool d0i3_supported_in_s0ix; }; /** diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index aa37c4ab0adb..21cd41fec7a9 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -1,8 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // // tegra186_dspk.c - Tegra186 DSPK driver -// -// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. #include <linux/clk.h> #include <linux/device.h> @@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - cif_conf.client_bits = TEGRA_ACIF_BITS_24; - switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_16; + cif_conf.client_bits = TEGRA_ACIF_BITS_16; break; case SNDRV_PCM_FORMAT_S32_LE: cif_conf.audio_bits = TEGRA_ACIF_BITS_32; + cif_conf.client_bits = TEGRA_ACIF_BITS_24; break; default: dev_err(dev, "unsupported format!\n"); diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index b892d66f7847..1e760c315521 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -2417,12 +2417,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp_reparent_fck(pdev); - ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, - &davinci_mcasp_dai[mcasp->op_mode], 1); - - if (ret != 0) - goto err; - ret = davinci_mcasp_get_dma_type(mcasp); switch (ret) { case PCM_EDMA: @@ -2449,6 +2443,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) goto err; } + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, + &davinci_mcasp_dai[mcasp->op_mode], 1); + + if (ret != 0) + goto err; + no_audio: ret = davinci_mcasp_init_gpiochip(mcasp); if (ret) { |