ALSA: hda - Load firmware in hda_intel.c
authorTakashi Iwai <tiwai@suse.de>
Thu, 9 Aug 2012 10:33:28 +0000 (12:33 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 9 Aug 2012 14:28:19 +0000 (16:28 +0200)
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>
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c

index c422d330ca54fe018379e5b14b24dcd03a4e208e..39e43753ddbf4f692d0ac1f05d954f2c83e6ba3d 100644 (file)
@@ -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
 
 /*
index 6b2efb8cb1f9c6bded4e7d318467f8825be75903..b9a644ca03b34faee8940a6ebbfcc74bce40e9fc 100644 (file)
@@ -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);
index c8aced182fd15738cf165505d532e24e89bcd906..b25d5392c3b28b1f7cec00d5595181431994d818 100644 (file)
@@ -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) {