~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/avs/skl.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 //
  3 // Copyright(c) 2021-2022 Intel Corporation
  4 //
  5 // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
  6 //          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
  7 //
  8 
  9 #include <linux/devcoredump.h>
 10 #include <linux/slab.h>
 11 #include <sound/hdaudio_ext.h>
 12 #include "avs.h"
 13 #include "cldma.h"
 14 #include "messages.h"
 15 
 16 void avs_skl_ipc_interrupt(struct avs_dev *adev)
 17 {
 18         const struct avs_spec *spec = adev->spec;
 19         u32 hipc_ack, hipc_rsp;
 20 
 21         snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
 22                               AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0);
 23 
 24         hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset);
 25         hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
 26 
 27         /* DSP acked host's request. */
 28         if (hipc_ack & spec->hipc->ack_done_mask) {
 29                 complete(&adev->ipc->done_completion);
 30 
 31                 /* Tell DSP it has our attention. */
 32                 snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask,
 33                                       spec->hipc->ack_done_mask);
 34         }
 35 
 36         /* DSP sent new response to process */
 37         if (hipc_rsp & spec->hipc->rsp_busy_mask) {
 38                 union avs_reply_msg msg;
 39 
 40                 msg.primary = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
 41                 msg.ext.val = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE);
 42 
 43                 avs_dsp_process_response(adev, msg.val);
 44 
 45                 /* Tell DSP we accepted its message. */
 46                 snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY,
 47                                       SKL_ADSP_HIPCT_BUSY);
 48         }
 49 
 50         snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
 51                               AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY,
 52                               AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY);
 53 }
 54 
 55 static irqreturn_t avs_skl_dsp_interrupt(struct avs_dev *adev)
 56 {
 57         u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS);
 58         irqreturn_t ret = IRQ_NONE;
 59 
 60         if (adspis == UINT_MAX)
 61                 return ret;
 62 
 63         if (adspis & AVS_ADSP_ADSPIS_CLDMA) {
 64                 hda_cldma_interrupt(&code_loader);
 65                 ret = IRQ_HANDLED;
 66         }
 67 
 68         if (adspis & AVS_ADSP_ADSPIS_IPC) {
 69                 avs_skl_ipc_interrupt(adev);
 70                 ret = IRQ_HANDLED;
 71         }
 72 
 73         return ret;
 74 }
 75 
 76 static int __maybe_unused
 77 avs_skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
 78                     u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
 79 {
 80         struct avs_skl_log_state_info *info;
 81         u32 size, num_cores = adev->hw_cfg.dsp_cores;
 82         int ret, i;
 83 
 84         if (fls_long(resource_mask) > num_cores)
 85                 return -EINVAL;
 86         size = struct_size(info, logs_core, num_cores);
 87         info = kzalloc(size, GFP_KERNEL);
 88         if (!info)
 89                 return -ENOMEM;
 90 
 91         info->core_mask = resource_mask;
 92         if (enable)
 93                 for_each_set_bit(i, &resource_mask, num_cores) {
 94                         info->logs_core[i].enable = enable;
 95                         info->logs_core[i].min_priority = *priorities++;
 96                 }
 97         else
 98                 for_each_set_bit(i, &resource_mask, num_cores)
 99                         info->logs_core[i].enable = enable;
100 
101         ret = avs_ipc_set_enable_logs(adev, (u8 *)info, size);
102         kfree(info);
103         if (ret)
104                 return AVS_IPC_RET(ret);
105 
106         return 0;
107 }
108 
109 int avs_skl_log_buffer_offset(struct avs_dev *adev, u32 core)
110 {
111         return core * avs_log_buffer_size(adev);
112 }
113 
114 /* fw DbgLogWp registers */
115 #define FW_REGS_DBG_LOG_WP(core) (0x30 + 0x4 * core)
116 
117 static int avs_skl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
118 {
119         void __iomem *buf;
120         u16 size, write, offset;
121 
122         if (!avs_logging_fw(adev))
123                 return 0;
124 
125         size = avs_log_buffer_size(adev) / 2;
126         write = readl(avs_sram_addr(adev, AVS_FW_REGS_WINDOW) + FW_REGS_DBG_LOG_WP(msg->log.core));
127         /* determine buffer half */
128         offset = (write < size) ? size : 0;
129 
130         /* Address is guaranteed to exist in SRAM2. */
131         buf = avs_log_buffer_addr(adev, msg->log.core) + offset;
132         avs_dump_fw_log_wakeup(adev, buf, size);
133 
134         return 0;
135 }
136 
137 static int avs_skl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
138 {
139         u8 *dump;
140 
141         dump = vzalloc(AVS_FW_REGS_SIZE);
142         if (!dump)
143                 return -ENOMEM;
144 
145         memcpy_fromio(dump, avs_sram_addr(adev, AVS_FW_REGS_WINDOW), AVS_FW_REGS_SIZE);
146         dev_coredumpv(adev->dev, dump, AVS_FW_REGS_SIZE, GFP_KERNEL);
147 
148         return 0;
149 }
150 
151 static bool avs_skl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
152 {
153         /* unsupported on cAVS 1.5 hw */
154         return false;
155 }
156 
157 static int avs_skl_set_d0ix(struct avs_dev *adev, bool enable)
158 {
159         /* unsupported on cAVS 1.5 hw */
160         return 0;
161 }
162 
163 const struct avs_dsp_ops avs_skl_dsp_ops = {
164         .power = avs_dsp_core_power,
165         .reset = avs_dsp_core_reset,
166         .stall = avs_dsp_core_stall,
167         .dsp_interrupt = avs_skl_dsp_interrupt,
168         .int_control = avs_dsp_interrupt_control,
169         .load_basefw = avs_cldma_load_basefw,
170         .load_lib = avs_cldma_load_library,
171         .transfer_mods = avs_cldma_transfer_modules,
172         .log_buffer_offset = avs_skl_log_buffer_offset,
173         .log_buffer_status = avs_skl_log_buffer_status,
174         .coredump = avs_skl_coredump,
175         .d0ix_toggle = avs_skl_d0ix_toggle,
176         .set_d0ix = avs_skl_set_d0ix,
177         AVS_SET_ENABLE_LOGS_OP(skl)
178 };
179 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php