From de120d092eeb69b5285586a9fd33b1778ce9ee27 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:49 +0800 Subject: [PATCH 01/27] dt-bindings: display: sun4i: Add component endpoint ID numbering scheme The Allwinner display pipeline contains many hardware components, some of which can consume data from one of multiple upstream components. The numbering scheme of these components must be encoded into the device tree so the driver can figure out which component out of two or more of the same type it is supposed to use or program. This patch adds the constraint that local endpoint IDs must be the index or number of the remote endpoint's hardware block, for all components in the display pipeline up to the TCONs. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- .../devicetree/bindings/display/sunxi/sun4i-drm.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index 57a8d0610062..7acdbf14ae1c 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -4,6 +4,16 @@ Allwinner A10 Display Pipeline The Allwinner A10 Display pipeline is composed of several components that are going to be documented below: +For the input port of all components up to the TCON in the display +pipeline, if there are multiple components, the local endpoint IDs +must correspond to the index of the upstream block. For example, if +the remote endpoint is Frontend 1, then the local endpoint ID must +be 1. + +Conversely, for the output ports of the same group, the remote endpoint +ID must be the index of the local hardware block. If the local backend +is backend 1, then the remote endpoint ID must be 1. + TV Encoder ---------- From 80a58240efef576ef909f7d99180ae2a70ca68a5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:50 +0800 Subject: [PATCH 02/27] drm/sun4i: Use lists to track registered display backends and TCONs To support multiple display pipelines, we need to keep track of the multiple display backends and TCONs registered with the driver. Switch to lists to track registered components. Components are only appended to their respective lists if the bind process was successful. The TCON bind function now defers if a backend was not registered. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 6 +++++- drivers/gpu/drm/sun4i/sun4i_backend.h | 4 ++++ drivers/gpu/drm/sun4i/sun4i_drv.c | 2 ++ drivers/gpu/drm/sun4i/sun4i_drv.h | 5 +++-- drivers/gpu/drm/sun4i/sun4i_tcon.c | 14 ++++++++++++-- drivers/gpu/drm/sun4i/sun4i_tcon.h | 4 ++++ 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index d660741ba475..95a77c6a9161 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "sun4i_backend.h" @@ -310,7 +311,6 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, if (!backend) return -ENOMEM; dev_set_drvdata(dev, backend); - drv->backend = backend; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); @@ -369,6 +369,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, } } + list_add_tail(&backend->list, &drv->backend_list); + /* Reset the registers */ for (i = 0x800; i < 0x1000; i += 4) regmap_write(backend->regs, i, 0); @@ -400,6 +402,8 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master, { struct sun4i_backend *backend = dev_get_drvdata(dev); + list_del(&backend->list); + if (of_device_is_compatible(dev->of_node, "allwinner,sun8i-a33-display-backend")) sun4i_backend_free_sat(dev); diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 83e63cc702b4..9c8287309c65 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -14,6 +14,7 @@ #define _SUN4I_BACKEND_H_ #include +#include #include #include @@ -149,6 +150,9 @@ struct sun4i_backend { struct clk *sat_clk; struct reset_control *sat_reset; + + /* Backend list management */ + struct list_head list; }; void sun4i_backend_apply_color_correction(struct sun4i_backend *backend); diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 8ddd72cd5873..c52f7a9eb045 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -91,6 +91,8 @@ static int sun4i_drv_bind(struct device *dev) goto free_drm; } drm->dev_private = drv; + INIT_LIST_HEAD(&drv->backend_list); + INIT_LIST_HEAD(&drv->tcon_list); ret = of_reserved_mem_device_init(dev); if (ret && ret != -ENODEV) { diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index 5df50126ff52..250c29017ef5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h @@ -14,11 +14,12 @@ #define _SUN4I_DRV_H_ #include +#include #include struct sun4i_drv { - struct sun4i_backend *backend; - struct sun4i_tcon *tcon; + struct list_head backend_list; + struct list_head tcon_list; struct drm_fbdev_cma *fbdev; }; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 9a83a85529ac..5adb643ed41d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -25,6 +25,7 @@ #include #include +#include "sun4i_backend.h" #include "sun4i_crtc.h" #include "sun4i_dotclock.h" #include "sun4i_drv.h" @@ -407,14 +408,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, { struct drm_device *drm = data; struct sun4i_drv *drv = drm->dev_private; + struct sun4i_backend *backend; struct sun4i_tcon *tcon; int ret; + /* Wait for a backend to be registered */ + if (list_empty(&drv->backend_list)) + return -EPROBE_DEFER; + tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); if (!tcon) return -ENOMEM; dev_set_drvdata(dev, tcon); - drv->tcon = tcon; tcon->drm = drm; tcon->dev = dev; tcon->quirks = of_device_get_match_data(dev); @@ -459,7 +464,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_dotclock; } - tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon); + backend = list_first_entry(&drv->backend_list, + struct sun4i_backend, list); + tcon->crtc = sun4i_crtc_init(drm, backend, tcon); if (IS_ERR(tcon->crtc)) { dev_err(dev, "Couldn't create our CRTC\n"); ret = PTR_ERR(tcon->crtc); @@ -470,6 +477,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, if (ret < 0) goto err_free_clocks; + list_add_tail(&tcon->list, &drv->tcon_list); + return 0; err_free_dotclock: @@ -486,6 +495,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, { struct sun4i_tcon *tcon = dev_get_drvdata(dev); + list_del(&tcon->list); sun4i_dclk_free(tcon); sun4i_tcon_free_clocks(tcon); } diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index f636343a935d..1bda4d183eec 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -17,6 +17,7 @@ #include #include +#include #include #define SUN4I_TCON_GCTL_REG 0x0 @@ -172,6 +173,9 @@ struct sun4i_tcon { /* Associated crtc */ struct sun4i_crtc *crtc; + + /* TCON list management */ + struct list_head list; }; struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); From fdde6e7bcd5e2de4da6da7b0aab9676c478f319e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:51 +0800 Subject: [PATCH 03/27] drm/sun4i: backend: Drop trailing 0 from backend in error message Now that we support multiple instances of backends, the trailing 0 implying only one backend no longer makes sense. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 95a77c6a9161..e17e20036aa3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -320,7 +320,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, backend->regs = devm_regmap_init_mmio(dev, regs, &sun4i_backend_regmap_config); if (IS_ERR(backend->regs)) { - dev_err(dev, "Couldn't create the backend0 regmap\n"); + dev_err(dev, "Couldn't create the backend regmap\n"); return PTR_ERR(backend->regs); } From da3a1c30dc10858b39a759432d8141f42b8529e8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:52 +0800 Subject: [PATCH 04/27] drm/sun4i: backend: Fetch backend ID from device tree Some Allwinner SoCs have 2 display pipelines, as in 2 of each components, including the frontend, backend, TCON, and any other extras. As the backend and TCON are always paired together and form the CRTC, we need to know which backend or TCON we are currently probing, so we can pair them when initializing the CRTC. This patch figures out the backend's ID from the device tree and stores it in the backend's data structure. It does this by looking at the "reg" property of any remote endpoints connected to the backend's input port. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 44 +++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_backend.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index e17e20036aa3..0b4222312e49 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -20,6 +20,7 @@ #include #include +#include #include #include "sun4i_backend.h" @@ -289,6 +290,45 @@ static int sun4i_backend_free_sat(struct device *dev) { return 0; } +/* + * The display backend can take video output from the display frontend, or + * the display enhancement unit on the A80, as input for one it its layers. + * This relationship within the display pipeline is encoded in the device + * tree with of_graph, and we use it here to figure out which backend, if + * there are 2 or more, we are currently probing. The number would be in + * the "reg" property of the upstream output port endpoint. + */ +static int sun4i_backend_of_get_id(struct device_node *node) +{ + struct device_node *port, *ep; + int ret = -EINVAL; + + /* input is port 0 */ + port = of_graph_get_port_by_id(node, 0); + if (!port) + return -EINVAL; + + /* try finding an upstream endpoint */ + for_each_available_child_of_node(port, ep) { + struct device_node *remote; + u32 reg; + + remote = of_parse_phandle(ep, "remote-endpoint", 0); + if (!remote) + continue; + + ret = of_property_read_u32(remote, "reg", ®); + if (ret) + continue; + + ret = reg; + } + + of_node_put(port); + + return ret; +} + static struct regmap_config sun4i_backend_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -312,6 +352,10 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, return -ENOMEM; dev_set_drvdata(dev, backend); + backend->id = sun4i_backend_of_get_id(dev->of_node); + if (backend->id < 0) + return backend->id; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 9c8287309c65..45b7fc110590 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -151,6 +151,8 @@ struct sun4i_backend { struct clk *sat_clk; struct reset_control *sat_reset; + int id; + /* Backend list management */ struct list_head list; }; From 2c03e2fb063f33694e35bbade6d9186274b9a02f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:53 +0800 Subject: [PATCH 05/27] drm/sun4i: backend: Save pointer to device tree node Save a pointer to the backend's underlying device tree node in its data structure. This will be used later for downstream tcons to find and match their respective upstream backends. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 1 + drivers/gpu/drm/sun4i/sun4i_backend.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 0b4222312e49..e9eca057ff35 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -352,6 +352,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, return -ENOMEM; dev_set_drvdata(dev, backend); + backend->node = dev->of_node; backend->id = sun4i_backend_of_get_id(dev->of_node); if (backend->id < 0) return backend->id; diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 45b7fc110590..6327a2985fe6 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -140,6 +141,7 @@ #define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) struct sun4i_backend { + struct device_node *node; struct regmap *regs; struct reset_control *reset; From b317fa3ba11a10eee45c3e64d6396015ff87e8dc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:54 +0800 Subject: [PATCH 06/27] drm/sun4i: tcon: Find matching display backend by device node matching With Allwinner's Display Engine 1.0, each TCON's input is tied to a specific display backend, and the 2 comprise what is known as a crtc in DRM KMS land: The layer, framebuffer, and compositing functions are provided by the backend, while the TCON provides the display timing signals and vblank interrupts. This 1 to 1 relationship is represented in the device tree. On some systems there is an intermediate DRC component. Pointers to both matching components must be provided when initializing the crtc. As the backend is always registered before the associated tcon, we can recursively search upwards through the of_graph to find the matching backend. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 55 +++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 5adb643ed41d..b13a7c2029df 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -403,6 +403,53 @@ static int sun4i_tcon_init_regmap(struct device *dev, return 0; } +/* + * On SoCs with the old display pipeline design (Display Engine 1.0), + * the TCON is always tied to just one backend. Hence we can traverse + * the of_graph upwards to find the backend our tcon is connected to, + * and take its ID as our own. + * + * We can either identify backends from their compatible strings, which + * means maintaining a large list of them. Or, since the backend is + * registered and binded before the TCON, we can just go through the + * list of registered backends and compare the device node. + */ +static struct sun4i_backend *sun4i_tcon_find_backend(struct sun4i_drv *drv, + struct device_node *node) +{ + struct device_node *port, *ep, *remote; + struct sun4i_backend *backend; + + port = of_graph_get_port_by_id(node, 0); + if (!port) + return ERR_PTR(-EINVAL); + + for_each_available_child_of_node(port, ep) { + remote = of_graph_get_remote_port_parent(ep); + if (!remote) + continue; + + /* does this node match any registered backends? */ + list_for_each_entry(backend, &drv->backend_list, list) { + if (remote == backend->node) { + of_node_put(remote); + of_node_put(port); + return backend; + } + } + + /* keep looking through upstream ports */ + backend = sun4i_tcon_find_backend(drv, remote); + if (!IS_ERR(backend)) { + of_node_put(remote); + of_node_put(port); + return backend; + } + } + + return ERR_PTR(-EINVAL); +} + static int sun4i_tcon_bind(struct device *dev, struct device *master, void *data) { @@ -412,9 +459,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, struct sun4i_tcon *tcon; int ret; - /* Wait for a backend to be registered */ - if (list_empty(&drv->backend_list)) + backend = sun4i_tcon_find_backend(drv, dev->of_node); + if (IS_ERR(backend)) { + dev_err(dev, "Couldn't find matching backend\n"); return -EPROBE_DEFER; + } tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL); if (!tcon) @@ -464,8 +513,6 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_dotclock; } - backend = list_first_entry(&drv->backend_list, - struct sun4i_backend, list); tcon->crtc = sun4i_crtc_init(drm, backend, tcon); if (IS_ERR(tcon->crtc)) { dev_err(dev, "Couldn't create our CRTC\n"); From d281c862de30381c144145a75ec1f0d5efc307ae Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 21 Apr 2017 16:38:55 +0800 Subject: [PATCH 07/27] drm/sun4i: tcon: Copy ID from associated backend The tcons and backends have a one-to-one relationship. Their IDs, or indexes in the documentation, are also the same. Copy the ID from the associated backend and save it in the tcon structure. This will later be used when we add support for the output data path muxes. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 1 + drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index b13a7c2029df..5d7866fce78b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -471,6 +471,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, dev_set_drvdata(dev, tcon); tcon->drm = drm; tcon->dev = dev; + tcon->id = backend->id; tcon->quirks = of_device_get_match_data(dev); tcon->lcd_rst = devm_reset_control_get(dev, "lcd"); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 1bda4d183eec..d37e1e2ed60e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -174,6 +174,8 @@ struct sun4i_tcon { /* Associated crtc */ struct sun4i_crtc *crtc; + int id; + /* TCON list management */ struct list_head list; }; From 86cf6788a661b8cb459f259e373c5daf09221abe Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 25 Apr 2017 23:25:04 +0800 Subject: [PATCH 08/27] drm/sun4i: Set TCON clock inside sun4i_tconX_mode_set Currently we are configuring the TCON's dot clock or special clock directly from the encoder mode_set functions. Since we already provide mode_set helper functions for the TCON's 2 channels, we can set the respective clock from those helpers, and reduce the exposure of the TCON's internals. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 -- drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 ++++++ drivers/gpu/drm/sun4i/sun4i_tv.c | 2 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 67f0b91a99de..c9bbb3b560a5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -176,8 +176,6 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, sun4i_tcon0_mode_set(tcon, mode); - clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); - /* FIXME: This seems to be board specific */ clk_set_phase(tcon->dclk, 120); } diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 5d7866fce78b..8b6aaa60037d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -130,6 +130,9 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, u8 clk_delay; u32 val = 0; + /* Configure the dot clock */ + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); + /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 0); regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, @@ -205,6 +208,9 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, WARN_ON(!tcon->quirks->has_channel_1); + /* Configure the dot clock */ + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); + /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 49c49431a053..542da220818b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -486,8 +486,6 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, SUN4I_TVE_RESYNC_FIELD : 0)); regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0); - - clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); } static struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = { From cf80aeef958f2e5b0041c72b567ae949f5b2738d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 25 Apr 2017 23:25:05 +0800 Subject: [PATCH 09/27] drm/sun4i: backend: Clarify sun4i_backend_layer_enable debug message sun4i_backend_layer_enable can be called to enable or disable a layer. However the debug message always says "Enable", which is confusing. This patch makes the debug message vary according to the enable state. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_backend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index e9eca057ff35..e53107418add 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -73,7 +73,8 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend, { u32 val; - DRM_DEBUG_DRIVER("Enabling layer %d\n", layer); + DRM_DEBUG_DRIVER("%sabling layer %d\n", enable ? "En" : "Dis", + layer); if (enable) val = SUN4I_BACKEND_MODCTL_LAY_EN(layer); From f23c68a992def240fe46df8517f15171d7bd6ec2 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 15 May 2017 00:30:35 +0800 Subject: [PATCH 10/27] dt-bindings: add bindings for DE2 on V3s SoC Allwinner V3s SoC have a display engine which have a different pipeline with older SoCs. Add document for it (new compatibles and the new "mixer" part). Signed-off-by: Icenowy Zheng Acked-by: Rob Herring Signed-off-by: Maxime Ripard --- .../bindings/display/sunxi/sun4i-drm.txt | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index 7acdbf14ae1c..66b85a195ef2 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt @@ -41,6 +41,7 @@ Required properties: * allwinner,sun6i-a31-tcon * allwinner,sun6i-a31s-tcon * allwinner,sun8i-a33-tcon + * allwinner,sun8i-v3s-tcon - reg: base address and size of memory-mapped region - interrupts: interrupt associated to this IP - clocks: phandles to the clocks feeding the TCON. Three are needed: @@ -62,7 +63,7 @@ Required properties: second the block connected to the TCON channel 1 (usually the TV encoder) -On SoCs other than the A33, there is one more clock required: +On SoCs other than the A33 and V3s, there is one more clock required: - 'tcon-ch1': The clock driving the TCON channel 1 DRC @@ -148,6 +149,26 @@ Required properties: Documentation/devicetree/bindings/media/video-interfaces.txt. The first port should be the input endpoints, the second one the outputs +Display Engine 2.0 Mixer +------------------------ + +The DE2 mixer have many functionalities, currently only layer blending is +supported. + +Required properties: + - compatible: value must be one of: + * allwinner,sun8i-v3s-de2-mixer + - reg: base address and size of the memory-mapped region. + - clocks: phandles to the clocks feeding the mixer + * bus: the mixer interface clock + * mod: the mixer module clock + - clock-names: the clock names mentioned above + - resets: phandles to the reset controllers driving the mixer + +- ports: A ports node with endpoint definitions as defined in + Documentation/devicetree/bindings/media/video-interfaces.txt. The + first port should be the input endpoints, the second one the output + Display Engine Pipeline ----------------------- @@ -162,9 +183,10 @@ Required properties: * allwinner,sun6i-a31-display-engine * allwinner,sun6i-a31s-display-engine * allwinner,sun8i-a33-display-engine + * allwinner,sun8i-v3s-display-engine - allwinner,pipelines: list of phandle to the display engine - frontends available. + frontends (DE 1.0) or mixers (DE 2.0) available. Example: From 7921e1477a5327ff22cc38a0ec74ace5d26dbba9 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 15 May 2017 00:30:36 +0800 Subject: [PATCH 11/27] drm/sun4i: return only planes for layers created As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm driver, we will finally have two types of layers. Each layer is bound to a drm_plane that is CRTC-specific, so we create them when initializing CRTC (calling sun4i_layers_init, which will be generalized in next patch). The drm_plane's will be used when creating CRTC, but the CRTC initialization code do not care other properties of the layer, so we let the sun4i_layers_init function return drm_plane's only. As we have no need to trace the layers after the CRTC is properly created, we drop the layers pointer in sun4i_crtc struct. Doing this uncouples the CRTC code from the type of layer (the sun4i_layers_init function name is still hardcoded and will be changed in the next patch), so that we can finally gain support for the mixer in DE2, which has different layers. Signed-off-by: Icenowy Zheng Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 23 ++++++++++++----------- drivers/gpu/drm/sun4i/sun4i_crtc.h | 1 - drivers/gpu/drm/sun4i/sun4i_layer.c | 18 ++++++++++-------- drivers/gpu/drm/sun4i/sun4i_layer.h | 4 ++-- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 3c876c3a356a..708b3543d4e9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -139,6 +139,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, struct sun4i_tcon *tcon) { struct sun4i_crtc *scrtc; + struct drm_plane **planes; struct drm_plane *primary = NULL, *cursor = NULL; int ret, i; @@ -149,22 +150,22 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, scrtc->tcon = tcon; /* Create our layers */ - scrtc->layers = sun4i_layers_init(drm, scrtc->backend); - if (IS_ERR(scrtc->layers)) { + planes = sun4i_layers_init(drm, scrtc); + if (IS_ERR(planes)) { dev_err(drm->dev, "Couldn't create the planes\n"); return NULL; } /* find primary and cursor planes for drm_crtc_init_with_planes */ - for (i = 0; scrtc->layers[i]; i++) { - struct sun4i_layer *layer = scrtc->layers[i]; + for (i = 0; planes[i]; i++) { + struct drm_plane *plane = planes[i]; - switch (layer->plane.type) { + switch (plane->type) { case DRM_PLANE_TYPE_PRIMARY: - primary = &layer->plane; + primary = plane; break; case DRM_PLANE_TYPE_CURSOR: - cursor = &layer->plane; + cursor = plane; break; default: break; @@ -188,12 +189,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, 1); /* Set possible_crtcs to this crtc for overlay planes */ - for (i = 0; scrtc->layers[i]; i++) { + for (i = 0; planes[i]; i++) { uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc)); - struct sun4i_layer *layer = scrtc->layers[i]; + struct drm_plane *plane = planes[i]; - if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY) - layer->plane.possible_crtcs = possible_crtcs; + if (plane->type == DRM_PLANE_TYPE_OVERLAY) + plane->possible_crtcs = possible_crtcs; } return scrtc; diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h index 230cb8f0d601..4dae3508424a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h @@ -19,7 +19,6 @@ struct sun4i_crtc { struct sun4i_backend *backend; struct sun4i_tcon *tcon; - struct sun4i_layer **layers; }; static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index f26bde5b9117..e1f03e1cc0ac 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -16,6 +16,7 @@ #include #include "sun4i_backend.h" +#include "sun4i_crtc.h" #include "sun4i_layer.h" struct sun4i_plane_desc { @@ -128,15 +129,16 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, return layer; } -struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, - struct sun4i_backend *backend) +struct drm_plane **sun4i_layers_init(struct drm_device *drm, + struct sun4i_crtc *crtc) { - struct sun4i_layer **layers; + struct drm_plane **planes; + struct sun4i_backend *backend = crtc->backend; int i; - layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, - sizeof(*layers), GFP_KERNEL); - if (!layers) + planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, + sizeof(*planes), GFP_KERNEL); + if (!planes) return ERR_PTR(-ENOMEM); /* @@ -178,8 +180,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); layer->id = i; - layers[i] = layer; + planes[i] = &layer->plane; }; - return layers; + return planes; } diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index 4be1f0919df2..5ea5c994d6ea 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h @@ -26,7 +26,7 @@ plane_to_sun4i_layer(struct drm_plane *plane) return container_of(plane, struct sun4i_layer, plane); } -struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, - struct sun4i_backend *backend); +struct drm_plane **sun4i_layers_init(struct drm_device *drm, + struct sun4i_crtc *crtc); #endif /* _SUN4I_LAYER_H_ */ From 87969338436710638076d8083dda8b0de703f4a5 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Wed, 17 May 2017 22:47:17 +0800 Subject: [PATCH 12/27] drm/sun4i: abstract a engine type 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, and is part of the "Display Engine" called by Allwinner, 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). In order to preserve bisectability, we also switch the backend and layer code in its own module. Signed-off-by: Icenowy Zheng Reviewed-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/Makefile | 5 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 78 +++++++++++---------- drivers/gpu/drm/sun4i/sun4i_backend.h | 19 +++--- drivers/gpu/drm/sun4i/sun4i_crtc.c | 11 ++- drivers/gpu/drm/sun4i/sun4i_crtc.h | 4 +- drivers/gpu/drm/sun4i/sun4i_drv.c | 2 +- drivers/gpu/drm/sun4i/sun4i_drv.h | 2 +- drivers/gpu/drm/sun4i/sun4i_layer.c | 9 ++- drivers/gpu/drm/sun4i/sun4i_layer.h | 4 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 38 ++++++----- drivers/gpu/drm/sun4i/sun4i_tv.c | 9 ++- drivers/gpu/drm/sun4i/sunxi_engine.h | 98 +++++++++++++++++++++++++++ 12 files changed, 192 insertions(+), 87 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sunxi_engine.h diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 59b757350a1f..a251fb36c951 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -5,9 +5,10 @@ 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_backend.o sun4i_layer.o obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o -obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o +obj-$(CONFIG_DRM_SUN4I) += 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 e53107418add..cf480218daa5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -25,6 +25,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, @@ -32,41 +34,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) @@ -81,10 +80,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) @@ -144,33 +142,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) @@ -185,7 +183,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); @@ -199,12 +197,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) @@ -232,19 +230,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); @@ -330,6 +328,13 @@ static int sun4i_backend_of_get_id(struct device_node *node) return ret; } +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, @@ -353,21 +358,22 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, return -ENOMEM; dev_set_drvdata(dev, backend); - backend->node = dev->of_node; - backend->id = sun4i_backend_of_get_id(dev->of_node); - if (backend->id < 0) - return backend->id; + backend->engine.node = dev->of_node; + backend->engine.ops = &sun4i_backend_engine_ops; + backend->engine.id = sun4i_backend_of_get_id(dev->of_node); + if (backend->engine.id < 0) + return backend->engine.id; 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 backend regmap\n"); - return PTR_ERR(backend->regs); + return PTR_ERR(backend->engine.regs); } backend->reset = devm_reset_control_get(dev, NULL); @@ -415,18 +421,18 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, } } - list_add_tail(&backend->list, &drv->backend_list); + list_add_tail(&backend->engine.list, &drv->engine_list); /* 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); @@ -448,7 +454,7 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master, { struct sun4i_backend *backend = dev_get_drvdata(dev); - list_del(&backend->list); + list_del(&backend->engine.list); if (of_device_is_compatible(dev->of_node, "allwinner,sun8i-a33-display-backend")) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 6327a2985fe6..21945af67a9d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -19,6 +19,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) @@ -141,8 +143,7 @@ #define SUN4I_BACKEND_PIPE_OFF(p) (0x5000 + (0x400 * (p))) struct sun4i_backend { - struct device_node *node; - struct regmap *regs; + struct sunxi_engine engine; struct reset_control *reset; @@ -152,17 +153,13 @@ struct sun4i_backend { struct clk *sat_clk; struct reset_control *sat_reset; - - int id; - - /* Backend list management */ - struct list_head list; }; -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