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

TOMOYO Linux Cross Reference
Linux/sound/soc/sof/intel/cnl.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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 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) 2018 Intel Corporation
  7 //
  8 // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
  9 //          Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
 10 //          Rander Wang <rander.wang@intel.com>
 11 //          Keyon Jie <yang.jie@linux.intel.com>
 12 //
 13 
 14 /*
 15  * Hardware interface for audio DSP on Cannonlake.
 16  */
 17 
 18 #include <sound/sof/ext_manifest4.h>
 19 #include <sound/sof/ipc4/header.h>
 20 #include <trace/events/sof_intel.h>
 21 #include "../ipc4-priv.h"
 22 #include "../ops.h"
 23 #include "hda.h"
 24 #include "hda-ipc.h"
 25 #include "../sof-audio.h"
 26 
 27 static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = {
 28         {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
 29         {"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
 30         {"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
 31 };
 32 
 33 static void cnl_ipc_host_done(struct snd_sof_dev *sdev);
 34 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev);
 35 
 36 irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
 37 {
 38         struct sof_ipc4_msg notification_data = {{ 0 }};
 39         struct snd_sof_dev *sdev = context;
 40         bool ack_received = false;
 41         bool ipc_irq = false;
 42         u32 hipcida, hipctdr;
 43 
 44         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
 45         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
 46         if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
 47                 /* DSP received the message */
 48                 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
 49                                         CNL_DSP_REG_HIPCCTL,
 50                                         CNL_DSP_REG_HIPCCTL_DONE, 0);
 51                 cnl_ipc_dsp_done(sdev);
 52 
 53                 ipc_irq = true;
 54                 ack_received = true;
 55         }
 56 
 57         if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
 58                 /* Message from DSP (reply or notification) */
 59                 u32 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
 60                                                CNL_DSP_REG_HIPCTDD);
 61                 u32 primary = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
 62                 u32 extension = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
 63 
 64                 if (primary & SOF_IPC4_MSG_DIR_MASK) {
 65                         /* Reply received */
 66                         if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
 67                                 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
 68 
 69                                 data->primary = primary;
 70                                 data->extension = extension;
 71 
 72                                 spin_lock_irq(&sdev->ipc_lock);
 73 
 74                                 snd_sof_ipc_get_reply(sdev);
 75                                 cnl_ipc_host_done(sdev);
 76                                 snd_sof_ipc_reply(sdev, data->primary);
 77 
 78                                 spin_unlock_irq(&sdev->ipc_lock);
 79                         } else {
 80                                 dev_dbg_ratelimited(sdev->dev,
 81                                                     "IPC reply before FW_READY: %#x|%#x\n",
 82                                                     primary, extension);
 83                         }
 84                 } else {
 85                         /* Notification received */
 86                         notification_data.primary = primary;
 87                         notification_data.extension = extension;
 88 
 89                         sdev->ipc->msg.rx_data = &notification_data;
 90                         snd_sof_ipc_msgs_rx(sdev);
 91                         sdev->ipc->msg.rx_data = NULL;
 92 
 93                         /* Let DSP know that we have finished processing the message */
 94                         cnl_ipc_host_done(sdev);
 95                 }
 96 
 97                 ipc_irq = true;
 98         }
 99 
