Nikula, thx for reminder, will update it. -----Original Message----- From: Jani Nikula [mailto:jani.nikula@xxxxxxxxxxxxxxx] Sent: Tuesday, October 14, 2014 9:27 PM To: Cheng, Yao; intel-gfx@xxxxxxxxxxxxxxxxxxxxx Cc: Jiang, Fei; dri-devel@xxxxxxxxxxxxxxxxxxxxx; Vetter, Daniel Subject: Re: [Intel-gfx] [RFC PATCH 1/3] drm/i915: add vxd392 bridge in i915 On Mon, 13 Oct 2014, Yao Cheng <yao.cheng@xxxxxxxxx> wrote: > Setup following resources during i915_driver_load: > 1. create a child platform and resource 2. allocate a new IRQ line and > irq chip 3. set up IRQ mask/unmask callbacks > vxd392 driver (if installed) will bind itself to the platform device > and create new drm device > > Signed-off-by: Yao Cheng <yao.cheng@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_dma.c | 98 +++++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/i915_drv.h | 6 +++ > drivers/gpu/drm/i915/i915_irq.c | 70 ++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/i915_reg.h | 4 ++ > drivers/gpu/drm/i915/i915_trace.h | 15 ++++++ > 5 files changed, 193 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_dma.c > b/drivers/gpu/drm/i915/i915_dma.c index 85d14e1..73c78d1 100644 > --- a/drivers/gpu/drm/i915/i915_dma.c > +++ b/drivers/gpu/drm/i915/i915_dma.c > @@ -85,6 +85,96 @@ intel_read_legacy_status_page(struct > drm_i915_private *dev_priv, int reg) #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) > #define I915_BREADCRUMB_INDEX 0x21 > > +static int valleyview_ved_init(struct drm_device *dev) { > + int ret; > + int irq = -1; > + struct resource *rsc = NULL; > + struct drm_i915_private *dev_priv = dev->dev_private;; > + > + dev_priv->ved_platdev = platform_device_alloc("ipvr-ved", -1); > + if (unlikely(!dev_priv->ved_platdev)) { > + DRM_ERROR("Failed to allocate VED platform device\n"); > + ret = -ENOMEM; > + goto err; > + } > + > + rsc = kzalloc(sizeof(*rsc) * 3, GFP_KERNEL); > + if (unlikely(!rsc)) { > + DRM_ERROR("Failed to allocate resource for VED platform device\n"); > + ret = -ENOMEM; > + goto err; > + } > + > + /* init IRQ number and chip/callbacks */ > + irq = irq_alloc_descs(-1, 0, 1, 0); > + if (unlikely(irq < 0)) { > + DRM_ERROR("Failed to allocate IRQ number: %d\n", irq); > + ret = -ENOMEM; > + goto err; > + } > + > + ret = valleyview_initialize_ved_irq(dev, irq); > + if (unlikely(ret)) { > + DRM_ERROR("Failed to initialize VED IRQ: %d\n", ret); > + goto err; > + } > + > + dev_priv->ved_irq = irq; > + rsc[0].start = rsc[0].end = irq; > + rsc[0].flags = IORESOURCE_IRQ; > + rsc[0].name = "ipvr-ved-irq"; > + > + /* MMIO/REG for child's use */ > + rsc[1].start = pci_resource_start(dev->pdev, 0); > + rsc[1].end = pci_resource_start(dev->pdev, 0) + 2*1024*1024; /* gen7 */ > + rsc[1].flags = IORESOURCE_MEM; > + rsc[1].name = "ipvr-ved-mmio"; > + > + rsc[2].start = VLV_VED_BASE; > + rsc[2].end = VLV_VED_BASE + VLV_VED_SIZE; > + rsc[2].flags = IORESOURCE_REG; > + rsc[2].name = "ipvr-ved-reg"; > + > + ret = platform_device_add_resources(dev_priv->ved_platdev, rsc, 3); > + if (unlikely(ret)) { > + DRM_ERROR("Failed to add resource for VED platform device: %d\n", ret); > + goto err; > + } > + > + /* Runtime-PM hook */ > + dev_priv->ved_platdev->dev.parent = dev->dev; > + ret = platform_device_add(dev_priv->ved_platdev); > + if (unlikely(ret)) { > + DRM_ERROR("Failed to add VED platform device: %d\n", ret); > + goto err; > + } > + > + kfree(rsc); > + DRM_INFO("Successfully initialized Valleyview-VED\n"); > + return 0; > +err: > + if (rsc) > + kfree(rsc); > + if (dev_priv->ved_platdev) > + platform_device_unregister(dev_priv->ved_platdev); > + if (irq >= 0) > + irq_free_desc(irq); > + return ret; > +} > + > +static void valleyview_ved_cleanup(struct drm_device *dev) { > + int irq; > + struct drm_i915_private *dev_priv = dev->dev_private; > + > + irq = platform_get_irq(dev_priv->ved_platdev, 0); > + if (irq >= 0) > + irq_free_desc(irq); > + > + platform_device_unregister(dev_priv->ved_platdev); > +} > + > void i915_update_dri1_breadcrumb(struct drm_device *dev) { > struct drm_i915_private *dev_priv = dev->dev_private; @@ -1793,6 > +1883,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long > flags) > > intel_runtime_pm_enable(dev_priv); > > + if (IS_VALLEYVIEW(dev)) { > + BUG_ON(valleyview_ved_init(dev)); Just a quick drive-by comment, please don't bring down the machine if this one fails. Thanks, Jani. > + } > + > return 0; > > out_power_well: > @@ -1833,6 +1927,10 @@ int i915_driver_unload(struct drm_device *dev) > struct drm_i915_private *dev_priv = dev->dev_private; > int ret; > > + if (IS_VALLEYVIEW(dev)) { > + valleyview_ved_cleanup(dev); > + } > + > ret = i915_gem_suspend(dev); > if (ret) { > DRM_ERROR("failed to idle hardware: %d\n", ret); diff --git > a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 821ba26..aa8a183 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1709,6 +1709,10 @@ struct drm_i915_private { > > uint32_t bios_vgacntr; > > + /* used for setup sub device for valleyview */ > + struct platform_device *ved_platdev; > + int ved_irq; > + > /* Old dri1 support infrastructure, beware the dragons ya fools entering > * here! */ > struct i915_dri1_state dri1; > @@ -2921,6 +2925,8 @@ void vlv_flisdsi_write(struct drm_i915_private > *dev_priv, u32 reg, u32 val); int vlv_gpu_freq(struct > drm_i915_private *dev_priv, int val); int vlv_freq_opcode(struct > drm_i915_private *dev_priv, int val); > > +extern int valleyview_initialize_ved_irq(struct drm_device *dev, int > +irq); > + > #define FORCEWAKE_RENDER (1 << 0) > #define FORCEWAKE_MEDIA (1 << 1) > #define FORCEWAKE_ALL (FORCEWAKE_RENDER | FORCEWAKE_MEDIA) > diff --git a/drivers/gpu/drm/i915/i915_irq.c > b/drivers/gpu/drm/i915/i915_irq.c index 737b239..25c8cde 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -2142,12 +2142,75 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev) > } > } > > +static void valleyview_enable_ved_irq(struct irq_data *d) { > + struct drm_device *dev = d->chip_data; > + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; > + unsigned long irqflags; > + u32 imr, ier; > + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); > + > + ier = I915_READ(VLV_IER); > + ier |= VLV_VED_BLOCK_INTERRUPT; > + DRM_DEBUG_DRIVER("%s IER=>0x%08x\n", __func__, ier); > + I915_WRITE(VLV_IER, ier); > + POSTING_READ(VLV_IER); > + > + imr = I915_READ(VLV_IMR); > + imr &= ~VLV_VED_BLOCK_INTERRUPT; > + dev_priv->irq_mask = imr; > + DRM_DEBUG_DRIVER("%s IMR=>0x%08x\n", __func__, imr); > + I915_WRITE(VLV_IMR, imr); > + POSTING_READ(VLV_IMR); > + > + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } > + > +static void valleyview_disable_ved_irq(struct irq_data *d) { > + struct drm_device *dev = d->chip_data; > + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; > + unsigned long irqflags; > + u32 imr, ier; > + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); > + > + ier = I915_READ(VLV_IER); > + ier &= ~VLV_VED_BLOCK_INTERRUPT; > + DRM_DEBUG_DRIVER("%s IER=>0x%08x\n", __func__, ier); > + I915_WRITE(VLV_IER, ier); > + POSTING_READ(VLV_IER); > + > + imr = I915_READ(VLV_IMR); > + imr |= VLV_VED_BLOCK_INTERRUPT; > + dev_priv->irq_mask = imr; > + DRM_DEBUG_DRIVER("%s IMR=>0x%08x\n", __func__, imr); > + I915_WRITE(VLV_IMR, imr); > + POSTING_READ(VLV_IMR); > + > + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } > + > +int valleyview_initialize_ved_irq(struct drm_device *dev, int irq) { > + static struct irq_chip ved_irqchip = { > + .name = "ipvr_ved_irqchip", > + .irq_mask = valleyview_disable_ved_irq, > + .irq_unmask = valleyview_enable_ved_irq, > + }; > + irq_set_chip_and_handler_name(irq, > + &ved_irqchip, > + handle_simple_irq, > + "ipvr_ved_irq_handler"); > + return irq_set_chip_data(irq, dev); > +} > + > static irqreturn_t valleyview_irq_handler(int irq, void *arg) { > struct drm_device *dev = arg; > struct drm_i915_private *dev_priv = dev->dev_private; > u32 iir, gt_iir, pm_iir; > irqreturn_t ret = IRQ_NONE; > + int ved_ret; > > while (true) { > /* Find, clear, then process each source of interrupt */ @@ -2177,6 > +2240,13 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) > snb_gt_irq_handler(dev, dev_priv, gt_iir); > if (pm_iir) > gen6_rps_irq_handler(dev_priv, pm_iir); > + if (IS_VALLEYVIEW(dev) && dev_priv->ved_irq >= 0 > + && (iir & VLV_VED_BLOCK_INTERRUPT)) { > + ved_ret = generic_handle_irq(dev_priv->ved_irq); > + if (ved_ret) > + DRM_ERROR("Error forwarding VED irq: %d\n", ved_ret); > + trace_valleyview_ved_event(iir); > + } > /* Call regardless, as some status bits might not be > * signalled in iir */ > valleyview_pipestat_irq_handler(dev, iir); diff --git > a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 2ed02c3..89c8a06 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -1281,9 +1281,13 @@ enum punit_power_well { > #define GFX_PSMI_GRANULARITY (1<<10) > #define GFX_PPGTT_ENABLE (1<<9) > > +#define VLV_VED_BASE 0x170000 > +#define VLV_VED_SIZE 0x010000 > #define VLV_DISPLAY_BASE 0x180000 > #define VLV_MIPI_BASE VLV_DISPLAY_BASE > > +#define VLV_VED_BLOCK_INTERRUPT (1 << 23) > + > #define VLV_GU_CTL0 (VLV_DISPLAY_BASE + 0x2030) > #define VLV_GU_CTL1 (VLV_DISPLAY_BASE + 0x2034) > #define SCPD0 0x0209c /* 915+ only */ > diff --git a/drivers/gpu/drm/i915/i915_trace.h > b/drivers/gpu/drm/i915/i915_trace.h > index f5aa006..522bd1d 100644 > --- a/drivers/gpu/drm/i915/i915_trace.h > +++ b/drivers/gpu/drm/i915/i915_trace.h > @@ -587,6 +587,21 @@ TRACE_EVENT(intel_gpu_freq_change, > TP_printk("new_freq=%u", __entry->freq) ); > > +TRACE_EVENT(valleyview_ved_event, > + TP_PROTO(u32 iir), > + TP_ARGS(iir), > + > + TP_STRUCT__entry( > + __field(u32, iir) > + ), > + > + TP_fast_assign( > + __entry->iir = iir; > + ), > + > + TP_printk("forwarded with iir 0x%08x", __entry->iir) ); > + > #endif /* _I915_TRACE_H_ */ > > /* This part must be outside protection */ > -- > 1.9.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Jani Nikula, Intel Open Source Technology Center _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel