diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-11-17 14:32:57 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-11-17 14:32:57 +0100 |
commit | 3975797f3e72bd115c6ba80210c5fe65ebd9e14e (patch) | |
tree | f2fa6fe843d9d0d458f5455b3852960439572913 /drivers/gpu/drm/imx | |
parent | 78424c927cf194e2eb689b7871780e9182bd8c13 (diff) | |
parent | b7c0e47d98249c2ddf21ea197b651093c6aaee00 (diff) |
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
Tvrtko needs
commit b3c11ac267d461d3d597967164ff7278a919a39f
Author: Eric Engestrom <eric@engestrom.ch>
Date: Sat Nov 12 01:12:56 2016 +0000
drm: move allocation out of drm_get_format_name()
to be able to apply his patches without conflicts.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r-- | drivers/gpu/drm/imx/imx-drm-core.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/imx-ldb.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.c | 187 |
3 files changed, 112 insertions, 123 deletions
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 98df09c2b388..33404295b447 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -18,7 +18,6 @@ #include <linux/dma-buf.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/reservation.h> #include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -151,38 +150,11 @@ static int imx_drm_atomic_check(struct drm_device *dev, return ret; } -static int imx_drm_atomic_commit(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock) -{ - struct drm_plane_state *plane_state; - struct drm_plane *plane; - struct dma_buf *dma_buf; - int i; - - /* - * If the plane fb has an dma-buf attached, fish out the exclusive - * fence for the atomic helper to wait on. - */ - for_each_plane_in_state(state, plane, plane_state, i) { - if ((plane->state->fb != plane_state->fb) && plane_state->fb) { - dma_buf = drm_fb_cma_get_gem_obj(plane_state->fb, - 0)->base.dma_buf; - if (!dma_buf) - continue; - plane_state->fence = - reservation_object_get_excl_rcu(dma_buf->resv); - } - } - - return drm_atomic_helper_commit(dev, state, nonblock); -} - static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = imx_drm_output_poll_changed, .atomic_check = imx_drm_atomic_check, - .atomic_commit = imx_drm_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, }; static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) @@ -357,8 +329,8 @@ static int imx_drm_bind(struct device *dev) int ret; drm = drm_dev_alloc(&imx_drm_driver, dev); - if (!drm) - return -ENOMEM; + if (IS_ERR(drm)) + return PTR_ERR(drm); imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL); if (!imxdrm) { @@ -436,9 +408,11 @@ static int imx_drm_bind(struct device *dev) err_fbhelper: drm_kms_helper_poll_fini(drm); +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) if (imxdrm->fbhelper) drm_fbdev_cma_fini(imxdrm->fbhelper); err_unbind: +#endif component_unbind_all(drm->dev, drm); err_vblank: drm_vblank_cleanup(drm); diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 3ce391c239b0..b300998dce7d 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -319,18 +319,6 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) struct imx_ldb *ldb = imx_ldb_ch->ldb; int mux, ret; - /* - * imx_ldb_encoder_disable is called by - * drm_helper_disable_unused_functions without - * the encoder being enabled before. - */ - if (imx_ldb_ch == &ldb->channel[0] && - (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0) - return; - else if (imx_ldb_ch == &ldb->channel[1] && - (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0) - return; - drm_panel_disable(imx_ldb_ch->panel); if (imx_ldb_ch == &ldb->channel[0]) diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index ce22d0a0ddc8..e74a0ad52950 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -50,6 +50,12 @@ static const uint32_t ipu_plane_formats[] = { DRM_FORMAT_YVYU, DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, + DRM_FORMAT_NV12, + DRM_FORMAT_NV16, DRM_FORMAT_RGB565, }; @@ -64,13 +70,14 @@ drm_plane_state_to_eba(struct drm_plane_state *state) { struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 0); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[0] + - fb->pitches[0] * (state->src_y >> 16) + - (fb->bits_per_pixel >> 3) * (state->src_x >> 16); + return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + + drm_format_plane_cpp(fb->pixel_format, 0) * x; } static inline unsigned long @@ -79,13 +86,17 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; unsigned long eba = drm_plane_state_to_eba(state); + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[1] + - fb->pitches[1] * (state->src_y >> 16) / 2 + - (state->src_x >> 16) / 2 - eba; + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); + + return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + + drm_format_plane_cpp(fb->pixel_format, 1) * x - eba; } static inline unsigned long @@ -94,69 +105,17 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *cma_obj; unsigned long eba = drm_plane_state_to_eba(state); + int x = state->src_x >> 16; + int y = state->src_y >> 16; cma_obj = drm_fb_cma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); - return cma_obj->paddr + fb->offsets[2] + - fb->pitches[2] * (state->src_y >> 16) / 2 + - (state->src_x >> 16) / 2 - eba; -} - -static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane, - struct drm_plane_state *old_state) -{ - struct drm_plane *plane = &ipu_plane->base; - struct drm_plane_state *state = plane->state; - struct drm_framebuffer *fb = state->fb; - unsigned long eba, ubo, vbo; - int active; - - eba = drm_plane_state_to_eba(state); - - switch (fb->pixel_format) { - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - if (old_state->fb) - break; - - /* - * Multiplanar formats have to meet the following restrictions: - * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO - * - EBA, UBO and VBO are a multiple of 8 - * - UBO and VBO are unsigned and not larger than 0xfffff8 - * - Only EBA may be changed while scanout is active - * - The strides of U and V planes must be identical. - */ - ubo = drm_plane_state_to_ubo(state); - vbo = drm_plane_state_to_vbo(state); - - if (fb->pixel_format == DRM_FORMAT_YUV420) - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], ubo, vbo); - else - ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, - fb->pitches[1], vbo, ubo); - - dev_dbg(ipu_plane->base.dev->dev, - "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, - state->src_x >> 16, state->src_y >> 16); - break; - default: - dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", - eba, state->src_x >> 16, state->src_y >> 16); - - break; - } + x /= drm_format_horz_chroma_subsampling(fb->pixel_format); + y /= drm_format_vert_chroma_subsampling(fb->pixel_format); - if (old_state->fb) { - active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); - ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); - } else { - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); - } + return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + + drm_format_plane_cpp(fb->pixel_format, 2) * x - eba; } void ipu_plane_put_resources(struct ipu_plane *ipu_plane) @@ -259,6 +218,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, struct drm_framebuffer *fb = state->fb; struct drm_framebuffer *old_fb = old_state->fb; unsigned long eba, ubo, vbo, old_ubo, old_vbo; + int hsub, vsub; /* Ok to disable */ if (!fb) @@ -338,6 +298,10 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, switch (fb->pixel_format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: /* * Multiplanar formats have to meet the following restrictions: * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO @@ -346,30 +310,49 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, * - Only EBA may be changed while scanout is active * - The strides of U and V planes must be identical. */ - ubo = drm_plane_state_to_ubo(state); vbo = drm_plane_state_to_vbo(state); - if ((ubo & 0x7) || (vbo & 0x7)) + if (vbo & 0x7 || vbo > 0xfffff8) return -EINVAL; - if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) - return -EINVAL; - - if (old_fb) { - old_ubo = drm_plane_state_to_ubo(old_state); + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { old_vbo = drm_plane_state_to_vbo(old_state); - if (ubo != old_ubo || vbo != old_vbo) - return -EINVAL; + if (vbo != old_vbo) + crtc_state->mode_changed = true; } if (fb->pitches[1] != fb->pitches[2]) return -EINVAL; + /* fall-through */ + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + ubo = drm_plane_state_to_ubo(state); + + if (ubo & 0x7 || ubo > 0xfffff8) + return -EINVAL; + + if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { + old_ubo = drm_plane_state_to_ubo(old_state); + if (ubo != old_ubo) + crtc_state->mode_changed = true; + } + if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) return -EINVAL; if (old_fb && old_fb->pitches[1] != fb->pitches[1]) crtc_state->mode_changed = true; + + /* + * The x/y offsets must be even in case of horizontal/vertical + * chroma subsampling. + */ + hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); + vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); + if (((state->src_x >> 16) & (hsub - 1)) || + ((state->src_y >> 16) & (vsub - 1))) + return -EINVAL; } return 0; @@ -386,15 +369,19 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, { struct ipu_plane *ipu_plane = to_ipu_plane(plane); struct drm_plane_state *state = plane->state; + struct drm_crtc_state *crtc_state = state->crtc->state; + struct drm_framebuffer *fb = state->fb; + unsigned long eba, ubo, vbo; enum ipu_color_space ics; + int active; - if (old_state->fb) { - struct drm_crtc_state *crtc_state = state->crtc->state; + eba = drm_plane_state_to_eba(state); - if (!drm_atomic_crtc_needs_modeset(crtc_state)) { - ipu_plane_atomic_set_base(ipu_plane, old_state); - return; - } + if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { + active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); + ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); + return; } switch (ipu_plane->dp_flow) { @@ -424,6 +411,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); break; default: + ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); break; } } @@ -437,11 +425,50 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); - ipu_plane_atomic_set_base(ipu_plane, old_state); + switch (fb->pixel_format) { + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + ubo = drm_plane_state_to_ubo(state); + vbo = drm_plane_state_to_vbo(state); + if (fb->pixel_format == DRM_FORMAT_YVU420 || + fb->pixel_format == DRM_FORMAT_YVU422 || + fb->pixel_format == DRM_FORMAT_YVU444) + swap(ubo, vbo); + + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], ubo, vbo); + + dev_dbg(ipu_plane->base.dev->dev, + "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo, + state->src_x >> 16, state->src_y >> 16); + break; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + ubo = drm_plane_state_to_ubo(state); + + ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, + fb->pitches[1], ubo, ubo); + + dev_dbg(ipu_plane->base.dev->dev, + "phy = %lu %lu, x = %d, y = %d", eba, ubo, + state->src_x >> 16, state->src_y >> 16); + break; + default: + dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", + eba, state->src_x >> 16, state->src_y >> 16); + break; + } + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); ipu_plane_enable(ipu_plane); } static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = { + .prepare_fb = drm_fb_cma_prepare_fb, .atomic_check = ipu_plane_atomic_check, .atomic_disable = ipu_plane_atomic_disable, .atomic_update = ipu_plane_atomic_update, |