[Intel-gfx] [RFC PATCH v2 1/8] drm/i915: setup bridge for HDMI LPE audio driver

Pierre-Louis Bossart pierre-louis.bossart at linux.intel.com
Thu Oct 13 19:38:30 UTC 2016


Thanks Ville for the review. A lot of the comments are related to the 
initial VED code we took pretty much as is, no issues to clean-up further.

BTW, it looks like Jerome's patches were stuck for 10+ days on the 
intel-gfx server for some reason so not everyone saw the initial post?

>> @@ -1141,7 +1141,13 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
>>  	if (IS_GEN5(dev_priv))
>>  		intel_gpu_ips_init(dev_priv);
>>
>> -	i915_audio_component_init(dev_priv);
>> +	if (intel_lpe_audio_detect(dev_priv)) {
>> +		if (intel_lpe_audio_setup(dev_priv) < 0)
>> +			DRM_ERROR("failed to setup LPE Audio bridge\n");
>> +	}
>
> I'd move all that into the lpe audio code. No need to have anything here
> but a single function call IMO.

something like intel_lpe_audio_init() for symmetry with the hda 
component stuff, with both detection and setup handled internally?
>
>> +
>> +	if (!IS_LPE_AUDIO_ENABLED(dev_priv))
>
> I don't like that too much. I think I would just make
> that HAS_LPE_AUDIO(). The current IS_VLV||IS_CHV check can just be
> inlined into the init function.

ok


>>
>>  #define HAS_POOLED_EU(dev)	(INTEL_INFO(dev)->has_pooled_eu)
>>
>> +#define HAS_LPE_AUDIO(dev)	(IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
>> +#define IS_LPE_AUDIO_ENABLED(dev_priv) \
>> +				(__I915__(dev_priv)->lpe_audio.platdev != NULL)
>> +#define IS_LPE_AUDIO_IRQ_VALID(dev_priv) \
>> +				(__I915__(dev_priv)->lpe_audio.irq >= 0)
>
> Seems useless. We should just not register the lpe audio thing if we
> have no irq.

ok

>> --- a/drivers/gpu/drm/i915/i915_irq.c
>> +++ b/drivers/gpu/drm/i915/i915_irq.c
>> @@ -1827,6 +1827,13 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
>>  		 * signalled in iir */
>>  		valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
>>
>> +		if (IS_LPE_AUDIO_ENABLED(dev_priv))
>> +			if (IS_LPE_AUDIO_IRQ_VALID(dev_priv))
>
> I think both of these checks can be removed. We won't unmask the
> interrupts unless lpe is enabled, so the IIR bits will never be set in
> that case.
>
>> +				if (iir & (I915_LPE_PIPE_A_INTERRUPT |
>> +					I915_LPE_PIPE_B_INTERRUPT |
>> +					I915_LPE_PIPE_C_INTERRUPT))
>> +					intel_lpe_audio_irq_handler(dev_priv);
>> +

ok.

>>  		/*
>>  		 * VLV_IIR is single buffered, and reflects the level
>>  		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
>> @@ -1907,6 +1914,13 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
>>  		 * signalled in iir */
>>  		valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);
>>
>> +		if (IS_LPE_AUDIO_ENABLED(dev_priv))
>> +			if (IS_LPE_AUDIO_IRQ_VALID(dev_priv))
>> +				if (iir & (I915_LPE_PIPE_A_INTERRUPT |
>> +					I915_LPE_PIPE_B_INTERRUPT |
>> +					I915_LPE_PIPE_C_INTERRUPT))
>> +					intel_lpe_audio_irq_handler(dev_priv);
>> +
>
> ditto

ok


>> +	platdev = platform_device_alloc("hdmi-lpe-audio", -1);
>> +	if (!platdev) {
>> +		ret = -ENOMEM;
>> +		DRM_ERROR("Failed to allocate LPE audio platform device\n");
>> +		goto err;
>> +	}
>> +
>> +	/* to work-around check_addr in nommu_map_sg() */
>
> What's this about?

Dunno, this was in the original VED series that we used as a baseline. 
Unless someone has memories from that time, i'll just remove this comment.


>> +	DRM_DEBUG("%s: HDMI_AUDIO rsc.start[0] = 0x%x\n",
>> +		__func__, (int)(rsc[0].start));
>
> __func__ pointless since DRM_DEBUG alreay adds it. Also saying
> "rsc.start[0]" in the message doesn't tell anyone anything useful.
> And I think irq numbers are usually printed in decimal.

