Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/avs/loader.c
26583 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
//
3
// Copyright(c) 2021-2022 Intel Corporation
4
//
5
// Authors: Cezary Rojewski <[email protected]>
6
// Amadeusz Slawinski <[email protected]>
7
//
8
9
#include <linux/firmware.h>
10
#include <linux/module.h>
11
#include <linux/slab.h>
12
#include <linux/string.h>
13
#include <sound/hdaudio.h>
14
#include <sound/hdaudio_ext.h>
15
#include "avs.h"
16
#include "cldma.h"
17
#include "messages.h"
18
#include "registers.h"
19
#include "topology.h"
20
21
#define AVS_ROM_STS_MASK 0xFF
22
#define AVS_ROM_INIT_DONE 0x1
23
#define SKL_ROM_BASEFW_ENTERED 0xF
24
#define APL_ROM_FW_ENTERED 0x5
25
#define AVS_ROM_INIT_POLLING_US 5
26
#define SKL_ROM_INIT_TIMEOUT_US 1000000
27
#define APL_ROM_INIT_TIMEOUT_US 300000
28
#define APL_ROM_INIT_RETRIES 3
29
30
#define AVS_FW_INIT_POLLING_US 500
31
#define AVS_FW_INIT_TIMEOUT_MS 3000
32
#define AVS_FW_INIT_TIMEOUT_US (AVS_FW_INIT_TIMEOUT_MS * 1000)
33
34
#define AVS_CLDMA_START_DELAY_MS 100
35
36
#define AVS_ROOT_DIR "intel/avs"
37
#define AVS_BASEFW_FILENAME "dsp_basefw.bin"
38
#define AVS_EXT_MANIFEST_MAGIC 0x31454124
39
#define SKL_MANIFEST_MAGIC 0x00000006
40
#define SKL_ADSPFW_OFFSET 0x284
41
#define APL_MANIFEST_MAGIC 0x44504324
42
#define APL_ADSPFW_OFFSET 0x2000
43
44
/* Occasionally, engineering (release candidate) firmware is provided for testing. */
45
static bool debug_ignore_fw_version;
46
module_param_named(ignore_fw_version, debug_ignore_fw_version, bool, 0444);
47
MODULE_PARM_DESC(ignore_fw_version, "Ignore firmware version check 0=no (default), 1=yes");
48
49
#define AVS_LIB_NAME_SIZE 8
50
51
struct avs_fw_manifest {
52
u32 id;
53
u32 len;
54
char name[AVS_LIB_NAME_SIZE];
55
u32 preload_page_count;
56
u32 img_flags;
57
u32 feature_mask;
58
struct avs_fw_version version;
59
} __packed;
60
static_assert(sizeof(struct avs_fw_manifest) == 36);
61
62
struct avs_fw_ext_manifest {
63
u32 id;
64
u32 len;
65
u16 version_major;
66
u16 version_minor;
67
u32 entries;
68
} __packed;
69
static_assert(sizeof(struct avs_fw_ext_manifest) == 16);
70
71
static int avs_fw_ext_manifest_strip(struct firmware *fw)
72
{
73
struct avs_fw_ext_manifest *man;
74
75
if (fw->size < sizeof(*man))
76
return -EINVAL;
77
78
man = (struct avs_fw_ext_manifest *)fw->data;
79
if (man->id == AVS_EXT_MANIFEST_MAGIC) {
80
fw->data += man->len;
81
fw->size -= man->len;
82
}
83
84
return 0;
85
}
86
87
static int avs_fw_manifest_offset(struct firmware *fw)
88
{
89
/* Header type found in first DWORD of fw binary. */
90
u32 magic = *(u32 *)fw->data;
91
92
switch (magic) {
93
case SKL_MANIFEST_MAGIC:
94
return SKL_ADSPFW_OFFSET;
95
case APL_MANIFEST_MAGIC:
96
return APL_ADSPFW_OFFSET;
97
default:
98
return -EINVAL;
99
}
100
}
101
102
static int avs_fw_manifest_strip_verify(struct avs_dev *adev, struct firmware *fw,
103
const struct avs_fw_version *min)
104
{
105
struct avs_fw_manifest *man;
106
int offset, ret;
107
108
ret = avs_fw_ext_manifest_strip(fw);
109
if (ret)
110
return ret;
111
112
offset = avs_fw_manifest_offset(fw);
113
if (offset < 0)
114
return offset;
115
116
if (fw->size < offset + sizeof(*man))
117
return -EINVAL;
118
if (!min)
119
return 0;
120
121
man = (struct avs_fw_manifest *)(fw->data + offset);
122
if (man->version.major != min->major ||
123
man->version.minor != min->minor ||
124
man->version.hotfix != min->hotfix ||
125
man->version.build < min->build) {
126
dev_warn(adev->dev, "bad FW version %d.%d.%d.%d, expected %d.%d.%d.%d or newer\n",
127
man->version.major, man->version.minor,
128
man->version.hotfix, man->version.build,
129
min->major, min->minor, min->hotfix, min->build);
130
131
if (!debug_ignore_fw_version)
132
return -EINVAL;
133
}
134
135
return 0;
136
}
137
138
int avs_cldma_load_basefw(struct avs_dev *adev, struct firmware *fw)
139
{
140
struct hda_cldma *cl = &code_loader;
141
unsigned int reg;
142
int ret;
143
144
ret = avs_dsp_op(adev, power, AVS_MAIN_CORE_MASK, true);
145
if (ret < 0)
146
return ret;
147
148
ret = avs_dsp_op(adev, reset, AVS_MAIN_CORE_MASK, false);
149
if (ret < 0)
150
return ret;
151
152
ret = hda_cldma_reset(cl);
153
if (ret < 0) {
154
dev_err(adev->dev, "cldma reset failed: %d\n", ret);
155
return ret;
156
}
157
hda_cldma_setup(cl);
158
159
ret = avs_dsp_op(adev, stall, AVS_MAIN_CORE_MASK, false);
160
if (ret < 0)
161
return ret;
162
163
reinit_completion(&adev->fw_ready);
164
avs_dsp_op(adev, int_control, true);
165
166
/* await ROM init */
167
ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg,
168
(reg & AVS_ROM_INIT_DONE) == AVS_ROM_INIT_DONE,
169
AVS_ROM_INIT_POLLING_US, SKL_ROM_INIT_TIMEOUT_US);
170
if (ret < 0) {
171
dev_err(adev->dev, "rom init failed: %d, status: 0x%08x, lec: 0x%08x\n",
172
ret, reg, snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
173
avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
174
return ret;
175
}
176
177
hda_cldma_set_data(cl, (void *)fw->data, fw->size);
178
/* transfer firmware */
179
hda_cldma_transfer(cl, 0);
180
ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg,
181
(reg & AVS_ROM_STS_MASK) == SKL_ROM_BASEFW_ENTERED,
182
AVS_FW_INIT_POLLING_US, AVS_FW_INIT_TIMEOUT_US);
183
hda_cldma_stop(cl);
184
if (ret < 0) {
185
dev_err(adev->dev, "transfer fw failed: %d, status: 0x%08x, lec: 0x%08x\n",
186
ret, reg, snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
187
avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
188
return ret;
189
}
190
191
return 0;
192
}
193
194
int avs_cldma_load_library(struct avs_dev *adev, struct firmware *lib, u32 id)
195
{
196
struct hda_cldma *cl = &code_loader;
197
int ret;
198
199
hda_cldma_set_data(cl, (void *)lib->data, lib->size);
200
/* transfer modules manifest */
201
hda_cldma_transfer(cl, msecs_to_jiffies(AVS_CLDMA_START_DELAY_MS));
202
203
/* DMA id ignored as there is only ever one code-loader DMA */
204
ret = avs_ipc_load_library(adev, 0, id);
205
hda_cldma_stop(cl);
206
207
if (ret) {
208
ret = AVS_IPC_RET(ret);
209
dev_err(adev->dev, "transfer lib %d failed: %d\n", id, ret);
210
}
211
212
return ret;
213
}
214
215
static int avs_cldma_load_module(struct avs_dev *adev, struct avs_module_entry *mentry)
216
{
217
struct hda_cldma *cl = &code_loader;
218
const struct firmware *mod;
219
char *mod_name;
220
int ret;
221
222
mod_name = kasprintf(GFP_KERNEL, "%s/%s/dsp_mod_%pUL.bin", AVS_ROOT_DIR,
223
adev->spec->name, mentry->uuid.b);
224
if (!mod_name)
225
return -ENOMEM;
226
227
ret = avs_request_firmware(adev, &mod, mod_name);
228
kfree(mod_name);
229
if (ret < 0)
230
return ret;
231
232
avs_hda_power_gating_enable(adev, false);
233
avs_hda_clock_gating_enable(adev, false);
234
avs_hda_l1sen_enable(adev, false);
235
236
hda_cldma_set_data(cl, (void *)mod->data, mod->size);
237
hda_cldma_transfer(cl, msecs_to_jiffies(AVS_CLDMA_START_DELAY_MS));
238
ret = avs_ipc_load_modules(adev, &mentry->module_id, 1);
239
hda_cldma_stop(cl);
240
241
avs_hda_l1sen_enable(adev, true);
242
avs_hda_clock_gating_enable(adev, true);
243
avs_hda_power_gating_enable(adev, true);
244
245
if (ret) {
246
dev_err(adev->dev, "load module %d failed: %d\n", mentry->module_id, ret);
247
avs_release_last_firmware(adev);
248
return AVS_IPC_RET(ret);
249
}
250
251
return 0;
252
}
253
254
int avs_cldma_transfer_modules(struct avs_dev *adev, bool load,
255
struct avs_module_entry *mods, u32 num_mods)
256
{
257
u16 *mod_ids;
258
int ret, i;
259
260
/* Either load to DSP or unload them to free space. */
261
if (load) {
262
for (i = 0; i < num_mods; i++) {
263
ret = avs_cldma_load_module(adev, &mods[i]);
264
if (ret)
265
return ret;
266
}
267
268
return 0;
269
}
270
271
mod_ids = kcalloc(num_mods, sizeof(u16), GFP_KERNEL);
272
if (!mod_ids)
273
return -ENOMEM;
274
275
for (i = 0; i < num_mods; i++)
276
mod_ids[i] = mods[i].module_id;
277
278
ret = avs_ipc_unload_modules(adev, mod_ids, num_mods);
279
kfree(mod_ids);
280
if (ret)
281
return AVS_IPC_RET(ret);
282
283
return 0;
284
}
285
286
static int
287
avs_hda_init_rom(struct avs_dev *adev, unsigned int dma_id, bool purge)
288
{
289
const struct avs_spec *const spec = adev->spec;
290
unsigned int corex_mask, reg;
291
int ret;
292
293
corex_mask = spec->core_init_mask & ~AVS_MAIN_CORE_MASK;
294
295
ret = avs_dsp_op(adev, power, spec->core_init_mask, true);
296
if (ret < 0)
297
goto err;
298
299
ret = avs_dsp_op(adev, reset, AVS_MAIN_CORE_MASK, false);
300
if (ret < 0)
301
goto err;
302
303
reinit_completion(&adev->fw_ready);
304
avs_dsp_op(adev, int_control, true);
305
306
/* set boot config */
307
ret = avs_ipc_set_boot_config(adev, dma_id, purge);
308
if (ret) {
309
ret = AVS_IPC_RET(ret);
310
goto err;
311
}
312
313
/* await ROM init */
314
ret = snd_hdac_adsp_readl_poll(adev, spec->hipc->sts_offset, reg,
315
(reg & 0xF) == AVS_ROM_INIT_DONE ||
316
(reg & 0xF) == APL_ROM_FW_ENTERED,
317
AVS_ROM_INIT_POLLING_US, APL_ROM_INIT_TIMEOUT_US);
318
if (ret < 0) {
319
dev_err(adev->dev, "rom init failed: %d, status: 0x%08x, lec: 0x%08x\n",
320
ret, reg, snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
321
goto err;
322
}
323
324
/* power down non-main cores */
325
if (corex_mask) {
326
ret = avs_dsp_op(adev, power, corex_mask, false);
327
if (ret < 0)
328
goto err;
329
}
330
331
return 0;
332
333
err:
334
avs_dsp_core_disable(adev, spec->core_init_mask);
335
return ret;
336
}
337
338
static int avs_imr_load_basefw(struct avs_dev *adev)
339
{
340
int ret;
341
342
/* DMA id ignored when flashing from IMR as no transfer occurs. */
343
ret = avs_hda_init_rom(adev, 0, false);
344
if (ret < 0)
345
return ret;
346
347
ret = wait_for_completion_timeout(&adev->fw_ready,
348
msecs_to_jiffies(AVS_FW_INIT_TIMEOUT_MS));
349
if (!ret) {
350
dev_err(adev->dev, "firmware ready timeout, status: 0x%08x, lec: 0x%08x\n",
351
snd_hdac_adsp_readl(adev, AVS_FW_REG_STATUS(adev)),
352
snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
353
avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
354
return -ETIMEDOUT;
355
}
356
357
return 0;
358
}
359
360
int avs_hda_load_basefw(struct avs_dev *adev, struct firmware *fw)
361
{
362
struct snd_pcm_substream substream;
363
struct snd_dma_buffer dmab;
364
struct hdac_ext_stream *estream;
365
struct hdac_stream *hstream;
366
struct hdac_bus *bus = &adev->base.core;
367
unsigned int sdfmt, reg;
368
int ret, i;
369
370
/* configure hda dma */
371
memset(&substream, 0, sizeof(substream));
372
substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
373
estream = snd_hdac_ext_stream_assign(bus, &substream,
374
HDAC_EXT_STREAM_TYPE_HOST);
375
if (!estream)
376
return -ENODEV;
377
hstream = hdac_stream(estream);
378
379
/* code loading performed with default format */
380
sdfmt = snd_hdac_stream_format(1, 32, 48000);
381
ret = snd_hdac_dsp_prepare(hstream, sdfmt, fw->size, &dmab);
382
if (ret < 0)
383
goto release_stream;
384
385
/* enable SPIB for hda stream */
386
snd_hdac_stream_spbcap_enable(bus, true, hstream->index);
387
ret = snd_hdac_stream_set_spib(bus, hstream, fw->size);
388
if (ret)
389
goto cleanup_resources;
390
391
memcpy(dmab.area, fw->data, fw->size);
392
393
for (i = 0; i < APL_ROM_INIT_RETRIES; i++) {
394
unsigned int dma_id = hstream->stream_tag - 1;
395
396
ret = avs_hda_init_rom(adev, dma_id, true);
397
if (!ret)
398
break;
399
dev_info(adev->dev, "#%d rom init failed: %d\n", i + 1, ret);
400
}
401
if (ret < 0)
402
goto cleanup_resources;
403
404
/* transfer firmware */
405
snd_hdac_dsp_trigger(hstream, true);
406
ret = snd_hdac_adsp_readl_poll(adev, AVS_FW_REG_STATUS(adev), reg,
407
(reg & AVS_ROM_STS_MASK) == APL_ROM_FW_ENTERED,
408
AVS_FW_INIT_POLLING_US, AVS_FW_INIT_TIMEOUT_US);
409
snd_hdac_dsp_trigger(hstream, false);
410
if (ret < 0) {
411
dev_err(adev->dev, "transfer fw failed: %d, status: 0x%08x, lec: 0x%08x\n",
412
ret, reg, snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
413
avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
414
}
415
416
cleanup_resources:
417
/* disable SPIB for hda stream */
418
snd_hdac_stream_spbcap_enable(bus, false, hstream->index);
419
snd_hdac_stream_set_spib(bus, hstream, 0);
420
421
snd_hdac_dsp_cleanup(hstream, &dmab);
422
release_stream:
423
snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST);
424
425
return ret;
426
}
427
428
int avs_hda_load_library(struct avs_dev *adev, struct firmware *lib, u32 id)
429
{
430
struct snd_pcm_substream substream;
431
struct snd_dma_buffer dmab;
432
struct hdac_ext_stream *estream;
433
struct hdac_stream *stream;
434
struct hdac_bus *bus = &adev->base.core;
435
unsigned int sdfmt;
436
int ret;
437
438
/* configure hda dma */
439
memset(&substream, 0, sizeof(substream));
440
substream.stream = SNDRV_PCM_STREAM_PLAYBACK;
441
estream = snd_hdac_ext_stream_assign(bus, &substream,
442
HDAC_EXT_STREAM_TYPE_HOST);
443
if (!estream)
444
return -ENODEV;
445
stream = hdac_stream(estream);
446
447
/* code loading performed with default format */
448
sdfmt = snd_hdac_stream_format(1, 32, 48000);
449
ret = snd_hdac_dsp_prepare(stream, sdfmt, lib->size, &dmab);
450
if (ret < 0)
451
goto release_stream;
452
453
/* enable SPIB for hda stream */
454
snd_hdac_stream_spbcap_enable(bus, true, stream->index);
455
snd_hdac_stream_set_spib(bus, stream, lib->size);
456
457
memcpy(dmab.area, lib->data, lib->size);
458
459
/* transfer firmware */
460
snd_hdac_dsp_trigger(stream, true);
461
ret = avs_ipc_load_library(adev, stream->stream_tag - 1, id);
462
snd_hdac_dsp_trigger(stream, false);
463
if (ret) {
464
dev_err(adev->dev, "transfer lib %d failed: %d\n", id, ret);
465
ret = AVS_IPC_RET(ret);
466
}
467
468
/* disable SPIB for hda stream */
469
snd_hdac_stream_spbcap_enable(bus, false, stream->index);
470
snd_hdac_stream_set_spib(bus, stream, 0);
471
472
snd_hdac_dsp_cleanup(stream, &dmab);
473
release_stream:
474
snd_hdac_ext_stream_release(estream, HDAC_EXT_STREAM_TYPE_HOST);
475
476
return ret;
477
}
478
479
int avs_hda_transfer_modules(struct avs_dev *adev, bool load,
480
struct avs_module_entry *mods, u32 num_mods)
481
{
482
/*
483
* All platforms without CLDMA are equipped with IMR,
484
* and thus the module transferring is offloaded to DSP.
485
*/
486
return 0;
487
}
488
489
int avs_dsp_load_libraries(struct avs_dev *adev, struct avs_tplg_library *libs, u32 num_libs)
490
{
491
int start, id, i = 0;
492
int ret;
493
494
/* Calculate the id to assign for the next lib. */
495
for (id = 0; id < adev->fw_cfg.max_libs_count; id++)
496
if (adev->lib_names[id][0] == '\0')
497
break;
498
if (id + num_libs >= adev->fw_cfg.max_libs_count)
499
return -EINVAL;
500
501
start = id;
502
while (i < num_libs) {
503
struct avs_fw_manifest *man;
504
const struct firmware *fw;
505
struct firmware stripped_fw;
506
char *filename;
507
int j;
508
509
filename = kasprintf(GFP_KERNEL, "%s/%s/%s", AVS_ROOT_DIR, adev->spec->name,
510
libs[i].name);
511
if (!filename)
512
return -ENOMEM;
513
514
/*
515
* If any call after this one fails, requested firmware is not released with
516
* avs_release_last_firmware() as failing to load code results in need for reload
517
* of entire driver module. And then avs_release_firmwares() is in place already.
518
*/
519
ret = avs_request_firmware(adev, &fw, filename);
520
kfree(filename);
521
if (ret < 0)
522
return ret;
523
524
stripped_fw = *fw;
525
ret = avs_fw_manifest_strip_verify(adev, &stripped_fw, NULL);
526
if (ret) {
527
dev_err(adev->dev, "invalid library data: %d\n", ret);
528
return ret;
529
}
530
531
ret = avs_fw_manifest_offset(&stripped_fw);
532
if (ret < 0)
533
return ret;
534
man = (struct avs_fw_manifest *)(stripped_fw.data + ret);
535
536
/* Don't load anything that's already in DSP memory. */
537
for (j = 0; j < id; j++)
538
if (!strncmp(adev->lib_names[j], man->name, AVS_LIB_NAME_SIZE))
539
goto next_lib;
540
541
ret = avs_dsp_op(adev, load_lib, &stripped_fw, id);
542
if (ret)
543
return ret;
544
545
strscpy(adev->lib_names[id], man->name, AVS_LIB_NAME_SIZE);
546
id++;
547
next_lib:
548
i++;
549
}
550
551
return start == id ? 1 : 0;
552
}
553
554
static int avs_dsp_load_basefw(struct avs_dev *adev)
555
{
556
const struct avs_fw_version *min_req;
557
const struct avs_spec *const spec = adev->spec;
558
const struct firmware *fw;
559
struct firmware stripped_fw;
560
char *filename;
561
int ret;
562
563
filename = kasprintf(GFP_KERNEL, "%s/%s/%s", AVS_ROOT_DIR, spec->name, AVS_BASEFW_FILENAME);
564
if (!filename)
565
return -ENOMEM;
566
567
ret = avs_request_firmware(adev, &fw, filename);
568
kfree(filename);
569
if (ret < 0) {
570
dev_err(adev->dev, "request firmware failed: %d\n", ret);
571
return ret;
572
}
573
574
stripped_fw = *fw;
575
min_req = &adev->spec->min_fw_version;
576
577
ret = avs_fw_manifest_strip_verify(adev, &stripped_fw, min_req);
578
if (ret < 0) {
579
dev_err(adev->dev, "invalid firmware data: %d\n", ret);
580
goto release_fw;
581
}
582
583
ret = avs_dsp_op(adev, load_basefw, &stripped_fw);
584
if (ret < 0) {
585
dev_err(adev->dev, "basefw load failed: %d\n", ret);
586
goto release_fw;
587
}
588
589
ret = wait_for_completion_timeout(&adev->fw_ready,
590
msecs_to_jiffies(AVS_FW_INIT_TIMEOUT_MS));
591
if (!ret) {
592
dev_err(adev->dev, "firmware ready timeout, status: 0x%08x, lec: 0x%08x\n",
593
snd_hdac_adsp_readl(adev, AVS_FW_REG_STATUS(adev)),
594
snd_hdac_adsp_readl(adev, AVS_FW_REG_ERROR(adev)));
595
avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
596
ret = -ETIMEDOUT;
597
goto release_fw;
598
}
599
600
return 0;
601
602
release_fw:
603
avs_release_last_firmware(adev);
604
return ret;
605
}
606
607
static int avs_load_firmware(struct avs_dev *adev, bool purge)
608
{
609
struct avs_soc_component *acomp;
610
int ret, i;
611
612
/* Forgo full boot if flash from IMR succeeds. */
613
if (!purge && avs_platattr_test(adev, IMR)) {
614
ret = avs_imr_load_basefw(adev);
615
if (!ret)
616
return 0;
617
618
dev_dbg(adev->dev, "firmware flash from imr failed: %d\n", ret);
619
}
620
621
/* Full boot, clear cached data except for basefw (slot 0). */
622
for (i = 1; i < adev->fw_cfg.max_libs_count; i++)
623
memset(adev->lib_names[i], 0, AVS_LIB_NAME_SIZE);
624
625
avs_hda_power_gating_enable(adev, false);
626
avs_hda_clock_gating_enable(adev, false);
627
avs_hda_l1sen_enable(adev, false);
628
629
ret = avs_dsp_load_basefw(adev);
630
if (ret)
631
goto reenable_gating;
632
633
mutex_lock(&adev->comp_list_mutex);
634
list_for_each_entry(acomp, &adev->comp_list, node) {
635
struct avs_tplg *tplg = acomp->tplg;
636
637
ret = avs_dsp_load_libraries(adev, tplg->libs, tplg->num_libs);
638
if (ret < 0)
639
break;
640
}
641
mutex_unlock(&adev->comp_list_mutex);
642
643
reenable_gating:
644
avs_hda_l1sen_enable(adev, true);
645
avs_hda_clock_gating_enable(adev, true);
646
avs_hda_power_gating_enable(adev, true);
647
648
if (ret < 0)
649
return ret;
650
651
/* With all code loaded, refresh module information. */
652
ret = avs_module_info_init(adev, true);
653
if (ret) {
654
dev_err(adev->dev, "init module info failed: %d\n", ret);
655
return ret;
656
}
657
658
return 0;
659
}
660
661
static int avs_config_basefw(struct avs_dev *adev)
662
{
663
int ret;
664
665
if (adev->spec->dsp_ops->config_basefw) {
666
ret = avs_dsp_op(adev, config_basefw);
667
if (ret)
668
return ret;
669
}
670
671
return 0;
672
}
673
674
int avs_dsp_boot_firmware(struct avs_dev *adev, bool purge)
675
{
676
int ret;
677
678
ret = avs_load_firmware(adev, purge);
679
if (ret)
680
return ret;
681
682
return avs_config_basefw(adev);
683
}
684
685
static int avs_dsp_alloc_resources(struct avs_dev *adev)
686
{
687
struct hdac_ext_link *link;
688
int ret, i;
689
690
ret = avs_ipc_get_hw_config(adev, &adev->hw_cfg);
691
if (ret)
692
return AVS_IPC_RET(ret);
693
694
ret = avs_ipc_get_fw_config(adev, &adev->fw_cfg);
695
if (ret)
696
return AVS_IPC_RET(ret);
697
698
/* If hw allows, read capabilities directly from it. */
699
if (avs_platattr_test(adev, ALTHDA)) {
700
link = snd_hdac_ext_bus_get_hlink_by_id(&adev->base.core,
701
AZX_REG_ML_LEPTR_ID_INTEL_SSP);
702
if (link)
703
adev->hw_cfg.i2s_caps.ctrl_count = link->slcount;
704
}
705
706
adev->core_refs = devm_kcalloc(adev->dev, adev->hw_cfg.dsp_cores,
707
sizeof(*adev->core_refs), GFP_KERNEL);
708
adev->lib_names = devm_kcalloc(adev->dev, adev->fw_cfg.max_libs_count,
709
sizeof(*adev->lib_names), GFP_KERNEL);
710
if (!adev->core_refs || !adev->lib_names)
711
return -ENOMEM;
712
713
for (i = 0; i < adev->fw_cfg.max_libs_count; i++) {
714
adev->lib_names[i] = devm_kzalloc(adev->dev, AVS_LIB_NAME_SIZE, GFP_KERNEL);
715
if (!adev->lib_names[i])
716
return -ENOMEM;
717
}
718
719
/* basefw always occupies slot 0 */
720
strscpy(adev->lib_names[0], "BASEFW", AVS_LIB_NAME_SIZE);
721
722
ida_init(&adev->ppl_ida);
723
return 0;
724
}
725
726
int avs_dsp_first_boot_firmware(struct avs_dev *adev)
727
{
728
int ret;
729
730
if (avs_platattr_test(adev, CLDMA)) {
731
ret = hda_cldma_init(&code_loader, &adev->base.core,
732
adev->dsp_ba, AVS_CL_DEFAULT_BUFFER_SIZE);
733
if (ret < 0) {
734
dev_err(adev->dev, "cldma init failed: %d\n", ret);
735
return ret;
736
}
737
}
738
739
ret = avs_dsp_core_disable(adev, AVS_MAIN_CORE_MASK);
740
if (ret < 0)
741
return ret;
742
743
ret = avs_dsp_boot_firmware(adev, true);
744
if (ret < 0) {
745
dev_err(adev->dev, "firmware boot failed: %d\n", ret);
746
return ret;
747
}
748
749
return avs_dsp_alloc_resources(adev);
750
}
751
752