100         if (!ipc_irq)
101                 /* This interrupt is not shared so no need to return IRQ_NONE. */
102                 dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
103 
104         if (ack_received) {
105                 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
106 
107                 if (hdev->delayed_ipc_tx_msg)
108                         cnl_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg);
109         }
110 
111         return IRQ_HANDLED;
112 }
113 EXPORT_SYMBOL_NS(cnl_ipc4_irq_thread, SND_SOC_SOF_INTEL_CNL);
114 
115 irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
116 {
117         struct snd_sof_dev *sdev = context;
118         u32 hipci;
119         u32 hipcida;
120         u32 hipctdr;
121         u32 hipctdd;
122         u32 msg;
123         u32 msg_ext;
124         bool ipc_irq = false;
125 
126         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
127         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
128         hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
129         hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
130 
131         /* reply message from DSP */
132         if (hipcida & CNL_DSP_REG_HIPCIDA_DONE) {
133                 msg_ext = hipci & CNL_DSP_REG_HIPCIDR_MSG_MASK;
134                 msg = hipcida & CNL_DSP_REG_HIPCIDA_MSG_MASK;
135 
136                 trace_sof_intel_ipc_firmware_response(sdev, msg, msg_ext);
137 
138                 /* mask Done interrupt */
139                 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
140                                         CNL_DSP_REG_HIPCCTL,
141                                         CNL_DSP_REG_HIPCCTL_DONE, 0);
142 
143                 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
144                         spin_lock_irq(&sdev->ipc_lock);
145 
146                         /* handle immediate reply from DSP core */
147                         hda_dsp_ipc_get_reply(sdev);
148                         snd_sof_ipc_reply(sdev, msg);
149 
150                         cnl_ipc_dsp_done(sdev);
151 
152                         spin_unlock_irq(&sdev->ipc_lock);
153                 } else {
154                         dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
155                                             msg);
156                 }
157 
158                 ipc_irq = true;
159         }
160 
161         /* new message from DSP */
162         if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) {
163                 msg = hipctdr & CNL_DSP_REG_HIPCTDR_MSG_MASK;
164                 msg_ext = hipctdd & CNL_DSP_REG_HIPCTDD_MSG_MASK;
165 
166                 trace_sof_intel_ipc_firmware_initiated(sdev, msg, msg_ext);
167 
168                 /* handle messages from DSP */
169                 if ((hipctdr & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
170                         struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
171                         bool non_recoverable = true;
172 
173                         /*
174                          * This is a PANIC message!
175                          *
176                          * If it is arriving during firmware boot and it is not
177                          * the last boot attempt then change the non_recoverable
178                          * to false as the DSP might be able to boot in the next
179                          * iteration(s)
180                          */
181                         if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS &&
182                             hda->boot_iteration < HDA_FW_BOOT_ATTEMPTS)
183                                 non_recoverable = false;
184 
185                         snd_sof_dsp_panic(sdev, HDA_DSP_PANIC_OFFSET(msg_ext),
186                                           non_recoverable);
187                 } else {
188                         snd_sof_ipc_msgs_rx(sdev);
189                 }
190 
191                 cnl_ipc_host_done(sdev);
192 
193                 ipc_irq = true;
194         }
195 
196         if (!ipc_irq) {
197                 /*
198                  * This interrupt is not shared so no need to return IRQ_NONE.
199                  */
200                 dev_dbg_ratelimited(sdev->dev,
201                                     "nothing to do in IPC IRQ thread\n");
202         }
203 
204         return IRQ_HANDLED;
205 }
206 EXPORT_SYMBOL_NS(cnl_ipc_irq_thread, SND_SOC_SOF_INTEL_CNL);
207 
208 static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
209 {
210         /*
211          * clear busy interrupt to tell dsp controller this
212          * interrupt has been accepted, not trigger it again
213          */
214         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
215                                        CNL_DSP_REG_HIPCTDR,
216                                        CNL_DSP_REG_HIPCTDR_BUSY,
217                                        CNL_DSP_REG_HIPCTDR_BUSY);
218         /*
219          * set done bit to ack dsp the msg has been
220          * processed and send reply msg to dsp
221          */
222         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
223                                        CNL_DSP_REG_HIPCTDA,
224                                        CNL_DSP_REG_HIPCTDA_DONE,
225                                        CNL_DSP_REG_HIPCTDA_DONE);
226 }
227 
228 static void cnl_ipc_dsp_done(struct snd_sof_dev *sdev)
229 {
230         /*
231          * set DONE bit - tell DSP we have received the reply msg
232          * from DSP, and processed it, don't send more reply to host
233          */
234         snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR,
235                                        CNL_DSP_REG_HIPCIDA,
236                                        CNL_DSP_REG_HIPCIDA_DONE,
237                                        CNL_DSP_REG_HIPCIDA_DONE);
238 
239         /* unmask Done interrupt */
240         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
241                                 CNL_DSP_REG_HIPCCTL,
242                                 CNL_DSP_REG_HIPCCTL_DONE,
243                                 CNL_DSP_REG_HIPCCTL_DONE);
244 }
245 
246 static bool cnl_compact_ipc_compress(struct snd_sof_ipc_msg *msg,
247                                      u32 *dr, u32 *dd)
248 {
249         struct sof_ipc_pm_gate *pm_gate = msg->msg_data;
250 
251         if (pm_gate->hdr.cmd == (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE)) {
252                 /* send the compact message via the primary register */
253                 *dr = HDA_IPC_MSG_COMPACT | HDA_IPC_PM_GATE;
254 
255                 /* send payload via the extended data register */
256                 *dd = pm_gate->flags;
257 
258                 return true;
259         }
260 
261         return false;
262 }
263 
264 int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
265 {
266         struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
267         struct sof_ipc4_msg *msg_data = msg->msg_data;
268 
269         if (hda_ipc4_tx_is_busy(sdev)) {
270                 hdev->delayed_ipc_tx_msg = msg;
271                 return 0;
272         }
273 
274         hdev->delayed_ipc_tx_msg = NULL;
275 
276         /* send the message via mailbox */
277         if (msg_data->data_size)
278                 sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
279                                   msg_data->data_size);
280 
281         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD, msg_data->extension);
282         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
283                           msg_data->primary | CNL_DSP_REG_HIPCIDR_BUSY);
284 
285         hda_dsp_ipc4_schedule_d0i3_work(hdev, msg);
286 
287         return 0;
288 }
289 EXPORT_SYMBOL_NS(cnl_ipc4_send_msg, SND_SOC_SOF_INTEL_CNL);
290 
291 int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
292 {
293         struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
294         struct sof_ipc_cmd_hdr *hdr;
295         u32 dr = 0;
296         u32 dd = 0;
297 
298         /*
299          * Currently the only compact IPC supported is the PM_GATE
300          * IPC which is used for transitioning the DSP between the
301          * D0I0 and D0I3 states. And these are sent only during the
302          * set_power_state() op. Therefore, there will never be a case
303          * that a compact IPC results in the DSP exiting D0I3 without
304          * the host and FW being in sync.
305          */
306         if (cnl_compact_ipc_compress(msg, &dr, &dd)) {
307                 /* send the message via IPC registers */
308                 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD,
309                                   dd);
310                 snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
311                                   CNL_DSP_REG_HIPCIDR_BUSY | dr);
312                 return 0;
313         }
314 
315         /* send the message via mailbox */
316         sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
317                           msg->msg_size);
318         snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR,
319                           CNL_DSP_REG_HIPCIDR_BUSY);
320 
321         hdr = msg->msg_data;
322 
323         /*
324          * Use mod_delayed_work() to schedule the delayed work
325          * to avoid scheduling multiple workqueue items when
326          * IPCs are sent at a high-rate. mod_delayed_work()
327          * modifies the timer if the work is pending.
328          * Also, a new delayed work should not be queued after the
329          * CTX_SAVE IPC, which is sent before the DSP enters D3.
330          */
331         if (hdr->cmd != (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE))
332                 mod_delayed_work(system_wq, &hdev->d0i3_work,
333                                  msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS));
334 
335         return 0;
336 }
337 EXPORT_SYMBOL_NS(cnl_ipc_send_msg, SND_SOC_SOF_INTEL_CNL);
338 
339 void cnl_ipc_dump(struct snd_sof_dev *sdev)
340 {
341         u32 hipcctl;
342         u32 hipcida;
343         u32 hipctdr;
344 
345         hda_ipc_irq_dump(sdev);
346 
347         /* read IPC status */
348         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
349         hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
350         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
351 
352         /* dump the IPC regs */
353         /* TODO: parse the raw msg */
354         dev_err(sdev->dev,
355                 "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
356                 hipcida, hipctdr, hipcctl);
357 }
358 EXPORT_SYMBOL_NS(cnl_ipc_dump, SND_SOC_SOF_INTEL_CNL);
359 
360 void cnl_ipc4_dump(struct snd_sof_dev *sdev)
361 {
362         u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl;
363 
364         hda_ipc_irq_dump(sdev);
365 
366         hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR);
367         hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDD);
368         hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDA);
369         hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDR);
370         hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDD);
371         hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCTDA);
372         hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCCTL);
373 
374         /* dump the IPC regs */
375         /* TODO: parse the raw msg */
376         dev_err(sdev->dev,
377                 "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
378                 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
379 }
380 EXPORT_SYMBOL_NS(cnl_ipc4_dump, SND_SOC_SOF_INTEL_CNL);
381 
382 /* cannonlake ops */
383 struct snd_sof_dsp_ops sof_cnl_ops;
384 EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_CNL);
385 
386 int sof_cnl_ops_init(struct snd_sof_dev *sdev)
387 {
388         /* common defaults */
389         memcpy(&sof_cnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
390 
391         /* probe/remove/shutdown */
392         sof_cnl_ops.shutdown    = hda_dsp_shutdown;
393 
394         /* ipc */
395         if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3) {
396                 /* doorbell */
397                 sof_cnl_ops.irq_thread  = cnl_ipc_irq_thread;
398 
399                 /* ipc */
400                 sof_cnl_ops.send_msg    = cnl_ipc_send_msg;
401 
402                 /* debug */
403                 sof_cnl_ops.ipc_dump    = cnl_ipc_dump;
404 
405                 sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc3;
406         }
407 
408         if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) {
409                 struct sof_ipc4_fw_data *ipc4_data;
410 
411                 sdev->private = kzalloc(sizeof(*ipc4_data), GFP_KERNEL);
412                 if (!sdev->private)
413                         return -ENOMEM;
414 
415                 ipc4_data = sdev->private;
416                 ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
417 
418                 ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_1_8;
419 
420                 /* External library loading support */
421                 ipc4_data->load_library = hda_dsp_ipc4_load_library;
422 
423                 /* doorbell */
424                 sof_cnl_ops.irq_thread  = cnl_ipc4_irq_thread;
425 
426                 /* ipc */
427                 sof_cnl_ops.send_msg    = cnl_ipc4_send_msg;
428 
429                 /* debug */
430                 sof_cnl_ops.ipc_dump    = cnl_ipc4_dump;
431 
432                 sof_cnl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
433         }
434 
435         /* set DAI driver ops */
436         hda_set_dai_drv_ops(sdev, &sof_cnl_ops);
437 
438         /* debug */
439         sof_cnl_ops.debug_map   = cnl_dsp_debugfs;
440         sof_cnl_ops.debug_map_count     = ARRAY_SIZE(cnl_dsp_debugfs);
441 
442         /* pre/post fw run */
443         sof_cnl_ops.post_fw_run = hda_dsp_post_fw_run;
444 
445         /* firmware run */
446         sof_cnl_ops.run = hda_dsp_cl_boot_firmware;
447 
448         /* dsp core get/put */
449         sof_cnl_ops.core_get = hda_dsp_core_get;
450 
451         return 0;
452 };
453 EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_CNL);
454 
455 const struct sof_intel_dsp_desc cnl_chip_info = {
456         /* Cannonlake */
457         .cores_num = 4,
458         .init_core_mask = 1,
459         .host_managed_cores_mask = GENMASK(3, 0),
460         .ipc_req = CNL_DSP_REG_HIPCIDR,
461         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
462         .ipc_ack = CNL_DSP_REG_HIPCIDA,
463         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
464         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
465         .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
466         .rom_init_timeout       = 300,
467         .ssp_count = CNL_SSP_COUNT,
468         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
469         .sdw_shim_base = SDW_SHIM_BASE,
470         .sdw_alh_base = SDW_ALH_BASE,
471         .d0i3_offset = SOF_HDA_VS_D0I3C,
472         .read_sdw_lcount =  hda_sdw_check_lcount_common,
473         .enable_sdw_irq = hda_common_enable_sdw_irq,
474         .check_sdw_irq  = hda_common_check_sdw_irq,
475         .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common,
476         .sdw_process_wakeen = hda_sdw_process_wakeen_common,
477         .check_ipc_irq  = hda_dsp_check_ipc_irq,
478         .cl_init = cl_dsp_init,
479         .power_down_dsp = hda_power_down_dsp,
480         .disable_interrupts = hda_dsp_disable_interrupts,
481         .hw_ip_version = SOF_INTEL_CAVS_1_8,
482 };
483 
484 /*
485  * JasperLake is technically derived from IceLake, and should be in
486  * described in icl.c. However since JasperLake was designed with
487  * two cores, it cannot support the IceLake-specific power-up sequences
488  * which rely on core3. To simplify, JasperLake uses the CannonLake ops and
489  * is described in cnl.c
490  */
491 const struct sof_intel_dsp_desc jsl_chip_info = {
492         /* Jasperlake */
493         .cores_num = 2,
494         .init_core_mask = 1,
495         .host_managed_cores_mask = GENMASK(1, 0),
496         .ipc_req = CNL_DSP_REG_HIPCIDR,
497         .ipc_req_mask = CNL_DSP_REG_HIPCIDR_BUSY,
498         .ipc_ack = CNL_DSP_REG_HIPCIDA,
499         .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE,
500         .ipc_ctl = CNL_DSP_REG_HIPCCTL,
501         .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS,
502         .rom_init_timeout       = 300,
503         .ssp_count = ICL_SSP_COUNT,
504         .ssp_base_offset = CNL_SSP_BASE_OFFSET,
505         .sdw_shim_base = SDW_SHIM_BASE,
506         .sdw_alh_base = SDW_ALH_BASE,
507         .d0i3_offset = SOF_HDA_VS_D0I3C,
508         .read_sdw_lcount =  hda_sdw_check_lcount_common,
509         .enable_sdw_irq = hda_common_enable_sdw_irq,
510         .check_sdw_irq  = hda_common_check_sdw_irq,
511         .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common,
512         .sdw_process_wakeen = hda_sdw_process_wakeen_common,
513         .check_ipc_irq  = hda_dsp_check_ipc_irq,
514         .cl_init = cl_dsp_init,
515         .power_down_dsp = hda_power_down_dsp,
516         .disable_interrupts = hda_dsp_disable_interrupts,
517         .hw_ip_version = SOF_INTEL_CAVS_2_0,
518 };
519 EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_CNL);
520 

~ [ 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