Same, this was taken from the VED series, no issue to clean-up.

>
>> +
>> +	rsc[1].start    = pci_resource_start(dev->pdev, 0) +
>> +		I915_HDMI_LPE_AUDIO_BASE;
>> +	rsc[1].end      = pci_resource_start(dev->pdev, 0) +
>> +		I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
>> +	rsc[1].flags    = IORESOURCE_MEM;
>> +	rsc[1].name     = "hdmi-lpe-audio-mmio";
>> +
>> +	DRM_DEBUG("%s: HDMI_AUDIO rsc.start[1] = 0x%x\n",
>> +		__func__, (int)(rsc[1].start));
>
> Again "rsc[0].start" doesn't seem like anything useful to print in a
> debug message. Don't see much point in the whole debug message TBH since
> the start/end are fixed.

so are you saying we should remove the code or move the level to 
DRM_INFO - for extra verbose debug?

>
>> +
>> +	ret = platform_device_add_resources(platdev, rsc, 2);
>> +	if (ret) {
>> +		DRM_ERROR("Failed to add resource for platform device: %d\n",
>> +			ret);
>> +		goto err_put_dev;
>> +	}
>> +
>> +	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
>> +
>> +	if (pdata == NULL) {
>> +		ret = -ENOMEM;
>> +		goto err_put_dev;
>> +	}
>> +	platdev->dev.platform_data = pdata;
>> +
>> +	/* for LPE audio driver's runtime-PM */
>> +	platdev->dev.parent = dev->dev;
>> +	ret = platform_device_add(platdev);
>> +	if (ret) {
>> +		DRM_ERROR("Failed to add LPE audio platform device: %d\n",
>> +			ret);
>> +		goto err_put_dev;
>> +	}
>> +	spin_lock_init(&pdata->lpe_audio_slock);
>
> Should init it before adding the device I suppose? It's not used in the
> patch so hard to say. In general the patch split is not the best due to
> not being able to see the use of things.

ok. we'll look into this.


>> +static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
>> +{
>> +	if (dev_priv->lpe_audio.platdev) {
>> +		platform_device_unregister(dev_priv->lpe_audio.platdev);
>> +		kfree(dev_priv->lpe_audio.platdev->dev.dma_mask);
>> +	}
>
> I usually prefer
>
> {
> 	if (!stuff)
> 		return;
>
> 	other stuff;
> }
>
> just to keep the indentation better in check.

ok

>
>> +}
>> +
>> +static void lpe_audio_irq_unmask(struct irq_data *d)
>> +{
>> +	struct drm_device *dev = d->chip_data;
>> +	struct drm_i915_private *dev_priv = to_i915(dev);
>> +	unsigned long irqflags;
>> +	u32 val = (I915_LPE_PIPE_A_INTERRUPT |
>> +		I915_LPE_PIPE_B_INTERRUPT |
>> +		I915_LPE_PIPE_C_INTERRUPT);
>> +
>> +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>> +
>> +	/*
>> +	 * VLV_IER is already set in the vlv_display_postinstall(),
>> +	 * we only change VLV_IIR and VLV_IMR
>> +	 */
>> +	dev_priv->irq_mask &= ~val;
>> +	I915_WRITE(VLV_IIR, val);
>> +	I915_WRITE(VLV_IIR, val);
>> +	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
>> +
>
> Extra newline here for some reason. No such thing in the counterpart.

ok


>> +static int lpe_audio_irq_init(struct drm_i915_private *dev_priv)
>> +{
>> +	int irq = dev_priv->lpe_audio.irq;
>> +
>> +	WARN_ON(!intel_irqs_enabled(dev_priv));
>
> Could leave a blank like here to make things look less convoluted.

ok

>
>> +	irq_set_chip_and_handler_name(irq,
>> +		&lpe_audio_irqchip,
>> +		handle_simple_irq,
>> +		"hdmi_lpe_audio_irq_handler");
>
> Indentation isn't quite right.

ok

>
>> +
>> +	return irq_set_chip_data(irq, &dev_priv->drm);
>> +}
>> +
>> +/**
>> + * intel_lpe_audio_irq_handler() - forwards the LPE audio irq
>> + * @dev_priv: the i915 drm device private data
>> + *
>> + * the LPE Audio irq is forwarded to the irq handler registered by LPE audio
>> + * driver.
>> + */
>> +void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
>> +{
>> +	int ret;
>> +
>> +	ret = generic_handle_irq(dev_priv->lpe_audio.irq);
>> +	if (ret)
>> +		DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n",
>> +				ret);
>> +}
>> +
>> +/**
>> + * intel_lpe_audio_detect() - check & setup lpe audio if present
>> + * @dev_priv: the i915 drm device private data
>> + *
>> + * Detect if lpe audio is present
>> + *
>> + * Return: true if lpe audio present else Return = false
>> + */
>> +int intel_lpe_audio_detect(struct drm_i915_private *dev_priv)
>> +{
>> +	int lpe_present = false;
>> +	struct drm_device *dev = &dev_priv->drm;
>> +
>> +	if (HAS_LPE_AUDIO(dev)) {
>> +		static const struct pci_device_id atom_hdaudio_ids[] = {
>> +			/* Baytrail */
>> +			{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f04)},
>> +			/* Braswell */
>> +			{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2284)},
>> +			{}
>> +		};
>
> Hmm. Maybe I asked already, but could we use a class match instead?
> There's some kind of HDA class right?

