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@loongson.cn
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