From b5ceff202c4b4e81052b83853f33832a60cefae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Mar 2015 14:35:20 +0200 Subject: [PATCH 01/15] drm/atomic: Constify a bunch of functions pointer structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the helper function pointer structs const to make it clear they should not be modified. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index a7458813af2b..5bcb4baeb9cb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -151,7 +151,7 @@ steal_encoder(struct drm_atomic_state *state, static int update_connector_routing(struct drm_atomic_state *state, int conn_idx) { - struct drm_connector_helper_funcs *funcs; + const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; struct drm_crtc *encoder_crtc; struct drm_connector *connector; @@ -264,7 +264,7 @@ mode_fixup(struct drm_atomic_state *state) } for (i = 0; i < state->num_connector; i++) { - struct drm_encoder_helper_funcs *funcs; + const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; conn_state = state->connector_states[i]; @@ -317,7 +317,7 @@ mode_fixup(struct drm_atomic_state *state) } for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc; crtc_state = state->crtc_states[i]; @@ -481,7 +481,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, int i, ret = 0; for (i = 0; i < nplanes; i++) { - struct drm_plane_helper_funcs *funcs; + const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; @@ -504,7 +504,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc = state->crtcs[i]; if (!crtc) @@ -571,9 +571,9 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) int i; for (i = 0; i < old_state->num_connector; i++) { + const struct drm_encoder_helper_funcs *funcs; struct drm_connector_state *old_conn_state; struct drm_connector *connector; - struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; struct drm_crtc_state *old_crtc_state; @@ -623,7 +623,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) } for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -713,7 +713,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) int i; for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc; crtc = old_state->crtcs[i]; @@ -732,9 +732,9 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) } for (i = 0; i < old_state->num_connector; i++) { + const struct drm_encoder_helper_funcs *funcs; struct drm_connector *connector; struct drm_crtc_state *new_crtc_state; - struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; struct drm_display_mode *mode, *adjusted_mode; @@ -812,7 +812,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, int i; for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc; crtc = old_state->crtcs[i]; @@ -838,8 +838,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, } for (i = 0; i < old_state->num_connector; i++) { + const struct drm_encoder_helper_funcs *funcs; struct drm_connector *connector; - struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; connector = old_state->connectors[i]; @@ -1114,7 +1114,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, int ret, i; for (i = 0; i < nplanes; i++) { - struct drm_plane_helper_funcs *funcs; + const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; struct drm_framebuffer *fb; @@ -1137,7 +1137,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, fail: for (i--; i >= 0; i--) { - struct drm_plane_helper_funcs *funcs; + const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = state->planes[i]; struct drm_plane_state *plane_state = state->plane_states[i]; struct drm_framebuffer *fb; @@ -1179,7 +1179,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, int i; for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc = old_state->crtcs[i]; if (!crtc) @@ -1194,7 +1194,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, } for (i = 0; i < nplanes; i++) { - struct drm_plane_helper_funcs *funcs; + const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = old_state->planes[i]; struct drm_plane_state *old_plane_state; @@ -1219,7 +1219,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, } for (i = 0; i < ncrtcs; i++) { - struct drm_crtc_helper_funcs *funcs; + const struct drm_crtc_helper_funcs *funcs; struct drm_crtc *crtc = old_state->crtcs[i]; if (!crtc) @@ -1254,7 +1254,7 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, int i; for (i = 0; i < nplanes; i++) { - struct drm_plane_helper_funcs *funcs; + const struct drm_plane_helper_funcs *funcs; struct drm_plane *plane = old_state->planes[i]; struct drm_plane_state *plane_state = old_state->plane_states[i]; struct drm_framebuffer *old_fb; From 967667fd6d96a16fd4a216251eee112a214207ec Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 11 Mar 2015 08:35:47 +0100 Subject: [PATCH 02/15] drm/plane-helper: Fixup mismerge I somehow manage to screw up applying Laurent's patch in eca93e28c256: "drm: Check in setcrtc if the primary plane supports the fb pixel format". It was a conflict with commit 3461b30b3e171e16498f3d7bc59ab703aec475c8 Author: Daniel Vetter Date: Thu Mar 5 10:32:44 2015 +0100 drm/plane-helper: unexport drm_primary_helper_create_plane and I just didn't check that the solution from wiggle made sense. Cc: Dan Carpenter Cc: laurent.pinchart@ideasonboard.com Reported-by: Dan Carpenter Acked-by: laurent.pinchart@ideasonboard.com Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_plane_helper.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index b62b03635050..33807e0adac7 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -353,13 +353,14 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev) if (primary == NULL) { DRM_DEBUG_KMS("Failed to allocate primary plane\n"); return NULL; - /* - * Remove the format_default field from drm_plane when dropping - * this helper. - */ - primary->format_default = true; } + /* + * Remove the format_default field from drm_plane when dropping + * this helper. + */ + primary->format_default = true; + /* possible_crtc's will be filled in later by crtc_init */ ret = drm_universal_plane_init(dev, primary, 0, &drm_primary_helper_funcs, From 1d002fa720738bcd0bddb9178e9ea0773288e1dd Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Tue, 10 Feb 2015 18:38:08 +0000 Subject: [PATCH 03/15] drm/dp: Use large transactions for I2C over AUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older DisplayPort to DVI-D Dual Link adapters designed by Bizlink have bugs in their I2C over AUX implementation (fixed in newer revisions). They work fine with Windows, but fail with Linux. It turns out that they cannot keep an I2C transaction open unless the previous read was 16 bytes; shorter reads can only be followed by a zero byte transfer ending the I2C transaction. Copy Windows's behaviour, and read 16 bytes at a time. If we get a short reply, assume that there's a hardware bottleneck, and shrink our read size to match. For this purpose, use the algorithm in the DisplayPort 1.2 spec, in the hopes that it'll be closest to what Windows does. Also provide an unsafe module parameter for testing smaller transfer sizes, in case there are sinks out there that cannot work with Windows. Note also that despite the previous comment in drm_dp_i2c_xfer, this speeds up native DP EDID reads; Ville Syrjälä found the following changes in his testing: Device under test: old -> with this patch DP->DVI (OUI 001cf8): 40ms -> 35ms DP->VGA (OUI 0022b9): 45ms -> 38ms Zotac DP->2xHDMI: 25ms -> 4ms Asus PB278 monitor: 22ms -> 3ms A back of the envelope calculation shows that peak theoretical transfer rate for 1 byte reads is around 60 kbit/s; with 16 byte reads, this increases to around 500 kbit/s, which explains the increase in speed. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55228 Tested-by: Aidan Marks (v3) Signed-off-by: Simon Farnsworth Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_helper.c | 76 +++++++++++++++++++++++++-------- include/drm/drm_dp_helper.h | 5 +++ 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f1283878ff6d..d5368ea56a0f 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -427,11 +427,13 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) * retrying the transaction as appropriate. It is assumed that the * aux->transfer function does not modify anything in the msg other than the * reply field. + * + * Returns bytes transferred on success, or a negative error code on failure. */ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { unsigned int retry; - int err; + int ret; /* * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device @@ -440,14 +442,14 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) */ for (retry = 0; retry < 7; retry++) { mutex_lock(&aux->hw_mutex); - err = aux->transfer(aux, msg); + ret = aux->transfer(aux, msg); mutex_unlock(&aux->hw_mutex); - if (err < 0) { - if (err == -EBUSY) + if (ret < 0) { + if (ret == -EBUSY) continue; - DRM_DEBUG_KMS("transaction failed: %d\n", err); - return err; + DRM_DEBUG_KMS("transaction failed: %d\n", ret); + return ret; } @@ -488,9 +490,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) * Both native ACK and I2C ACK replies received. We * can assume the transfer was successful. */ - if (err < msg->size) - return -EPROTO; - return 0; + return ret; case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("I2C nack\n"); @@ -513,14 +513,55 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return -EREMOTEIO; } +/* + * Keep retrying drm_dp_i2c_do_msg until all data has been transferred. + * + * Returns an error code on failure, or a recommended transfer size on success. + */ +static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *orig_msg) +{ + int err, ret = orig_msg->size; + struct drm_dp_aux_msg msg = *orig_msg; + + while (msg.size > 0) { + err = drm_dp_i2c_do_msg(aux, &msg); + if (err <= 0) + return err == 0 ? -EPROTO : err; + + if (err < msg.size && err < ret) { + DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n", + msg.size, err); + ret = err; + } + + msg.size -= err; + msg.buffer += err; + } + + return ret; +} + +/* + * Bizlink designed DP->DVI-D Dual Link adapters require the I2C over AUX + * packets to be as large as possible. If not, the I2C transactions never + * succeed. Hence the default is maximum. + */ +static int dp_aux_i2c_transfer_size __read_mostly = DP_AUX_MAX_PAYLOAD_BYTES; +module_param_unsafe(dp_aux_i2c_transfer_size, int, 0644); +MODULE_PARM_DESC(dp_aux_i2c_transfer_size, + "Number of bytes to transfer in a single I2C over DP AUX CH message, (1-16, default 16)"); + static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct drm_dp_aux *aux = adapter->algo_data; unsigned int i, j; + unsigned transfer_size; struct drm_dp_aux_msg msg; int err = 0; + dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES); + memset(&msg, 0, sizeof(msg)); for (i = 0; i < num; i++) { @@ -538,20 +579,19 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, err = drm_dp_i2c_do_msg(aux, &msg); if (err < 0) break; - /* - * Many hardware implementations support FIFOs larger than a - * single byte, but it has been empirically determined that - * transferring data in larger chunks can actually lead to - * decreased performance. Therefore each message is simply - * transferred byte-by-byte. + /* We want each transaction to be as large as possible, but + * we'll go to smaller sizes if the hardware gives us a + * short reply. */ - for (j = 0; j < msgs[i].len; j++) { + transfer_size = dp_aux_i2c_transfer_size; + for (j = 0; j < msgs[i].len; j += msg.size) { msg.buffer = msgs[i].buf + j; - msg.size = 1; + msg.size = min(transfer_size, msgs[i].len - j); - err = drm_dp_i2c_do_msg(aux, &msg); + err = drm_dp_i2c_drain_msg(aux, &msg); if (err < 0) break; + transfer_size = err; } if (err < 0) break; diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c5fdc2d3ca97..523f04c90dea 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -42,6 +42,8 @@ * 1.2 formally includes both eDP and DPI definitions. */ +#define DP_AUX_MAX_PAYLOAD_BYTES 16 + #define DP_AUX_I2C_WRITE 0x0 #define DP_AUX_I2C_READ 0x1 #define DP_AUX_I2C_STATUS 0x2 @@ -680,6 +682,9 @@ struct drm_dp_aux_msg { * transactions. The drm_dp_aux_register_i2c_bus() function registers an * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. + * The I2C adapter uses long transfers by default; if a partial response is + * received, the adapter will drop down to the size given by the partial + * response for this transaction only. * * Note that the aux helper code assumes that the .transfer() function * only modifies the reply field of the drm_dp_aux_msg structure. The From b7b5ee593118f9dc884fc21237f51b9f599cc432 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:08 -0400 Subject: [PATCH 04/15] drm/fb: document drm_fb_helper_surface_size There has been some confusion about this struct. Lack of documentation probably didn't help. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- include/drm/drm_fb_helper.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 21b944c456f6..0dfd94def593 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -44,6 +44,25 @@ struct drm_fb_helper_crtc { int x, y; }; +/** + * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size + * @fb_width: fbdev width + * @fb_height: fbdev height + * @surface_width: scanout buffer width + * @surface_height: scanout buffer height + * @surface_bpp: scanout buffer bpp + * @surface_depth: scanout buffer depth + * + * Note that the scanout surface width/height may be larger than the fbdev + * width/height. In case of multiple displays, the scanout surface is sized + * according to the largest width/height (so it is large enough for all CRTCs + * to scanout). But the fbdev width/height is sized to the minimum width/ + * height of all the displays. This ensures that fbcon fits on the smallest + * of the attached displays. + * + * So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, + * rather than the surface size. + */ struct drm_fb_helper_surface_size { u32 fb_width; u32 fb_height; From 08855fae10f088d83527bdf108199d3e35be503b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:09 -0400 Subject: [PATCH 05/15] drm/atomic: minor kerneldoc typo fix Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..7b5c661b37d8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -915,7 +915,7 @@ struct drm_bridge { }; /** - * struct struct drm_atomic_state - the global state object for atomic updates + * struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics From 8d76612bd49a73dca018e6fe5c790c943dbde98f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:10 -0400 Subject: [PATCH 06/15] drm/cma: use correct fb width/height What is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, rather than the surface size. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index cc0ae047ed3b..5c1aca443e54 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -304,7 +304,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, } drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); offset = fbi->var.xoffset * bytes_per_pixel; offset += fbi->var.yoffset * fb->pitches[0]; From ecbf1d5afe993f05f0c513a4b99256589ab5c810 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:11 -0400 Subject: [PATCH 07/15] drm/exynos: use correct fb width/height What is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, rather than the surface size. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 84f8dfe1c5ec..e71e331f0188 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -76,6 +76,7 @@ static struct fb_ops exynos_drm_fb_ops = { }; static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes, struct drm_framebuffer *fb) { struct fb_info *fbi = helper->fbdev; @@ -85,7 +86,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, unsigned long offset; drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); /* RGB formats use only one buffer */ buffer = exynos_drm_fb_buffer(fb, 0); @@ -189,7 +190,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, goto err_destroy_framebuffer; } - ret = exynos_drm_fbdev_update(helper, helper->fb); + ret = exynos_drm_fbdev_update(helper, sizes, helper->fb); if (ret < 0) goto err_dealloc_cmap; From d3c8ea3460fa9ca8a19eea8813071dee0b07c293 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:12 -0400 Subject: [PATCH 08/15] drm/rockchip: use correct fb width/height What is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, rather than the surface size. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index a5d889a8716b..ff04877e837c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -106,7 +106,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, fb = helper->fb; drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); + drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); offset = fbi->var.xoffset * bytes_per_pixel; offset += fbi->var.yoffset * fb->pitches[0]; From 675c8328db6548f00a4e60770e66ab53752d6bf2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:13 -0400 Subject: [PATCH 09/15] drm/fb: small cleanup Flip conditional to reduce indentation level of rest of fxn, and use min/max to make the code clearer. v2: surface_width -> surface_height typo Signed-off-by: Rob Clark Reviewed-by: Daniel Kurtz Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1e6a0c760c5d..dca98a40a550 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1035,22 +1035,24 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_display_mode *desired_mode; int x, y; + desired_mode = fb_helper->crtc_info[i].desired_mode; + + if (!desired_mode) + continue; + + crtc_count++; + x = fb_helper->crtc_info[i].x; y = fb_helper->crtc_info[i].y; - if (desired_mode) { - if (gamma_size == 0) - gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; - if (desired_mode->hdisplay + x < sizes.fb_width) - sizes.fb_width = desired_mode->hdisplay + x; - if (desired_mode->vdisplay + y < sizes.fb_height) - sizes.fb_height = desired_mode->vdisplay + y; - if (desired_mode->hdisplay + x > sizes.surface_width) - sizes.surface_width = desired_mode->hdisplay + x; - if (desired_mode->vdisplay + y > sizes.surface_height) - sizes.surface_height = desired_mode->vdisplay + y; - crtc_count++; - } + + if (gamma_size == 0) + gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size; + + sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); + sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); + sizes.fb_width = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width); + sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height); } if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { From 0e3704c94c5737f42e9ac49a5dcca366674e5229 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:14 -0400 Subject: [PATCH 10/15] drm/fb: handle tiled connectors better We don't want tile 0,0 to artificially constrain the size of the legacy fbdev device. Instead when reducing fb_size to be the minimum of all displays, only consider the rightmost and bottommost tiles. Signed-off-by: Rob Clark Tested-by: Hai Li Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index dca98a40a550..1a20db7c971f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1034,9 +1034,16 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, crtc_count = 0; for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_display_mode *desired_mode; - int x, y; + struct drm_mode_set *mode_set; + int x, y, j; + /* in case of tile group, are we the last tile vert or horiz? + * If no tile group you are always the last one both vertically + * and horizontally + */ + bool lastv = true, lasth = true; desired_mode = fb_helper->crtc_info[i].desired_mode; + mode_set = &fb_helper->crtc_info[i].mode_set; if (!desired_mode) continue; @@ -1051,8 +1058,21 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width); sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height); - sizes.fb_width = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width); - sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height); + + for (j = 0; j < mode_set->num_connectors; j++) { + struct drm_connector *connector = mode_set->connectors[j]; + if (connector->has_tile) { + lasth = (connector->tile_h_loc == (connector->num_h_tile - 1)); + lastv = (connector->tile_v_loc == (connector->num_v_tile - 1)); + /* cloning to multiple tiles is just crazy-talk, so: */ + break; + } + } + + if (lasth) + sizes.fb_width = min_t(u32, desired_mode->hdisplay + x, sizes.fb_width); + if (lastv) + sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height); } if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { From 2ee762b34899328e0cf561b77adca841794f104c Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Wed, 11 Mar 2015 22:13:50 -0500 Subject: [PATCH 11/15] drm: %pF is only for function pointers Use %pS for actual addresses, otherwise you'll get bad output on arches like ppc64 where %pF expects a function descriptor. Signed-off-by: Scott Wood Cc: dri-devel@lists.freedesktop.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index d51213464672..48f7359e2a6b 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -70,7 +70,7 @@ void drm_err(const char *format, ...) vaf.fmt = format; vaf.va = &args; - printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV", + printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV", __builtin_return_address(0), &vaf); va_end(args); From 43fc884efe20bcc0fae60d8212c6e66426a3d8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Mar 2015 14:51:25 +0200 Subject: [PATCH 12/15] drm: Silence sparse warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../drivers/gpu/drm/drm_vm.c:405:6: warning: symbol 'drm_vm_open_locked' was not declared. Should it be static? ../drivers/gpu/drm/drm_vm.c:431:6: warning: symbol 'drm_vm_close_locked' was not declared. Should it be static? ../drivers/gpu/drm/drm_vm.c:681:5: warning: symbol 'drm_vma_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_pci.c:146:5: warning: symbol 'drm_pci_set_unique' was not declared. Should it be static? ../drivers/gpu/drm/drm_pci.c:216:5: warning: symbol 'drm_irq_by_busid' was not declared. Should it be static? ../drivers/gpu/drm/drm_info.c:47:5: warning: symbol 'drm_name_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_info.c:72:5: warning: symbol 'drm_vm_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_info.c:116:5: warning: symbol 'drm_bufs_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_info.c:159:5: warning: symbol 'drm_clients_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_info.c:209:5: warning: symbol 'drm_gem_name_info' was not declared. Should it be static? ../drivers/gpu/drm/drm_ioc32.c:1019:20: warning: symbol 'drm_compat_ioctls' was not declared. Should it be static? ../drivers/gpu/drm/drm_bridge.c:52:12: warning: function 'drm_bridge_attach' with external linkage has definition Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_bridge.c | 2 +- drivers/gpu/drm/drm_info.c | 1 + drivers/gpu/drm/drm_ioc32.c | 2 +- drivers/gpu/drm/drm_pci.c | 1 + drivers/gpu/drm/drm_vm.c | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index d1187e571c6d..eaa5790c2a6f 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -49,7 +49,7 @@ void drm_bridge_remove(struct drm_bridge *bridge) } EXPORT_SYMBOL(drm_bridge_remove); -extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) +int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge) { if (!dev || !bridge) return -EINVAL; diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index f1b32f91d941..cbb4fc0fc969 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -37,6 +37,7 @@ #include #include +#include "drm_internal.h" #include "drm_legacy.h" /** diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 2f4c4343dfa3..aa8bbb460c57 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -1016,7 +1016,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, return 0; } -drm_ioctl_compat_t *drm_compat_ioctls[] = { +static drm_ioctl_compat_t *drm_compat_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version, [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique, [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap, diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index fd29f03645b8..1b1bd42b0368 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -27,6 +27,7 @@ #include #include #include +#include "drm_internal.h" #include "drm_legacy.h" /** diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 4a2c328959e5..aab49ee4ed40 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -41,6 +41,7 @@ #include #endif #include +#include "drm_internal.h" #include "drm_legacy.h" struct drm_vma_entry { From f98bd3eff592fa708bb260cf3c6403e443cd40b7 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Tue, 17 Mar 2015 15:30:26 +0800 Subject: [PATCH 13/15] drm: Fix some typo mistake of the annotations There are some mistakes that the function name in the annotaions is not matching the real function name. And some duplication word in annotations Signed-off-by: John Hunter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5bcb4baeb9cb..52e7e18c102a 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -346,7 +346,7 @@ needs_modeset(struct drm_crtc_state *state) } /** - * drm_atomic_helper_check - validate state object for modeset changes + * drm_atomic_helper_check_modeset - validate state object for modeset changes * @dev: DRM device * @state: the driver state object * @@ -461,7 +461,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_check_modeset); /** - * drm_atomic_helper_check - validate state object for modeset changes + * drm_atomic_helper_check_planes - validate state object for planes changes * @dev: DRM device * @state: the driver state object * @@ -605,7 +605,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) /* * Each encoder has at most one connector (since we always steal - * it away), so we won't call call disable hooks twice. + * it away), so we won't call disable hooks twice. */ if (encoder->bridge) encoder->bridge->funcs->disable(encoder->bridge); @@ -757,7 +757,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) /* * Each encoder has at most one connector (since we always steal - * it away), so we won't call call mode_set hooks twice. + * it away), so we won't call mode_set hooks twice. */ if (funcs->mode_set) funcs->mode_set(encoder, mode, adjusted_mode); @@ -858,7 +858,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, /* * Each encoder has at most one connector (since we always steal - * it away), so we won't call call enable hooks twice. + * it away), so we won't call enable hooks twice. */ if (encoder->bridge) encoder->bridge->funcs->pre_enable(encoder->bridge); @@ -1025,7 +1025,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, /* * Everything below can be run asynchronously without the need to grab - * any modeset locks at all under one conditions: It must be guaranteed + * any modeset locks at all under one condition: It must be guaranteed * that the asynchronous work has either been cancelled (if the driver * supports it, which at least requires that the framebuffers get * cleaned up with drm_atomic_helper_cleanup_planes()) or completed From 0388df05088def7ce5f3dd1b2293f05739be2a23 Mon Sep 17 00:00:00 2001 From: John Hunter Date: Tue, 17 Mar 2015 15:30:28 +0800 Subject: [PATCH 14/15] drm: change connector to tmp_connector This wasn't too harmful since we already look at connector, which has the same effect as the loop for any non-cloned configs. Only when we have a cloned configuration is it important to look at other connectors. Furthermore existing userspace always changes dpms on all of them anyway. Signed-off-by: JohnHunter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 52e7e18c102a..d9ed9a54fd1e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2001,10 +2001,10 @@ retry: WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); list_for_each_entry(tmp_connector, &config->connector_list, head) { - if (connector->state->crtc != crtc) + if (tmp_connector->state->crtc != crtc) continue; - if (connector->dpms == DRM_MODE_DPMS_ON) { + if (tmp_connector->dpms == DRM_MODE_DPMS_ON) { active = true; break; } From 522cf91f30cb0102fd5cb6e8979d45b6151cdcfc Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 17 Mar 2015 12:05:29 +0100 Subject: [PATCH 15/15] drm: check that planes types are correct while initializing CRTC Be warned if primary or cursor planes haven't the correct type Signed-off-by: Benjamin Gaignard Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5785336695ca..111849c4c8c2 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -659,6 +659,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; int ret; + WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY); + WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR); + crtc->dev = dev; crtc->funcs = funcs; crtc->invert_dimensions = false;