Re: [PATCH v2 3/3] drm/loongson: Add interrupt driver for LS7A

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 15, 2021 at 09:58:09AM +0800, lichenyang wrote:
> Add LS7A DC vsync interrupt enable and close function, and
> register irq_handler function interface.
> Add vbrank event processing flow.
> 
> V2:
> - Remove the useless flags parameter.

Do this in a separate patch.  It is an unrelated cleanup.

> - Added error handling in the loongson_drm_load function.
> 
> Signed-off-by: lichenyang <lichenyang@xxxxxxxxxxx>
> ---
>  drivers/gpu/drm/loongson/Makefile        |   3 +-
>  drivers/gpu/drm/loongson/loongson_crtc.c |  43 +++++++++-
>  drivers/gpu/drm/loongson/loongson_drv.c  |  22 +++--
>  drivers/gpu/drm/loongson/loongson_drv.h  |  17 +++-
>  drivers/gpu/drm/loongson/loongson_irq.c  | 105 +++++++++++++++++++++++
>  5 files changed, 179 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/loongson/loongson_irq.c
> 
> diff --git a/drivers/gpu/drm/loongson/Makefile b/drivers/gpu/drm/loongson/Makefile
> index 773b806e99a2..cc50b65c7e03 100644
> --- a/drivers/gpu/drm/loongson/Makefile
> +++ b/drivers/gpu/drm/loongson/Makefile
> @@ -11,5 +11,6 @@ loongson-y := loongson_drv.o \
>  	loongson_device.o \
>  	loongson_connector.o \
>  	loongson_encoder.o \
> -	loongson_i2c.o
> +	loongson_i2c.o \
> +	loongson_irq.o
>  obj-$(CONFIG_DRM_LOONGSON) += loongson.o
> diff --git a/drivers/gpu/drm/loongson/loongson_crtc.c b/drivers/gpu/drm/loongson/loongson_crtc.c
> index 4cb65fa08778..4c62d5b2bd56 100644
> --- a/drivers/gpu/drm/loongson/loongson_crtc.c
> +++ b/drivers/gpu/drm/loongson/loongson_crtc.c
> @@ -154,19 +154,25 @@ static void loongson_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  }
>  
>  static void loongson_crtc_atomic_enable(struct drm_crtc *crtc,
> -					struct drm_atomic_state *old_state)
> +					struct drm_atomic_state *old_crtc_state)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct loongson_device *ldev = dev->dev_private;
>  	struct loongson_crtc *lcrtc = to_loongson_crtc(crtc);
>  	u32 reg_offset = lcrtc->reg_offset;
>  
> +	if (lcrtc->cfg_reg & CFG_ENABLE)
> +		goto vblank_on;
> +
>  	lcrtc->cfg_reg |= CFG_ENABLE;
>  	ls7a_mm_wreg(ldev, FB_CFG_REG + reg_offset, lcrtc->cfg_reg);
> +
> +vblank_on:
> +	drm_crtc_vblank_on(crtc);
>  }
>  
>  static void loongson_crtc_atomic_disable(struct drm_crtc *crtc,
> -					 struct drm_atomic_state *old_state)
> +					 struct drm_atomic_state *old_crtc_state)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct loongson_device *ldev = dev->dev_private;
> @@ -175,10 +181,36 @@ static void loongson_crtc_atomic_disable(struct drm_crtc *crtc,
>  
>  	lcrtc->cfg_reg &= ~CFG_ENABLE;
>  	ls7a_mm_wreg(ldev, FB_CFG_REG + reg_offset, lcrtc->cfg_reg);
> +
> +	spin_lock_irq(&crtc->dev->event_lock);
> +	if (crtc->state->event) {
> +		drm_crtc_send_vblank_event(crtc, crtc->state->event);
> +		crtc->state->event = NULL;
> +	}
> +	spin_unlock_irq(&crtc->dev->event_lock);
> +
> +	drm_crtc_vblank_off(crtc);
> +}
> +
> +static void loongson_crtc_atomic_flush(struct drm_crtc *crtc,
> +				       struct drm_crtc_state *old_crtc_state)
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (event) {

Flip this around:

	if (!event)
		return;


> +		crtc->state->event = NULL;
> +
> +		spin_lock_irq(&crtc->dev->event_lock);
> +		if (drm_crtc_vblank_get(crtc) == 0)
> +			drm_crtc_arm_vblank_event(crtc, event);
> +		else
> +			drm_crtc_send_vblank_event(crtc, event);
> +		spin_unlock_irq(&crtc->dev->event_lock);
> +	}
>  }
>  
>  static enum drm_mode_status loongson_mode_valid(struct drm_crtc *crtc,
> -						const struct drm_display_mode *mode)
> +		const struct drm_display_mode *mode)
>  {
>  	if (mode->hdisplay > 1920)
>  		return MODE_BAD;
> @@ -194,9 +226,10 @@ static enum drm_mode_status loongson_mode_valid(struct drm_crtc *crtc,
>  
>  static const struct drm_crtc_helper_funcs loongson_crtc_helper_funcs = {
>  	.mode_valid = loongson_mode_valid,
> +	.mode_set_nofb = loongson_crtc_mode_set_nofb,
> +	.atomic_flush = loongson_crtc_atomic_flush,
>  	.atomic_enable = loongson_crtc_atomic_enable,
>  	.atomic_disable = loongson_crtc_atomic_disable,
> -	.mode_set_nofb = loongson_crtc_mode_set_nofb,
>  };
>  
>  static const struct drm_crtc_funcs loongson_crtc_funcs = {
> @@ -206,6 +239,8 @@ static const struct drm_crtc_funcs loongson_crtc_funcs = {
>  	.destroy = drm_crtc_cleanup,
>  	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
>  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +	.enable_vblank = loongson_crtc_enable_vblank,
> +	.disable_vblank = loongson_crtc_disable_vblank,
>  };
>  
>  int loongson_crtc_init(struct loongson_device *ldev, int index)
> diff --git a/drivers/gpu/drm/loongson/loongson_drv.c b/drivers/gpu/drm/loongson/loongson_drv.c
> index 252be9e25aff..13003f6ae062 100644
> --- a/drivers/gpu/drm/loongson/loongson_drv.c
> +++ b/drivers/gpu/drm/loongson/loongson_drv.c
> @@ -24,7 +24,7 @@ static const struct drm_mode_config_funcs loongson_mode_funcs = {
>  	.mode_valid = drm_vram_helper_mode_valid
>  };
>  
> -static int loongson_device_init(struct drm_device *dev, uint32_t flags)
> +static int loongson_device_init(struct drm_device *dev)
>  {
>  	struct loongson_device *ldev = dev->dev_private;
>  	struct pci_dev *gpu_pdev;
> @@ -131,7 +131,7 @@ int loongson_modeset_init(struct loongson_device *ldev)
>  	return 0;
>  }
>  
> -static int loongson_drm_load(struct drm_device *dev, unsigned long flags)
> +static int loongson_drm_load(struct drm_device *dev)
>  {
>  	struct loongson_device *ldev;
>  	int ret;
> @@ -143,7 +143,7 @@ static int loongson_drm_load(struct drm_device *dev, unsigned long flags)
>  	dev->dev_private = ldev;
>  	ldev->dev = dev;
>  
> -	ret = loongson_device_init(dev, flags);
> +	ret = loongson_device_init(dev);
>  	if (ret)
>  		goto err;
>  
> @@ -164,8 +164,16 @@ static int loongson_drm_load(struct drm_device *dev, unsigned long flags)
>  	pci_set_drvdata(dev->pdev, dev);
>  
>  	ret = loongson_modeset_init(ldev);
> -	if (ret)
> +	if (ret) {
>  		dev_err(dev->dev, "Fatal error during modeset init: %d\n", ret);
> +		goto err;
> +	}
> +
> +	ret = loongson_irq_init(ldev);
> +	if (ret) {
> +		dev_err(dev->dev, "Fatal error during irq init: %d\n", ret);
> +		goto err;
> +	}
>  
>  	drm_kms_helper_poll_init(dev);
>  	drm_mode_config_reset(dev);
> @@ -192,6 +200,10 @@ static struct drm_driver loongson_drm_driver = {
>  	.fops = &fops,
>  	DRM_GEM_VRAM_DRIVER,
>  
> +	.irq_handler = loongson_irq_handler,
> +	.irq_preinstall = loongson_irq_preinstall,
> +	.irq_uninstall = loongson_irq_uninstall,
> +
>  	.name = DRIVER_NAME,
>  	.desc = DRIVER_DESC,
>  	.date = DRIVER_DATE,
> @@ -221,7 +233,7 @@ static int loongson_pci_probe(struct pci_dev *pdev,
>  		goto err_free;
>  	}
>  
> -	ret = loongson_drm_load(dev, 0x0);
> +	ret = loongson_drm_load(dev);
>  	if (ret) {
>  		drm_err(dev, "failed to load loongson: %d\n", ret);
>  		goto err_pdev;
> diff --git a/drivers/gpu/drm/loongson/loongson_drv.h b/drivers/gpu/drm/loongson/loongson_drv.h
> index 24a534c3c79c..60f5bd48f7f2 100644
> --- a/drivers/gpu/drm/loongson/loongson_drv.h
> +++ b/drivers/gpu/drm/loongson/loongson_drv.h
> @@ -4,9 +4,11 @@
>  #define __LOONGSON_DRV_H__
>  
>  #include <drm/drm_drv.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_vblank.h>
>  #include <drm/drm_gem.h>
> +#include <drm/drm_irq.h>
>  #include <drm/drm_fb_helper.h>
> -#include <drm/drm_fourcc.h>
>  #include <drm/drm_probe_helper.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> @@ -49,6 +51,7 @@
>  #define FB_HSYNC_REG (0x1420)
>  #define FB_VDISPLAY_REG (0x1480)
>  #define FB_VSYNC_REG (0x14a0)
> +#define FB_INT_REG (0x1570)
>  
>  #define CFG_FMT GENMASK(2, 0)
>  #define CFG_FBSWITCH BIT(7)
> @@ -60,6 +63,10 @@
>  #define FB_PANCFG_DEF 0x80001311
>  #define FB_HSYNC_PULSE (1 << 30)
>  #define FB_VSYNC_PULSE (1 << 30)
> +#define FB_VSYNC1_ENABLE (1 << 16)
> +#define FB_VSYNC0_ENABLE (1 << 18)
> +#define FB_VSYNC1_INT (1 << 0)
> +#define FB_VSYNC0_INT (1 << 2)
>  
>  /* PIX PLL */
>  #define LOOPC_MIN 24
> @@ -136,6 +143,14 @@ int loongson_encoder_init(struct loongson_device *ldev, int index);
>  /* plane */
>  int loongson_plane_init(struct loongson_crtc *lcrtc);
>  
> +/* irq */
> +int loongson_irq_init(struct loongson_device *ldev);
> +int loongson_crtc_enable_vblank(struct drm_crtc *crtc);
> +void loongson_crtc_disable_vblank(struct drm_crtc *crtc);
> +irqreturn_t loongson_irq_handler(int irq, void *arg);
> +void loongson_irq_preinstall(struct drm_device *dev);
> +void loongson_irq_uninstall(struct drm_device *dev);
> +
>  /* i2c */
>  int loongson_dc_gpio_init(struct loongson_device *ldev);
>  
> diff --git a/drivers/gpu/drm/loongson/loongson_irq.c b/drivers/gpu/drm/loongson/loongson_irq.c
> new file mode 100644
> index 000000000000..d212e16f3c00
> --- /dev/null
> +++ b/drivers/gpu/drm/loongson/loongson_irq.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +
> +#include "loongson_drv.h"
> +#include <linux/pci.h>
> +
> +int loongson_irq_init(struct loongson_device *ldev)
> +{
> +	struct drm_device *dev;
> +	int ret, irq;
> +
> +	dev = ldev->dev;
> +	irq = dev->pdev->irq;
> +
> +	ret = drm_vblank_init(dev, ldev->num_crtc);
> +	if (ret) {
> +		dev_err(dev->dev, "Fatal error during vblank init: %d\n", ret);
> +		return ret;
> +	}
> +	DRM_INFO("drm vblank init finished\n");
> +
> +	ret = drm_irq_install(dev, irq);
> +	if (ret) {
> +		dev_err(dev->dev, "Fatal error during irq install: %d\n", ret);
> +		return ret;
> +	}
> +	DRM_INFO("loongson irq initialized\n");
> +
> +	return 0;
> +}
> +
> +int loongson_crtc_enable_vblank(struct drm_crtc *crtc)
> +{
> +	struct loongson_crtc *lcrtc = to_loongson_crtc(crtc);
> +	struct loongson_device *ldev = lcrtc->ldev;
> +	u32 reg_val;
> +
> +	if (lcrtc->crtc_id) {
> +		reg_val = ls7a_mm_rreg(ldev, FB_INT_REG);
> +		reg_val |= FB_VSYNC1_ENABLE;
> +		ls7a_mm_wreg(ldev, FB_INT_REG, reg_val);
> +	} else {
> +		reg_val = ls7a_mm_rreg(ldev, FB_INT_REG);
> +		reg_val |= FB_VSYNC0_ENABLE;
> +		ls7a_mm_wreg(ldev, FB_INT_REG, reg_val);
> +	}
> +
> +	return 0;
> +}
> +
> +void loongson_crtc_disable_vblank(struct drm_crtc *crtc)
> +{
> +	struct loongson_crtc *lcrtc = to_loongson_crtc(crtc);
> +	struct loongson_device *ldev = lcrtc->ldev;
> +	u32 reg_val;
> +
> +	if (lcrtc->crtc_id) {
> +		reg_val = ls7a_mm_rreg(ldev, FB_INT_REG);
> +		reg_val &= ~FB_VSYNC1_ENABLE;
> +		ls7a_mm_wreg(ldev, FB_INT_REG, reg_val);
> +	} else {
> +		reg_val = ls7a_mm_rreg(ldev, FB_INT_REG);
> +		reg_val &= ~FB_VSYNC0_ENABLE;
> +		ls7a_mm_wreg(ldev, FB_INT_REG, reg_val);
> +	}

More readable to pull the common code in one place:

	reg_val = ls7a_mm_rreg(ldev, FB_INT_REG);

	if (lcrtc->crtc_id)
		reg_val &= ~FB_VSYNC1_ENABLE;
	else
		reg_val &= ~FB_VSYNC0_ENABLE;

	ls7a_mm_wreg(ldev, FB_INT_REG, reg_val);


> +}
> +

regards,
dan carpenter




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux