summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-11-11 09:31:27 +1000
committerDave Airlie <airlied@redhat.com>2016-11-11 09:31:27 +1000
commit628d16555e019c0cc6897b603bbea29c3b6d2c9f (patch)
tree27159fc9e6c0922802dbe7c7be88fb8b7af115d3 /drivers/gpu/drm/imx
parent3e91168a6a76f7e21c44f04ebf953589ca59f03c (diff)
parentb5b457b33dcd2a6aa6f70a07f8a9b469727ffeec (diff)
Merge tag 'imx-drm-next-2016-11-10' of git://git.pengutronix.de/git/pza/linux into drm-next
imx-drm plane update cleanup, YUV formats - request modeset if plane offsets changed, only the plane base address can be changed without disabling the plane IDMAC channel. - cleanup of plane atomic_update - remove unused ipu_cpmem_set_yuv_planar function - support YUV 4:4:4, 4:2:2, NV12 and NV16 plane formats - not only mask interrupts during irq init, also clear them - remove a legacy check from imx-ldb - add support to set the CSI downsizing bits - silence an obnoxious warning during modeset * tag 'imx-drm-next-2016-11-10' of git://git.pengutronix.de/git/pza/linux: gpu: ipu-di: silence videomode logspam gpu: ipu-v3: add ipu_csi_set_downsize drm/imx: imx-ldb: remove unnecessary double disable check gpu: ipu-v3: initially clear all interrupts drm/imx: ipuv3-plane: add support for YUV 4:2:2 and 4:4:4, NV12, and NV16 formats gpu: ipu-v3: add YUV 4:4:4 support gpu: ipu-cpmem: remove unused ipu_cpmem_set_yuv_planar function drm/imx: ipuv3-plane: let drm_plane_state_to_ubo/vbo handle chroma subsampling other than 4:2:0 drm/imx: ipuv3-plane: merge ipu_plane_atomic_set_base into atomic_update drm/imx: ipuv3-plane: request modeset if plane offsets changed
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c12
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c176
2 files changed, 94 insertions, 94 deletions
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 d5864ed4d772..6a97e396fce3 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 *plane = &ipu_plane->base;
- 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;
- int active;
-
- eba = drm_plane_state_to_eba(state);
-
- switch (fb->pixel_format) {
- case DRM_FORMAT_YUV420:
- case DRM_FORMAT_YVU420:
- if (!drm_atomic_crtc_needs_modeset(crtc_state))
- break;
+ x /= drm_format_horz_chroma_subsampling(fb->pixel_format);
+ y /= drm_format_vert_chroma_subsampling(fb->pixel_format);
- /*
- * 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;
- }
-
- if (!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);
- } 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)
@@ -339,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
@@ -347,27 +310,34 @@ 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))
- return -EINVAL;
-
- if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
+ if (vbo & 0x7 || vbo > 0xfffff8)
return -EINVAL;
- if (old_fb &&
- (old_fb->pixel_format == DRM_FORMAT_YUV420 ||
- old_fb->pixel_format == DRM_FORMAT_YVU420)) {
- 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;
@@ -399,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);
- 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) {
@@ -451,7 +425,45 @@ 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);
+ 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);
}