mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ALSA: hda/i915: Allow delayed i915 audio component binding
Currently HD-audio i915 audio binding doesn't support any delayed binding, and supposes that the i915 driver registers the component immediately. This has been OK, so far, but the work-in-progress change in i915 may introduce the asynchronous binding, which effectively delays the component registration. For addressing it, implement a completion to be synced with the master binding. The timeout is set to 10 seconds which should be long enough and hopefully be not too annoying if anyone boots up a debugging session with i915 KMS turned off. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									1ea0358ecb
								
							
						
					
					
						commit
						f9b54e1961
					
				
					 1 changed files with 22 additions and 2 deletions
				
			
		| 
						 | 
					@ -20,6 +20,8 @@
 | 
				
			||||||
#include <sound/hda_i915.h>
 | 
					#include <sound/hda_i915.h>
 | 
				
			||||||
#include <sound/hda_register.h>
 | 
					#include <sound/hda_register.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct completion bind_complete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
 | 
					#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
 | 
				
			||||||
				((pci)->device == 0x0c0c) || \
 | 
									((pci)->device == 0x0c0c) || \
 | 
				
			||||||
				((pci)->device == 0x0d0c) || \
 | 
									((pci)->device == 0x0d0c) || \
 | 
				
			||||||
| 
						 | 
					@ -97,6 +99,19 @@ static bool i915_gfx_present(void)
 | 
				
			||||||
	return pci_dev_present(ids);
 | 
						return pci_dev_present(ids);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int i915_master_bind(struct device *dev,
 | 
				
			||||||
 | 
								    struct drm_audio_component *acomp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						complete_all(&bind_complete);
 | 
				
			||||||
 | 
						/* clear audio_ops here as it was needed only for completion call */
 | 
				
			||||||
 | 
						acomp->audio_ops = NULL;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct drm_audio_component_audio_ops i915_init_ops = {
 | 
				
			||||||
 | 
						.master_bind = i915_master_bind
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * snd_hdac_i915_init - Initialize i915 audio component
 | 
					 * snd_hdac_i915_init - Initialize i915 audio component
 | 
				
			||||||
 * @bus: HDA core bus
 | 
					 * @bus: HDA core bus
 | 
				
			||||||
| 
						 | 
					@ -117,7 +132,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
 | 
				
			||||||
	if (!i915_gfx_present())
 | 
						if (!i915_gfx_present())
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = snd_hdac_acomp_init(bus, NULL,
 | 
						init_completion(&bind_complete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = snd_hdac_acomp_init(bus, &i915_init_ops,
 | 
				
			||||||
				  i915_component_master_match,
 | 
									  i915_component_master_match,
 | 
				
			||||||
				  sizeof(struct i915_audio_component) - sizeof(*acomp));
 | 
									  sizeof(struct i915_audio_component) - sizeof(*acomp));
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
| 
						 | 
					@ -125,8 +142,11 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
 | 
				
			||||||
	acomp = bus->audio_component;
 | 
						acomp = bus->audio_component;
 | 
				
			||||||
	if (!acomp)
 | 
						if (!acomp)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
	if (!acomp->ops)
 | 
						if (!acomp->ops) {
 | 
				
			||||||
		request_module("i915");
 | 
							request_module("i915");
 | 
				
			||||||
 | 
							/* 10s timeout */
 | 
				
			||||||
 | 
							wait_for_completion_timeout(&bind_complete, 10 * 1000);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (!acomp->ops) {
 | 
						if (!acomp->ops) {
 | 
				
			||||||
		snd_hdac_acomp_exit(bus);
 | 
							snd_hdac_acomp_exit(bus);
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue