diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-08-09 07:49:23 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-08-09 10:28:51 -0400 |
commit | 5cb543dba9867588786f87af2e64fca371b69283 (patch) | |
tree | c8986219ff6f502e99d16c369ae903f97d73c634 /sound/pci/hda/hda_intel.c | |
parent | 4918cdab497d693f4de288a576fb22e8ff9df21e (diff) |
ALSA: hda - Deferred probing with request_firmware_nowait()
For processing the firmware handling properly for built-in kernels,
implement an asynchronous firmware loading with
request_firmware_nowait(). This means that the codec probing is
deferred when the patch option is specified.
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>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b25d5392c3b2..3de3a5cbf1dc 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -564,13 +564,17 @@ enum { | |||
564 | * VGA-switcher support | 564 | * VGA-switcher support |
565 | */ | 565 | */ |
566 | #ifdef SUPPORT_VGA_SWITCHEROO | 566 | #ifdef SUPPORT_VGA_SWITCHEROO |
567 | #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo) | ||
568 | #else | ||
569 | #define use_vga_switcheroo(chip) 0 | ||
570 | #endif | ||
571 | |||
572 | #if defined(SUPPORT_VGA_SWITCHEROO) || defined(CONFIG_SND_HDA_PATCH_LOADER) | ||
567 | #define DELAYED_INIT_MARK | 573 | #define DELAYED_INIT_MARK |
568 | #define DELAYED_INITDATA_MARK | 574 | #define DELAYED_INITDATA_MARK |
569 | #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo) | ||
570 | #else | 575 | #else |
571 | #define DELAYED_INIT_MARK __devinit | 576 | #define DELAYED_INIT_MARK __devinit |
572 | #define DELAYED_INITDATA_MARK __devinitdata | 577 | #define DELAYED_INITDATA_MARK __devinitdata |
573 | #define use_vga_switcheroo(chip) 0 | ||
574 | #endif | 578 | #endif |
575 | 579 | ||
576 | static char *driver_short_names[] DELAYED_INITDATA_MARK = { | 580 | static char *driver_short_names[] DELAYED_INITDATA_MARK = { |
@@ -3155,12 +3159,38 @@ static void power_down_all_codecs(struct azx *chip) | |||
3155 | #endif | 3159 | #endif |
3156 | } | 3160 | } |
3157 | 3161 | ||
3162 | /* callback from request_firmware_nowait() */ | ||
3163 | static void azx_firmware_cb(const struct firmware *fw, void *context) | ||
3164 | { | ||
3165 | struct snd_card *card = context; | ||
3166 | struct azx *chip = card->private_data; | ||
3167 | struct pci_dev *pci = chip->pci; | ||
3168 | |||
3169 | if (!fw) { | ||
3170 | snd_printk(KERN_ERR SFX "Cannot load firmware, aborting\n"); | ||
3171 | goto error; | ||
3172 | } | ||
3173 | |||
3174 | chip->fw = fw; | ||
3175 | if (!chip->disabled) { | ||
3176 | /* continue probing */ | ||
3177 | if (azx_probe_continue(chip)) | ||
3178 | goto error; | ||
3179 | } | ||
3180 | return; /* OK */ | ||
3181 | |||
3182 | error: | ||
3183 | snd_card_free(card); | ||
3184 | pci_set_drvdata(pci, NULL); | ||
3185 | } | ||
3186 | |||
3158 | static int __devinit azx_probe(struct pci_dev *pci, | 3187 | static int __devinit azx_probe(struct pci_dev *pci, |
3159 | const struct pci_device_id *pci_id) | 3188 | const struct pci_device_id *pci_id) |
3160 | { | 3189 | { |
3161 | static int dev; | 3190 | static int dev; |
3162 | struct snd_card *card; | 3191 | struct snd_card *card; |
3163 | struct azx *chip; | 3192 | struct azx *chip; |
3193 | bool probe_now; | ||
3164 | int err; | 3194 | int err; |
3165 | 3195 | ||
3166 | if (dev >= SNDRV_CARDS) | 3196 | if (dev >= SNDRV_CARDS) |
@@ -3182,18 +3212,22 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
3182 | if (err < 0) | 3212 | if (err < 0) |
3183 | goto out_free; | 3213 | goto out_free; |
3184 | card->private_data = chip; | 3214 | card->private_data = chip; |
3215 | probe_now = !chip->disabled; | ||
3185 | 3216 | ||
3186 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 3217 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
3187 | if (patch[dev] && *patch[dev]) { | 3218 | if (patch[dev] && *patch[dev]) { |
3188 | snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n", | 3219 | snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n", |
3189 | patch[dev]); | 3220 | patch[dev]); |
3190 | err = request_firmware(&chip->fw, patch[dev], &pci->dev); | 3221 | err = request_firmware_nowait(THIS_MODULE, true, patch[dev], |
3222 | &pci->dev, GFP_KERNEL, card, | ||
3223 | azx_firmware_cb); | ||
3191 | if (err < 0) | 3224 | if (err < 0) |
3192 | goto out_free; | 3225 | goto out_free; |
3226 | probe_now = false; /* continued in azx_firmware_cb() */ | ||
3193 | } | 3227 | } |
3194 | #endif /* CONFIG_SND_HDA_PATCH_LOADER */ | 3228 | #endif /* CONFIG_SND_HDA_PATCH_LOADER */ |
3195 | 3229 | ||
3196 | if (!chip->disabled) { | 3230 | if (probe_now) { |
3197 | err = azx_probe_continue(chip); | 3231 | err = azx_probe_continue(chip); |
3198 | if (err < 0) | 3232 | if (err < 0) |
3199 | goto out_free; | 3233 | goto out_free; |