1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Driver for Digigram VX soundcards |
4 | * |
5 | * DSP firmware management |
6 | * |
7 | * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/firmware.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/vmalloc.h> |
14 | #include <linux/module.h> |
15 | #include <sound/core.h> |
16 | #include <sound/hwdep.h> |
17 | #include <sound/vx_core.h> |
18 | |
19 | MODULE_FIRMWARE("vx/bx_1_vxp.b56" ); |
20 | MODULE_FIRMWARE("vx/bx_1_vp4.b56" ); |
21 | MODULE_FIRMWARE("vx/x1_1_vx2.xlx" ); |
22 | MODULE_FIRMWARE("vx/x1_2_v22.xlx" ); |
23 | MODULE_FIRMWARE("vx/x1_1_vxp.xlx" ); |
24 | MODULE_FIRMWARE("vx/x1_1_vp4.xlx" ); |
25 | MODULE_FIRMWARE("vx/bd56002.boot" ); |
26 | MODULE_FIRMWARE("vx/bd563v2.boot" ); |
27 | MODULE_FIRMWARE("vx/bd563s3.boot" ); |
28 | MODULE_FIRMWARE("vx/l_1_vx2.d56" ); |
29 | MODULE_FIRMWARE("vx/l_1_v22.d56" ); |
30 | MODULE_FIRMWARE("vx/l_1_vxp.d56" ); |
31 | MODULE_FIRMWARE("vx/l_1_vp4.d56" ); |
32 | |
33 | int snd_vx_setup_firmware(struct vx_core *chip) |
34 | { |
35 | static const char * const fw_files[VX_TYPE_NUMS][4] = { |
36 | [VX_TYPE_BOARD] = { |
37 | NULL, "x1_1_vx2.xlx" , "bd56002.boot" , "l_1_vx2.d56" , |
38 | }, |
39 | [VX_TYPE_V2] = { |
40 | NULL, "x1_2_v22.xlx" , "bd563v2.boot" , "l_1_v22.d56" , |
41 | }, |
42 | [VX_TYPE_MIC] = { |
43 | NULL, "x1_2_v22.xlx" , "bd563v2.boot" , "l_1_v22.d56" , |
44 | }, |
45 | [VX_TYPE_VXPOCKET] = { |
46 | "bx_1_vxp.b56" , "x1_1_vxp.xlx" , "bd563s3.boot" , "l_1_vxp.d56" |
47 | }, |
48 | [VX_TYPE_VXP440] = { |
49 | "bx_1_vp4.b56" , "x1_1_vp4.xlx" , "bd563s3.boot" , "l_1_vp4.d56" |
50 | }, |
51 | }; |
52 | |
53 | int i, err; |
54 | |
55 | for (i = 0; i < 4; i++) { |
56 | char path[32]; |
57 | const struct firmware *fw; |
58 | if (! fw_files[chip->type][i]) |
59 | continue; |
60 | sprintf(buf: path, fmt: "vx/%s" , fw_files[chip->type][i]); |
61 | if (request_firmware(fw: &fw, name: path, device: chip->dev)) { |
62 | snd_printk(KERN_ERR "vx: can't load firmware %s\n" , path); |
63 | return -ENOENT; |
64 | } |
65 | err = chip->ops->load_dsp(chip, i, fw); |
66 | if (err < 0) { |
67 | release_firmware(fw); |
68 | return err; |
69 | } |
70 | if (i == 1) |
71 | chip->chip_status |= VX_STAT_XILINX_LOADED; |
72 | #ifdef CONFIG_PM |
73 | chip->firmware[i] = fw; |
74 | #else |
75 | release_firmware(fw); |
76 | #endif |
77 | } |
78 | |
79 | /* ok, we reached to the last one */ |
80 | /* create the devices if not built yet */ |
81 | err = snd_vx_pcm_new(chip); |
82 | if (err < 0) |
83 | return err; |
84 | |
85 | err = snd_vx_mixer_new(chip); |
86 | if (err < 0) |
87 | return err; |
88 | |
89 | if (chip->ops->add_controls) { |
90 | err = chip->ops->add_controls(chip); |
91 | if (err < 0) |
92 | return err; |
93 | } |
94 | |
95 | chip->chip_status |= VX_STAT_DEVICE_INIT; |
96 | chip->chip_status |= VX_STAT_CHIP_INIT; |
97 | |
98 | return snd_card_register(card: chip->card); |
99 | } |
100 | |
101 | /* exported */ |
102 | void snd_vx_free_firmware(struct vx_core *chip) |
103 | { |
104 | #ifdef CONFIG_PM |
105 | int i; |
106 | for (i = 0; i < 4; i++) |
107 | release_firmware(fw: chip->firmware[i]); |
108 | #endif |
109 | } |
110 | |
111 | EXPORT_SYMBOL(snd_vx_setup_firmware); |
112 | EXPORT_SYMBOL(snd_vx_free_firmware); |
113 | |