From 92caf9bede544d4f26c183bf7e5b390b5d80a66e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:24 +0800 Subject: drm/sun4i: Move drm_mode_config_cleanup call to main driver drm_mode_config_cleanup is the complement of drm_mode_config_init, which is called in the bind function of sun4i_drv. drm_mode_config_cleanup should be put in the unbind function to match. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_drv.c | 1 + drivers/gpu/drm/sun4i/sun4i_framebuffer.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 9ccf7c4deb6d..cd26ed94c41b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -160,6 +160,7 @@ static void sun4i_drv_unbind(struct device *dev) drm_dev_unregister(drm); drm_kms_helper_poll_fini(drm); sun4i_framebuffer_free(drm); + drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); drm_dev_unref(drm); } diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c index 2c3beff8b53e..9872e0fc03b0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c +++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c @@ -48,5 +48,4 @@ void sun4i_framebuffer_free(struct drm_device *drm) struct sun4i_drv *drv = drm->dev_private; drm_fbdev_cma_fini(drv->fbdev); - drm_mode_config_cleanup(drm); } -- cgit v1.2.3 From 9d56defb44b15427f4342c543a70fb7886fc06f5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:25 +0800 Subject: drm/sun4i: Fix up error path cleanup for master bind function The master bind function calls numerous drm functions which initialize underlying structures. It also tries to bind the various components of the display pipeline, some of which may add additional drm objects. This patch adds proper cleanup functions in the error path of the master bind function. This requires the patch "drm/sun4i: Move drm_mode_config_cleanup call to main driver", which splits out drm_mode_config_cleanup from sun4i_framebuffer_free so we can call it separately. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_drv.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index cd26ed94c41b..7ae179e88309 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -108,7 +108,7 @@ static int sun4i_drv_bind(struct device *dev) ret = component_bind_all(drm->dev, drm); if (ret) { dev_err(drm->dev, "Couldn't bind all pipelines components\n"); - goto free_drm; + goto cleanup_mode_config; } /* Create our layers */ @@ -116,7 +116,7 @@ static int sun4i_drv_bind(struct device *dev) if (IS_ERR(drv->layers)) { dev_err(drm->dev, "Couldn't create the planes\n"); ret = PTR_ERR(drv->layers); - goto free_drm; + goto cleanup_mode_config; } /* Create our CRTC */ @@ -124,7 +124,7 @@ static int sun4i_drv_bind(struct device *dev) if (!drv->crtc) { dev_err(drm->dev, "Couldn't create the CRTC\n"); ret = -EINVAL; - goto free_drm; + goto cleanup_mode_config; } drm->irq_enabled = true; @@ -136,7 +136,7 @@ static int sun4i_drv_bind(struct device *dev) if (IS_ERR(drv->fbdev)) { dev_err(drm->dev, "Couldn't create our framebuffer\n"); ret = PTR_ERR(drv->fbdev); - goto free_drm; + goto cleanup_mode_config; } /* Enable connectors polling */ @@ -144,10 +144,16 @@ static int sun4i_drv_bind(struct device *dev) ret = drm_dev_register(drm, 0); if (ret) - goto free_drm; + goto finish_poll; return 0; +finish_poll: + drm_kms_helper_poll_fini(drm); + sun4i_framebuffer_free(drm); +cleanup_mode_config: + drm_mode_config_cleanup(drm); + drm_vblank_cleanup(drm); free_drm: drm_dev_unref(drm); return ret; -- cgit v1.2.3 From 92b300c4e6f7f6fc22e1cc02d7c07627769a6339 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:26 +0800 Subject: drm/sun4i: Check return value of drm_vblank_init drm_vblank_init can fail due to insufficient memory. Ignoring the error and proceeding may cause the kernel to dereference an invalid pointer when vblank is enabled. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_drv.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 7ae179e88309..46887c3044d0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -102,7 +102,11 @@ static int sun4i_drv_bind(struct device *dev) } drm->dev_private = drv; - drm_vblank_init(drm, 1); + /* drm_vblank_init calls kcalloc, which can fail */ + ret = drm_vblank_init(drm, 1); + if (ret) + goto free_drm; + drm_mode_config_init(drm); ret = component_bind_all(drm->dev, drm); -- cgit v1.2.3 From f43fbe7a59b6e2fd8b366321e5163c3499b80b26 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:27 +0800 Subject: drm/sun4i: Fix kcalloc element size in sun4i_layers_init In sun4i_layers_init we are allocating an array of pointers to struct sun4i_layer: layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes), sizeof(**layers), GFP_KERNEL); The element size should be the size of an individual element of the array. Change it to sizeof(*layers) to avoid wasting a lot of memory. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 5d53c977bca5..62552a356d66 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -140,7 +140,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) int i; layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes), - sizeof(**layers), GFP_KERNEL); + sizeof(*layers), GFP_KERNEL); if (!layers) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 8a16469b74af0fb584686e5e18d2cf3570424e4b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:28 +0800 Subject: drm/sun4i: Drop useless assignment in sun4i_layers_init The assignment found in the main loop in sun4i_layers_init: struct sun4i_layer *layer = layers[i]; is useless as it gets overwritten by the next line: layer = sun4i_layer_init_one(drm, plane); Drop the assignment. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 62552a356d66..92ecc967dcb1 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -167,7 +167,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) */ for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; - struct sun4i_layer *layer = layers[i]; + struct sun4i_layer *layer; layer = sun4i_layer_init_one(drm, plane); if (IS_ERR(layer)) { -- cgit v1.2.3 From 903795d60ffa89918b521064b0cbcba139ae4047 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:29 +0800 Subject: drm/sun4i: Save newly created layer in layers array in sun4i_layers_init sun4i_layers_init allocates an array to store pointers to newly created layers returned by sun4i_layer_init_one(), but fails to actually store them. But it actually returns the empty array to unsuspecting users. Save the pointers in the array, so that they may be used later. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 92ecc967dcb1..41bc0f860f5c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -183,6 +183,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); layer->id = i; + layers[i] = layer; }; return layers; -- cgit v1.2.3 From ea411fd2c8d5704fc247be106026d436d27c900f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 17 Feb 2017 11:13:30 +0800 Subject: drm/sun4i: Make sun4i_crtc_init return ERR_PTR style error codes sun4i_crtc_init can fail for a number of reasons. Instead of returning a NULL pointer when it fails, pass back the encountered error using ERR_PTR. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 4 ++-- drivers/gpu/drm/sun4i/sun4i_drv.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index a5d546a68e16..7d332fce6770 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -145,7 +145,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); if (!scrtc) - return NULL; + return ERR_PTR(-ENOMEM); scrtc->drv = drv; ret = drm_crtc_init_with_planes(drm, &scrtc->crtc, @@ -155,7 +155,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) NULL); if (ret) { dev_err(drm->dev, "Couldn't init DRM CRTC\n"); - return NULL; + return ERR_PTR(ret); } drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs); diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 46887c3044d0..9adf1263e1e3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -125,9 +125,9 @@ static int sun4i_drv_bind(struct device *dev) /* Create our CRTC */ drv->crtc = sun4i_crtc_init(drm); - if (!drv->crtc) { + if (IS_ERR(drv->crtc)) { dev_err(drm->dev, "Couldn't create the CRTC\n"); - ret = -EINVAL; + ret = PTR_ERR(drv->crtc); goto cleanup_mode_config; } drm->irq_enabled = true; -- cgit v1.2.3 From a6fbffb0301196df7735aa4aacd35610858e471f Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:33 +0800 Subject: drm/sun4i: Make sunxi_rgb2yuv_coef constant sunxi_rgb2yuv_coef is a table of RGB-to-YUV conversion coefficients. They are programmed into the hardware, and can be declared constant. Reported-by: Priit Laes 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(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 08ce15070f80..d660741ba475 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -24,7 +24,7 @@ #include "sun4i_backend.h" #include "sun4i_drv.h" -static u32 sunxi_rgb2yuv_coef[12] = { +static const u32 sunxi_rgb2yuv_coef[12] = { 0x00000107, 0x00000204, 0x00000064, 0x00000108, 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808, 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 -- cgit v1.2.3 From 7544860733d158e3edbf309f27e79e258c8f66bd Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:34 +0800 Subject: drm/sun4i: Set drm_crtc.port to the underlying TCON's output port node The way drm_of_find_possible_crtcs works is it tries to match the remote-endpoint of the given node's various endpoints to all the crtc's .port field. Thus we need to set drm_crtc.port to the output port node of the underlying TCON. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 7d332fce6770..eec13cea3144 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -160,5 +161,9 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs); + /* Set crtc.port to output port node of the tcon */ + scrtc->crtc.port = of_graph_get_port_by_id(drv->tcon->dev->of_node, + 1); + return scrtc; } -- cgit v1.2.3 From 2b2c22bf1c7017d8b4ac088c33b58fae4786d569 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:35 +0800 Subject: drm/sun4i: Add end of list element for sun4i_layers_init's returned list The number of defined planes in sun4i_layer is unknown to other parts of the sun4i drm driver. Since the return value of sun4i_layers_init is a list of layers, make it return 1 more empty layer as an end of list guard value. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 41bc0f860f5c..0b703fb02656 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -139,7 +139,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) struct sun4i_layer **layers; int i; - layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes), + layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1, sizeof(*layers), GFP_KERNEL); if (!layers) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From b3f266e428db3f08bb57f6edd6be10c4d092c38d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:36 +0800 Subject: drm/sun4i: Move layers from sun4i_drv to sun4i_crtc This patch moves the sun4i_layers_init call from sun4i_drv_bind to sun4i_crtc_init, and the layers pointer from struct sun4i_drv to struct sun4i_crtc. The layers are bound to a specific crtc, and they are not directly used once initiated. They are used through their included drm_plane structures. Moving the layers into the crtc facilitates binding them to the crtc explicitly, by setting the corresponding bit in their .possible_crtcs fields right after the crtc is initialized. This is done in a later patch. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 8 ++++++++ drivers/gpu/drm/sun4i/sun4i_crtc.h | 1 + drivers/gpu/drm/sun4i/sun4i_drv.c | 10 +--------- drivers/gpu/drm/sun4i/sun4i_drv.h | 2 -- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index eec13cea3144..bcc1c9533d67 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -28,6 +28,7 @@ #include "sun4i_backend.h" #include "sun4i_crtc.h" #include "sun4i_drv.h" +#include "sun4i_layer.h" #include "sun4i_tcon.h" static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, @@ -149,6 +150,13 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) return ERR_PTR(-ENOMEM); scrtc->drv = drv; + /* Create our layers */ + scrtc->layers = sun4i_layers_init(drm); + if (IS_ERR(scrtc->layers)) { + dev_err(drm->dev, "Couldn't create the planes\n"); + return ERR_CAST(scrtc->layers); + } + ret = drm_crtc_init_with_planes(drm, &scrtc->crtc, drv->primary, NULL, diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h index dec8ce4d9b25..0a888f73c983 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h @@ -18,6 +18,7 @@ struct sun4i_crtc { struct drm_pending_vblank_event *event; struct sun4i_drv *drv; + 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_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 9adf1263e1e3..084c158611de 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -23,7 +23,7 @@ #include "sun4i_crtc.h" #include "sun4i_drv.h" #include "sun4i_framebuffer.h" -#include "sun4i_layer.h" +#include "sun4i_tcon.h" static const struct file_operations sun4i_drv_fops = { .owner = THIS_MODULE, @@ -115,14 +115,6 @@ static int sun4i_drv_bind(struct device *dev) goto cleanup_mode_config; } - /* Create our layers */ - drv->layers = sun4i_layers_init(drm); - if (IS_ERR(drv->layers)) { - dev_err(drm->dev, "Couldn't create the planes\n"); - ret = PTR_ERR(drv->layers); - goto cleanup_mode_config; - } - /* Create our CRTC */ drv->crtc = sun4i_crtc_init(drm); if (IS_ERR(drv->crtc)) { diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index 597353eab728..e22ee536677e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h @@ -23,8 +23,6 @@ struct sun4i_drv { struct drm_plane *primary; struct drm_fbdev_cma *fbdev; - - struct sun4i_layer **layers; }; #endif /* _SUN4I_DRV_H_ */ -- cgit v1.2.3 From 46cce6dac316a707309b374d9b6786b4269e7274 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:37 +0800 Subject: drm/sun4i: Initialize crtc from tcon bind function The tcon provides part of the functionality of the crtc, and also provides the device node for the output port of the crtc. To be able to use drm_of_find_possible_crtcs(), all crtc must be initialized before any downstream encoders. The other part of the crtc is the display backend. The Rockchip DRM driver does this by first binding all vops, which is their crtc, and this step also creates the crtc objects. Then all remaining hardware components are bound. With the Allwinner display pipeline, we have multiple components comprising the crtc, and varying depths of the display pipeline. Since components are added with a depth first search of the of_graph, we can initialize the crtc object within the tcon bind function. Since the backend precedes the tcon, and the backends cannot be muxed or switched around, we can be sure that the associated backend is already initialized. This patch also moves the crtc pointer from the main drm_device data to the tcon device data. Besides the crtc callbacks, the crtc structure is only used within the tcon driver to signal vblank events from its interrupt handler. As the crtc and layer bits are now called from the tcon bits, we must move them from the sun4i-drm module to the sun4i-tcon module to avoid circular dependencies between the two modules. This is because sun4i-drm also calls into sun4i-tcon. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/Makefile | 4 ++-- drivers/gpu/drm/sun4i/sun4i_drv.c | 8 -------- drivers/gpu/drm/sun4i/sun4i_drv.h | 1 - drivers/gpu/drm/sun4i/sun4i_tcon.c | 10 ++++++++-- drivers/gpu/drm/sun4i/sun4i_tcon.h | 3 +++ 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index d625a82a6e5f..59b757350a1f 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile @@ -1,11 +1,11 @@ -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-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 obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 084c158611de..1de15cd1b102 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -20,7 +20,6 @@ #include #include -#include "sun4i_crtc.h" #include "sun4i_drv.h" #include "sun4i_framebuffer.h" #include "sun4i_tcon.h" @@ -115,13 +114,6 @@ static int sun4i_drv_bind(struct device *dev) goto cleanup_mode_config; } - /* Create our CRTC */ - drv->crtc = sun4i_crtc_init(drm); - if (IS_ERR(drv->crtc)) { - dev_err(drm->dev, "Couldn't create the CRTC\n"); - ret = PTR_ERR(drv->crtc); - goto cleanup_mode_config; - } drm->irq_enabled = true; /* Remove early framebuffers (ie. simplefb) */ diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index e22ee536677e..7a3345b7b6d1 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h @@ -18,7 +18,6 @@ struct sun4i_drv { struct sun4i_backend *backend; - struct sun4i_crtc *crtc; struct sun4i_tcon *tcon; struct drm_plane *primary; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index ea2906f87cb9..3f3eb3f0b209 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -290,8 +290,7 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) { struct sun4i_tcon *tcon = private; struct drm_device *drm = tcon->drm; - struct sun4i_drv *drv = drm->dev_private; - struct sun4i_crtc *scrtc = drv->crtc; + struct sun4i_crtc *scrtc = tcon->crtc; unsigned int status; regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); @@ -524,6 +523,13 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_clocks; } + tcon->crtc = sun4i_crtc_init(drm); + if (IS_ERR(tcon->crtc)) { + dev_err(dev, "Couldn't create our CRTC\n"); + ret = PTR_ERR(tcon->crtc); + goto err_free_clocks; + } + ret = sun4i_rgb_init(drm); if (ret < 0) goto err_free_clocks; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index 166064bafe2e..f636343a935d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -169,6 +169,9 @@ struct sun4i_tcon { /* Platform adjustments */ const struct sun4i_tcon_quirks *quirks; + + /* Associated crtc */ + struct sun4i_crtc *crtc; }; struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); -- cgit v1.2.3 From dcd215801b0279f0a021516526cf7c0b67d5302e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:38 +0800 Subject: drm/sun4i: Drop primary layer pointer from sun4i_drv The current layer init code keeps a pointer to the primary plane layer in sun4i_drv. When we eventually support multiple display pipelines, this would force us to keep track of primary planes for all crtcs. And these pointers only get used at bind time. Instead, have the crtc init code iterate through the returned layers to find the primary and cursor layers. And drop the pointer from the sun4i_drv structure. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 25 +++++++++++++++++++++---- drivers/gpu/drm/sun4i/sun4i_drv.h | 1 - drivers/gpu/drm/sun4i/sun4i_layer.c | 3 --- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index bcc1c9533d67..81dcd5eee003 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -143,7 +143,8 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) { struct sun4i_drv *drv = drm->dev_private; struct sun4i_crtc *scrtc; - int ret; + struct drm_plane *primary = NULL, *cursor = NULL; + int ret, i; scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); if (!scrtc) @@ -154,12 +155,28 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) scrtc->layers = sun4i_layers_init(drm); if (IS_ERR(scrtc->layers)) { dev_err(drm->dev, "Couldn't create the planes\n"); - return ERR_CAST(scrtc->layers); + 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]; + + switch (layer->plane.type) { + case DRM_PLANE_TYPE_PRIMARY: + primary = &layer->plane; + break; + case DRM_PLANE_TYPE_CURSOR: + cursor = &layer->plane; + break; + default: + break; + } } ret = drm_crtc_init_with_planes(drm, &scrtc->crtc, - drv->primary, - NULL, + primary, + cursor, &sun4i_crtc_funcs, NULL); if (ret) { diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h index 7a3345b7b6d1..5df50126ff52 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.h +++ b/drivers/gpu/drm/sun4i/sun4i_drv.h @@ -20,7 +20,6 @@ struct sun4i_drv { struct sun4i_backend *backend; struct sun4i_tcon *tcon; - struct drm_plane *primary; struct drm_fbdev_cma *fbdev; }; diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 0b703fb02656..9c0baee25fae 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -127,9 +127,6 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, &sun4i_backend_layer_helper_funcs); layer->drv = drv; - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - drv->primary = &layer->plane; - return layer; } -- cgit v1.2.3 From a5154a4d01d7958788366894ceeddd9e1aab5b13 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:39 +0800 Subject: drm/sun4i: Drop hardcoded .possible_crtcs values from layers To support multiple display pipelines, we would have multiple crtcs, with one or more planes bound to them. Obviously having hardcoded values for the drm_plane .possible_crtcs field is not going to work. For primary and cursor planes, the value is set by drm_crtc_init_with_planes. We just need to set it for overlay planes. We also fix the value set for the RGB encoder, by referencing the crtc set in sun4i_drv. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 9 +++++++++ drivers/gpu/drm/sun4i/sun4i_layer.c | 3 ++- drivers/gpu/drm/sun4i/sun4i_rgb.c | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 81dcd5eee003..9d6fd2f40cf4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -190,5 +190,14 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) scrtc->crtc.port = of_graph_get_port_by_id(drv->tcon->dev->of_node, 1); + /* Set possible_crtcs to this crtc for overlay planes */ + for (i = 0; scrtc->layers[i]; i++) { + uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc)); + struct sun4i_layer *layer = scrtc->layers[i]; + + if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY) + layer->plane.possible_crtcs = possible_crtcs; + } + return scrtc; } diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 9c0baee25fae..431e13362b62 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -114,7 +114,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, if (!layer) return ERR_PTR(-ENOMEM); - ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), + /* possible crtcs are set later */ + ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun4i_backend_layer_funcs, plane->formats, plane->nformats, plane->type, NULL); diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 757208f51731..c4865bf1b392 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -17,6 +17,7 @@ #include #include +#include "sun4i_crtc.h" #include "sun4i_drv.h" #include "sun4i_tcon.h" #include "sun4i_rgb.h" @@ -238,7 +239,7 @@ int sun4i_rgb_init(struct drm_device *drm) } /* The RGB encoder can only work with the TCON channel 0 */ - rgb->encoder.possible_crtcs = BIT(0); + rgb->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc)); if (!IS_ERR(tcon->panel)) { drm_connector_helper_add(&rgb->connector, -- cgit v1.2.3 From 78428d672c2ecdb54c72ae427071c239650cb6c7 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:40 +0800 Subject: drm/sun4i: tv: Switch to drm_of_find_possible_crtcs Now that the crtcs have their .port field set properly, we can use drm_of_find_possible_crtcs to find the connected crtcs, instead of hardcoding the first crtc as usable. The new code also defers binding when the upstream crtc hasn't been registered yet. This makes it easier to support multiple tcons/crtcs. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index c6f47222e8fc..32ed5fdf0c4d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "sun4i_backend.h" @@ -623,7 +624,12 @@ static int sun4i_tv_bind(struct device *dev, struct device *master, goto err_disable_clk; } - tv->encoder.possible_crtcs = BIT(0); + tv->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm, + dev->of_node); + if (!tv->encoder.possible_crtcs) { + ret = -EPROBE_DEFER; + goto err_disable_clk; + } drm_connector_helper_add(&tv->connector, &sun4i_tv_comp_connector_helper_funcs); -- cgit v1.2.3 From b9c8506cb88b974522133d7eccc3d924ed29cf23 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:41 +0800 Subject: drm/sun4i: rgb: Pass tcon pointer when initializing RGB encoder The RGB encoder represents channel 0 of the TCON. Instead of fetching the pointer to its TCON from the main sun4i_drv structure, pass it in as part of the init call, save it, and use it directly in the encoder and connector callbacks. We can also drop the otherwise unused sun4i_drv pointer. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_rgb.c | 27 +++++++++------------------ drivers/gpu/drm/sun4i/sun4i_rgb.h | 2 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +- 3 files changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index c4865bf1b392..1147451eb993 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -18,7 +18,6 @@ #include #include "sun4i_crtc.h" -#include "sun4i_drv.h" #include "sun4i_tcon.h" #include "sun4i_rgb.h" @@ -26,7 +25,7 @@ struct sun4i_rgb { struct drm_connector connector; struct drm_encoder encoder; - struct sun4i_drv *drv; + struct sun4i_tcon *tcon; }; static inline struct sun4i_rgb * @@ -47,8 +46,7 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector) { struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; return drm_panel_get_modes(tcon->panel); } @@ -57,8 +55,7 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; u32 hsync = mode->hsync_end - mode->hsync_start; u32 vsync = mode->vsync_end - mode->vsync_start; unsigned long rate = mode->clock * 1000; @@ -115,8 +112,7 @@ static void sun4i_rgb_connector_destroy(struct drm_connector *connector) { struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; drm_panel_detach(tcon->panel); drm_connector_cleanup(connector); @@ -141,8 +137,7 @@ static int sun4i_rgb_atomic_check(struct drm_encoder *encoder, static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) { struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; DRM_DEBUG_DRIVER("Enabling RGB output\n"); @@ -158,8 +153,7 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) { struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; DRM_DEBUG_DRIVER("Disabling RGB output\n"); @@ -177,8 +171,7 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder); - struct sun4i_drv *drv = rgb->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_tcon *tcon = rgb->tcon; sun4i_tcon0_mode_set(tcon, mode); @@ -204,10 +197,8 @@ static struct drm_encoder_funcs sun4i_rgb_enc_funcs = { .destroy = sun4i_rgb_enc_destroy, }; -int sun4i_rgb_init(struct drm_device *drm) +int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon) { - struct sun4i_drv *drv = drm->dev_private; - struct sun4i_tcon *tcon = drv->tcon; struct drm_encoder *encoder; struct drm_bridge *bridge; struct sun4i_rgb *rgb; @@ -216,7 +207,7 @@ int sun4i_rgb_init(struct drm_device *drm) rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL); if (!rgb) return -ENOMEM; - rgb->drv = drv; + rgb->tcon = tcon; encoder = &rgb->encoder; tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node); diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.h b/drivers/gpu/drm/sun4i/sun4i_rgb.h index 7c4da4c8acdd..40c18f4a6c7e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.h +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.h @@ -13,6 +13,6 @@ #ifndef _SUN4I_RGB_H_ #define _SUN4I_RGB_H_ -int sun4i_rgb_init(struct drm_device *drm); +int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon); #endif /* _SUN4I_RGB_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 3f3eb3f0b209..505520baa585 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -530,7 +530,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_clocks; } - ret = sun4i_rgb_init(drm); + ret = sun4i_rgb_init(drm, tcon); if (ret < 0) goto err_free_clocks; -- cgit v1.2.3 From ace6c095ba3b113b5b41e30c1e6be1ca024ccef8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:42 +0800 Subject: drm/sun4i: Add backend pointer to sun4i_layer sun4i_layer only controls the backend hardware block of the display pipeline. Instead of getting a pointer to the underlying backend through the drm_device structure, leave one in itself. Also drop the drm_device pointer, since it is no longer needed. The next step forward would be to pass the pointer in through sun4i_layers_init as a parameter. This would make it easier to support multiple display pipelines layer on. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_layer.c | 8 +++----- drivers/gpu/drm/sun4i/sun4i_layer.h | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 431e13362b62..6feaf85a5942 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -36,8 +36,7 @@ static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { struct sun4i_layer *layer = plane_to_sun4i_layer(plane); - struct sun4i_drv *drv = layer->drv; - struct sun4i_backend *backend = drv->backend; + struct sun4i_backend *backend = layer->backend; sun4i_backend_layer_enable(backend, layer->id, false); } @@ -46,8 +45,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct sun4i_layer *layer = plane_to_sun4i_layer(plane); - struct sun4i_drv *drv = layer->drv; - struct sun4i_backend *backend = drv->backend; + struct sun4i_backend *backend = layer->backend; sun4i_backend_update_layer_coord(backend, layer->id, plane); sun4i_backend_update_layer_formats(backend, layer->id, plane); @@ -126,7 +124,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, drm_plane_helper_add(&layer->plane, &sun4i_backend_layer_helper_funcs); - layer->drv = drv; + layer->backend = drv->backend; return layer; } diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index a2f65d7a3f4e..a97e376bae17 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h @@ -16,6 +16,7 @@ struct sun4i_layer { struct drm_plane plane; struct sun4i_drv *drv; + struct sun4i_backend *backend; int id; }; -- cgit v1.2.3 From 3c64fb37475d7eb99aa01b46af1edb3863261640 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 23 Feb 2017 16:05:43 +0800 Subject: drm/sun4i: Add backend and tcon pointers to sun4i_crtc sun4i_crtc controls the backend and tcon hardware blocks of the display pipeline. Instead of doing so through the master drm structure, leave pointers to the corresponding backend and tcon in itself. Also drop the drm_device pointer, since it is no longer needed. The next step forward would be to pass the pointers in through sun4i_crtc_init as parameters. This would make it easier to support multiple display pipelines layer on. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 18 +++++++----------- drivers/gpu/drm/sun4i/sun4i_crtc.h | 3 ++- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 9d6fd2f40cf4..7bbcedff9f07 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -52,12 +52,11 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); - struct sun4i_drv *drv = scrtc->drv; struct drm_pending_vblank_event *event = crtc->state->event; DRM_DEBUG_DRIVER("Committing plane changes\n"); - sun4i_backend_commit(drv->backend); + sun4i_backend_commit(scrtc->backend); if (event) { crtc->state->event = NULL; @@ -74,11 +73,10 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc, static void sun4i_crtc_disable(struct drm_crtc *crtc) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); - struct sun4i_drv *drv = scrtc->drv; DRM_DEBUG_DRIVER("Disabling the CRTC\n"); - sun4i_tcon_disable(drv->tcon); + sun4i_tcon_disable(scrtc->tcon); if (crtc->state->event && !crtc->state->active) { spin_lock_irq(&crtc->dev->event_lock); @@ -92,11 +90,10 @@ static void sun4i_crtc_disable(struct drm_crtc *crtc) static void sun4i_crtc_enable(struct drm_crtc *crtc) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); - struct sun4i_drv *drv = scrtc->drv; DRM_DEBUG_DRIVER("Enabling the CRTC\n"); - sun4i_tcon_enable(drv->tcon); + sun4i_tcon_enable(scrtc->tcon); } static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { @@ -109,11 +106,10 @@ static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); - struct sun4i_drv *drv = scrtc->drv; DRM_DEBUG_DRIVER("Enabling VBLANK on crtc %p\n", crtc); - sun4i_tcon_enable_vblank(drv->tcon, true); + sun4i_tcon_enable_vblank(scrtc->tcon, true); return 0; } @@ -121,11 +117,10 @@ static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc) static void sun4i_crtc_disable_vblank(struct drm_crtc *crtc) { struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); - struct sun4i_drv *drv = scrtc->drv; DRM_DEBUG_DRIVER("Disabling VBLANK on crtc %p\n", crtc); - sun4i_tcon_enable_vblank(drv->tcon, false); + sun4i_tcon_enable_vblank(scrtc->tcon, false); } static const struct drm_crtc_funcs sun4i_crtc_funcs = { @@ -149,7 +144,8 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); if (!scrtc) return ERR_PTR(-ENOMEM); - scrtc->drv = drv; + scrtc->backend = drv->backend; + scrtc->tcon = drv->tcon; /* Create our layers */ scrtc->layers = sun4i_layers_init(drm); diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h index 0a888f73c983..cd0e633cce3a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h @@ -17,7 +17,8 @@ struct sun4i_crtc { struct drm_crtc crtc; struct drm_pending_vblank_event *event; - struct sun4i_drv *drv; + struct sun4i_backend *backend; + struct sun4i_tcon *tcon; struct sun4i_layer **layers; }; -- cgit v1.2.3 From 596afb6f051382aa0cb067e4d6b3080e51531ddc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 9 Feb 2017 17:39:18 +0100 Subject: drm/sun4i: Grab reserved memory region Allow to provide an optional memory region to allocate from for our DRM driver. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_drv.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 1de15cd1b102..767bbadcc85d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -101,10 +102,16 @@ static int sun4i_drv_bind(struct device *dev) } drm->dev_private = drv; + ret = of_reserved_mem_device_init(dev); + if (ret && ret != -ENODEV) { + dev_err(drm->dev, "Couldn't claim our memory region\n"); + goto free_drm; + } + /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, 1); if (ret) - goto free_drm; + goto free_mem_region; drm_mode_config_init(drm); @@ -142,6 +149,8 @@ finish_poll: cleanup_mode_config: drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); +free_mem_region: + of_reserved_mem_device_release(dev); free_drm: drm_dev_unref(drm); return ret; @@ -156,6 +165,7 @@ static void sun4i_drv_unbind(struct device *dev) sun4i_framebuffer_free(drm); drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); + of_reserved_mem_device_release(dev); drm_dev_unref(drm); } -- cgit v1.2.3 From 4c7f16d14a33a9cfb4af9cb780d8a73bcca64a92 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:24 +0800 Subject: drm/sun4i: Fix TCON clock and regmap initialization sequence The TCON driver calls sun4i_tcon_init_regmap and sun4i_tcon_init_clocks in its bind function. The former creates a regmap and writes to several register to clear its configuration to a known default. The latter initializes various clocks. This includes enabling the bus clock for register access and creating the dotclock. In order for the first step's writes to work, the bus clock must be enabled which is done in the second step. but the dotclock's ops use the regmap created in the first step. Rearrange the function calls such that the clocks are initialized before the regmap, and split out the dot clock creation to after the regmap is initialized. Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support") Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 505520baa585..ee51d7e77a6a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -335,12 +335,11 @@ static int sun4i_tcon_init_clocks(struct device *dev, } } - return sun4i_dclk_create(dev, tcon); + return 0; } static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon) { - sun4i_dclk_free(tcon); clk_disable_unprepare(tcon->clk); } @@ -505,22 +504,28 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, return ret; } + ret = sun4i_tcon_init_clocks(dev, tcon); + if (ret) { + dev_err(dev, "Couldn't init our TCON clocks\n"); + goto err_assert_reset; + } + ret = sun4i_tcon_init_regmap(dev, tcon); if (ret) { dev_err(dev, "Couldn't init our TCON regmap\n"); - goto err_assert_reset; + goto err_free_clocks; } - ret = sun4i_tcon_init_clocks(dev, tcon); + ret = sun4i_dclk_create(dev, tcon); if (ret) { - dev_err(dev, "Couldn't init our TCON clocks\n"); - goto err_assert_reset; + dev_err(dev, "Couldn't create our TCON dot clock\n"); + goto err_free_clocks; } ret = sun4i_tcon_init_irq(dev, tcon); if (ret) { dev_err(dev, "Couldn't init our TCON interrupts\n"); - goto err_free_clocks; + goto err_free_dotclock; } tcon->crtc = sun4i_crtc_init(drm); @@ -536,6 +541,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, return 0; +err_free_dotclock: + sun4i_dclk_free(tcon); err_free_clocks: sun4i_tcon_free_clocks(tcon); err_assert_reset: @@ -548,6 +555,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, { struct sun4i_tcon *tcon = dev_get_drvdata(dev); + sun4i_dclk_free(tcon); sun4i_tcon_free_clocks(tcon); } -- cgit v1.2.3 From 23a1cb11d90d8e66bfe3a506cfaa88486bbcfc61 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:25 +0800 Subject: drm/sun4i: Fix tcon channel 0 comment about backporch = backporch + hsync The backporch programmed into the tcon registers is actually the backporch + hsync length from the display timings, as indicated in the interface timing diagrams found in the user manual of the A31 and A33 SoCs. The comments for channel 0 mistakenly describe the discrepancy as TCON backporch = frontporch + hsync. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index ee51d7e77a6a..c52c482c8fd0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -143,7 +143,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, /* * This is called a backporch in the register documentation, - * but it really is the front porch + hsync + * but it really is the back porch + hsync */ bp = mode->crtc_htotal - mode->crtc_hsync_start; DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", @@ -156,7 +156,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon, /* * This is called a backporch in the register documentation, - * but it really is the front porch + hsync + * but it really is the back porch + hsync */ bp = mode->crtc_vtotal - mode->crtc_vsync_start; DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", -- cgit v1.2.3 From e4cdcb7cce2949fb36a04b9848f856a107a0a2da Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:26 +0800 Subject: drm/sun4i: Use embedded tcon pointer to get the tcon's output port node A pointer to the underlying tcon of the crtc was added to the sun4i_crtc structure in "drm/sun4i: Add backend and tcon pointers to sun4i_crtc". However the crtc init function was still using the copy from sun4i_drv to set drm_crtc.port. This was an oversight when the patches were reordered. Switch to using the embedded tcon pointer to get the tcon's ouptut port and assign it to drm_crtc.port. This makes it possible to remove the usage of sun4i_drv completely in subsequent patches. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 7bbcedff9f07..5323e3485988 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -183,7 +183,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs); /* Set crtc.port to output port node of the tcon */ - scrtc->crtc.port = of_graph_get_port_by_id(drv->tcon->dev->of_node, + scrtc->crtc.port = of_graph_get_port_by_id(scrtc->tcon->dev->of_node, 1); /* Set possible_crtcs to this crtc for overlay planes */ -- cgit v1.2.3 From 279156a33c33b385a78c1266ddf6ebc2d473193d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:27 +0800 Subject: drm/sun4i: tv: Get tcon and backend pointers from associated crtc The drm_encoder structure provides us with a pointer to the crtc currently tied to the encoder. Subsequently we can extract the tcon and backend pointers from our crtc structure, instead of getting it directly from the sun4i_drv structure. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_tv.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 32ed5fdf0c4d..49c49431a053 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -23,6 +23,7 @@ #include #include "sun4i_backend.h" +#include "sun4i_crtc.h" #include "sun4i_drv.h" #include "sun4i_tcon.h" @@ -350,8 +351,9 @@ static int sun4i_tv_atomic_check(struct drm_encoder *encoder, static void sun4i_tv_disable(struct drm_encoder *encoder) { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); - struct sun4i_drv *drv = tv->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); + struct sun4i_tcon *tcon = crtc->tcon; + struct sun4i_backend *backend = crtc->backend; DRM_DEBUG_DRIVER("Disabling the TV Output\n"); @@ -360,18 +362,19 @@ static void sun4i_tv_disable(struct drm_encoder *encoder) regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, SUN4I_TVE_EN_ENABLE, 0); - sun4i_backend_disable_color_correction(drv->backend); + sun4i_backend_disable_color_correction(backend); } static void sun4i_tv_enable(struct drm_encoder *encoder) { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); - struct sun4i_drv *drv = tv->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); + struct sun4i_tcon *tcon = crtc->tcon; + struct sun4i_backend *backend = crtc->backend; DRM_DEBUG_DRIVER("Enabling the TV Output\n"); - sun4i_backend_apply_color_correction(drv->backend); + sun4i_backend_apply_color_correction(backend); regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, SUN4I_TVE_EN_ENABLE, @@ -385,8 +388,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); - struct sun4i_drv *drv = tv->drv; - struct sun4i_tcon *tcon = drv->tcon; + struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); + struct sun4i_tcon *tcon = crtc->tcon; const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); sun4i_tcon1_mode_set(tcon, mode); -- cgit v1.2.3 From 18c3b300837b864e875d23f22eef5b7acefeccf1 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:28 +0800 Subject: drm/sun4i: Pass pointers for associated backend and tcon into crtc init sun4i_crtc controls the backend and tcon hardware blocks of the display pipeline. Pass pointers to the underlying devices into the crtc init function, instead of trying to fetch them from the drm_device structure. This avoids the headache of trying to figure out which devices the crtc is actually associated with. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 9 +++++---- drivers/gpu/drm/sun4i/sun4i_crtc.h | 4 +++- drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 5323e3485988..221e6d5ee970 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -134,9 +134,10 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = { .disable_vblank = sun4i_crtc_disable_vblank, }; -struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) +struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, + struct sun4i_backend *backend, + struct sun4i_tcon *tcon) { - struct sun4i_drv *drv = drm->dev_private; struct sun4i_crtc *scrtc; struct drm_plane *primary = NULL, *cursor = NULL; int ret, i; @@ -144,8 +145,8 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm) scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL); if (!scrtc) return ERR_PTR(-ENOMEM); - scrtc->backend = drv->backend; - scrtc->tcon = drv->tcon; + scrtc->backend = backend; + scrtc->tcon = tcon; /* Create our layers */ scrtc->layers = sun4i_layers_init(drm); diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h index cd0e633cce3a..230cb8f0d601 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h @@ -27,6 +27,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc) return container_of(crtc, struct sun4i_crtc, crtc); } -struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm); +struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, + struct sun4i_backend *backend, + struct sun4i_tcon *tcon); #endif /* _SUN4I_CRTC_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index c52c482c8fd0..3ced0b1cef6e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, goto err_free_dotclock; } - tcon->crtc = sun4i_crtc_init(drm); + tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon); if (IS_ERR(tcon->crtc)) { dev_err(dev, "Couldn't create our CRTC\n"); ret = PTR_ERR(tcon->crtc); -- cgit v1.2.3 From a0a68fb6872f545acd49035ea17c52a9f30d07dc Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 9 Mar 2017 18:05:29 +0800 Subject: drm/sun4i: Pass pointer for underlying backend into layer init sun4i_layer only controls the backend hardware block of the display pipeline. Pass pointers to the underlying backend in the layer init function, instead of trying to fetch it from the drm_device structure. This avoids the headache of trying to figure out which device the layers actually belong to. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/gpu/drm/sun4i/sun4i_crtc.c | 2 +- drivers/gpu/drm/sun4i/sun4i_layer.c | 13 ++++++------- drivers/gpu/drm/sun4i/sun4i_layer.h | 3 ++- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 221e6d5ee970..3c876c3a356a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -149,7 +149,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, scrtc->tcon = tcon; /* Create our layers */ - scrtc->layers = sun4i_layers_init(drm); + scrtc->layers = sun4i_layers_init(drm, scrtc->backend); if (IS_ERR(scrtc->layers)) { dev_err(drm->dev, "Couldn't create the planes\n"); return NULL; diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 6feaf85a5942..f26bde5b9117 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -16,7 +16,6 @@ #include #include "sun4i_backend.h" -#include "sun4i_drv.h" #include "sun4i_layer.h" struct sun4i_plane_desc { @@ -102,9 +101,9 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = { }; static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, + struct sun4i_backend *backend, const struct sun4i_plane_desc *plane) { - struct sun4i_drv *drv = drm->dev_private; struct sun4i_layer *layer; int ret; @@ -124,14 +123,14 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, drm_plane_helper_add(&layer->plane, &sun4i_backend_layer_helper_funcs); - layer->backend = drv->backend; + layer->backend = backend; return layer; } -struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) +struct sun4i_layer **sun4i_layers_init(struct drm_device *drm, + struct sun4i_backend *backend) { - struct sun4i_drv *drv = drm->dev_private; struct sun4i_layer **layers; int i; @@ -165,7 +164,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; struct sun4i_layer *layer; - layer = sun4i_layer_init_one(drm, plane); + layer = sun4i_layer_init_one(drm, backend, plane); if (IS_ERR(layer)) { dev_err(drm->dev, "Couldn't initialize %s plane\n", i ? "overlay" : "primary"); @@ -174,7 +173,7 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", i ? "overlay" : "primary", plane->pipe); - regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), + regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h index a97e376bae17..4be1f0919df2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.h +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h @@ -26,6 +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_layer **sun4i_layers_init(struct drm_device *drm, + struct sun4i_backend *backend); #endif /* _SUN4I_LAYER_H_ */ -- cgit v1.2.3