From 0fb2970b4b6bfc26817a731b8bc29a9bf9177c20 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 6 Jun 2015 21:46:53 +0100 Subject: drm/armada: remove non-component support Now that the transition of TDA998x to the component helpers is complete, remove the non-componentised support from the Armada DRM driver. All outputs are expected to use the component helpers from now on. Signed-off-by: Russell King --- drivers/gpu/drm/armada/Kconfig | 9 --- drivers/gpu/drm/armada/Makefile | 3 +- drivers/gpu/drm/armada/armada_crtc.c | 2 +- drivers/gpu/drm/armada/armada_crtc.h | 4 - drivers/gpu/drm/armada/armada_drv.c | 125 ++++------------------------- drivers/gpu/drm/armada/armada_output.c | 142 --------------------------------- drivers/gpu/drm/armada/armada_output.h | 33 -------- drivers/gpu/drm/armada/armada_slave.c | 139 -------------------------------- drivers/gpu/drm/armada/armada_slave.h | 26 ------ 9 files changed, 19 insertions(+), 464 deletions(-) delete mode 100644 drivers/gpu/drm/armada/armada_output.c delete mode 100644 drivers/gpu/drm/armada/armada_output.h delete mode 100644 drivers/gpu/drm/armada/armada_slave.c delete mode 100644 drivers/gpu/drm/armada/armada_slave.h (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/Kconfig b/drivers/gpu/drm/armada/Kconfig index 50ae88ad4d76..eb773e9af313 100644 --- a/drivers/gpu/drm/armada/Kconfig +++ b/drivers/gpu/drm/armada/Kconfig @@ -14,12 +14,3 @@ config DRM_ARMADA This driver provides no built-in acceleration; acceleration is performed by other IP found on the SoC. This driver provides kernel mode setting and buffer management to userspace. - -config DRM_ARMADA_TDA1998X - bool "Support TDA1998X HDMI output" - depends on DRM_ARMADA != n - depends on I2C && DRM_I2C_NXP_TDA998X = y - default y - help - Support the TDA1998x HDMI output device found on the Solid-Run - CuBox. diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile index d6f43e06150a..ffd673615772 100644 --- a/drivers/gpu/drm/armada/Makefile +++ b/drivers/gpu/drm/armada/Makefile @@ -1,6 +1,5 @@ armada-y := armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \ - armada_gem.o armada_output.o armada_overlay.o \ - armada_slave.o + armada_gem.o armada_overlay.o armada-y += armada_510.o armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 01ffe9bffe38..c7374a3ec67a 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1044,7 +1044,7 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) return 0; } -int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, +static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, struct resource *res, int irq, const struct armada_variant *variant, struct device_node *port) { diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 98102a5a9af5..a13469f5d72b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -75,10 +75,6 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) -struct device_node; -int armada_drm_crtc_create(struct drm_device *, struct device *, - struct resource *, int, const struct armada_variant *, - struct device_node *); void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 225034b74cda..b373cf9b2f65 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -18,47 +18,6 @@ #include #include "armada_ioctlP.h" -#ifdef CONFIG_DRM_ARMADA_TDA1998X -#include -#include "armada_slave.h" - -static struct tda998x_encoder_params params = { - /* With 0x24, there is no translation between vp_out and int_vp - FB LCD out Pins VIP Int Vp - R:23:16 R:7:0 VPC7:0 7:0 7:0[R] - G:15:8 G:15:8 VPB7:0 23:16 23:16[G] - B:7:0 B:23:16 VPA7:0 15:8 15:8[B] - */ - .swap_a = 2, - .swap_b = 3, - .swap_c = 4, - .swap_d = 5, - .swap_e = 0, - .swap_f = 1, - .audio_cfg = BIT(2), - .audio_frame[1] = 1, - .audio_format = AFMT_SPDIF, - .audio_sample_rate = 44100, -}; - -static const struct armada_drm_slave_config tda19988_config = { - .i2c_adapter_id = 0, - .crtcs = 1 << 0, /* Only LCD0 at the moment */ - .polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT, - .interlace_allowed = true, - .info = { - .type = "tda998x", - .addr = 0x70, - .platform_data = ¶ms, - }, -}; -#endif - -static bool is_componentized(struct device *dev) -{ - return dev->of_node || dev->platform_data; -} - static void armada_drm_unref_work(struct work_struct *work) { struct armada_private *priv = @@ -91,16 +50,11 @@ void armada_drm_queue_unref_work(struct drm_device *dev, static int armada_drm_load(struct drm_device *dev, unsigned long flags) { - const struct platform_device_id *id; - const struct armada_variant *variant; struct armada_private *priv; - struct resource *res[ARRAY_SIZE(priv->dcrtc)]; struct resource *mem = NULL; - int ret, n, i; + int ret, n; - memset(res, 0, sizeof(res)); - - for (n = i = 0; ; n++) { + for (n = 0; ; n++) { struct resource *r = platform_get_resource(dev->platformdev, IORESOURCE_MEM, n); if (!r) @@ -109,8 +63,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) /* Resources above 64K are graphics memory */ if (resource_size(r) > SZ_64K) mem = r; - else if (i < ARRAY_SIZE(priv->dcrtc)) - res[i++] = r; else return -EINVAL; } @@ -131,13 +83,6 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) platform_set_drvdata(dev->platformdev, dev); dev->dev_private = priv; - /* Get the implementation specific driver data. */ - id = platform_get_device_id(dev->platformdev); - if (!id) - return -ENXIO; - - variant = (const struct armada_variant *)id->driver_data; - INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work); INIT_KFIFO(priv->fb_unref); @@ -157,34 +102,9 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) dev->mode_config.funcs = &armada_drm_mode_config_funcs; drm_mm_init(&priv->linear, mem->start, resource_size(mem)); - /* Create all LCD controllers */ - for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) { - int irq; - - if (!res[n]) - break; - - irq = platform_get_irq(dev->platformdev, n); - if (irq < 0) - goto err_kms; - - ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, - variant, NULL); - if (ret) - goto err_kms; - } - - if (is_componentized(dev->dev)) { - ret = component_bind_all(dev->dev, dev); - if (ret) - goto err_kms; - } else { -#ifdef CONFIG_DRM_ARMADA_TDA1998X - ret = armada_drm_connector_slave_create(dev, &tda19988_config); - if (ret) - goto err_kms; -#endif - } + ret = component_bind_all(dev->dev, dev); + if (ret) + goto err_kms; ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) @@ -202,8 +122,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) return 0; err_comp: - if (is_componentized(dev->dev)) - component_unbind_all(dev->dev, dev); + component_unbind_all(dev->dev, dev); err_kms: drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); @@ -219,8 +138,7 @@ static int armada_drm_unload(struct drm_device *dev) drm_kms_helper_poll_fini(dev); armada_fbdev_fini(dev); - if (is_componentized(dev->dev)) - component_unbind_all(dev->dev, dev); + component_unbind_all(dev->dev, dev); drm_mode_config_cleanup(dev); drm_mm_takedown(&priv->linear); @@ -435,37 +353,28 @@ static const struct component_master_ops armada_master_ops = { static int armada_drm_probe(struct platform_device *pdev) { - if (is_componentized(&pdev->dev)) { - struct component_match *match = NULL; - int ret; - - ret = armada_drm_find_components(&pdev->dev, &match); - if (ret < 0) - return ret; - - return component_master_add_with_match(&pdev->dev, - &armada_master_ops, match); - } else { - return drm_platform_init(&armada_drm_driver, pdev); - } + struct component_match *match = NULL; + int ret; + + ret = armada_drm_find_components(&pdev->dev, &match); + if (ret < 0) + return ret; + + return component_master_add_with_match(&pdev->dev, &armada_master_ops, + match); } static int armada_drm_remove(struct platform_device *pdev) { - if (is_componentized(&pdev->dev)) - component_master_del(&pdev->dev, &armada_master_ops); - else - drm_put_dev(platform_get_drvdata(pdev)); + component_master_del(&pdev->dev, &armada_master_ops); return 0; } static const struct platform_device_id armada_drm_platform_ids[] = { { .name = "armada-drm", - .driver_data = (unsigned long)&armada510_ops, }, { .name = "armada-510-drm", - .driver_data = (unsigned long)&armada510_ops, }, { }, }; diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c deleted file mode 100644 index 5a9823178291..000000000000 --- a/drivers/gpu/drm/armada/armada_output.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include "armada_output.h" -#include "armada_drm.h" - -struct armada_connector { - struct drm_connector conn; - const struct armada_output_type *type; -}; - -#define drm_to_armada_conn(c) container_of(c, struct armada_connector, conn) - -struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn) -{ - struct drm_encoder *enc = conn->encoder; - - return enc ? enc : drm_encoder_find(conn->dev, conn->encoder_ids[0]); -} - -static enum drm_connector_status armada_drm_connector_detect( - struct drm_connector *conn, bool force) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - enum drm_connector_status status = connector_status_disconnected; - - if (dconn->type->detect) { - status = dconn->type->detect(conn, force); - } else { - struct drm_encoder *enc = armada_drm_connector_encoder(conn); - - if (enc) - status = encoder_helper_funcs(enc)->detect(enc, conn); - } - - return status; -} - -static void armada_drm_connector_destroy(struct drm_connector *conn) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - - drm_connector_unregister(conn); - drm_connector_cleanup(conn); - kfree(dconn); -} - -static int armada_drm_connector_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value) -{ - struct armada_connector *dconn = drm_to_armada_conn(conn); - - if (!dconn->type->set_property) - return -EINVAL; - - return dconn->type->set_property(conn, property, value); -} - -static const struct drm_connector_funcs armada_drm_conn_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = armada_drm_connector_detect, - .destroy = armada_drm_connector_destroy, - .set_property = armada_drm_connector_set_property, -}; - -/* Shouldn't this be a generic helper function? */ -int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode) -{ - struct drm_encoder *encoder = armada_drm_connector_encoder(conn); - int valid = MODE_BAD; - - if (encoder) { - struct drm_encoder_slave *slave = to_encoder_slave(encoder); - - valid = slave->slave_funcs->mode_valid(encoder, mode); - } - return valid; -} - -int armada_drm_slave_encoder_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value) -{ - struct drm_encoder *encoder = armada_drm_connector_encoder(conn); - int rc = -EINVAL; - - if (encoder) { - struct drm_encoder_slave *slave = to_encoder_slave(encoder); - - rc = slave->slave_funcs->set_property(encoder, conn, property, - value); - } - return rc; -} - -int armada_output_create(struct drm_device *dev, - const struct armada_output_type *type, const void *data) -{ - struct armada_connector *dconn; - int ret; - - dconn = kzalloc(sizeof(*dconn), GFP_KERNEL); - if (!dconn) - return -ENOMEM; - - dconn->type = type; - - ret = drm_connector_init(dev, &dconn->conn, &armada_drm_conn_funcs, - type->connector_type); - if (ret) { - DRM_ERROR("unable to init connector\n"); - goto err_destroy_dconn; - } - - ret = type->create(&dconn->conn, data); - if (ret) - goto err_conn; - - ret = drm_connector_register(&dconn->conn); - if (ret) - goto err_sysfs; - - return 0; - - err_sysfs: - if (dconn->conn.encoder) - dconn->conn.encoder->funcs->destroy(dconn->conn.encoder); - err_conn: - drm_connector_cleanup(&dconn->conn); - err_destroy_dconn: - kfree(dconn); - return ret; -} diff --git a/drivers/gpu/drm/armada/armada_output.h b/drivers/gpu/drm/armada/armada_output.h deleted file mode 100644 index f448785753e8..000000000000 --- a/drivers/gpu/drm/armada/armada_output.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef ARMADA_CONNETOR_H -#define ARMADA_CONNETOR_H - -#define encoder_helper_funcs(encoder) \ - ((const struct drm_encoder_helper_funcs *)encoder->helper_private) - -struct armada_output_type { - int connector_type; - enum drm_connector_status (*detect)(struct drm_connector *, bool); - int (*create)(struct drm_connector *, const void *); - int (*set_property)(struct drm_connector *, struct drm_property *, - uint64_t); -}; - -struct drm_encoder *armada_drm_connector_encoder(struct drm_connector *conn); - -int armada_drm_slave_encoder_mode_valid(struct drm_connector *conn, - struct drm_display_mode *mode); - -int armada_drm_slave_encoder_set_property(struct drm_connector *conn, - struct drm_property *property, uint64_t value); - -int armada_output_create(struct drm_device *dev, - const struct armada_output_type *type, const void *data); - -#endif diff --git a/drivers/gpu/drm/armada/armada_slave.c b/drivers/gpu/drm/armada/armada_slave.c deleted file mode 100644 index 00d0facb42f3..000000000000 --- a/drivers/gpu/drm/armada/armada_slave.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * Rewritten from the dovefb driver, and Armada510 manuals. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include "armada_drm.h" -#include "armada_output.h" -#include "armada_slave.h" - -static int armada_drm_slave_get_modes(struct drm_connector *conn) -{ - struct drm_encoder *enc = armada_drm_connector_encoder(conn); - int count = 0; - - if (enc) { - struct drm_encoder_slave *slave = to_encoder_slave(enc); - - count = slave->slave_funcs->get_modes(enc, conn); - } - - return count; -} - -static void armada_drm_slave_destroy(struct drm_encoder *enc) -{ - struct drm_encoder_slave *slave = to_encoder_slave(enc); - struct i2c_client *client = drm_i2c_encoder_get_client(enc); - - if (slave->slave_funcs) - slave->slave_funcs->destroy(enc); - if (client) - i2c_put_adapter(client->adapter); - - drm_encoder_cleanup(&slave->base); - kfree(slave); -} - -static const struct drm_encoder_funcs armada_drm_slave_encoder_funcs = { - .destroy = armada_drm_slave_destroy, -}; - -static const struct drm_connector_helper_funcs armada_drm_slave_helper_funcs = { - .get_modes = armada_drm_slave_get_modes, - .mode_valid = armada_drm_slave_encoder_mode_valid, - .best_encoder = armada_drm_connector_encoder, -}; - -static const struct drm_encoder_helper_funcs drm_slave_encoder_helpers = { - .dpms = drm_i2c_encoder_dpms, - .save = drm_i2c_encoder_save, - .restore = drm_i2c_encoder_restore, - .mode_fixup = drm_i2c_encoder_mode_fixup, - .prepare = drm_i2c_encoder_prepare, - .commit = drm_i2c_encoder_commit, - .mode_set = drm_i2c_encoder_mode_set, - .detect = drm_i2c_encoder_detect, -}; - -static int -armada_drm_conn_slave_create(struct drm_connector *conn, const void *data) -{ - const struct armada_drm_slave_config *config = data; - struct drm_encoder_slave *slave; - struct i2c_adapter *adap; - int ret; - - conn->interlace_allowed = config->interlace_allowed; - conn->doublescan_allowed = config->doublescan_allowed; - conn->polled = config->polled; - - drm_connector_helper_add(conn, &armada_drm_slave_helper_funcs); - - slave = kzalloc(sizeof(*slave), GFP_KERNEL); - if (!slave) - return -ENOMEM; - - slave->base.possible_crtcs = config->crtcs; - - adap = i2c_get_adapter(config->i2c_adapter_id); - if (!adap) { - kfree(slave); - return -EPROBE_DEFER; - } - - ret = drm_encoder_init(conn->dev, &slave->base, - &armada_drm_slave_encoder_funcs, - DRM_MODE_ENCODER_TMDS); - if (ret) { - DRM_ERROR("unable to init encoder\n"); - i2c_put_adapter(adap); - kfree(slave); - return ret; - } - - ret = drm_i2c_encoder_init(conn->dev, slave, adap, &config->info); - i2c_put_adapter(adap); - if (ret) { - DRM_ERROR("unable to init encoder slave\n"); - armada_drm_slave_destroy(&slave->base); - return ret; - } - - drm_encoder_helper_add(&slave->base, &drm_slave_encoder_helpers); - - ret = slave->slave_funcs->create_resources(&slave->base, conn); - if (ret) { - armada_drm_slave_destroy(&slave->base); - return ret; - } - - ret = drm_mode_connector_attach_encoder(conn, &slave->base); - if (ret) { - armada_drm_slave_destroy(&slave->base); - return ret; - } - - conn->encoder = &slave->base; - - return ret; -} - -static const struct armada_output_type armada_drm_conn_slave = { - .connector_type = DRM_MODE_CONNECTOR_HDMIA, - .create = armada_drm_conn_slave_create, - .set_property = armada_drm_slave_encoder_set_property, -}; - -int armada_drm_connector_slave_create(struct drm_device *dev, - const struct armada_drm_slave_config *config) -{ - return armada_output_create(dev, &armada_drm_conn_slave, config); -} diff --git a/drivers/gpu/drm/armada/armada_slave.h b/drivers/gpu/drm/armada/armada_slave.h deleted file mode 100644 index bf2374c96fc1..000000000000 --- a/drivers/gpu/drm/armada/armada_slave.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef ARMADA_SLAVE_H -#define ARMADA_SLAVE_H - -#include -#include - -struct armada_drm_slave_config { - int i2c_adapter_id; - uint32_t crtcs; - uint8_t polled; - bool interlace_allowed; - bool doublescan_allowed; - struct i2c_board_info info; -}; - -int armada_drm_connector_slave_create(struct drm_device *dev, - const struct armada_drm_slave_config *); - -#endif -- cgit v1.2.1 From 7c8f7e1abc75b853adf60d8ee0a589e058bcdb6b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 17:52:16 +0100 Subject: drm/armada: move vbl code into armada_crtc Our vblank event code belongs in armada_crtc.c rather than the core of the driver. Move it there. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 46 ++++++++++++++++++++++++++++++------ drivers/gpu/drm/armada/armada_crtc.h | 17 +++++++++++++ drivers/gpu/drm/armada/armada_drm.h | 16 ------------- drivers/gpu/drm/armada/armada_drv.c | 23 ------------------ 4 files changed, 56 insertions(+), 46 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index c7374a3ec67a..418594b19d1d 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -173,6 +173,44 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, return i; } +void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, + struct armada_vbl_event *evt) +{ + unsigned long flags; + bool not_on_list; + + WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num)); + + spin_lock_irqsave(&dcrtc->irq_lock, flags); + not_on_list = list_empty(&evt->node); + if (not_on_list) + list_add_tail(&evt->node, &dcrtc->vbl_list); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); + + if (!not_on_list) + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); +} + +void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, + struct armada_vbl_event *evt) +{ + if (!list_empty(&evt->node)) { + list_del_init(&evt->node); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + } +} + +static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) +{ + struct armada_vbl_event *e, *n; + + list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { + list_del_init(&e->node); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + e->fn(dcrtc, e->data); + } +} + static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { @@ -356,7 +394,6 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) { - struct armada_vbl_event *e, *n; void __iomem *base = dcrtc->base; if (stat & DMA_FF_UNDERFLOW) @@ -368,12 +405,7 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); spin_lock(&dcrtc->irq_lock); - - list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { - list_del_init(&e->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - e->fn(dcrtc, e->data); - } + armada_drm_vbl_event_run(dcrtc); if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index a13469f5d72b..a86243ef4a51 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -75,6 +75,23 @@ struct armada_crtc { }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) +struct armada_vbl_event { + struct list_head node; + void *data; + void (*fn)(struct armada_crtc *, void *); +}; + +void armada_drm_vbl_event_add(struct armada_crtc *, + struct armada_vbl_event *); +void armada_drm_vbl_event_remove(struct armada_crtc *, + struct armada_vbl_event *); +#define armada_drm_vbl_event_init(_e, _f, _d) do { \ + struct armada_vbl_event *__e = _e; \ + INIT_LIST_HEAD(&__e->node); \ + __e->data = _d; \ + __e->fn = _f; \ +} while (0) + void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index 5f6aef0dca59..4df6f2af2b21 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -37,22 +37,6 @@ static inline uint32_t armada_pitch(uint32_t width, uint32_t bpp) return ALIGN(pitch, 128); } -struct armada_vbl_event { - struct list_head node; - void *data; - void (*fn)(struct armada_crtc *, void *); -}; -void armada_drm_vbl_event_add(struct armada_crtc *, - struct armada_vbl_event *); -void armada_drm_vbl_event_remove(struct armada_crtc *, - struct armada_vbl_event *); -#define armada_drm_vbl_event_init(_e, _f, _d) do { \ - struct armada_vbl_event *__e = _e; \ - INIT_LIST_HEAD(&__e->node); \ - __e->data = _d; \ - __e->fn = _f; \ -} while (0) - struct armada_private; diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index b373cf9b2f65..3f1396e673dd 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -148,29 +148,6 @@ static int armada_drm_unload(struct drm_device *dev) return 0; } -void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - unsigned long flags; - - spin_lock_irqsave(&dcrtc->irq_lock, flags); - if (list_empty(&evt->node)) { - list_add_tail(&evt->node, &dcrtc->vbl_list); - - drm_vblank_get(dcrtc->crtc.dev, dcrtc->num); - } - spin_unlock_irqrestore(&dcrtc->irq_lock, flags); -} - -void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - if (!list_empty(&evt->node)) { - list_del_init(&evt->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - } -} - /* These are called under the vbl_lock. */ static int armada_drm_enable_vblank(struct drm_device *dev, int crtc) { -- cgit v1.2.1 From f8e140698234dae3a4ea7b971e7bf63a3e0c987a Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 17:52:42 +0100 Subject: drm/armada: use drm_plane_force_disable() to disable the overlay plane Use drm_plane_force_disable() to disable the overlay plane on a mode_set rather than coding this ourselves. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 418594b19d1d..bbf5ff785cd2 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -348,17 +348,11 @@ static void armada_drm_crtc_prepare(struct drm_crtc *crtc) /* * If we have an overlay plane associated with this CRTC, disable * it before the modeset to avoid its coordinates being outside - * the new mode parameters. DRM doesn't provide help with this. + * the new mode parameters. */ plane = dcrtc->plane; - if (plane) { - struct drm_framebuffer *fb = plane->fb; - - plane->funcs->disable_plane(plane); - plane->fb = NULL; - plane->crtc = NULL; - drm_framebuffer_unreference(fb); - } + if (plane) + drm_plane_force_disable(plane); } /* The mode_config.mutex will be held for this call */ -- cgit v1.2.1 From e0ac5e9b4b14ab4be7fbba48d666fc619342fd88 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 29 Jun 2015 18:01:38 +0100 Subject: drm/armada: disable CRTC clock during DPMS When the CRTC is in low power mode, it isn't running, and so there's no point keeping the CRTC clock enabled. Disable the CRTC clock during DPMS. We need to re-enable it in the mode_set callback to ensure that the variant's compute_clock() continues to see its clock in the expected state (enabled). Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index bbf5ff785cd2..8c43ecc19c15 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -325,7 +325,11 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms) if (dcrtc->dpms != dpms) { dcrtc->dpms = dpms; + if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms)) + WARN_ON(clk_prepare_enable(dcrtc->clk)); armada_drm_crtc_update(dcrtc); + if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms)) + clk_disable_unprepare(dcrtc->clk); if (dpms_blanked(dpms)) armada_drm_vblank_off(dcrtc); else @@ -563,6 +567,13 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, writel_relaxed(val, dcrtc->base + LCD_SPU_DUMB_CTRL); } + /* + * If we are blanked, we would have disabled the clock. Re-enable + * it so that compute_clock() does the right thing. + */ + if (!IS_ERR(dcrtc->clk) && dpms_blanked(dcrtc->dpms)) + WARN_ON(clk_prepare_enable(dcrtc->clk)); + /* Now compute the divider for real */ dcrtc->variant->compute_clock(dcrtc, adj, &sclk); -- cgit v1.2.1 From 709ffd82fc6ff760dc3a7f71bdf26d78a8e3caf0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:09:38 +0100 Subject: drm/armada: redo locking and atomics for armada_drm_crtc_complete_frame_work() We can do better with armada_drm_crtc_complete_frame_work() - we can avoid taking the event lock unless a call to drm_send_vblank_event() is required, and using cmpxchg() and xchg(), we can eliminate the locking around dcrtc->frame_work entirely. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 53 ++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 8c43ecc19c15..5d627646601e 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -215,7 +215,6 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - unsigned long flags; int ret; ret = drm_vblank_get(dev, dcrtc->num); @@ -224,30 +223,29 @@ static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, return ret; } - spin_lock_irqsave(&dev->event_lock, flags); - if (!dcrtc->frame_work) - dcrtc->frame_work = work; - else - ret = -EBUSY; - spin_unlock_irqrestore(&dev->event_lock, flags); - - if (ret) + if (cmpxchg(&dcrtc->frame_work, NULL, work)) { drm_vblank_put(dev, dcrtc->num); + ret = -EBUSY; + } return ret; } -static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc) +static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc, + struct armada_frame_work *work) { struct drm_device *dev = dcrtc->crtc.dev; - struct armada_frame_work *work = dcrtc->frame_work; - - dcrtc->frame_work = NULL; + unsigned long flags; + spin_lock_irqsave(&dcrtc->irq_lock, flags); armada_drm_crtc_update_regs(dcrtc, work->regs); + spin_unlock_irqrestore(&dcrtc->irq_lock, flags); - if (work->event) + if (work->event) { + spin_lock_irqsave(&dev->event_lock, flags); drm_send_vblank_event(dev, dcrtc->num, work->event); + spin_unlock_irqrestore(&dev->event_lock, flags); + } drm_vblank_put(dev, dcrtc->num); @@ -293,7 +291,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work; /* * Tell the DRM core that vblank IRQs aren't going to happen for @@ -302,10 +300,9 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc) drm_crtc_vblank_off(&dcrtc->crtc); /* Handle any pending flip event. */ - spin_lock_irq(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irq(&dev->event_lock); + work = xchg(&dcrtc->frame_work, NULL); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -434,12 +431,10 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ) { - struct drm_device *dev = dcrtc->crtc.dev; + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - spin_lock(&dev->event_lock); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock(&dev->event_lock); + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); wake_up(&dcrtc->frame_wait); } @@ -957,8 +952,6 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct armada_frame_work *work; - struct drm_device *dev = crtc->dev; - unsigned long flags; unsigned i; int ret; @@ -1004,10 +997,10 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * interrupt, so complete it now. */ if (dpms_blanked(dcrtc->dpms)) { - spin_lock_irqsave(&dev->event_lock, flags); - if (dcrtc->frame_work) - armada_drm_crtc_complete_frame_work(dcrtc); - spin_unlock_irqrestore(&dev->event_lock, flags); + struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); + + if (work) + armada_drm_crtc_complete_frame_work(dcrtc, work); } return 0; -- cgit v1.2.1 From 28a2aebed6374c4af5224114e4b4273a3aae649a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:23 +0100 Subject: drm/armada: rename overlay identifiers Include an _ovl infix into the overlay identifiers to separate them from the primary plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_overlay.c | 55 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index e939faba7fcc..9393a15183e2 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -16,7 +16,7 @@ #include #include "armada_ioctlP.h" -struct armada_plane_properties { +struct armada_ovl_plane_properties { uint32_t colorkey_yr; uint32_t colorkey_ug; uint32_t colorkey_vb; @@ -29,7 +29,7 @@ struct armada_plane_properties { uint32_t colorkey_mode; }; -struct armada_plane { +struct armada_ovl_plane { struct drm_plane base; spinlock_t lock; struct drm_framebuffer *old_fb; @@ -42,13 +42,13 @@ struct armada_plane { struct armada_regs regs[13]; wait_queue_head_t wait; } vbl; - struct armada_plane_properties prop; + struct armada_ovl_plane_properties prop; }; -#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) +#define drm_to_armada_ovl_plane(p) container_of(p, struct armada_ovl_plane, base) static void -armada_ovl_update_attr(struct armada_plane_properties *prop, +armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, struct armada_crtc *dcrtc) { writel_relaxed(prop->colorkey_yr, dcrtc->base + LCD_SPU_COLORKEY_Y); @@ -72,9 +72,9 @@ armada_ovl_update_attr(struct armada_plane_properties *prop, } /* === Plane support === */ -static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) +static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) { - struct armada_plane *dplane = data; + struct armada_ovl_plane *dplane = data; struct drm_framebuffer *fb; armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); @@ -91,12 +91,12 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) } static int -armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, +armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct drm_rect src = { .x1 = src_x, @@ -267,9 +267,9 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } -static int armada_plane_disable(struct drm_plane *plane) +static int armada_ovl_plane_disable(struct drm_plane *plane) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); struct drm_framebuffer *fb; struct armada_crtc *dcrtc; @@ -302,20 +302,20 @@ static int armada_plane_disable(struct drm_plane *plane) return 0; } -static void armada_plane_destroy(struct drm_plane *plane) +static void armada_ovl_plane_destroy(struct drm_plane *plane) { - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); drm_plane_cleanup(plane); kfree(dplane); } -static int armada_plane_set_property(struct drm_plane *plane, +static int armada_ovl_plane_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { struct armada_private *priv = plane->dev->dev_private; - struct armada_plane *dplane = drm_to_armada_plane(plane); + struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); bool update_attr = false; if (property == priv->colorkey_prop) { @@ -379,14 +379,14 @@ static int armada_plane_set_property(struct drm_plane *plane, return 0; } -static const struct drm_plane_funcs armada_plane_funcs = { - .update_plane = armada_plane_update, - .disable_plane = armada_plane_disable, - .destroy = armada_plane_destroy, - .set_property = armada_plane_set_property, +static const struct drm_plane_funcs armada_ovl_plane_funcs = { + .update_plane = armada_ovl_plane_update, + .disable_plane = armada_ovl_plane_disable, + .destroy = armada_ovl_plane_destroy, + .set_property = armada_ovl_plane_set_property, }; -static const uint32_t armada_formats[] = { +static const uint32_t armada_ovl_formats[] = { DRM_FORMAT_UYVY, DRM_FORMAT_YUYV, DRM_FORMAT_YUV420, @@ -456,7 +456,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) { struct armada_private *priv = dev->dev_private; struct drm_mode_object *mobj; - struct armada_plane *dplane; + struct armada_ovl_plane *dplane; int ret; ret = armada_overlay_create_properties(dev); @@ -469,11 +469,16 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) spin_lock_init(&dplane->lock); init_waitqueue_head(&dplane->vbl.wait); - armada_drm_vbl_event_init(&dplane->vbl.update, armada_plane_vbl, + armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); - drm_plane_init(dev, &dplane->base, crtcs, &armada_plane_funcs, - armada_formats, ARRAY_SIZE(armada_formats), false); + drm_plane_init(dev, &dplane->base, crtcs, &armada_ovl_plane_funcs, + armada_ovl_formats, ARRAY_SIZE(armada_ovl_formats), + false); + if (ret) { + kfree(dplane); + return ret; + } dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100; -- cgit v1.2.1 From fecfdb2db8b5fc2e6cb731a714889de5e43c2380 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: factor out retirement of old fb We have two identical places in the overlay code which retire the drm framebuffer. Factor these out into a common function. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_overlay.c | 37 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 9393a15183e2..093c2d4f2b79 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -71,21 +71,27 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, spin_unlock_irq(&dcrtc->irq_lock); } +static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, + struct drm_framebuffer *fb) +{ + struct drm_framebuffer *old_fb; + + spin_lock(&dplane->lock); + old_fb = dplane->old_fb; + dplane->old_fb = fb; + spin_unlock(&dplane->lock); + + if (old_fb) + armada_drm_queue_unref_work(dplane->base.dev, old_fb); +} + /* === Plane support === */ static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) { struct armada_ovl_plane *dplane = data; - struct drm_framebuffer *fb; armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); - - spin_lock(&dplane->lock); - fb = dplane->old_fb; - dplane->old_fb = NULL; - spin_unlock(&dplane->lock); - - if (fb) - armada_drm_queue_unref_work(dcrtc->crtc.dev, fb); + armada_ovl_retire_fb(dplane, NULL); wake_up(&dplane->vbl.wait); } @@ -175,17 +181,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, */ drm_framebuffer_reference(fb); - if (plane->fb) { - struct drm_framebuffer *older_fb; - - spin_lock_irq(&dplane->lock); - older_fb = dplane->old_fb; - dplane->old_fb = plane->fb; - spin_unlock_irq(&dplane->lock); - if (older_fb) - armada_drm_queue_unref_work(dcrtc->crtc.dev, - older_fb); - } + if (plane->fb) + armada_ovl_retire_fb(dplane, plane->fb); src_y = src.y1 >> 16; src_x = src.x1 >> 16; -- cgit v1.2.1 From 66377efa3fd468283a092f17692e81c2344b03ed Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: use xchg() to atomically update dplane->old_fb Rather than using a spinlock, use xchg() to atomically update dplane->old_fb. This allows us to eliminate dplane->lock. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_overlay.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 093c2d4f2b79..5e2dcecbf6ef 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -31,7 +31,6 @@ struct armada_ovl_plane_properties { struct armada_ovl_plane { struct drm_plane base; - spinlock_t lock; struct drm_framebuffer *old_fb; uint32_t src_hw; uint32_t dst_hw; @@ -76,10 +75,7 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, { struct drm_framebuffer *old_fb; - spin_lock(&dplane->lock); - old_fb = dplane->old_fb; - dplane->old_fb = fb; - spin_unlock(&dplane->lock); + old_fb = xchg(&dplane->old_fb, fb); if (old_fb) armada_drm_queue_unref_work(dplane->base.dev, old_fb); @@ -289,10 +285,7 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) if (plane->fb) drm_framebuffer_unreference(plane->fb); - spin_lock_irq(&dplane->lock); - fb = dplane->old_fb; - dplane->old_fb = NULL; - spin_unlock_irq(&dplane->lock); + fb = xchg(&dplane->old_fb, NULL); if (fb) drm_framebuffer_unreference(fb); @@ -464,7 +457,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) if (!dplane) return -ENOMEM; - spin_lock_init(&dplane->lock); init_waitqueue_head(&dplane->vbl.wait); armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); -- cgit v1.2.1 From d563c24514166d01b87cc96f92fe93b635d24c6e Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: update armada overlay to use drm_universal_plane_init() Use the new drm_universal_plane_init() rather than the legacy drm_plane_init(). Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_overlay.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 5e2dcecbf6ef..8f2b21693c76 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -461,9 +461,11 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); - drm_plane_init(dev, &dplane->base, crtcs, &armada_ovl_plane_funcs, - armada_ovl_formats, ARRAY_SIZE(armada_ovl_formats), - false); + ret = drm_universal_plane_init(dev, &dplane->base, crtcs, + &armada_ovl_plane_funcs, + armada_ovl_formats, + ARRAY_SIZE(armada_ovl_formats), + DRM_PLANE_TYPE_OVERLAY); if (ret) { kfree(dplane); return ret; -- cgit v1.2.1 From 561f60bc511f6ec054b566205b5c40ab9558a0ff Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: introduce generic armada_plane struct Introduce a generic armada_plane struct which will eventually be used for both the primary and overlay planes. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.h | 5 +++++ drivers/gpu/drm/armada/armada_overlay.c | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index a86243ef4a51..549b5f538266 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -34,6 +34,11 @@ struct armada_regs { struct armada_frame_work; struct armada_variant; +struct armada_plane { + struct drm_plane base; +}; +#define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) + struct armada_crtc { struct drm_crtc crtc; const struct armada_variant *variant; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 8f2b21693c76..e5a5b73a08cb 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -30,7 +30,7 @@ struct armada_ovl_plane_properties { }; struct armada_ovl_plane { - struct drm_plane base; + struct armada_plane base; struct drm_framebuffer *old_fb; uint32_t src_hw; uint32_t dst_hw; @@ -43,7 +43,8 @@ struct armada_ovl_plane { } vbl; struct armada_ovl_plane_properties prop; }; -#define drm_to_armada_ovl_plane(p) container_of(p, struct armada_ovl_plane, base) +#define drm_to_armada_ovl_plane(p) \ + container_of(p, struct armada_ovl_plane, base.base) static void @@ -78,7 +79,7 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, old_fb = xchg(&dplane->old_fb, fb); if (old_fb) - armada_drm_queue_unref_work(dplane->base.dev, old_fb); + armada_drm_queue_unref_work(dplane->base.base.dev, old_fb); } /* === Plane support === */ @@ -266,10 +267,10 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) struct drm_framebuffer *fb; struct armada_crtc *dcrtc; - if (!dplane->base.crtc) + if (!dplane->base.base.crtc) return 0; - dcrtc = drm_to_armada_crtc(dplane->base.crtc); + dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); dcrtc->plane = NULL; spin_lock_irq(&dcrtc->irq_lock); @@ -362,9 +363,9 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, update_attr = true; } - if (update_attr && dplane->base.crtc) + if (update_attr && dplane->base.base.crtc) armada_ovl_update_attr(&dplane->prop, - drm_to_armada_crtc(dplane->base.crtc)); + drm_to_armada_crtc(dplane->base.base.crtc)); return 0; } @@ -461,7 +462,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); - ret = drm_universal_plane_init(dev, &dplane->base, crtcs, + ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, &armada_ovl_plane_funcs, armada_ovl_formats, ARRAY_SIZE(armada_ovl_formats), @@ -479,7 +480,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) dplane->prop.contrast = 0x4000; dplane->prop.saturation = 0x4000; - mobj = &dplane->base.base; + mobj = &dplane->base.base.base; drm_object_attach_property(mobj, priv->colorkey_prop, 0x0101fe); drm_object_attach_property(mobj, priv->colorkey_min_prop, -- cgit v1.2.1 From 1c914cecb5bc4b097df07b799d39abac842ce193 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: add primary plane creation Use drm_primary_helper_create_plane() to create our primary plane, and register the CRTC with drm_crtc_init_with_planes(). This enables the primary plane to be initialised with the supported format information. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 5d627646601e..b96b77b61337 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -33,6 +33,23 @@ enum csc_mode { CSC_RGB_STUDIO = 2, }; +static const uint32_t armada_primary_formats[] = { + DRM_FORMAT_UYVY, + DRM_FORMAT_YUYV, + DRM_FORMAT_VYUY, + DRM_FORMAT_YVYU, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, +}; + /* * A note about interlacing. Let's consider HDMI 1920x1080i. * The timing parameters we have from X are: @@ -1080,6 +1097,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, { struct armada_private *priv = drm->dev_private; struct armada_crtc *dcrtc; + struct drm_plane *primary; void __iomem *base; int ret; @@ -1148,7 +1166,17 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, priv->dcrtc[dcrtc->num] = dcrtc; dcrtc->crtc.port = port; - drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs); + + primary = drm_primary_helper_create_plane(drm, armada_primary_formats, + ARRAY_SIZE(armada_primary_formats)); + if (!primary) + return -ENOMEM; + + ret = drm_crtc_init_with_planes(drm, &dcrtc->crtc, primary, NULL, + &armada_crtc_funcs); + if (ret) + goto err_crtc_init; + drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, @@ -1157,6 +1185,10 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, dcrtc->csc_rgb_mode); return armada_overlay_plane_create(drm, 1 << dcrtc->num); + +err_crtc_init: + primary->funcs->destroy(primary); + return ret; } static int -- cgit v1.2.1 From de32301b86030b20a51151a12d81fff6429cad0c Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:24 +0100 Subject: drm/armada: allocate primary plane ourselves Allocate our own primary plane as an armada_plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index b96b77b61337..f146fcf6b274 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1059,6 +1059,12 @@ static struct drm_crtc_funcs armada_crtc_funcs = { .set_property = armada_drm_crtc_set_property, }; +static const struct drm_plane_funcs armada_primary_plane_funcs = { + .update_plane = drm_primary_helper_update, + .disable_plane = drm_primary_helper_disable, + .destroy = drm_primary_helper_destroy, +}; + static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = { { CSC_AUTO, "Auto" }, { CSC_YUV_CCIR601, "CCIR601" }, @@ -1097,7 +1103,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, { struct armada_private *priv = drm->dev_private; struct armada_crtc *dcrtc; - struct drm_plane *primary; + struct armada_plane *primary; void __iomem *base; int ret; @@ -1167,12 +1173,21 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, dcrtc->crtc.port = port; - primary = drm_primary_helper_create_plane(drm, armada_primary_formats, - ARRAY_SIZE(armada_primary_formats)); + primary = kzalloc(sizeof(*primary), GFP_KERNEL); if (!primary) return -ENOMEM; - ret = drm_crtc_init_with_planes(drm, &dcrtc->crtc, primary, NULL, + ret = drm_universal_plane_init(drm, &primary->base, 0, + &armada_primary_plane_funcs, + armada_primary_formats, + ARRAY_SIZE(armada_primary_formats), + DRM_PLANE_TYPE_PRIMARY); + if (ret) { + kfree(primary); + return ret; + } + + ret = drm_crtc_init_with_planes(drm, &dcrtc->crtc, &primary->base, NULL, &armada_crtc_funcs); if (ret) goto err_crtc_init; @@ -1187,7 +1202,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, return armada_overlay_plane_create(drm, 1 << dcrtc->num); err_crtc_init: - primary->funcs->destroy(primary); + primary->base.funcs->destroy(&primary->base); return ret; } -- cgit v1.2.1 From 583268035825fc5ef0bbc467631fea0358831cbe Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:25 +0100 Subject: drm/armada: provide a common helper to disable a plane Provide a common helper to disable either the overlay or the primary plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 33 +++++++++++++++++++++++++++------ drivers/gpu/drm/armada/armada_crtc.h | 3 +++ drivers/gpu/drm/armada/armada_overlay.c | 7 +------ 3 files changed, 31 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index f146fcf6b274..007fc5d3eb54 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -700,18 +700,39 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return 0; } +void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc, + struct drm_plane *plane) +{ + u32 sram_para1; + + /* + * Drop our reference on any framebuffer attached to this plane. + * We don't need to NULL this out as drm_plane_force_disable(), + * and __setplane_internal() will do so for an overlay plane, and + * __drm_helper_disable_unused_functions() will do so for the + * primary plane. + */ + if (plane->fb) + drm_framebuffer_unreference(plane->fb); + + /* Power down the Y/U/V FIFOs */ + sram_para1 = CFG_PDWN16x66 | CFG_PDWN32x66; + + /* Power down most RAMs and FIFOs if this is the primary plane */ + if (plane->type == DRM_PLANE_TYPE_PRIMARY) + sram_para1 |= CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 | + CFG_PDWN32x32 | CFG_PDWN64x66; + + armada_updatel(sram_para1, 0, dcrtc->base + LCD_SPU_SRAM_PARA1); +} + /* The mode_config.mutex will be held for this call */ static void armada_drm_crtc_disable(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); armada_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - armada_drm_crtc_finish_fb(dcrtc, crtc->primary->fb, true); - - /* Power down most RAMs and FIFOs */ - writel_relaxed(CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 | - CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 | - CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1); + armada_drm_crtc_plane_disable(dcrtc, crtc->primary); } static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 549b5f538266..500ce0f43f64 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -103,6 +103,9 @@ void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); +void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc, + struct drm_plane *plane); + extern struct platform_driver armada_lcd_platform_driver; #endif diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index e5a5b73a08cb..1032f9b3d5f1 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -279,12 +279,7 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) dplane->ctrl0 = 0; spin_unlock_irq(&dcrtc->irq_lock); - /* Power down the Y/U/V FIFOs */ - armada_updatel(CFG_PDWN16x66 | CFG_PDWN32x66, 0, - dcrtc->base + LCD_SPU_SRAM_PARA1); - - if (plane->fb) - drm_framebuffer_unreference(plane->fb); + armada_drm_crtc_plane_disable(dcrtc, plane); fb = xchg(&dplane->old_fb, NULL); if (fb) -- cgit v1.2.1 From 9099ea19ca8ad21ab7f2a7abc06e270adeb8b02f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:25 +0100 Subject: drm/armada: move write to dma_ctrl0 to armada_drm_crtc_plane_disable() Move the write to clear the DMA enable bit, and augment it with clearing the graphics enable bit for the primary plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 12 ++++++++++-- drivers/gpu/drm/armada/armada_overlay.c | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 007fc5d3eb54..89decc5bdcd4 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -703,7 +703,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc, struct drm_plane *plane) { - u32 sram_para1; + u32 sram_para1, dma_ctrl0_mask; /* * Drop our reference on any framebuffer attached to this plane. @@ -719,9 +719,17 @@ void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc, sram_para1 = CFG_PDWN16x66 | CFG_PDWN32x66; /* Power down most RAMs and FIFOs if this is the primary plane */ - if (plane->type == DRM_PLANE_TYPE_PRIMARY) + if (plane->type == DRM_PLANE_TYPE_PRIMARY) { sram_para1 |= CFG_PDWN256x32 | CFG_PDWN256x24 | CFG_PDWN256x8 | CFG_PDWN32x32 | CFG_PDWN64x66; + dma_ctrl0_mask = CFG_GRA_ENA; + } else { + dma_ctrl0_mask = CFG_DMA_ENA; + } + + spin_lock_irq(&dcrtc->irq_lock); + armada_updatel(0, dma_ctrl0_mask, dcrtc->base + LCD_SPU_DMA_CTRL0); + spin_unlock_irq(&dcrtc->irq_lock); armada_updatel(sram_para1, 0, dcrtc->base + LCD_SPU_SRAM_PARA1); } diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 1032f9b3d5f1..9686d79335a0 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -275,7 +275,6 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) spin_lock_irq(&dcrtc->irq_lock); armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); - armada_updatel(0, CFG_DMA_ENA, dcrtc->base + LCD_SPU_DMA_CTRL0); dplane->ctrl0 = 0; spin_unlock_irq(&dcrtc->irq_lock); -- cgit v1.2.1 From 5c8752c6506abf29950d32366f826899dc87dde7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:25 +0100 Subject: drm/armada: move the update of dplane->ctrl0 out of spinlock It is not necessary to write dplane->ctrl0 under the CRTC spinlock, as this is only accessed under process context where the DRM locks will protect us instead. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_overlay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 9686d79335a0..e7e020d4372a 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -275,9 +275,10 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) spin_lock_irq(&dcrtc->irq_lock); armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); - dplane->ctrl0 = 0; spin_unlock_irq(&dcrtc->irq_lock); + dplane->ctrl0 = 0; + armada_drm_crtc_plane_disable(dcrtc, plane); fb = xchg(&dplane->old_fb, NULL); -- cgit v1.2.1 From 6908cf755af74b38d67195ee6607976a55f53d95 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:25 +0100 Subject: drm/armada: move the locking for armada_drm_vbl_event_remove() Move the locking for armada_drm_vbl_event_remove() into itself, which makes this function symmetrical with armada_drm_vbl_event_add(). Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 2 ++ drivers/gpu/drm/armada/armada_overlay.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 89decc5bdcd4..e3e6f81593c0 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -211,10 +211,12 @@ void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, struct armada_vbl_event *evt) { + spin_lock_irq(&dcrtc->irq_lock); if (!list_empty(&evt->node)) { list_del_init(&evt->node); drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); } + spin_unlock_irq(&dcrtc->irq_lock); } static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index e7e020d4372a..6ec42eb85981 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -273,9 +273,7 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); dcrtc->plane = NULL; - spin_lock_irq(&dcrtc->irq_lock); armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); - spin_unlock_irq(&dcrtc->irq_lock); dplane->ctrl0 = 0; -- cgit v1.2.1 From 5740d27fa5594344ed4d2c18d7ae7bea69002004 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Jul 2015 18:11:25 +0100 Subject: drm/armada: move frame wait into armada_frame Both the CRTC and overlay frames have their own wait queues. It would make more sense if these were part of the plane - the primary plane for the CRTC and overlay plane for the overlay. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 22 ++++++++++++++++++---- drivers/gpu/drm/armada/armada_crtc.h | 4 +++- drivers/gpu/drm/armada/armada_overlay.c | 12 ++++++++---- 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index e3e6f81593c0..46d932bc7678 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -455,7 +455,7 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) if (work) armada_drm_crtc_complete_frame_work(dcrtc, work); - wake_up(&dcrtc->frame_wait); + wake_up(&drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait); } } @@ -571,7 +571,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, adj->crtc_vtotal, tm, bm); /* Wait for pending flips to complete */ - wait_event(dcrtc->frame_wait, !dcrtc->frame_work); + wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, + !dcrtc->frame_work); drm_crtc_vblank_off(crtc); @@ -688,7 +689,8 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, armada_reg_queue_end(regs, i); /* Wait for pending flips to complete */ - wait_event(dcrtc->frame_wait, !dcrtc->frame_work); + wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, + !dcrtc->frame_work); /* Take a reference to the new fb as we're using it */ drm_framebuffer_reference(crtc->primary->fb); @@ -1096,6 +1098,13 @@ static const struct drm_plane_funcs armada_primary_plane_funcs = { .destroy = drm_primary_helper_destroy, }; +int armada_drm_plane_init(struct armada_plane *plane) +{ + init_waitqueue_head(&plane->frame_wait); + + return 0; +} + static struct drm_prop_enum_list armada_drm_csc_yuv_enum_list[] = { { CSC_AUTO, "Auto" }, { CSC_YUV_CCIR601, "CCIR601" }, @@ -1166,7 +1175,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, spin_lock_init(&dcrtc->irq_lock); dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR; INIT_LIST_HEAD(&dcrtc->vbl_list); - init_waitqueue_head(&dcrtc->frame_wait); /* Initialize some registers which we don't otherwise set */ writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV); @@ -1208,6 +1216,12 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, if (!primary) return -ENOMEM; + ret = armada_drm_plane_init(primary); + if (ret) { + kfree(primary); + return ret; + } + ret = drm_universal_plane_init(drm, &primary->base, 0, &armada_primary_plane_funcs, armada_primary_formats, diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 500ce0f43f64..3ec5101e13f7 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -36,9 +36,12 @@ struct armada_variant; struct armada_plane { struct drm_plane base; + wait_queue_head_t frame_wait; }; #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) +int armada_drm_plane_init(struct armada_plane *plane); + struct armada_crtc { struct drm_crtc crtc; const struct armada_variant *variant; @@ -71,7 +74,6 @@ struct armada_crtc { uint32_t dumb_ctrl; uint32_t spu_iopad_ctrl; - wait_queue_head_t frame_wait; struct armada_frame_work *frame_work; spinlock_t irq_lock; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 6ec42eb85981..9a5bab765085 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -39,7 +39,6 @@ struct armada_ovl_plane { struct { struct armada_vbl_event update; struct armada_regs regs[13]; - wait_queue_head_t wait; } vbl; struct armada_ovl_plane_properties prop; }; @@ -90,7 +89,7 @@ static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); armada_ovl_retire_fb(dplane, NULL); - wake_up(&dplane->vbl.wait); + wake_up(&dplane->base.frame_wait); } static int @@ -163,7 +162,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, dcrtc->base + LCD_SPU_SRAM_PARA1); } - wait_event_timeout(dplane->vbl.wait, + wait_event_timeout(dplane->base.frame_wait, list_empty(&dplane->vbl.update.node), HZ/25); @@ -451,7 +450,12 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) if (!dplane) return -ENOMEM; - init_waitqueue_head(&dplane->vbl.wait); + ret = armada_drm_plane_init(&dplane->base); + if (ret) { + kfree(dplane); + return ret; + } + armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, dplane); -- cgit v1.2.1 From 4b5dda82c20c2eee500520010c0558789592d62f Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 6 Aug 2015 16:37:18 +0100 Subject: drm/armada: move CRTC flip work to primary plane work Add a plane work implementation, and move the CRTC framebuffer flip work to it for the primary plane. The idea is to have a common plane work implementation for both the primary and overlay planes. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 102 ++++++++++++++++++++--------------- drivers/gpu/drm/armada/armada_crtc.h | 15 ++++-- 2 files changed, 70 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 46d932bc7678..0c1a1524f5d5 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -20,6 +20,7 @@ #include "armada_hw.h" struct armada_frame_work { + struct armada_plane_work work; struct drm_pending_vblank_event *event; struct armada_regs regs[4]; struct drm_framebuffer *old_fb; @@ -190,6 +191,41 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, return i; } +static void armada_drm_plane_work_run(struct armada_crtc *dcrtc, + struct armada_plane *plane) +{ + struct armada_plane_work *work = xchg(&plane->work, NULL); + + /* Handle any pending frame work. */ + if (work) { + work->fn(dcrtc, plane, work); + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + } +} + +int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, + struct armada_plane *plane, struct armada_plane_work *work) +{ + int ret; + + ret = drm_vblank_get(dcrtc->crtc.dev, dcrtc->num); + if (ret) { + DRM_ERROR("failed to acquire vblank counter\n"); + return ret; + } + + ret = cmpxchg(&plane->work, NULL, work) ? -EBUSY : 0; + if (ret) + drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); + + return ret; +} + +int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout) +{ + return wait_event_timeout(plane->frame_wait, !plane->work, timeout); +} + void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, struct armada_vbl_event *evt) { @@ -233,44 +269,31 @@ static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, struct armada_frame_work *work) { - struct drm_device *dev = dcrtc->crtc.dev; - int ret; + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); - ret = drm_vblank_get(dev, dcrtc->num); - if (ret) { - DRM_ERROR("failed to acquire vblank counter\n"); - return ret; - } - - if (cmpxchg(&dcrtc->frame_work, NULL, work)) { - drm_vblank_put(dev, dcrtc->num); - ret = -EBUSY; - } - - return ret; + return armada_drm_plane_work_queue(dcrtc, plane, &work->work); } static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc, - struct armada_frame_work *work) + struct armada_plane *plane, struct armada_plane_work *work) { + struct armada_frame_work *fwork = container_of(work, struct armada_frame_work, work); struct drm_device *dev = dcrtc->crtc.dev; unsigned long flags; spin_lock_irqsave(&dcrtc->irq_lock, flags); - armada_drm_crtc_update_regs(dcrtc, work->regs); + armada_drm_crtc_update_regs(dcrtc, fwork->regs); spin_unlock_irqrestore(&dcrtc->irq_lock, flags); - if (work->event) { + if (fwork->event) { spin_lock_irqsave(&dev->event_lock, flags); - drm_send_vblank_event(dev, dcrtc->num, work->event); + drm_send_vblank_event(dev, dcrtc->num, fwork->event); spin_unlock_irqrestore(&dev->event_lock, flags); } - drm_vblank_put(dev, dcrtc->num); - /* Finally, queue the process-half of the cleanup. */ - __armada_drm_queue_unref_work(dcrtc->crtc.dev, work->old_fb); - kfree(work); + __armada_drm_queue_unref_work(dcrtc->crtc.dev, fwork->old_fb); + kfree(fwork); } static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, @@ -290,6 +313,7 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, work = kmalloc(sizeof(*work), GFP_KERNEL); if (work) { int i = 0; + work->work.fn = armada_drm_crtc_complete_frame_work; work->event = NULL; work->old_fb = fb; armada_reg_queue_end(work->regs, i); @@ -310,18 +334,14 @@ static void armada_drm_crtc_finish_fb(struct armada_crtc *dcrtc, static void armada_drm_vblank_off(struct armada_crtc *dcrtc) { - struct armada_frame_work *work; + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); /* * Tell the DRM core that vblank IRQs aren't going to happen for * a while. This cleans up any pending vblank events for us. */ drm_crtc_vblank_off(&dcrtc->crtc); - - /* Handle any pending flip event. */ - work = xchg(&dcrtc->frame_work, NULL); - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); + armada_drm_plane_work_run(dcrtc, plane); } void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b, @@ -450,12 +470,9 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) spin_unlock(&dcrtc->irq_lock); if (stat & GRA_FRAME_IRQ) { - struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); - - wake_up(&drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait); + struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); + armada_drm_plane_work_run(dcrtc, plane); + wake_up(&plane->frame_wait); } } @@ -571,8 +588,8 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, adj->crtc_vtotal, tm, bm); /* Wait for pending flips to complete */ - wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, - !dcrtc->frame_work); + armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary), + MAX_SCHEDULE_TIMEOUT); drm_crtc_vblank_off(crtc); @@ -689,8 +706,8 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, armada_reg_queue_end(regs, i); /* Wait for pending flips to complete */ - wait_event(drm_to_armada_plane(dcrtc->crtc.primary)->frame_wait, - !dcrtc->frame_work); + armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary), + MAX_SCHEDULE_TIMEOUT); /* Take a reference to the new fb as we're using it */ drm_framebuffer_reference(crtc->primary->fb); @@ -1013,6 +1030,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, if (!work) return -ENOMEM; + work->work.fn = armada_drm_crtc_complete_frame_work; work->event = event; work->old_fb = dcrtc->crtc.primary->fb; @@ -1046,12 +1064,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, * Finally, if the display is blanked, we won't receive an * interrupt, so complete it now. */ - if (dpms_blanked(dcrtc->dpms)) { - struct armada_frame_work *work = xchg(&dcrtc->frame_work, NULL); - - if (work) - armada_drm_crtc_complete_frame_work(dcrtc, work); - } + if (dpms_blanked(dcrtc->dpms)) + armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary)); return 0; } diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 3ec5101e13f7..aaad5ab78673 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -31,16 +31,27 @@ struct armada_regs { #define armada_reg_queue_end(_r, _i) \ armada_reg_queue_mod(_r, _i, 0, 0, ~0) -struct armada_frame_work; +struct armada_crtc; +struct armada_plane; struct armada_variant; +struct armada_plane_work { + void (*fn)(struct armada_crtc *, + struct armada_plane *, + struct armada_plane_work *); +}; + struct armada_plane { struct drm_plane base; wait_queue_head_t frame_wait; + struct armada_plane_work *work; }; #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base) int armada_drm_plane_init(struct armada_plane *plane); +int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, + struct armada_plane *plane, struct armada_plane_work *work); +int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); struct armada_crtc { struct drm_crtc crtc; @@ -74,8 +85,6 @@ struct armada_crtc { uint32_t dumb_ctrl; uint32_t spu_iopad_ctrl; - struct armada_frame_work *frame_work; - spinlock_t irq_lock; uint32_t irq_ena; struct list_head vbl_list; -- cgit v1.2.1 From 4a8506d2d68724b6d326621118874c07095c6645 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Aug 2015 09:33:05 +0100 Subject: drm/armada: convert overlay plane vbl worker to a armada plane worker Convert the overlay plane to use the generic armada plane worker infrastructure which is shared with the primary plane. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 48 +++++++++------------------------ drivers/gpu/drm/armada/armada_crtc.h | 20 ++------------ drivers/gpu/drm/armada/armada_overlay.c | 27 +++++++++---------- 3 files changed, 26 insertions(+), 69 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 0c1a1524f5d5..418dbfad4271 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -226,44 +226,15 @@ int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout) return wait_event_timeout(plane->frame_wait, !plane->work, timeout); } -void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) +struct armada_plane_work *armada_drm_plane_work_cancel( + struct armada_crtc *dcrtc, struct armada_plane *plane) { - unsigned long flags; - bool not_on_list; - - WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num)); - - spin_lock_irqsave(&dcrtc->irq_lock, flags); - not_on_list = list_empty(&evt->node); - if (not_on_list) - list_add_tail(&evt->node, &dcrtc->vbl_list); - spin_unlock_irqrestore(&dcrtc->irq_lock, flags); + struct armada_plane_work *work = xchg(&plane->work, NULL); - if (!not_on_list) + if (work) drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); -} -void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, - struct armada_vbl_event *evt) -{ - spin_lock_irq(&dcrtc->irq_lock); - if (!list_empty(&evt->node)) { - list_del_init(&evt->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - } - spin_unlock_irq(&dcrtc->irq_lock); -} - -static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) -{ - struct armada_vbl_event *e, *n; - - list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { - list_del_init(&e->node); - drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); - e->fn(dcrtc, e->data); - } + return work; } static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, @@ -429,6 +400,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) { void __iomem *base = dcrtc->base; + struct drm_plane *ovl_plane; if (stat & DMA_FF_UNDERFLOW) DRM_ERROR("video underflow on crtc %u\n", dcrtc->num); @@ -439,7 +411,12 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); spin_lock(&dcrtc->irq_lock); - armada_drm_vbl_event_run(dcrtc); + ovl_plane = dcrtc->plane; + if (ovl_plane) { + struct armada_plane *plane = drm_to_armada_plane(ovl_plane); + armada_drm_plane_work_run(dcrtc, plane); + wake_up(&plane->frame_wait); + } if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; @@ -1188,7 +1165,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24; spin_lock_init(&dcrtc->irq_lock); dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR; - INIT_LIST_HEAD(&dcrtc->vbl_list); /* Initialize some registers which we don't otherwise set */ writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV); diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index aaad5ab78673..04fdd22d483b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h @@ -52,6 +52,8 @@ int armada_drm_plane_init(struct armada_plane *plane); int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, struct armada_plane *plane, struct armada_plane_work *work); int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); +struct armada_plane_work *armada_drm_plane_work_cancel( + struct armada_crtc *dcrtc, struct armada_plane *plane); struct armada_crtc { struct drm_crtc crtc; @@ -87,27 +89,9 @@ struct armada_crtc { spinlock_t irq_lock; uint32_t irq_ena; - struct list_head vbl_list; }; #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) -struct armada_vbl_event { - struct list_head node; - void *data; - void (*fn)(struct armada_crtc *, void *); -}; - -void armada_drm_vbl_event_add(struct armada_crtc *, - struct armada_vbl_event *); -void armada_drm_vbl_event_remove(struct armada_crtc *, - struct armada_vbl_event *); -#define armada_drm_vbl_event_init(_e, _f, _d) do { \ - struct armada_vbl_event *__e = _e; \ - INIT_LIST_HEAD(&__e->node); \ - __e->data = _d; \ - __e->fn = _f; \ -} while (0) - void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 9a5bab765085..5c22b380f8f3 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -37,7 +37,7 @@ struct armada_ovl_plane { uint32_t dst_yx; uint32_t ctrl0; struct { - struct armada_vbl_event update; + struct armada_plane_work work; struct armada_regs regs[13]; } vbl; struct armada_ovl_plane_properties prop; @@ -82,14 +82,13 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, } /* === Plane support === */ -static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) +static void armada_ovl_plane_work(struct armada_crtc *dcrtc, + struct armada_plane *plane, struct armada_plane_work *work) { - struct armada_ovl_plane *dplane = data; + struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); armada_ovl_retire_fb(dplane, NULL); - - wake_up(&dplane->base.frame_wait); } static int @@ -162,9 +161,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, dcrtc->base + LCD_SPU_SRAM_PARA1); } - wait_event_timeout(dplane->base.frame_wait, - list_empty(&dplane->vbl.update.node), - HZ/25); + if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) + armada_drm_plane_work_cancel(dcrtc, &dplane->base); if (plane->fb != fb) { struct armada_gem_object *obj = drm_fb_obj(fb); @@ -255,7 +253,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, } if (idx) { armada_reg_queue_end(dplane->vbl.regs, idx); - armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update); + armada_drm_plane_work_queue(dcrtc, &dplane->base, + &dplane->vbl.work); } return 0; } @@ -270,14 +269,13 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) return 0; dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); - dcrtc->plane = NULL; - armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); + armada_drm_plane_work_cancel(dcrtc, &dplane->base); + armada_drm_crtc_plane_disable(dcrtc, plane); + dcrtc->plane = NULL; dplane->ctrl0 = 0; - armada_drm_crtc_plane_disable(dcrtc, plane); - fb = xchg(&dplane->old_fb, NULL); if (fb) drm_framebuffer_unreference(fb); @@ -456,8 +454,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) return ret; } - armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, - dplane); + dplane->vbl.work.fn = armada_ovl_plane_work; ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, &armada_ovl_plane_funcs, -- cgit v1.2.1 From 7cb410cdbdc9b71e2d4f356f2e4cea0b925abb21 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 7 Aug 2015 13:34:26 +0100 Subject: drm/armada: move frame wait wakeup into plane work Move the wakeup for the frame wait into the armada plane work, to ensure that it is woken up every time we run a work. Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/armada') diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 418dbfad4271..cebcab560626 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -201,6 +201,8 @@ static void armada_drm_plane_work_run(struct armada_crtc *dcrtc, work->fn(dcrtc, plane, work); drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); } + + wake_up(&plane->frame_wait); } int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, @@ -415,7 +417,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) if (ovl_plane) { struct armada_plane *plane = drm_to_armada_plane(ovl_plane); armada_drm_plane_work_run(dcrtc, plane); - wake_up(&plane->frame_wait); } if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { @@ -449,7 +450,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) if (stat & GRA_FRAME_IRQ) { struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary); armada_drm_plane_work_run(dcrtc, plane); - wake_up(&plane->frame_wait); } } -- cgit v1.2.1