drm/msm/sde: add planes color fill/fence timeout
To prepare for input fence support, add a property to configure the
input fence timeout. Also, enable support for color fill (through
a plane property) so that it can be enabled if input fences ever time
out.
Change-Id: Iae79ebadb4731db444f39d3b7207b65cb2aa9243
Signed-off-by: Clarence Ip <cip@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index a99a354..b8bbfbe 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -79,7 +79,9 @@
/* range properties */
PLANE_PROP_ZPOS = PLANE_PROP_BLOBCOUNT,
PLANE_PROP_ALPHA,
+ PLANE_PROP_COLOR_FILL,
PLANE_PROP_SYNC_FENCE,
+ PLANE_PROP_SYNC_FENCE_TIMEOUT,
/* enum/bitmask properties */
PLANE_PROP_ROTATION,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 1c5089a..af9aded 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -77,12 +77,6 @@
#define VIG_0_QSEED2_SHARP 0x30
/*
- * MDP Solid fill configuration
- * argb8888
- */
-#define SSPP_SOLID_FILL 0x4037ff
-
-/*
* Definitions for ViG op modes
*/
#define VIG_OP_CSC_DST_DATAFMT BIT(19)
@@ -161,17 +155,15 @@
* Setup source pixel format, flip,
*/
static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- u32 flags)
+ struct sde_mdp_format_params *fmt, u32 flags)
{
struct sde_hw_blk_reg_map *c;
- struct sde_mdp_format_params *fmt;
u32 chroma_samp, unpack, src_format;
u32 secure = 0;
u32 opmode = 0;
u32 idx;
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !cfg)
+ if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx) || !fmt)
return;
c = &ctx->hw;
@@ -179,11 +171,6 @@
opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
- /* format info */
- fmt = cfg->src.format;
- if (WARN_ON(!fmt))
- return;
-
if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
secure = 0xF;
@@ -211,6 +198,9 @@
fmt->fetch_planes != SDE_MDP_PLANE_INTERLEAVED)
src_format |= BIT(8); /* SRCC3_EN */
+ if (flags & SDE_SSPP_SOLID_FILL)
+ src_format |= BIT(22);
+
unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
(fmt->element[1] << 8) | (fmt->element[0] << 0);
src_format |= ((fmt->unpack_count - 1) << 12) |
@@ -219,7 +209,8 @@
((fmt->bpp - 1) << 9);
if (fmt->fetch_mode != SDE_MDP_FETCH_LINEAR) {
- opmode |= MDSS_MDP_OP_BWC_EN;
+ if (SDE_FORMAT_IS_UBWC(fmt))
+ opmode |= MDSS_MDP_OP_BWC_EN;
src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
SDE_REG_WRITE(c, SSPP_FETCH_CONFIG,
SDE_MDP_FETCH_CONFIG_RESET_VALUE |
@@ -379,14 +370,10 @@
sde_hw_sspp_setup_pe_config(ctx, pe_ext);
/* src and dest rect programming */
- src_xy = (cfg->src_rect.y << 16) |
- (cfg->src_rect.x);
- src_size = (cfg->src_rect.h << 16) |
- (cfg->src_rect.w);
- dst_xy = (cfg->dst_rect.y << 16) |
- (cfg->dst_rect.x);
- dst_size = (cfg->dst_rect.h << 16) |
- (cfg->dst_rect.w);
+ src_xy = (cfg->src_rect.y << 16) | (cfg->src_rect.x);
+ src_size = (cfg->src_rect.h << 16) | (cfg->src_rect.w);
+ dst_xy = (cfg->dst_rect.y << 16) | (cfg->dst_rect.x);
+ dst_size = (cfg->dst_rect.h << 16) | (cfg->dst_rect.w);
ystride0 = (cfg->src.ystride[0]) |
(cfg->src.ystride[1] << 16);
@@ -402,8 +389,8 @@
_sde_hw_sspp_setup_scaler(ctx, pe_ext);
}
- /* Rectangle Register programming */
- SDE_REG_WRITE(c, SSPP_SRC_SIZE + idx, src_size);
+ /* rectangle register programming */
+ SDE_REG_WRITE(c, SSPP_SRC_SIZE + idx, src_size);
SDE_REG_WRITE(c, SSPP_SRC_XY + idx, src_xy);
SDE_REG_WRITE(c, SSPP_OUT_SIZE + idx, dst_size);
SDE_REG_WRITE(c, SSPP_OUT_XY + idx, dst_xy);
@@ -456,32 +443,14 @@
SDE_REG_WRITE(c, VIG_0_QSEED2_SHARP + idx + 0xC, cfg->noise_thr);
}
-static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx,
- u32 const_color,
- u32 flags)
+static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx, u32 color)
{
- struct sde_hw_blk_reg_map *c;
- u32 secure = 0;
- u32 unpack, src_format, opmode = 0;
u32 idx;
if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
return;
- c = &ctx->hw;
-
- /* format info */
- src_format = SSPP_SOLID_FILL;
- unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
- (C1_B_Cb << 8) | (C0_G_Y << 0);
- secure = (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) ? 0xF : 0x00;
- opmode = MDSS_MDP_OP_PE_OVERRIDE;
-
- SDE_REG_WRITE(c, SSPP_SRC_FORMAT + idx, src_format);
- SDE_REG_WRITE(c, SSPP_SRC_UNPACK_PATTERN + idx, unpack);
- SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
- SDE_REG_WRITE(c, SSPP_SRC_CONSTANT_COLOR + idx, const_color);
- SDE_REG_WRITE(c, SSPP_SRC_OP_MODE + idx, opmode);
+ SDE_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR + idx, color);
}
static void sde_hw_sspp_setup_histogram_v1(struct sde_hw_pipe *ctx,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index 6b1833b2..1bfbc21 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -16,6 +16,7 @@
#include "sde_hw_catalog.h"
#include "sde_hw_mdss.h"
#include "sde_hw_util.h"
+#include "sde_formats.h"
struct sde_hw_pipe;
@@ -27,6 +28,7 @@
#define SDE_SSPP_FLIP_UD 0x4
#define SDE_SSPP_SOURCE_ROTATED_90 0x8
#define SDE_SSPP_ROT_90 0x10
+#define SDE_SSPP_SOLID_FILL 0x20
/**
* Define all scaler feature bits in catalog
@@ -167,8 +169,7 @@
* @flags: Extra flags for format config
*/
void (*setup_format)(struct sde_hw_pipe *ctx,
- struct sde_hw_pipe_cfg *cfg,
- u32 flags);
+ struct sde_mdp_format_params *fmt, u32 flags);
/**
* setup_rects - setup pipe ROI rectangles
@@ -201,9 +202,7 @@
* @const_color: Fill color value
* @flags: Pipe flags
*/
- void (*setup_solidfill)(struct sde_hw_pipe *ctx,
- u32 const_color,
- u32 flags);
+ void (*setup_solidfill)(struct sde_hw_pipe *ctx, u32 color);
/**
* setup_sharpening - setup sharpening
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 0ffdb82..915732e 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -376,6 +376,18 @@
void sde_plane_complete_flip(struct drm_plane *plane);
struct drm_plane *sde_plane_init(struct drm_device *dev,
uint32_t pipe, bool primary_plane);
+int sde_plane_wait_sync_fence(struct drm_plane *plane);
+
+/**
+ * sde_plane_color_fill(): Enables color fill on plane
+ * @plane: Pointer to DRM plane object
+ * @color: RGB fill color value, [23..16] Blue, [15..8] Green, [7..0] Red
+ * @alpha: 8-bit fill alpha value, 255 selects 100% alpha
+ *
+ * Returns: 0 on success
+ */
+int sde_plane_color_fill(struct drm_plane *plane,
+ uint32_t color, uint32_t alpha);
/**
* CRTC functions
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 6666532..fa35b7a 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -92,10 +92,12 @@
DBG("0x%llX", fd);
}
-void *sde_plane_get_sync_fence(struct drm_plane *plane)
+int sde_plane_wait_sync_fence(struct drm_plane *plane)
{
struct sde_plane_state *pstate;
- void *ret = NULL;
+ void *sync_fence;
+ long wait_ms;
+ int ret = -EINVAL;
if (!plane) {
DRM_ERROR("Invalid plane\n");
@@ -103,11 +105,24 @@
DRM_ERROR("Invalid plane state\n");
} else {
pstate = to_sde_plane_state(plane->state);
- ret = pstate->sync_fence;
+ sync_fence = pstate->sync_fence;
- DBG("%s", to_sde_plane(plane)->pipe_name);
+ if (sync_fence) {
+ wait_ms = (long)sde_plane_get_property(pstate,
+ PLANE_PROP_SYNC_FENCE_TIMEOUT);
+
+ DBG("%s", to_sde_plane(plane)->pipe_name);
+ ret = sde_sync_wait(sync_fence, wait_ms);
+ if (!ret)
+ DBG("signaled");
+ else if (ret == -ETIME)
+ DRM_ERROR("timeout\n");
+ else
+ DRM_ERROR("error %d\n", ret);
+ } else {
+ ret = 0;
+ }
}
-
return ret;
}
@@ -148,7 +163,7 @@
}
}
-static void _sde_plane_setup_scaler3(struct drm_plane *plane,
+static void _sde_plane_setup_scaler3(struct sde_plane *psde,
uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
struct sde_hw_scaler3_cfg *scale_cfg,
struct sde_mdp_format_params *fmt,
@@ -156,11 +171,28 @@
{
}
-static void _sde_plane_setup_scaler2(struct drm_plane *plane,
+/**
+ * _sde_plane_setup_scaler2(): Determine default scaler phase steps/filter type
+ * @psde: Pointer to SDE plane object
+ * @src: Source size
+ * @dst: Destination size
+ * @phase_steps: Pointer to output array for phase steps
+ * @filter: Pointer to output array for filter type
+ * @fmt: Pointer to format definition
+ * @chroma_subsampling: Subsampling amount for chroma channel
+ *
+ * Returns: 0 on success
+ */
+static int _sde_plane_setup_scaler2(struct sde_plane *psde,
uint32_t src, uint32_t dst, uint32_t *phase_steps,
enum sde_hw_filter *filter, struct sde_mdp_format_params *fmt,
uint32_t chroma_subsampling)
{
+ if (!psde || !phase_steps || !filter || !fmt) {
+ DRM_ERROR("Invalid arguments\n");
+ return -EINVAL;
+ }
+
/* calculate phase steps, leave init phase as zero */
phase_steps[SDE_SSPP_COMP_0] =
mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
@@ -185,13 +217,30 @@
}
} else {
/* disable scaler */
+ DBG("Disable scaler");
filter[SDE_SSPP_COMP_0] = SDE_MDP_SCALE_FILTER_MAX;
filter[SDE_SSPP_COMP_1_2] = SDE_MDP_SCALE_FILTER_MAX;
filter[SDE_SSPP_COMP_3] = SDE_MDP_SCALE_FILTER_MAX;
}
+ return 0;
}
-static void _sde_plane_setup_pixel_ext(struct drm_plane *plane,
+/**
+ * _sde_plane_setup_pixel_ext - determine default pixel extension values
+ * @psde: Pointer to SDE plane object
+ * @src: Source size
+ * @dst: Destination size
+ * @decimated_src: Source size after decimation, if any
+ * @phase_steps: Pointer to output array for phase steps
+ * @out_src: Output array for pixel extension values
+ * @out_edge1: Output array for pixel extension first edge
+ * @out_edge2: Output array for pixel extension second edge
+ * @filter: Pointer to array for filter type
+ * @fmt: Pointer to format definition
+ * @chroma_subsampling: Subsampling amount for chroma channel
+ * @post_compare: Whether to chroma subsampled source size for comparisions
+ */
+static void _sde_plane_setup_pixel_ext(struct sde_plane *psde,
uint32_t src, uint32_t dst, uint32_t decimated_src,
uint32_t *phase_steps, uint32_t *out_src, int *out_edge1,
int *out_edge2, enum sde_hw_filter *filter,
@@ -202,7 +251,7 @@
uint32_t src_work;
int i, tmp;
- if (plane && phase_steps && out_src && out_edge1 &&
+ if (psde && phase_steps && out_src && out_edge1 &&
out_edge2 && filter && fmt) {
/* handle CAF for YUV formats */
if (SDE_FORMAT_IS_YUV(fmt) &&
@@ -429,95 +478,20 @@
psde->pipe_hw->ops.setup_csc(psde->pipe_hw, psde->csc_ptr);
}
-static int _sde_plane_mode_set(struct drm_plane *plane,
- struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
+static void _sde_plane_setup_scaler(struct sde_plane *psde,
+ struct sde_mdp_format_params *fmt,
+ struct sde_plane_state *pstate)
{
- struct sde_plane *psde;
- struct sde_plane_state *pstate;
- const struct mdp_format *format;
- uint32_t nplanes, pix_format, tmp;
- uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
- uint32_t src_fmt_flags;
- int i;
- struct sde_mdp_format_params *fmt;
- struct sde_hw_pixel_ext *pe;
- size_t sc_u_size = 0;
+ struct sde_hw_pixel_ext *pe = NULL;
struct sde_drm_scaler *sc_u = NULL;
struct sde_drm_scaler_v1 *sc_u1 = NULL;
+ size_t sc_u_size = 0;
+ uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
+ uint32_t tmp;
+ int i;
- DBG("");
-
- if (!plane || !plane->state) {
- DRM_ERROR("Invalid plane/state\n");
- return -EINVAL;
- }
- if (!crtc || !fb) {
- DRM_ERROR("Invalid crtc/fb\n");
- return -EINVAL;
- }
-
- psde = to_sde_plane(plane);
- pstate = to_sde_plane_state(plane->state);
- nplanes = drm_format_num_planes(fb->pixel_format);
-
- format = to_mdp_format(msm_framebuffer_format(fb));
- pix_format = format->base.pixel_format;
-
- /* src values are in Q16 fixed point, convert to integer */
- src_x = src_x >> 16;
- src_y = src_y >> 16;
- src_w = src_w >> 16;
- src_h = src_h >> 16;
-
- DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", psde->pipe_name,
- fb->base.id, src_x, src_y, src_w, src_h,
- crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
-
- /* update format configuration */
- memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
- src_fmt_flags = 0;
-
- psde->pipe_cfg.src.format = sde_mdp_get_format_params(pix_format,
- fb->modifier[0]);
- psde->pipe_cfg.src.width = fb->width;
- psde->pipe_cfg.src.height = fb->height;
- psde->pipe_cfg.src.num_planes = nplanes;
-
- _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
-
- /* flags */
- DBG("Flags 0x%llX, rotation 0x%llX",
- sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG),
- sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
- if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
- BIT(DRM_REFLECT_X))
- src_fmt_flags |= SDE_SSPP_FLIP_LR;
- if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
- BIT(DRM_REFLECT_Y))
- src_fmt_flags |= SDE_SSPP_FLIP_UD;
- if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
- BIT(SDE_DRM_DEINTERLACE)) {
- src_h /= 2;
- src_y = DIV_ROUND_UP(src_y, 2);
- src_y &= ~0x1;
- }
-
- psde->pipe_cfg.src_rect.x = src_x;
- psde->pipe_cfg.src_rect.y = src_y;
- psde->pipe_cfg.src_rect.w = src_w;
- psde->pipe_cfg.src_rect.h = src_h;
-
- psde->pipe_cfg.dst_rect.x = crtc_x;
- psde->pipe_cfg.dst_rect.y = crtc_y;
- psde->pipe_cfg.dst_rect.w = crtc_w;
- psde->pipe_cfg.dst_rect.h = crtc_h;
-
- /* get sde pixel format definition */
- fmt = psde->pipe_cfg.src.format;
+ if (!psde || !fmt)
+ return;
pe = &(psde->pixel_ext);
memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
@@ -543,21 +517,28 @@
if (sc_u1 && (sc_u1->enable & SDE_DRM_SCALER_DECIMATE)) {
psde->pipe_cfg.horz_decimation = sc_u1->horz_decimate;
psde->pipe_cfg.vert_decimation = sc_u1->vert_decimate;
+ } else {
+ psde->pipe_cfg.horz_decimation = 0;
+ psde->pipe_cfg.vert_decimation = 0;
}
/* don't chroma subsample if decimating */
chroma_subsmpl_h = psde->pipe_cfg.horz_decimation ? 1 :
- drm_format_horz_chroma_subsampling(pix_format);
+ drm_format_horz_chroma_subsampling(fmt->format);
chroma_subsmpl_v = psde->pipe_cfg.vert_decimation ? 1 :
- drm_format_vert_chroma_subsampling(pix_format);
+ drm_format_vert_chroma_subsampling(fmt->format);
/* update scaler */
if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
if (sc_u1 && (sc_u1->enable & SDE_DRM_SCALER_SCALER_3))
- DBG("QSEED3 blob detected");
+ DBG("SCALER3 blob detected");
else
- _sde_plane_setup_scaler3(plane, src_w, src_h, crtc_w,
- crtc_h, &psde->scaler3_cfg, fmt,
+ _sde_plane_setup_scaler3(psde,
+ psde->pipe_cfg.src_rect.w,
+ psde->pipe_cfg.src_rect.h,
+ psde->pipe_cfg.dst_rect.w,
+ psde->pipe_cfg.dst_rect.h,
+ &psde->scaler3_cfg, fmt,
chroma_subsmpl_h, chroma_subsmpl_v);
} else {
/* always calculate basic scaler config */
@@ -574,10 +555,14 @@
}
} else {
/* calculate phase steps */
- _sde_plane_setup_scaler2(plane, src_w, crtc_w,
+ _sde_plane_setup_scaler2(psde,
+ psde->pipe_cfg.src_rect.w,
+ psde->pipe_cfg.dst_rect.w,
pe->phase_step_x,
pe->horz_filter, fmt, chroma_subsmpl_h);
- _sde_plane_setup_scaler2(plane, src_h, crtc_h,
+ _sde_plane_setup_scaler2(psde,
+ psde->pipe_cfg.src_rect.h,
+ psde->pipe_cfg.dst_rect.h,
pe->phase_step_y,
pe->vert_filter, fmt, chroma_subsmpl_v);
}
@@ -586,6 +571,7 @@
/* update pixel extensions */
if (sc_u1 && (sc_u1->enable & SDE_DRM_SCALER_PIX_EXT)) {
/* populate from user space */
+ DBG("PIXEXT blob detected");
for (i = 0; i < SDE_MAX_PLANES; i++) {
pe->num_ext_pxls_left[i] = sc_u1->lr.num_pxls_start[i];
pe->num_ext_pxls_right[i] = sc_u1->lr.num_pxls_end[i];
@@ -605,20 +591,22 @@
}
} else {
/* calculate left/right/top/bottom pixel extensions */
- tmp = DECIMATED_DIMENSION(src_w,
+ tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.w,
psde->pipe_cfg.horz_decimation);
if (SDE_FORMAT_IS_YUV(fmt))
tmp &= ~0x1;
- _sde_plane_setup_pixel_ext(plane, src_w, crtc_w, tmp,
+ _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.w,
+ psde->pipe_cfg.dst_rect.w, tmp,
pe->phase_step_x,
pe->roi_w,
pe->num_ext_pxls_left,
pe->num_ext_pxls_right, pe->horz_filter, fmt,
chroma_subsmpl_h, 0);
- tmp = DECIMATED_DIMENSION(src_h,
+ tmp = DECIMATED_DIMENSION(psde->pipe_cfg.src_rect.h,
psde->pipe_cfg.vert_decimation);
- _sde_plane_setup_pixel_ext(plane, src_h, crtc_h, tmp,
+ _sde_plane_setup_pixel_ext(psde, psde->pipe_cfg.src_rect.h,
+ psde->pipe_cfg.dst_rect.h, tmp,
pe->phase_step_y,
pe->roi_h,
pe->num_ext_pxls_top,
@@ -655,10 +643,152 @@
pe->num_ext_pxls_btm[i];
}
}
+}
+
+int sde_plane_color_fill(struct drm_plane *plane,
+ uint32_t color, uint32_t alpha)
+{
+ struct sde_plane *psde;
+ struct sde_mdp_format_params *fmt;
+
+ if (!plane) {
+ DRM_ERROR("Invalid plane\n");
+ return -EINVAL;
+ }
+
+ psde = to_sde_plane(plane);
+ if (!psde->pipe_hw) {
+ DRM_ERROR("Invalid plane h/w pointer\n");
+ return -EINVAL;
+ }
+
+ /*
+ * select fill format to match user property expectation,
+ * h/w only supports RGB variants
+ */
+ fmt = sde_mdp_get_format_params(DRM_FORMAT_ABGR8888, 0);
+
+ /* update sspp */
+ if (fmt && psde->pipe_hw->ops.setup_solidfill) {
+ psde->pipe_hw->ops.setup_solidfill(psde->pipe_hw,
+ (color & 0xFFFFFF) | ((alpha & 0xFF) << 24));
+
+ /* override scaler/decimation if solid fill */
+ psde->pipe_cfg.src_rect.x = 0;
+ psde->pipe_cfg.src_rect.y = 0;
+ psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
+ psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
+
+ _sde_plane_setup_scaler(psde, fmt, 0);
+
+ if (psde->pipe_hw->ops.setup_format)
+ psde->pipe_hw->ops.setup_format(psde->pipe_hw,
+ fmt, SDE_SSPP_SOLID_FILL);
+
+ if (psde->pipe_hw->ops.setup_rects)
+ psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
+ &psde->pipe_cfg, &psde->pixel_ext);
+ }
+
+ return 0;
+}
+
+static int _sde_plane_mode_set(struct drm_plane *plane,
+ struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct sde_plane *psde;
+ struct sde_plane_state *pstate;
+ const struct mdp_format *format;
+ uint32_t nplanes, tmp;
+ uint32_t src_flags;
+ struct sde_mdp_format_params *fmt;
+
+ DBG("");
+
+ if (!plane || !plane->state) {
+ DRM_ERROR("Invalid plane/state\n");
+ return -EINVAL;
+ }
+ if (!crtc || !fb) {
+ DRM_ERROR("Invalid crtc/fb\n");
+ return -EINVAL;
+ }
+
+ psde = to_sde_plane(plane);
+ pstate = to_sde_plane_state(plane->state);
+ nplanes = drm_format_num_planes(fb->pixel_format);
+
+ format = to_mdp_format(msm_framebuffer_format(fb));
+ tmp = format->base.pixel_format;
+
+ /* src values are in Q16 fixed point, convert to integer */
+ src_x = src_x >> 16;
+ src_y = src_y >> 16;
+ src_w = src_w >> 16;
+ src_h = src_h >> 16;
+
+ DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", psde->pipe_name,
+ fb->base.id, src_x, src_y, src_w, src_h,
+ crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
+
+ /* update format configuration */
+ memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
+ src_flags = 0;
+
+ psde->pipe_cfg.src.format = sde_mdp_get_format_params(tmp,
+ fb->modifier[0]);
+ psde->pipe_cfg.src.width = fb->width;
+ psde->pipe_cfg.src.height = fb->height;
+ psde->pipe_cfg.src.num_planes = nplanes;
+
+ /* flags */
+ DBG("Flags 0x%llX, rotation 0x%llX",
+ sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG),
+ sde_plane_get_property(pstate, PLANE_PROP_ROTATION));
+ if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
+ BIT(DRM_REFLECT_X))
+ src_flags |= SDE_SSPP_FLIP_LR;
+ if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
+ BIT(DRM_REFLECT_Y))
+ src_flags |= SDE_SSPP_FLIP_UD;
+ if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+ BIT(SDE_DRM_DEINTERLACE)) {
+ src_h /= 2;
+ src_y = DIV_ROUND_UP(src_y, 2);
+ src_y &= ~0x1;
+ }
+
+ psde->pipe_cfg.src_rect.x = src_x;
+ psde->pipe_cfg.src_rect.y = src_y;
+ psde->pipe_cfg.src_rect.w = src_w;
+ psde->pipe_cfg.src_rect.h = src_h;
+
+ psde->pipe_cfg.dst_rect.x = crtc_x;
+ psde->pipe_cfg.dst_rect.y = crtc_y;
+ psde->pipe_cfg.dst_rect.w = crtc_w;
+ psde->pipe_cfg.dst_rect.h = crtc_h;
+
+ /* get sde pixel format definition */
+ fmt = psde->pipe_cfg.src.format;
+
+ /* check for color fill */
+ tmp = (uint32_t)sde_plane_get_property(pstate, PLANE_PROP_COLOR_FILL);
+ if (tmp & BIT(31)) {
+ /* force 100% alpha, stop other processing */
+ return sde_plane_color_fill(plane, tmp, 0xFF);
+ }
+
+ _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
+
+ _sde_plane_setup_scaler(psde, fmt, pstate);
if (psde->pipe_hw->ops.setup_format)
psde->pipe_hw->ops.setup_format(psde->pipe_hw,
- &psde->pipe_cfg, src_fmt_flags);
+ fmt, src_flags);
if (psde->pipe_hw->ops.setup_rects)
psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
&psde->pipe_cfg, &psde->pixel_ext);
@@ -1134,8 +1264,8 @@
DBG("");
- if (!psde || !psde->pipe_sblk || !catalog) {
- DRM_ERROR("Failed to identify catalog definition\n");
+ if (!psde || !psde->pipe_hw || !psde->pipe_sblk || !catalog) {
+ DRM_ERROR("Catalog or h/w driver definition error\n");
return;
}
@@ -1148,9 +1278,18 @@
_sde_plane_install_range_property(plane, dev, "alpha", 0, 255, 255,
PLANE_PROP_ALPHA);
+ if (psde->pipe_hw->ops.setup_solidfill)
+ _sde_plane_install_range_property(plane, dev, "color_fill",
+ 0, 0xFFFFFFFF, 0,
+ PLANE_PROP_COLOR_FILL);
+
_sde_plane_install_range_property(plane, dev, "sync_fence", 0, ~0, ~0,
PLANE_PROP_SYNC_FENCE);
+ _sde_plane_install_range_property(plane, dev, "sync_fence_timeout",
+ 0, ~0, 10000,
+ PLANE_PROP_SYNC_FENCE_TIMEOUT);
+
/* standard properties */
_sde_plane_install_rotation_property(plane, dev, PLANE_PROP_ROTATION);