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 /* 10 * Management of HDaudio multi-link (capabilities, power, coupling) 11 */ 12 13 #include <sound/hdaudio_ext.h> 14 #include <sound/hda_register.h> 15 16 #include <linux/acpi.h> 17 #include <linux/module.h> 18 #include <linux/soundwire/sdw.h> 19 #include <linux/soundwire/sdw_intel.h> 20 #include <sound/intel-dsp-config.h> 21 #include <sound/intel-nhlt.h> 22 #include <sound/sof.h> 23 #include <sound/sof/xtensa.h> 24 #include "../sof-audio.h" 25 #include "../sof-pci-dev.h" 26 #include "../ops.h" 27 #include "hda.h" 28 29 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) 30 31 void hda_bus_ml_get_capabilities(struct hdac_bus *bus) 32 { 33 if (bus->mlcap) 34 snd_hdac_ext_bus_get_ml_capabilities(bus); 35 } 36 37 void hda_bus_ml_free(struct hdac_bus *bus) 38 { 39 struct hdac_ext_link *hlink; 40 41 if (!bus->mlcap) 42 return; 43 44 while (!list_empty(&bus->hlink_list)) { 45 hlink = list_first_entry(&bus->hlink_list, struct hdac_ext_link, list); 46 list_del(&hlink->list); 47 kfree(hlink); 48 } 49 } 50 51 void hda_bus_ml_put_all(struct hdac_bus *bus) 52 { 53 struct hdac_ext_link *hlink; 54 55 list_for_each_entry(hlink, &bus->hlink_list, list) 56 snd_hdac_ext_bus_link_put(bus, hlink); 57 } 58 59 void hda_bus_ml_reset_losidv(struct hdac_bus *bus) 60 { 61 struct hdac_ext_link *hlink; 62 63 /* Reset stream-to-link mapping */ 64 list_for_each_entry(hlink, &bus->hlink_list, list) 65 writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV); 66 } 67 68 int hda_bus_ml_resume(struct hdac_bus *bus) 69 { 70 struct hdac_ext_link *hlink; 71 int ret; 72 73 /* power up links that were active before suspend */ 74 list_for_each_entry(hlink, &bus->hlink_list, list) { 75 if (hlink->ref_count) { 76 ret = snd_hdac_ext_bus_link_power_up(hlink); 77 if (ret < 0) 78 return ret; 79 } 80 } 81 return 0; 82 } 83 84 int hda_bus_ml_suspend(struct hdac_bus *bus) 85 { 86 return snd_hdac_ext_bus_link_power_down_all(bus); 87 } 88 89 #endif 90