I am not aware of any class, this is really the only means we found to 
test if the HDaudio controller is disabled or fused out. Maybe a 
question for Takashi?

>
>> +
>> +		if (!pci_dev_present(atom_hdaudio_ids)) {
>> +			DRM_INFO("%s%s\n", "HDaudio controller not detected,",
>> +				"using LPE audio instead\n");
>> +			lpe_present = true;
>> +		}
>> +	}
>> +	return lpe_present;
>> +}
>> +
>> +/**
>> + * intel_lpe_audio_setup() - setup the bridge between HDMI LPE Audio
>> + * driver and i915
>> + * @dev_priv: the i915 drm device private data
>> + *
>> + * set up the minimum required resources for the bridge: irq chip,
>> + * platform resource and platform device. i915 device is set as parent
>> + * of the new platform device.
>> + *
>> + * Return: 0 if successful. non-zero if allocation/initialization fails
>> + */
>> +int intel_lpe_audio_setup(struct drm_i915_private *dev_priv)
>> +{
>> +	int ret;
>> +
>> +	dev_priv->lpe_audio.irq = irq_alloc_descs(-1, 0, 1, 0);
>
> aka. irq_alloc_desc() ?

not sure, will look into this.

>
>> +	if (dev_priv->lpe_audio.irq < 0) {
>> +		DRM_ERROR("Failed to allocate IRQ desc: %d\n",
>> +			dev_priv->lpe_audio.irq);
>> +		ret = dev_priv->lpe_audio.irq;
>> +		goto err;
>> +	}
>> +
>> +	DRM_DEBUG("%s : irq = %d\n", __func__, dev_priv->lpe_audio.irq);
>
> Another __func__ that's not needed. And we're printing the irq twice
> now?

ok

>
>> +
>> +	ret = lpe_audio_irq_init(dev_priv);
>> +
>> +	if (ret) {
>> +
>> +		DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
>> +			ret);
>
> Indentation looks off.

ok
>
>> +		goto err_free_irq;
>> +	}
>> +
>> +	dev_priv->lpe_audio.platdev = lpe_audio_platdev_create(dev_priv);
>> +
>> +	if (IS_ERR(dev_priv->lpe_audio.platdev)) {
>> +		ret = PTR_ERR(dev_priv->lpe_audio.platdev);
>> +		DRM_ERROR("Failed to create lpe audio platform device: %d\n",
>> +			ret);
>
> ditto

ok

>> +void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
>> +{
>> +	unsigned long irqflags;
>> +	struct irq_desc *desc;
>> +
>> +	desc = IS_LPE_AUDIO_IRQ_VALID(dev_priv) ?
>> +			irq_to_desc(dev_priv->lpe_audio.irq) : NULL;
>> +
>> +	/**
>> +	 * mask LPE audio irq before destroying
>> +	 */
>> +	if (desc)
>
> Seems overly defensive. Should just check if we have the platform device
> at the start, and otherwise we can assume that all the things we need to
> free are there.
>
> This looks racy too. We should unregister the platform device as the
> first thing, and only then free up the resources and whatnot.

will clean up




More information about the Intel-gfx mailing list