From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Return-Path: Sender: Daniel Vetter Date: Fri, 30 Oct 2015 15:44:09 +0100 From: Daniel Vetter To: Maxime Ripard Cc: Mike Turquette , Stephen Boyd , David Airlie , Thierry Reding , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-sunxi@googlegroups.com, Laurent Pinchart , Chen-Yu Tsai , Hans de Goede , Alexander Kaplan , Wynter Woods , Boris Brezillon , Thomas Petazzoni , Rob Clark , Daniel Vetter Subject: Re: [PATCH 08/19] drm: Add Allwinner A10 Display Engine support Message-ID: <20151030144409.GZ16848@phenom.ffwll.local> References: <1446214865-3972-1-git-send-email-maxime.ripard@free-electrons.com> <1446214865-3972-9-git-send-email-maxime.ripard@free-electrons.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii In-Reply-To: <1446214865-3972-9-git-send-email-maxime.ripard@free-electrons.com> List-ID: On Fri, Oct 30, 2015 at 03:20:54PM +0100, Maxime Ripard wrote: > The Allwinner A10 and subsequent SoCs share the same display pipeline, with > variations in the number of controllers (1 or 2), or the presence or not of > some output (HDMI, TV, VGA) or not. > > This hardware supports 4 layers and 32 sprites, even though we only support > one primary layer for now. > > Signed-off-by: Maxime Ripard Quickly (well, very quickly because jetlag and between travels) read through this. Looks good overall, bunch of comments below. Cheers, Daniel > --- > drivers/gpu/drm/Kconfig | 2 + > drivers/gpu/drm/Makefile | 3 +- > drivers/gpu/drm/sun4i/Kconfig | 14 + > drivers/gpu/drm/sun4i/Makefile | 8 + > drivers/gpu/drm/sun4i/sun4i_backend.c | 271 +++++++++++++++++ > drivers/gpu/drm/sun4i/sun4i_backend.h | 159 ++++++++++ > drivers/gpu/drm/sun4i/sun4i_crtc.c | 117 ++++++++ > drivers/gpu/drm/sun4i/sun4i_crtc.h | 31 ++ > drivers/gpu/drm/sun4i/sun4i_drv.c | 281 ++++++++++++++++++ > drivers/gpu/drm/sun4i/sun4i_drv.h | 30 ++ > drivers/gpu/drm/sun4i/sun4i_framebuffer.c | 54 ++++ > drivers/gpu/drm/sun4i/sun4i_framebuffer.h | 19 ++ > drivers/gpu/drm/sun4i/sun4i_layer.c | 111 +++++++ > drivers/gpu/drm/sun4i/sun4i_layer.h | 30 ++ > drivers/gpu/drm/sun4i/sun4i_tcon.c | 478 ++++++++++++++++++++++++++++++ > drivers/gpu/drm/sun4i/sun4i_tcon.h | 182 ++++++++++++ > 16 files changed, 1789 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/sun4i/Kconfig > create mode 100644 drivers/gpu/drm/sun4i/Makefile > create mode 100644 drivers/gpu/drm/sun4i/sun4i_backend.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_backend.h > create mode 100644 drivers/gpu/drm/sun4i/sun4i_crtc.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_crtc.h > create mode 100644 drivers/gpu/drm/sun4i/sun4i_drv.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_drv.h > create mode 100644 drivers/gpu/drm/sun4i/sun4i_framebuffer.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_framebuffer.h > create mode 100644 drivers/gpu/drm/sun4i/sun4i_layer.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_layer.h > create mode 100644 drivers/gpu/drm/sun4i/sun4i_tcon.c > create mode 100644 drivers/gpu/drm/sun4i/sun4i_tcon.h > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig > index 1a0a8df2eed8..ecf93fafa33c 100644 > --- a/drivers/gpu/drm/Kconfig > +++ b/drivers/gpu/drm/Kconfig > @@ -239,6 +239,8 @@ source "drivers/gpu/drm/rcar-du/Kconfig" > > source "drivers/gpu/drm/shmobile/Kconfig" > > +source "drivers/gpu/drm/sun4i/Kconfig" > + > source "drivers/gpu/drm/omapdrm/Kconfig" > > source "drivers/gpu/drm/tilcdc/Kconfig" > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > index 45e7719846b1..2e5f547db672 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -1,4 +1,4 @@ > -# > + > # Makefile for the drm device driver. This driver provides support for the > # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. > > @@ -58,6 +58,7 @@ obj-$(CONFIG_DRM_ARMADA) += armada/ > obj-$(CONFIG_DRM_ATMEL_HLCDC) += atmel-hlcdc/ > obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/ > obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ > +obj-$(CONFIG_DRM_SUN4I) += sun4i/ > obj-$(CONFIG_DRM_OMAP) += omapdrm/ > obj-y += tilcdc/ > obj-$(CONFIG_DRM_QXL) += qxl/ > diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig > new file mode 100644 > index 000000000000..99510e64e91a > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/Kconfig > @@ -0,0 +1,14 @@ > +config DRM_SUN4I > + tristate "DRM Support for Allwinner A10 Display Engine" > + depends on DRM && ARM > + depends on ARCH_SUNXI || COMPILE_TEST > + select DRM_GEM_CMA_HELPER > + select DRM_KMS_HELPER > + select DRM_KMS_CMA_HELPER > + select DRM_PANEL > + select REGMAP_MMIO > + select VIDEOMODE_HELPERS > + help > + Choose this option if you have an Allwinner SoC with a > + Display Engine. If M is selected the module will be called > + sun4i-drm. > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile > new file mode 100644 > index 000000000000..bc2df12beb42 > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/Makefile > @@ -0,0 +1,8 @@ > +sun4i-drm-y += sun4i_backend.o > +sun4i-drm-y += sun4i_crtc.o > +sun4i-drm-y += sun4i_drv.o > +sun4i-drm-y += sun4i_framebuffer.o > +sun4i-drm-y += sun4i_layer.o > +sun4i-drm-y += sun4i_tcon.o > + > +obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o > diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c > new file mode 100644 > index 000000000000..74eac55f1244 > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c > @@ -0,0 +1,271 @@ > +/* > + * Copyright (C) 2015 Free Electrons > + * Copyright (C) 2015 NextThing Co > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "sun4i_backend.h" > +#include "sun4i_drv.h" > + > +static u32 sunxi_rgb2yuv_coef[12] = { > + 0x00000107, 0x00000204, 0x00000064, 0x00000108, > + 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808, > + 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 > +}; > + > +void sun4i_backend_apply_color_correction(struct sun4i_backend *backend) > +{ > + int i; > + > + /* Set color correction */ > + regmap_write(backend->regs, SUN4I_BACKEND_OCCTL_REG, > + SUN4I_BACKEND_OCCTL_ENABLE); > + > + for (i = 0; i < 12; i++) > + regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i), > + sunxi_rgb2yuv_coef[i]); > +} > + > +void sun4i_backend_commit(struct sun4i_backend *backend) > +{ > + DRM_DEBUG_DRIVER("Committing changes\n"); > + > + regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG, > + SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS | > + SUN4I_BACKEND_REGBUFFCTL_LOADCTL); > +} > + > +void sun4i_backend_layer_enable(struct sun4i_backend *backend, > + int layer, bool enable) > +{ > + u32 val; > + > + DRM_DEBUG_DRIVER("Enabling layer %d\n", layer); > + > + if (enable) > + val = SUN4I_BACKEND_MODCTL_LAY_EN(layer); > + else > + val = 0; > + > + regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG, > + SUN4I_BACKEND_MODCTL_LAY_EN(layer), val); > +} > + > +static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) > +{ > + switch (format) { > + case DRM_FORMAT_XRGB8888: > + *mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888; > + break; > + > + case DRM_FORMAT_RGB888: > + *mode = SUN4I_BACKEND_LAY_FBFMT_RGB888; > + break; > + > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane) > +{ > + struct drm_plane_state *state = plane->state; > + struct drm_framebuffer *fb = state->fb; > + > + DRM_DEBUG_DRIVER("Updating layer %d\n", layer); > + > + 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, > + 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), > + 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), > + 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), > + SUN4I_BACKEND_LAYCOOR(state->crtc_x, > + state->crtc_y)); > + > + return 0; > +} > + > +int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane) > +{ > + struct drm_plane_state *state = plane->state; > + struct drm_framebuffer *fb = state->fb; > + bool interlaced = false; > + u32 val; > + int ret; > + > + if (plane->state->crtc) > + interlaced = plane->state->crtc->state->adjusted_mode.flags > + & DRM_MODE_FLAG_INTERLACE; > + > + regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG, > + SUN4I_BACKEND_MODCTL_ITLMOD_EN, > + interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0); > + > + DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", > + interlaced ? "on" : "off"); > + > + ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val); > + if (ret) { > + DRM_DEBUG_DRIVER("Invalid format\n"); > + return val; > + } > + > + regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG1(layer), > + SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val); > + > + return 0; > +} > + > +int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane) > +{ > + struct drm_plane_state *state = plane->state; > + struct drm_framebuffer *fb = state->fb; > + struct drm_gem_cma_object *gem; > + u32 lo_paddr, hi_paddr; > + dma_addr_t paddr; > + int bpp; > + > + /* Get the physical address of the buffer in memory */ > + gem = drm_fb_cma_get_gem_obj(fb, 0); > + > + DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr); > + > + /* Compute the start of the displayed memory */ > + bpp = drm_format_plane_cpp(fb->pixel_format, 0); > + paddr = gem->paddr + fb->offsets[0]; > + paddr += state->src_x * bpp; > + paddr += state->src_y * fb->pitches[0]; > + > + DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr); > + > + /* 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), > + 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, > + SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer), > + SUN4I_BACKEND_LAYFB_H4ADD(layer, hi_paddr)); > + > + return 0; > +} > + > +static struct regmap_config sun4i_backend_regmap_config = { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = 0x5800, > + .name = "backend", > +}; > + > +struct sun4i_backend *sun4i_backend_init(struct drm_device *drm) > +{ > + struct sun4i_backend *backend; > + struct resource *res; > + void __iomem *regs; > + int i; > + > + backend = devm_kzalloc(drm->dev, sizeof(*backend), GFP_KERNEL); > + if (!backend) > + return ERR_PTR(-ENOMEM); > + > + res = platform_get_resource_byname(to_platform_device(drm->dev), > + IORESOURCE_MEM, "backend0"); > + regs = devm_ioremap_resource(drm->dev, res); > + if (IS_ERR(regs)) { > + dev_err(drm->dev, "Couldn't map the backend0 registers\n"); > + return ERR_CAST(regs); > + } > + > + backend->regs = devm_regmap_init_mmio(drm->dev, regs, > + &sun4i_backend_regmap_config); > + if (IS_ERR(backend->regs)) { > + dev_err(drm->dev, "Couldn't create the backend0 regmap\n"); > + return ERR_CAST(backend->regs); > + } > + > + backend->bus_clk = devm_clk_get(drm->dev, "backend0-bus"); > + if (IS_ERR(backend->bus_clk)) { > + dev_err(drm->dev, "Couldn't get the backend bus clock\n"); > + return ERR_CAST(backend->bus_clk); > + } > + clk_prepare_enable(backend->bus_clk); > + > + backend->mod_clk = devm_clk_get(drm->dev, "backend0-mod"); > + if (IS_ERR(backend->mod_clk)) { > + dev_err(drm->dev, "Couldn't get the backend module clock\n"); > + return ERR_CAST(backend->mod_clk); > + } > + clk_prepare_enable(backend->mod_clk); > + > + backend->ram_clk = devm_clk_get(drm->dev, "backend0-ram"); > + if (IS_ERR(backend->ram_clk)) { > + dev_err(drm->dev, "Couldn't get the backend RAM clock\n"); > + return ERR_CAST(backend->ram_clk); > + } > + clk_prepare_enable(backend->ram_clk); > + > + /* Reset the registers */ > + for (i = 0x800; i < 0x1000; i += 4) > + regmap_write(backend->regs, i, 0); > + > + /* Disable registers autoloading */ > + regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG, > + SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS); > + > + /* Enable the backend */ > + regmap_write(backend->regs, SUN4I_BACKEND_MODCTL_REG, > + SUN4I_BACKEND_MODCTL_DEBE_EN | > + SUN4I_BACKEND_MODCTL_START_CTL); > + > + return backend; > +} > + > +void sun4i_backend_free(struct sun4i_backend *backend) > +{ > + clk_disable_unprepare(backend->ram_clk); > + clk_disable_unprepare(backend->mod_clk); > + clk_disable_unprepare(backend->bus_clk); > +} > diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h > new file mode 100644 > index 000000000000..8b3dca39d089 > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h > @@ -0,0 +1,159 @@ > +/* > + * Copyright (C) 2015 Free Electrons > + * Copyright (C) 2015 NextThing Co > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#ifndef _SUN4I_BACKEND_H_ > +#define _SUN4I_BACKEND_H_ > + > +#include > +#include > + > +#define SUN4I_BACKEND_MODCTL_REG 0x800 > +#define SUN4I_BACKEND_MODCTL_LINE_SEL BIT(29) > +#define SUN4I_BACKEND_MODCTL_ITLMOD_EN BIT(28) > +#define SUN4I_BACKEND_MODCTL_OUT_SEL GENMASK(22, 20) > +#define SUN4I_BACKEND_MODCTL_OUT_LCD (0 << 20) > +#define SUN4I_BACKEND_MODCTL_OUT_FE0 (6 << 20) > +#define SUN4I_BACKEND_MODCTL_OUT_FE1 (7 << 20) > +#define SUN4I_BACKEND_MODCTL_HWC_EN BIT(16) > +#define SUN4I_BACKEND_MODCTL_LAY_EN(l) BIT(8 + l) > +#define SUN4I_BACKEND_MODCTL_OCSC_EN BIT(5) > +#define SUN4I_BACKEND_MODCTL_DFLK_EN BIT(4) > +#define SUN4I_BACKEND_MODCTL_DLP_START_CTL BIT(2) > +#define SUN4I_BACKEND_MODCTL_START_CTL BIT(1) > +#define SUN4I_BACKEND_MODCTL_DEBE_EN BIT(0) > + > +#define SUN4I_BACKEND_BACKCOLOR_REG 0x804 > +#define SUN4I_BACKEND_BACKCOLOR(r, g, b) (((r) << 16) | ((g) << 8) | (b)) > + > +#define SUN4I_BACKEND_DISSIZE_REG 0x808 > +#define SUN4I_BACKEND_DISSIZE(w, h) (((((h) - 1) & 0xffff) << 16) | \ > + (((w) - 1) & 0xffff)) > + > +#define SUN4I_BACKEND_LAYSIZE_REG(l) (0x810 + (0x4 * (l))) > +#define SUN4I_BACKEND_LAYSIZE(w, h) (((((h) - 1) & 0x1fff) << 16) | \ > + (((w) - 1) & 0x1fff)) > + > +#define SUN4I_BACKEND_LAYCOOR_REG(l) (0x820 + (0x4 * (l))) > +#define SUN4I_BACKEND_LAYCOOR(x, y) ((((u32)(y) & 0xffff) << 16) | \ > + ((u32)(x) & 0xffff)) > + > +#define SUN4I_BACKEND_LAYLINEWIDTH_REG(l) (0x840 + (0x4 * (l))) > + > +#define SUN4I_BACKEND_LAYFB_L32ADD_REG(l) (0x850 + (0x4 * (l))) > + > +#define SUN4I_BACKEND_LAYFB_H4ADD_REG 0x860 > +#define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l) GENMASK(3 + ((l) * 8), 0) > +#define SUN4I_BACKEND_LAYFB_H4ADD(l, val) ((val) << ((l) * 8)) > + > +#define SUN4I_BACKEND_REGBUFFCTL_REG 0x870 > +#define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS BIT(1) > +#define SUN4I_BACKEND_REGBUFFCTL_LOADCTL BIT(0) > + > +#define SUN4I_BACKEND_CKMAX_REG 0x880 > +#define SUN4I_BACKEND_CKMIN_REG 0x884 > +#define SUN4I_BACKEND_CKCFG_REG 0x888 > +#define SUN4I_BACKEND_ATTCTL_REG0(l) (0x890 + (0x4 * (l))) > + > +#define SUN4I_BACKEND_ATTCTL_REG1(l) (0x8a0 + (0x4 * (l))) > +#define SUN4I_BACKEND_ATTCTL_REG1_LAY_HSCAFCT GENMASK(15, 14) > +#define SUN4I_BACKEND_ATTCTL_REG1_LAY_WSCAFCT GENMASK(13, 12) > +#define SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT GENMASK(11, 8) > +#define SUN4I_BACKEND_LAY_FBFMT_1BPP (0 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_2BPP (1 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_4BPP (2 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_8BPP (3 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGB655 (4 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGB565 (5 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGB556 (6 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_ARGB1555 (7 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGBA5551 (8 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_XRGB8888 (9 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_ARGB8888 (10 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGB888 (11 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_ARGB4444 (12 << 8) > +#define SUN4I_BACKEND_LAY_FBFMT_RGBA4444 (13 << 8) > + > +#define SUN4I_BACKEND_DLCDPCTL_REG 0x8b0 > +#define SUN4I_BACKEND_DLCDPFRMBUF_ADDRCTL_REG 0x8b4 > +#define SUN4I_BACKEND_DLCDPCOOR_REG0 0x8b8 > +#define SUN4I_BACKEND_DLCDPCOOR_REG1 0x8bc > + > +#define SUN4I_BACKEND_INT_EN_REG 0x8c0 > +#define SUN4I_BACKEND_INT_FLAG_REG 0x8c4 > +#define SUN4I_BACKEND_REG_LOAD_FINISHED BIT(1) > + > +#define SUN4I_BACKEND_HWCCTL_REG 0x8d8 > +#define SUN4I_BACKEND_HWCFBCTL_REG 0x8e0 > +#define SUN4I_BACKEND_WBCTL_REG 0x8f0 > +#define SUN4I_BACKEND_WBADD_REG 0x8f4 > +#define SUN4I_BACKEND_WBLINEWIDTH_REG 0x8f8 > +#define SUN4I_BACKEND_SPREN_REG 0x900 > +#define SUN4I_BACKEND_SPRFMTCTL_REG 0x908 > +#define SUN4I_BACKEND_SPRALPHACTL_REG 0x90c > +#define SUN4I_BACKEND_IYUVCTL_REG 0x920 > +#define SUN4I_BACKEND_IYUVADD_REG(c) (0x930 + (0x4 * (c))) > +#define SUN4I_BACKEND_IYUVLINEWITDTH_REG(c) (0x940 + (0x4 * (c))) > +#define SUN4I_BACKEND_YGCOEF_REG(c) (0x950 + (0x4 * (c))) > +#define SUN4I_BACKEND_YGCONS_REG 0x95c > +#define SUN4I_BACKEND_URCOEF_REG(c) (0x960 + (0x4 * (c))) > +#define SUN4I_BACKEND_URCONS_REG 0x96c > +#define SUN4I_BACKEND_VBCOEF_REG(c) (0x970 + (0x4 * (c))) > +#define SUN4I_BACKEND_VBCONS_REG 0x97c > +#define SUN4I_BACKEND_KSCTL_REG 0x980 > +#define SUN4I_BACKEND_KSBKCOLOR_REG 0x984 > +#define SUN4I_BACKEND_KSFSTLINEWIDTH_REG 0x988 > +#define SUN4I_BACKEND_KSVSCAFCT_REG 0x98c > +#define SUN4I_BACKEND_KSHSCACOEF_REG(x) (0x9a0 + (0x4 * (x))) > +#define SUN4I_BACKEND_OCCTL_REG 0x9c0 > +#define SUN4I_BACKEND_OCCTL_ENABLE BIT(0) > + > +#define SUN4I_BACKEND_OCRCOEF_REG(x) (0x9d0 + (0x4 * (x))) > +#define SUN4I_BACKEND_OCRCONS_REG 0x9dc > +#define SUN4I_BACKEND_OCGCOEF_REG(x) (0x9e0 + (0x4 * (x))) > +#define SUN4I_BACKEND_OCGCONS_REG 0x9ec > +#define SUN4I_BACKEND_OCBCOEF_REG(x) (0x9f0 + (0x4 * (x))) > +#define SUN4I_BACKEND_OCBCONS_REG 0x9fc > +#define SUN4I_BACKEND_SPRCOORCTL_REG(s) (0xa00 + (0x4 * (s))) > +#define SUN4I_BACKEND_SPRATTCTL_REG(s) (0xb00 + (0x4 * (s))) > +#define SUN4I_BACKEND_SPRADD_REG(s) (0xc00 + (0x4 * (s))) > +#define SUN4I_BACKEND_SPRLINEWIDTH_REG(s) (0xd00 + (0x4 * (s))) > + > +#define SUN4I_BACKEND_SPRPALTAB_OFF 0x4000 > +#define SUN4I_BACKEND_GAMMATAB_OFF 0x4400 > +#define SUN4I_BACKEND_HWCPATTERN_OFF 0x4800 > +#define SUN4I_BACKEND_HWCCOLORTAB_OFF 0x4c00 > +#define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) > + > +struct sun4i_backend { > + struct regmap *regs; > + > + struct clk *bus_clk; > + struct clk *mod_clk; > + struct clk *ram_clk; > +}; > + > +void sun4i_backend_apply_color_correction(struct sun4i_backend *backend); > +void sun4i_backend_commit(struct sun4i_backend *backend); > + > +void sun4i_backend_layer_enable(struct sun4i_backend *backend, > + int layer, bool enable); > +int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane); > +int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane); > +int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend, > + int layer, struct drm_plane *plane); > + > +struct sun4i_backend *sun4i_backend_init(struct drm_device *drm); > +void sun4i_backend_free(struct sun4i_backend *backend); > + > +#endif /* _SUN4I_BACKEND_H_ */ > diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c > new file mode 100644 > index 000000000000..ec4045fc31ee > --- /dev/null > +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c > @@ -0,0 +1,117 @@ > +/* > + * Copyright (C) 2015 Free Electrons > + * Copyright (C) 2015 NextThing Co > + * > + * Maxime Ripard > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of > + * the License, or (at your option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include