Nikula, thx for reminder, will update it.

-----Original Message-----
From: Jani Nikula [mailto:jani.nik...@linux.intel.com] 
Sent: Tuesday, October 14, 2014 9:27 PM
To: Cheng, Yao; intel-gfx@lists.freedesktop.org
Cc: Jiang, Fei; dri-de...@lists.freedesktop.org; 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.ch...@intel.com> 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.ch...@intel.com>
> ---
>  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@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

--
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to