1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2021-2024 Intel Corporation 4 // 5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com> 6 // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 7 // 8 9 #include <linux/slab.h> 10 #include <sound/hdaudio.h> 11 #include <sound/hdaudio_ext.h> 12 #include "avs.h" 13 #include "messages.h" 14 15 #define ICL_VS_LTRP_GB_ICCMAX 95 16 17 #ifdef CONFIG_DEBUG_FS 18 int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 19 u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) 20 { 21 struct avs_icl_log_state_info *info; 22 u32 size, num_libs = adev->fw_cfg.max_libs_count; 23 int i, ret; 24 25 if (fls_long(resource_mask) > num_libs) 26 return -EINVAL; 27 size = struct_size(info, logs_priorities_mask, num_libs); 28 info = kzalloc(size, GFP_KERNEL); 29 if (!info) 30 return -ENOMEM; 31 32 info->aging_timer_period = aging_period; 33 info->fifo_full_timer_period = fifo_full_period; 34 info->enable = enable; 35 if (enable) 36 for_each_set_bit(i, &resource_mask, num_libs) 37 info->logs_priorities_mask[i] = *priorities++; 38 39 ret = avs_ipc_set_enable_logs(adev, (u8 *)info, size); 40 kfree(info); 41 if (ret) 42 return AVS_IPC_RET(ret); 43 44 return 0; 45 } 46 #endif 47 48 union avs_icl_memwnd2_slot_type { 49 u32 val; 50 struct { 51 u32 resource_id:8; 52 u32 type:24; 53 }; 54 } __packed; 55 static_assert(sizeof(union avs_icl_memwnd2_slot_type) == 4); 56 57 struct avs_icl_memwnd2_desc { 58 u32 resource_id; 59 union avs_icl_memwnd2_slot_type slot_id; 60 u32 vma; 61 } __packed; 62 static_assert(sizeof(struct avs_icl_memwnd2_desc) == 12); 63 64 #define AVS_ICL_MEMWND2_SLOTS_COUNT 15 65 66 struct avs_icl_memwnd2 { 67 union { 68 struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT]; 69 u8 rsvd[SZ_4K]; 70 }; 71 u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][SZ_4K]; 72 } __packed; 73 static_assert(sizeof(struct avs_icl_memwnd2) == 65536); 74 75 #define AVS_ICL_SLOT_UNUSED \ 76 ((union avs_icl_memwnd2_slot_type) { 0x00000000U }) 77 #define AVS_ICL_SLOT_CRITICAL_LOG \ 78 ((union avs_icl_memwnd2_slot_type) { 0x54524300U }) 79 #define AVS_ICL_SLOT_DEBUG_LOG \ 80 ((union avs_icl_memwnd2_slot_type) { 0x474f4c00U }) 81 #define AVS_ICL_SLOT_GDB_STUB \ 82 ((union avs_icl_memwnd2_slot_type) { 0x42444700U }) 83 #define AVS_ICL_SLOT_BROKEN \ 84 ((union avs_icl_memwnd2_slot_type) { 0x44414544U }) 85 86 static int avs_icl_slot_offset(struct avs_dev *adev, union avs_icl_memwnd2_slot_type slot_type) 87 { 88 struct avs_icl_memwnd2_desc desc[AVS_ICL_MEMWND2_SLOTS_COUNT]; 89 int i; 90 91 memcpy_fromio(&desc, avs_sram_addr(adev, AVS_DEBUG_WINDOW), sizeof(desc)); 92 93 for (i = 0; i < AVS_ICL_MEMWND2_SLOTS_COUNT; i++) 94 if (desc[i].slot_id.val == slot_type.val) 95 return offsetof(struct avs_icl_memwnd2, slot_array) + i * SZ_4K; 96 return -ENXIO; 97 } 98 99 int avs_icl_log_buffer_offset(struct avs_dev *adev, u32 core) 100 { 101 union avs_icl_memwnd2_slot_type slot_type = AVS_ICL_SLOT_DEBUG_LOG; 102 int ret; 103 104 slot_type.resource_id = core; 105 ret = avs_icl_slot_offset(adev, slot_type); 106 if (ret < 0) 107 dev_dbg(adev->dev, "No slot offset found for: %x\n", 108 slot_type.val); 109 110 return ret; 111 } 112 113 bool avs_icl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake) 114 { 115 /* Full-power when starting DMA engines. */ 116 if (tx->glb.set_ppl_state.state == AVS_PPL_STATE_RUNNING) 117 return true; 118 119 /* Payload-less IPCs do not take part in d0ix toggling. */ 120 return tx->size; 121 } 122 123 int avs_icl_set_d0ix(struct avs_dev *adev, bool enable) 124 { 125 int ret; 126 127 ret = avs_ipc_set_d0ix(adev, enable, false); 128 return AVS_IPC_RET(ret); 129 } 130 131 int avs_icl_load_basefw(struct avs_dev *adev, struct firmware *fw) 132 { 133 struct hdac_bus *bus = &adev->base.core; 134 struct hdac_ext_stream *host_stream; 135 struct snd_pcm_substream substream; 136 struct snd_dma_buffer dmab; 137 unsigned int sd_fmt; 138 u8 ltrp_gb; 139 int ret; 140 141 /* 142 * ICCMAX: 143 * 144 * For ICL+ platforms, as per HW recommendation LTRP_GB is set to 95us 145 * during FW load. Its original value shall be restored once load completes. 146 * 147 * To avoid DMI/OPIO L1 entry during the load procedure, additional CAPTURE 148 * stream is allocated and set to run. 149 */ 150 151 memset(&substream, 0, sizeof(substream)); 152 substream.stream = SNDRV_PCM_STREAM_CAPTURE; 153 154 host_stream = snd_hdac_ext_stream_assign(bus, &substream, HDAC_EXT_STREAM_TYPE_HOST); 155 if (!host_stream) 156 return -EBUSY; 157 158 ltrp_gb = snd_hdac_chip_readb(bus, VS_LTRP) & AZX_REG_VS_LTRP_GB_MASK; 159 /* Carries no real data, use default format. */ 160 sd_fmt = snd_hdac_stream_format(1, 32, 48000); 161 162 ret = snd_hdac_dsp_prepare(hdac_stream(host_stream), sd_fmt, fw->size, &dmab); 163 if (ret < 0) 164 goto release_stream; 165 166 snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ICL_VS_LTRP_GB_ICCMAX); 167 168 spin_lock(&bus->reg_lock); 169 snd_hdac_stream_start(hdac_stream(host_stream)); 170 spin_unlock(&bus->reg_lock); 171 172 ret = avs_hda_load_basefw(adev, fw); 173 174 spin_lock(&bus->reg_lock); 175 snd_hdac_stream_stop(hdac_stream(host_stream)); 176 spin_unlock(&bus->reg_lock); 177 178 snd_hdac_dsp_cleanup(hdac_stream(host_stream), &dmab); 179 180 release_stream: 181 snd_hdac_ext_stream_release(host_stream, HDAC_EXT_STREAM_TYPE_HOST); 182 snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ltrp_gb); 183 184 return ret; 185 } 186 187 const struct avs_dsp_ops avs_icl_dsp_ops = { 188 .power = avs_dsp_core_power, 189 .reset = avs_dsp_core_reset, 190 .stall = avs_dsp_core_stall, 191 .dsp_interrupt = avs_cnl_dsp_interrupt, 192 .int_control = avs_dsp_interrupt_control, 193 .load_basefw = avs_icl_load_basefw, 194 .load_lib = avs_hda_load_library, 195 .transfer_mods = avs_hda_transfer_modules, 196 .log_buffer_offset = avs_icl_log_buffer_offset, 197 .log_buffer_status = avs_apl_log_buffer_status, 198 .coredump = avs_apl_coredump, 199 .d0ix_toggle = avs_icl_d0ix_toggle, 200 .set_d0ix = avs_icl_set_d0ix, 201 AVS_SET_ENABLE_LOGS_OP(icl) 202 }; 203