/*
- * Copyright 2017 NXP
+ * Copyright 2017-2018 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
.format_mod_supported = dcss_plane_format_mod_supported,
};
+static bool dcss_plane_can_rotate(u32 pixel_format, bool mod_present,
+ u64 modifier, unsigned int rotation)
+{
+ enum dcss_color_space cs = dcss_drm_fourcc_to_colorspace(pixel_format);
+ bool linear_format = !mod_present ||
+ (mod_present && modifier == DRM_FORMAT_MOD_LINEAR);
+ u32 supported_rotation = DRM_MODE_ROTATE_0;
+
+ if (cs == DCSS_COLORSPACE_RGB && linear_format)
+ supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+ DRM_MODE_REFLECT_MASK;
+ else if (cs == DCSS_COLORSPACE_RGB &&
+ modifier == DRM_FORMAT_MOD_VIVANTE_TILED)
+ supported_rotation = DRM_MODE_ROTATE_MASK |
+ DRM_MODE_REFLECT_MASK;
+ else if (cs == DCSS_COLORSPACE_RGB &&
+ modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED_FC)
+ supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+ DRM_MODE_REFLECT_MASK;
+ else if (cs == DCSS_COLORSPACE_YUV && linear_format &&
+ (pixel_format == DRM_FORMAT_NV12 ||
+ pixel_format == DRM_FORMAT_NV21))
+ supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+ DRM_MODE_REFLECT_MASK;
+ else if (cs == DCSS_COLORSPACE_YUV && linear_format &&
+ pixel_format == DRM_FORMAT_P010)
+ supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y;
+
+ return !!(rotation & supported_rotation);
+}
+
static int dcss_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
if (!drm_rect_intersect(&crtc_rect, &disp_rect))
return -EINVAL;
+ if (!dcss_plane_can_rotate(fb->format->format,
+ !!(fb->flags & DRM_MODE_FB_MODIFIERS),
+ fb->modifier,
+ state->rotation)) {
+ DRM_ERROR("requested rotation is not allowed!\n");
+ return -EINVAL;
+ }
+
/* cropping is only available on overlay planes when DTRC is used */
if (state->crtc_x < 0 || state->crtc_y < 0 ||
state->crtc_x + state->crtc_w > hdisplay ||
state->src_w != old_state->src_w ||
state->src_h != old_state->src_h ||
fb->format->format != old_fb->format->format ||
- fb->modifier != old_fb->modifier;
+ fb->modifier != old_fb->modifier ||
+ state->rotation != old_state->rotation;
}
static void dcss_plane_adjust(struct drm_rect *dis_rect,
dcss_dpr_set_res(dcss_plane->dcss, dcss_plane->ch_num,
src_w, src_h, adj_w, adj_h);
+ dcss_dpr_set_rotation(dcss_plane->dcss, dcss_plane->ch_num,
+ state->rotation);
dcss_plane_atomic_set_base(dcss_plane);
if (fb->modifier == DRM_FORMAT_MOD_VSI_G2_TILED_COMPRESSED) {
if (ret)
return ERR_PTR(ret);
+ drm_plane_create_rotation_property(&dcss_plane->base,
+ DRM_MODE_ROTATE_0,
+ DRM_MODE_ROTATE_0 |
+ DRM_MODE_ROTATE_90 |
+ DRM_MODE_ROTATE_180 |
+ DRM_MODE_ROTATE_270 |
+ DRM_MODE_REFLECT_X |
+ DRM_MODE_REFLECT_Y);
+
dcss_plane->ch_num = 2 - zpos;
dcss_plane->alpha_val = 255;
/*
- * Copyright (C) 2017 NXP
+ * Copyright (C) 2017-2018 NXP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include <linux/sizes.h>
#include <linux/io.h>
#include <linux/seq_file.h>
+#include <drm/drmP.h>
#include <drm/drm_fourcc.h>
#include <video/imx-dcss.h>
dcss_writel(en ? 0xfe : 0xff, dpr->ch[1].base_reg + DCSS_DPR_IRQ_MASK);
dcss_writel(en ? 0xfe : 0xff, dpr->ch[2].base_reg + DCSS_DPR_IRQ_MASK);
}
+
+void dcss_dpr_set_rotation(struct dcss_soc *dcss, int ch_num, u32 rotation)
+{
+ struct dcss_dpr_ch *ch = &dcss->dpr_priv->ch[ch_num];
+
+ ch->frame_ctrl &= ~(HFLIP_EN | VFLIP_EN | ROT_ENC_MASK);
+
+ ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_X ? HFLIP_EN : 0;
+ ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_Y ? VFLIP_EN : 0;
+
+ if (rotation & DRM_MODE_ROTATE_90)
+ ch->frame_ctrl |= 1 << ROT_ENC_POS;
+ else if (rotation & DRM_MODE_ROTATE_180)
+ ch->frame_ctrl |= 2 << ROT_ENC_POS;
+ else if (rotation & DRM_MODE_ROTATE_270)
+ ch->frame_ctrl |= 3 << ROT_ENC_POS;
+}
+EXPORT_SYMBOL(dcss_dpr_set_rotation);