From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1045103AbdDWKlU (ORCPT ); Sun, 23 Apr 2017 06:41:20 -0400 Received: from hermes.aosc.io ([199.195.250.187]:45575 "EHLO hermes.aosc.io" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1045034AbdDWKjH (ORCPT ); Sun, 23 Apr 2017 06:39:07 -0400 From: Icenowy Zheng To: Rob Herring , Maxime Ripard , Chen-Yu Tsai , Jernej Skrabec Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-sunxi@googlegroups.com, Icenowy Zheng Subject: [PATCH v5 05/11] drm/sun4i: abstract a engine type Date: Sun, 23 Apr 2017 18:37:48 +0800 Message-Id: <20170423103754.50012-6-icenowy@aosc.io> In-Reply-To: <20170423103754.50012-1-icenowy@aosc.io> References: <20170423103754.50012-1-icenowy@aosc.io> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As we are going to add support for the Allwinner DE2 engine in sun4i-drm driver, we will finally have two types of display engines -- the DE1 backend and the DE2 mixer. They both do some display blending and feed graphics data to TCON, so I choose to call them both "engine" here. Abstract the engine type to a new struct with an ops struct, which contains functions that should be called outside the engine-specified code (in TCON, CRTC or TV Encoder code). A dedicated Kconfig option is also added to control whether sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should be built. As we removed the codes in CRTC code that directly call the layer code, we can now extract the layer part and combine it with the backend part into a new module, sun4i-backend.ko. Signed-off-by: Icenowy Zheng --- Changes in v5: - Really made a sunxi_engine struct type, and moved ops pointer into it. - Added checked ops wrappers. - Changed the second parameter of layers_init from crtc to engine. Changes in v4: - Comments to tag the color correction functions as optional. - Check before calling the optional functions. - Change layers_init to satisfy new PATCH v4 04/11. drivers/gpu/drm/sun4i/Kconfig | 10 ++++ drivers/gpu/drm/sun4i/Makefile | 6 ++- drivers/gpu/drm/sun4i/sun4i_backend.c | 68 ++++++++++++++------------ drivers/gpu/drm/sun4i/sun4i_backend.h | 13 +++-- drivers/gpu/drm/sun4i/sun4i_crtc.c | 11 ++--- drivers/gpu/drm/sun4i/sun4i_crtc.h | 4 +- drivers/gpu/drm/sun4i/sun4i_drv.h | 2 +- drivers/gpu/drm/sun4i/sun4i_layer.c | 8 ++- drivers/gpu/drm/sun4i/sun4i_layer.h | 5 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +- drivers/gpu/drm/sun4i/sun4i_tv.c | 9 ++-- drivers/gpu/drm/sun4i/sunxi_engine.h | 91 +++++++++++++++++++++++++++++++++++ 12 files changed, 169 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sunxi_engine.h diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index a4b357db8856..5a8227f37cc4 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -12,3 +12,13 @@ config DRM_SUN4I Choose this option if you have an Allwinner SoC with a Display Engine. If M is selected the module will be called sun4i-drm. + +config DRM_SUN4I_BACKEND + tristate "Support for Allwinner A10 Display Engine Backend" + depends on DRM_SUN4I + default DRM_SUN4I + help + Choose this option if you have an Allwinner SoC with the + original Allwinner Display Engine, which has a backend to + do some alpha blending and feed graphics to TCON. If M is + selected the module will be called sun4i-backend. diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 59b757350a1f..1db1068b9be1 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o sun4i-tcon-y += sun4i_rgb.o sun4i-tcon-y += sun4i_dotclock.o sun4i-tcon-y += sun4i_crtc.o -sun4i-tcon-y += sun4i_layer.o + +sun4i-backend-y += sun4i_layer.o +sun4i-backend-y += sun4i_backend.o obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o -obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o +obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index d660741ba475..360ab046121b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -23,6 +23,8 @@ #include "sun4i_backend.h" #include "sun4i_drv.h" +#include "sun4i_layer.h" +#include "sunxi_engine.h" static const u32 sunxi_rgb2yuv_coef[12] = { 0x00000107, 0x00000204, 0x00000064, 0x00000108, @@ -30,41 +32,38 @@ static const u32 sunxi_rgb2yuv_coef[12] = { 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 }; -void sun4i_backend_apply_color_correction(struct sun4i_backend *backend) +static void sun4i_backend_apply_color_correction(struct sunxi_engine *engine) { int i; DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n"); /* Set color correction */ - regmap_write(backend->regs, SUN4I_BACKEND_OCCTL_REG, + regmap_write(engine->regs, SUN4I_BACKEND_OCCTL_REG, SUN4I_BACKEND_OCCTL_ENABLE); for (i = 0; i < 12; i++) - regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i), + regmap_write(engine->regs, SUN4I_BACKEND_OCRCOEF_REG(i), sunxi_rgb2yuv_coef[i]); } -EXPORT_SYMBOL(sun4i_backend_apply_color_correction); -void sun4i_backend_disable_color_correction(struct sun4i_backend *backend) +static void sun4i_backend_disable_color_correction(struct sunxi_engine *engine) { DRM_DEBUG_DRIVER("Disabling color correction\n"); /* Disable color correction */ - regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG, + regmap_update_bits(engine->regs, SUN4I_BACKEND_OCCTL_REG, SUN4I_BACKEND_OCCTL_ENABLE, 0); } -EXPORT_SYMBOL(sun4i_backend_disable_color_correction); -void sun4i_backend_commit(struct sun4i_backend *backend) +static void sun4i_backend_commit(struct sunxi_engine *engine) { DRM_DEBUG_DRIVER("Committing changes\n"); - regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG, + regmap_write(engine->regs, SUN4I_BACKEND_REGBUFFCTL_REG, SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS | SUN4I_BACKEND_REGBUFFCTL_LOADCTL); } -EXPORT_SYMBOL(sun4i_backend_commit); void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable) @@ -78,10 +77,9 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend, else val = 0; - regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG, + regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, SUN4I_BACKEND_MODCTL_LAY_EN(layer), val); } -EXPORT_SYMBOL(sun4i_backend_layer_enable); static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, u32 format, u32 *mode) @@ -141,33 +139,33 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, if (plane->type == DRM_PLANE_TYPE_PRIMARY) { DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n", state->crtc_w, state->crtc_h); - regmap_write(backend->regs, SUN4I_BACKEND_DISSIZE_REG, + regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG, SUN4I_BACKEND_DISSIZE(state->crtc_w, state->crtc_h)); } /* Set the line width */ DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8); - regmap_write(backend->regs, SUN4I_BACKEND_LAYLINEWIDTH_REG(layer), + regmap_write(backend->engine.regs, + SUN4I_BACKEND_LAYLINEWIDTH_REG(layer), fb->pitches[0] * 8); /* Set height and width */ DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", state->crtc_w, state->crtc_h); - regmap_write(backend->regs, SUN4I_BACKEND_LAYSIZE_REG(layer), + regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYSIZE_REG(layer), SUN4I_BACKEND_LAYSIZE(state->crtc_w, state->crtc_h)); /* Set base coordinates */ DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n", state->crtc_x, state->crtc_y); - regmap_write(backend->regs, SUN4I_BACKEND_LAYCOOR_REG(layer), + regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYCOOR_REG(layer), SUN4I_BACKEND_LAYCOOR(state->crtc_x, state->crtc_y)); return 0; } -EXPORT_SYMBOL(sun4i_backend_update_layer_coord); int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, int layer, struct drm_plane *plane) @@ -182,7 +180,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, interlaced = plane->state->crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE; - regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG, + regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, SUN4I_BACKEND_MODCTL_ITLMOD_EN, interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0); @@ -196,12 +194,12 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, return ret; } - regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG1(layer), + regmap_update_bits(backend->engine.regs, + SUN4I_BACKEND_ATTCTL_REG1(layer), SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val); return 0; } -EXPORT_SYMBOL(sun4i_backend_update_layer_formats); int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, int layer, struct drm_plane *plane) @@ -229,19 +227,19 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, /* Write the 32 lower bits of the address (in bits) */ lo_paddr = paddr << 3; DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr); - regmap_write(backend->regs, SUN4I_BACKEND_LAYFB_L32ADD_REG(layer), + regmap_write(backend->engine.regs, + SUN4I_BACKEND_LAYFB_L32ADD_REG(layer), lo_paddr); /* And the upper bits */ hi_paddr = paddr >> 29; DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr); - regmap_update_bits(backend->regs, SUN4I_BACKEND_LAYFB_H4ADD_REG, + regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG, SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer), SUN4I_BACKEND_LAYFB_H4ADD(layer, hi_paddr)); return 0; } -EXPORT_SYMBOL(sun4i_backend_update_layer_buffer); static int sun4i_backend_init_sat(struct device *dev) { struct sun4i_backend *backend = dev_get_drvdata(dev); @@ -288,6 +286,13 @@ static int sun4i_backend_free_sat(struct device *dev) { return 0; } +static const struct sunxi_engine_ops sun4i_backend_engine_ops = { + .commit = sun4i_backend_commit, + .layers_init = sun4i_layers_init, + .apply_color_correction = sun4i_backend_apply_color_correction, + .disable_color_correction = sun4i_backend_disable_color_correction, +}; + static struct regmap_config sun4i_backend_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -310,18 +315,19 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, if (!backend) return -ENOMEM; dev_set_drvdata(dev, backend); - drv->backend = backend; + drv->engine = &backend->engine; + drv->engine->ops = &sun4i_backend_engine_ops; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); - backend->regs = devm_regmap_init_mmio(dev, regs, - &sun4i_backend_regmap_config); - if (IS_ERR(backend->regs)) { + backend->engine.regs = devm_regmap_init_mmio(dev, regs, + &sun4i_backend_regmap_config); + if (IS_ERR(backend->engine.regs)) { dev_err(dev, "Couldn't create the backend0 regmap\n"); - return PTR_ERR(backend->regs); + return PTR_ERR(backend->engine.regs); } backend->reset = devm_reset_control_get(dev, NULL); @@ -371,14 +377,14 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, /* Reset the registers */ for (i = 0x800; i < 0x1000; i += 4) - regmap_write(backend->regs, i, 0); + regmap_write(backend->engine.regs, i, 0); /* Disable registers autoloading */ - regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG, + regmap_write(backend->engine.regs, SUN4I_BACKEND_REGBUFFCTL_REG, SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS); /* Enable the backend */ - regmap_write(backend->regs, SUN4I_BACKEND_MODCTL_REG, + regmap_write(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, SUN4I_BACKEND_MODCTL_DEBE_EN | SUN4I_BACKEND_MODCTL_START_CTL); diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 83e63cc702b4..a92f50eca948 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -17,6 +17,8 @@ #include #include +#include "sunxi_engine.h" + #define SUN4I_BACKEND_MODCTL_REG 0x800 #define SUN4I_BACKEND_MODCTL_LINE_SEL BIT(29) #define SUN4I_BACKEND_MODCTL_ITLMOD_EN BIT(28) @@ -139,7 +141,7 @@ #define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) struct sun4i_backend { - struct regmap *regs; + struct sunxi_engine engine; struct reset_control *reset; @@ -151,10 +153,11 @@ struct sun4i_backend { struct reset_control *sat_reset; }; -void sun4i_backend_apply_color_correction(struct sun4i_backend *backend); -void sun4i_backend_disable_color_correction(struct sun4i_backend *backend); - -void sun4i_backend_commit(struct sun4i_backend *backend); +static inline struct sun4i_backend * +engine_to_sun4i_backend(struct sunxi_engine *engine) +{ + return container_of(engine, struct sun4i_backend, engine); +} void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable); diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 708b3543d4e9..f8c70439d1e2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -25,10 +25,9 @@ #include