ALSA: hda - Load firmware in hda_intel.c
This is a preliminary work for the deferred probing for request_firmware() errors at init. This patch moves the call of request_firmware() to hda_intel.c, and call it in the earlier stage of probing rather than azx_probe_continue(). Tested-by: Thierry Reding <thierry.reding@avionic-design.de> Reviewed-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
94c142a160
commit
4918cdab49
|
@ -1072,7 +1072,7 @@ static inline void snd_hda_power_down(struct hda_codec *codec) {}
|
|||
/*
|
||||
* patch firmware
|
||||
*/
|
||||
int snd_hda_load_patch(struct hda_bus *bus, const char *patch);
|
||||
int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/export.h>
|
||||
#include <sound/core.h>
|
||||
#include "hda_codec.h"
|
||||
|
@ -747,18 +746,21 @@ static int parse_line_mode(char *buf, struct hda_bus *bus)
|
|||
*
|
||||
* the spaces at the beginning and the end of the line are stripped
|
||||
*/
|
||||
static int get_line_from_fw(char *buf, int size, struct firmware *fw)
|
||||
static int get_line_from_fw(char *buf, int size, size_t *fw_size_p,
|
||||
const void **fw_data_p)
|
||||
{
|
||||
int len;
|
||||
const char *p = fw->data;
|
||||
while (isspace(*p) && fw->size) {
|
||||
size_t fw_size = *fw_size_p;
|
||||
const char *p = *fw_data_p;
|
||||
|
||||
while (isspace(*p) && fw_size) {
|
||||
p++;
|
||||
fw->size--;
|
||||
fw_size--;
|
||||
}
|
||||
if (!fw->size)
|
||||
if (!fw_size)
|
||||
return 0;
|
||||
|
||||
for (len = 0; len < fw->size; len++) {
|
||||
for (len = 0; len < fw_size; len++) {
|
||||
if (!*p)
|
||||
break;
|
||||
if (*p == '\n') {
|
||||
|
@ -770,8 +772,8 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw)
|
|||
*buf++ = *p++;
|
||||
}
|
||||
*buf = 0;
|
||||
fw->size -= len;
|
||||
fw->data = p;
|
||||
*fw_size_p = fw_size - len;
|
||||
*fw_data_p = p;
|
||||
remove_trail_spaces(buf);
|
||||
return 1;
|
||||
}
|
||||
|
@ -779,29 +781,15 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw)
|
|||
/*
|
||||
* load a "patch" firmware file and parse it
|
||||
*/
|
||||
int snd_hda_load_patch(struct hda_bus *bus, const char *patch)
|
||||
int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
|
||||
{
|
||||
int err;
|
||||
const struct firmware *fw;
|
||||
struct firmware tmp;
|
||||
char buf[128];
|
||||
struct hda_codec *codec;
|
||||
int line_mode;
|
||||
struct device *dev = bus->card->dev;
|
||||
|
||||
if (snd_BUG_ON(!dev))
|
||||
return -ENODEV;
|
||||
err = request_firmware(&fw, patch, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "hda-codec: Cannot load the patch '%s'\n",
|
||||
patch);
|
||||
return err;
|
||||
}
|
||||
|
||||
tmp = *fw;
|
||||
line_mode = LINE_MODE_NONE;
|
||||
codec = NULL;
|
||||
while (get_line_from_fw(buf, sizeof(buf) - 1, &tmp)) {
|
||||
while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) {
|
||||
if (!*buf || *buf == '#' || *buf == '\n')
|
||||
continue;
|
||||
if (*buf == '[')
|
||||
|
@ -810,7 +798,6 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch)
|
|||
(codec || !patch_items[line_mode].need_codec))
|
||||
patch_items[line_mode].parser(buf, bus, &codec);
|
||||
}
|
||||
release_firmware(fw);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_HDA(snd_hda_load_patch);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include <sound/initval.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "hda_codec.h"
|
||||
|
||||
|
||||
|
@ -470,6 +471,10 @@ struct azx {
|
|||
struct snd_dma_buffer rb;
|
||||
struct snd_dma_buffer posbuf;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
const struct firmware *fw;
|
||||
#endif
|
||||
|
||||
/* flags */
|
||||
int position_fix[2]; /* for both playback/capture streams */
|
||||
int poll_count;
|
||||
|
@ -2639,6 +2644,10 @@ static int azx_free(struct azx *chip)
|
|||
pci_release_regions(chip->pci);
|
||||
pci_disable_device(chip->pci);
|
||||
kfree(chip->azx_dev);
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (chip->fw)
|
||||
release_firmware(chip->fw);
|
||||
#endif
|
||||
kfree(chip);
|
||||
|
||||
return 0;
|
||||
|
@ -3167,7 +3176,6 @@ static int __devinit azx_probe(struct pci_dev *pci,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* set this here since it's referred in snd_hda_load_patch() */
|
||||
snd_card_set_dev(card, &pci->dev);
|
||||
|
||||
err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
|
||||
|
@ -3175,6 +3183,16 @@ static int __devinit azx_probe(struct pci_dev *pci,
|
|||
goto out_free;
|
||||
card->private_data = chip;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (patch[dev] && *patch[dev]) {
|
||||
snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n",
|
||||
patch[dev]);
|
||||
err = request_firmware(&chip->fw, patch[dev], &pci->dev);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
}
|
||||
#endif /* CONFIG_SND_HDA_PATCH_LOADER */
|
||||
|
||||
if (!chip->disabled) {
|
||||
err = azx_probe_continue(chip);
|
||||
if (err < 0)
|
||||
|
@ -3205,12 +3223,13 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip)
|
|||
if (err < 0)
|
||||
goto out_free;
|
||||
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
||||
if (patch[dev] && *patch[dev]) {
|
||||
snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n",
|
||||
patch[dev]);
|
||||
err = snd_hda_load_patch(chip->bus, patch[dev]);
|
||||
if (chip->fw) {
|
||||
err = snd_hda_load_patch(chip->bus, chip->fw->size,
|
||||
chip->fw->data);
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
release_firmware(chip->fw); /* no longer needed */
|
||||
chip->fw = NULL;
|
||||
}
|
||||
#endif
|
||||
if ((probe_only[dev] & 1) == 0) {
|
||||
|
|
Loading…
Reference in New Issue