drm/msm/sde: enable blending across all planes
Updates to sspp to enable dma pipe support, and adjust plane
property creation based on pipe availability. Enable support
for the BLEND_OP property within the crtc.
Change-Id: Iec063eb2a3b206fb3d66fb2a176536d7838b08bf
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 6110da8..dd653a46 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -79,7 +79,6 @@
/* range properties */
PLANE_PROP_ZPOS = PLANE_PROP_BLOBCOUNT,
PLANE_PROP_ALPHA,
- PLANE_PROP_PREMULTIPLIED,
PLANE_PROP_H_DECIMATE,
PLANE_PROP_V_DECIMATE,
PLANE_PROP_SYNC_FENCE,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 313b82d..76d1d90 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -11,6 +11,7 @@
*/
#include <linux/sort.h>
+#include <uapi/drm/sde_drm.h>
#include <drm/drm_mode.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
@@ -199,52 +200,62 @@
{
struct drm_plane *plane;
const struct mdp_format *format;
+ uint32_t blend_op;
format = to_mdp_format(
msm_framebuffer_format(pstate->base.fb));
plane = pstate->base.plane;
memset(cfg, 0, sizeof(*cfg));
- cfg->fg.const_alpha = pstate->property_values[PLANE_PROP_ALPHA];
+
+ /* default to opaque blending */
+ cfg->fg.alpha_sel = ALPHA_FG_CONST;
+ cfg->bg.alpha_sel = ALPHA_BG_CONST;
+ cfg->fg.const_alpha =
+ sde_plane_get_property32(pstate, PLANE_PROP_ALPHA);
cfg->bg.const_alpha = 0xFF - cfg->fg.const_alpha;
- if (format->alpha_enable &&
- pstate->property_values[PLANE_PROP_PREMULTIPLIED]) {
- cfg->fg.alpha_sel = ALPHA_FG_CONST;
- cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
- if (pstate->property_values[PLANE_PROP_ALPHA] != 0xff) {
- cfg->bg.const_alpha =
- (u32)pstate->property_values[PLANE_PROP_ALPHA];
- cfg->bg.inv_alpha_sel = 1;
- cfg->bg.mod_alpha = 1;
- } else {
- cfg->bg.inv_mode_alpha = 1;
- }
- } else if (format->alpha_enable) {
- cfg->fg.alpha_sel = ALPHA_FG_PIXEL;
- cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
- if (pstate->property_values[PLANE_PROP_ALPHA] != 0xff) {
- cfg->bg.const_alpha =
- (u32)pstate->property_values[PLANE_PROP_ALPHA];
- cfg->fg.mod_alpha = 1;
- cfg->bg.inv_alpha_sel = 1;
- cfg->bg.mod_alpha = 1;
- cfg->bg.inv_mode_alpha = 1;
- } else {
- cfg->bg.inv_mode_alpha = 1;
+ blend_op = sde_plane_get_property32(pstate, PLANE_PROP_BLEND_OP);
+
+ if (format->alpha_enable) {
+ switch (blend_op) {
+ case SDE_DRM_BLEND_OP_PREMULTIPLIED:
+ cfg->fg.alpha_sel = ALPHA_FG_CONST;
+ cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
+ if (cfg->fg.const_alpha != 0xff) {
+ cfg->bg.const_alpha = cfg->fg.const_alpha;
+ cfg->bg.mod_alpha = 1;
+ cfg->bg.inv_alpha_sel = 1;
+ } else {
+ cfg->bg.inv_mode_alpha = 1;
+ }
+ break;
+ case SDE_DRM_BLEND_OP_COVERAGE:
+ cfg->fg.alpha_sel = ALPHA_FG_PIXEL;
+ cfg->bg.alpha_sel = ALPHA_FG_PIXEL;
+ if (cfg->fg.const_alpha != 0xff) {
+ cfg->bg.const_alpha = cfg->fg.const_alpha;
+ cfg->fg.mod_alpha = 1;
+ cfg->bg.inv_alpha_sel = 1;
+ cfg->bg.mod_alpha = 1;
+ cfg->bg.inv_mode_alpha = 1;
+ } else {
+ cfg->bg.inv_mode_alpha = 1;
+ }
+ break;
+ default:
+ /* do nothing */
+ break;
}
} else {
- /* opaque blending */
- cfg->fg.alpha_sel = ALPHA_FG_CONST;
- cfg->bg.alpha_sel = ALPHA_BG_CONST;
cfg->bg.inv_alpha_sel = 1;
cfg->fg.const_alpha = 0xFF;
cfg->bg.const_alpha = 0x00;
}
- DBG("format 0x%x, alpha_enable %u premultiplied %llu",
+ DBG("format 0x%x, alpha_enable %u blend_op %u",
format->base.pixel_format, format->alpha_enable,
- pstate->property_values[PLANE_PROP_PREMULTIPLIED]);
+ blend_op);
DBG("fg alpha config %d %d %d %d %d",
cfg->fg.alpha_sel, cfg->fg.const_alpha, cfg->fg.mod_alpha,
cfg->fg.inv_alpha_sel, cfg->fg.inv_mode_alpha);
@@ -290,7 +301,7 @@
pstate = to_sde_plane_state(plane->state);
stage_cfg.stage[pstate->stage][i] =
sde_plane_pipe(plane);
- DBG(" crtc_id %d, layer %d, at stage %d\n",
+ DBG("crtc_id %d, layer %d, at stage %d",
sde_crtc->id,
sde_plane_pipe(plane),
pstate->stage);
@@ -566,8 +577,8 @@
struct plane_state *pa = (struct plane_state *)a;
struct plane_state *pb = (struct plane_state *)b;
- return (int)pa->state->property_values[PLANE_PROP_ZPOS] -
- (int)pb->state->property_values[PLANE_PROP_ZPOS];
+ return (int)sde_plane_get_property(pa->state, PLANE_PROP_ZPOS) -
+ (int)sde_plane_get_property(pb->state, PLANE_PROP_ZPOS);
}
static int sde_crtc_atomic_check(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
index 6e425ce..20e0cc5 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_8996.c
@@ -58,6 +58,9 @@
#define WB2_17X_MASK \
(BIT(SDE_WB_LINE_MODE) | BIT(SDE_WB_TRAFFIC_SHAPER))
+#define DECIMATION_17X_MAX_H 4
+#define DECIMATION_17X_MAX_V 4
+
/**
* set_cfg_1xx_init(): populate sde sub-blocks reg offsets and instance counts
*/
@@ -70,7 +73,8 @@
.danger_lut = 0xFFFF,
.safe_lut = 0xFF00,
.maxdwnscale = 4, .maxupscale = 20,
- .maxhdeciexp = 4, .maxvdeciexp = 4,
+ .maxhdeciexp = DECIMATION_17X_MAX_H,
+ .maxvdeciexp = DECIMATION_17X_MAX_V,
.src_blk = {.id = SDE_SSPP_SRC,
.base = 0x00, .len = 0x150,},
.scaler_blk = {.id = SDE_SSPP_SCALER_QSEED2,
@@ -90,12 +94,13 @@
.danger_lut = 0xFFFF,
.safe_lut = 0xFF00,
.maxdwnscale = 0, .maxupscale = 0,
- .maxhdeciexp = 4, .maxvdeciexp = 4,
- .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
+ .maxhdeciexp = DECIMATION_17X_MAX_H,
+ .maxvdeciexp = DECIMATION_17X_MAX_V,
+ .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x150,},
.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
- .hist_lut = {.id = 0, .base = 0x00, .len = 0x0,},
+ .pa_blk = {.id = 0, .base = 0x200, .len = 0x0,},
+ .hist_lut = {.id = 0, .base = 0xA00, .len = 0x0,},
.pcc_blk = {.id = SDE_SSPP_PCC, .base = 0x01780, .len = 0x64,},
};
@@ -104,8 +109,9 @@
.danger_lut = 0xFFFF,
.safe_lut = 0xFF00,
.maxdwnscale = 0, .maxupscale = 0,
- .maxhdeciexp = 4, .maxvdeciexp = 4,
- .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x0,},
+ .maxhdeciexp = DECIMATION_17X_MAX_H,
+ .maxvdeciexp = DECIMATION_17X_MAX_V,
+ .src_blk = {.id = SDE_SSPP_SRC, .base = 0x00, .len = 0x150,},
.scaler_blk = {.id = 0, .base = 0x00, .len = 0x0,},
.csc_blk = {.id = 0, .base = 0x00, .len = 0x0,},
.pa_blk = {.id = 0, .base = 0x00, .len = 0x0,},
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
index 2eac304..47c5cda 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
@@ -256,7 +256,7 @@
break;
case SSPP_VIG3:
mixercfg |= (i + 1) << 26;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 4;
+ mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 6;
break;
case SSPP_RGB0:
mixercfg |= (i + 1) << 9;
@@ -275,12 +275,12 @@
mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 14;
break;
case SSPP_DMA0:
- mixercfg |= (i + 1) << 0;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
+ mixercfg |= (i + 1) << 18;
+ mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 16;
break;
case SSPP_DMA1:
- mixercfg |= (i + 1) << 0;
- mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 0;
+ mixercfg |= (i + 1) << 21;
+ mixercfg_ext |= ((i > SDE_STAGE_5) ? 1:0) << 18;
break;
case SSPP_CURSOR0:
mixercfg_ext |= (i + 1) << 20;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index f998225..1c5089a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -444,7 +444,8 @@
struct sde_hw_blk_reg_map *c;
u32 idx;
- if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED2, &idx) || !cfg)
+ if (_sspp_subblk_offset(ctx, SDE_SSPP_SCALER_QSEED2, &idx) || !cfg ||
+ !test_bit(SDE_SSPP_SCALER_QSEED2, &ctx->cap->features))
return;
c = &ctx->hw;
@@ -521,7 +522,7 @@
unsigned long features)
{
if (test_bit(SDE_SSPP_SRC, &features)) {
- ops->setup_sourceformat = sde_hw_sspp_setup_format;
+ ops->setup_format = sde_hw_sspp_setup_format;
ops->setup_rects = sde_hw_sspp_setup_rects;
ops->setup_sourceaddress = sde_hw_sspp_setup_sourceaddress;
ops->setup_solidfill = sde_hw_sspp_setup_solidfill;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index db6f14f..6b1833b2 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -161,12 +161,12 @@
*/
struct sde_hw_sspp_ops {
/**
- * setup_sourceformat - setup pixel format cropping rectangle, flip
+ * setup_format - setup pixel format cropping rectangle, flip
* @ctx: Pointer to pipe context
* @cfg: Pointer to pipe config structure
- * @flags: Format flags
+ * @flags: Extra flags for format config
*/
- void (*setup_sourceformat)(struct sde_hw_pipe *ctx,
+ void (*setup_format)(struct sde_hw_pipe *ctx,
struct sde_hw_pipe_cfg *cfg,
u32 flags);
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index ea183a98..c4d3881 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -141,7 +141,30 @@
};
#define to_sde_plane_state(x) \
- container_of(x, struct sde_plane_state, base)
+ container_of(x, struct sde_plane_state, base)
+
+/**
+ * sde_plane_get_property - Query integer value of plane property
+ *
+ * @S: Pointer to plane state
+ * @X: Property index, from enum msm_mdp_plane_property
+ *
+ * Return: Integer value of requested property
+ */
+#define sde_plane_get_property(S, X) \
+ ((S) && ((X) < PLANE_PROP_COUNT) ? ((S)->property_values[(X)]) : 0)
+
+/**
+ * sde_plane_get_property32 - Query 32-bit representation of plane property
+ *
+ * @S: Pointer to plane state
+ * @X: Property index, from enum msm_mdp_plane_property
+ *
+ * Return: 32-bit value of requested property
+ */
+#define sde_plane_get_property32(S, X) \
+ ((S) && ((X) < PLANE_PROP_COUNT) ? \
+ (uint32_t)((S)->property_values[(X)]) : 0)
int sde_disable(struct sde_kms *sde_kms);
int sde_enable(struct sde_kms *sde_kms);
@@ -348,7 +371,7 @@
*/
enum sde_sspp sde_plane_pipe(struct drm_plane *plane);
struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe,
- bool private_plane);
+ bool primary_plane);
/**
* CRTC functions
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 00daa6b..8817a3b 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -43,6 +43,8 @@
struct sde_hw_sharp_cfg sharp_cfg;
struct sde_hw_scaler3_cfg scaler3_cfg;
+ const struct sde_sspp_sub_blks *pipe_sblk;
+
char pipe_name[SDE_NAME_SIZE];
/* debugfs related stuff */
@@ -53,12 +55,6 @@
};
#define to_sde_plane(x) container_of(x, struct sde_plane, base)
-/* macro to obtain int/enum value from plane state, no error checking */
-#define SDE_PLANE_GETINT(S, X) ((S)->property_values[(X)])
-
-/* macro to obtain blob ptr from plane state, no error checking */
-#define SDE_PLANE_GETBLOB(S, X) ((S)->property_blobs[(X)])
-
static bool sde_plane_enabled(struct drm_plane_state *state)
{
return state->fb && state->crtc;
@@ -74,7 +70,7 @@
if (pipe_cfg && fb && psde->pipe_hw->ops.setup_sourceaddress) {
/* stride */
- if (SDE_PLANE_GETINT(pstate, PLANE_PROP_SRC_CONFIG) &
+ if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
BIT(SDE_DRM_DEINTERLACE))
shift = 1;
else
@@ -109,7 +105,7 @@
enum sde_hw_filter *filter, struct sde_mdp_format_params *fmt,
uint32_t chroma_subsampling)
{
- /* calcualte phase steps, leave init phase as zero */
+ /* calculate phase steps, leave init phase as zero */
phase_steps[SDE_SSPP_COMP_0] =
mult_frac(1 << PHASE_STEP_SHIFT, src, dst);
phase_steps[SDE_SSPP_COMP_1_2] =
@@ -224,8 +220,10 @@
size_t len = 0;
void *ret = 0;
- if (pstate && (property < PLANE_PROP_BLOBCOUNT)) {
- blob = SDE_PLANE_GETBLOB(pstate, property);
+ if (!pstate || (property >= PLANE_PROP_BLOBCOUNT)) {
+ DRM_ERROR("Invalid argument(s)\n");
+ } else {
+ blob = pstate->property_blobs[property];
if (blob) {
len = blob->length;
ret = &blob->data;
@@ -429,21 +427,21 @@
/* decimation */
psde->pipe_cfg.horz_decimation =
- SDE_PLANE_GETINT(pstate, PLANE_PROP_H_DECIMATE);
+ sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
psde->pipe_cfg.vert_decimation =
- SDE_PLANE_GETINT(pstate, PLANE_PROP_V_DECIMATE);
+ sde_plane_get_property(pstate, PLANE_PROP_V_DECIMATE);
/* flags */
DBG("Flags 0x%llX, rotation 0x%llX",
- SDE_PLANE_GETINT(pstate, PLANE_PROP_SRC_CONFIG),
- SDE_PLANE_GETINT(pstate, PLANE_PROP_ROTATION));
- if (SDE_PLANE_GETINT(pstate, PLANE_PROP_ROTATION) &
+ 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_GETINT(pstate, PLANE_PROP_ROTATION) &
+ if (sde_plane_get_property(pstate, PLANE_PROP_ROTATION) &
BIT(DRM_REFLECT_Y))
src_fmt_flags |= SDE_SSPP_FLIP_UD;
- if (SDE_PLANE_GETINT(pstate, PLANE_PROP_SRC_CONFIG) &
+ 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);
@@ -594,8 +592,8 @@
}
}
- if (psde->pipe_hw->ops.setup_sourceformat)
- psde->pipe_hw->ops.setup_sourceformat(psde->pipe_hw,
+ if (psde->pipe_hw->ops.setup_format)
+ psde->pipe_hw->ops.setup_format(psde->pipe_hw,
&psde->pipe_cfg, src_fmt_flags);
if (psde->pipe_hw->ops.setup_rects)
psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
@@ -831,9 +829,40 @@
}
}
+static int _sde_plane_get_property_index(struct drm_plane *plane,
+ struct drm_property *property)
+{
+ struct drm_property **prop_array;
+ int idx = PLANE_PROP_COUNT;
+
+ if (!plane) {
+ DRM_ERROR("Invalid plane\n");
+ } else if (!plane->dev || !plane->dev->dev_private) {
+ /* don't access dev_private if !dev */
+ DRM_ERROR("Invalid device\n");
+ } else if (!property) {
+ DRM_ERROR("Incoming property is NULL\n");
+ } else {
+ prop_array = ((struct msm_drm_private *)
+ (plane->dev->dev_private))->plane_property;
+ if (!prop_array)
+ /* should never hit this */
+ DRM_ERROR("Invalid property array\n");
+
+ /* linear search is okay */
+ for (idx = 0; idx < PLANE_PROP_COUNT; ++idx) {
+ if (prop_array[idx] == property)
+ break;
+ }
+ }
+
+ return idx;
+}
+
/* helper to install properties which are common to planes and crtcs */
static void _sde_plane_install_properties(struct drm_plane *plane,
- struct drm_mode_object *obj)
+ struct drm_mode_object *obj,
+ struct sde_mdss_cfg *catalog)
{
static const struct drm_prop_enum_list e_blend_op[] = {
{SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"},
@@ -847,33 +876,29 @@
struct sde_plane *psde = to_sde_plane(plane);
struct drm_device *dev = plane->dev;
struct msm_drm_private *dev_priv = dev->dev_private;
- const struct sde_sspp_sub_blks *sblk = 0;
- const struct sde_sspp_cfg *cfg = 0;
DBG("");
- if (psde && psde->pipe_hw)
- cfg = psde->pipe_hw->cap;
- if (cfg)
- sblk = cfg->sblk;
- if (!sblk) {
+ if (!psde || !psde->pipe_sblk || !catalog) {
DRM_ERROR("Failed to identify catalog definition\n");
return;
}
/* range properties */
- _sde_plane_install_range_property(plane, dev, "zpos", 1, 255, 1,
+ _sde_plane_install_range_property(plane, dev, "zpos", 0, 255, 1,
&(dev_priv->plane_property[PLANE_PROP_ZPOS]));
_sde_plane_install_range_property(plane, dev, "alpha", 0, 255, 255,
&(dev_priv->plane_property[PLANE_PROP_ALPHA]));
+ /* max range of first pipe will be used */
_sde_plane_install_range_property(plane, dev, "h_decimate",
- 0, sblk->maxhdeciexp, 0,
+ 0, psde->pipe_sblk->maxhdeciexp, 0,
&(dev_priv->plane_property[PLANE_PROP_H_DECIMATE]));
+ /* max range of first pipe will be used */
_sde_plane_install_range_property(plane, dev, "v_decimate",
- 0, sblk->maxvdeciexp, 0,
+ 0, psde->pipe_sblk->maxvdeciexp, 0,
&(dev_priv->plane_property[PLANE_PROP_V_DECIMATE]));
_sde_plane_install_range_property(plane, dev, "sync_fence", 0, ~0, 0,
@@ -892,60 +917,56 @@
&(dev_priv->plane_property[PLANE_PROP_SRC_CONFIG]));
/* blob properties */
- _sde_plane_install_blob_property(plane, dev, "scaler",
+ if (psde->features & SDE_SSPP_SCALER)
+ _sde_plane_install_blob_property(plane, dev, "scaler",
&(dev_priv->plane_property[PLANE_PROP_SCALER]));
- _sde_plane_install_blob_property(plane, dev, "csc",
- &(dev_priv->plane_property[PLANE_PROP_CSC]));
+ if (psde->features & BIT(SDE_SSPP_CSC))
+ _sde_plane_install_blob_property(plane, dev, "csc",
+ &(dev_priv->plane_property[PLANE_PROP_CSC]));
}
static int sde_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state, struct drm_property *property,
uint64_t val)
{
- struct drm_device *dev = plane->dev;
struct sde_plane_state *pstate;
- struct drm_property_blob *blob, **prp_blob;
- struct msm_drm_private *dev_priv = dev->dev_private;
+ struct drm_property_blob *blob, **pr_blob;
int idx, ret = -EINVAL;
DBG("");
- pstate = to_sde_plane_state(state);
+ idx = _sde_plane_get_property_index(plane, property);
+ if (!state) {
+ DRM_ERROR("Invalid state\n");
+ } else if (idx < PLANE_PROP_COUNT) {
+ DBG("Set property %d <= %d", idx, (int)val);
+ pstate = to_sde_plane_state(state);
- for (idx = 0; idx < PLANE_PROP_COUNT && ret; ++idx) {
- if (dev_priv->plane_property[idx] == property) {
- DBG("Set property %d <= %d", idx, (int)val);
+ /* extra handling for incoming blob properties */
+ if ((property->flags & DRM_MODE_PROP_BLOB) &&
+ (idx < PLANE_PROP_BLOBCOUNT)) {
+ /* DRM lookup also takes a reference */
+ blob = drm_property_lookup_blob(plane->dev,
+ (uint32_t)val);
+ if (!blob) {
+ DRM_ERROR("Blob not found\n");
+ val = 0;
+ } else {
+ DBG("Blob %u saved", blob->base.id);
+ val = blob->base.id;
- /* extra handling for incoming blob properties */
- if ((property->flags & DRM_MODE_PROP_BLOB) &&
- (idx < PLANE_PROP_BLOBCOUNT)) {
- /* DRM lookup also takes a reference */
- blob = drm_property_lookup_blob(dev,
- (uint32_t)val);
- if (!blob) {
- DRM_ERROR("Blob not found\n");
- val = 0;
- } else {
- DBG("Blob %u saved", blob->base.id);
- val = blob->base.id;
-
- /* save blobs for later */
- prp_blob = &pstate->property_blobs[idx];
- /* need to clear previous reference */
- if (*prp_blob)
- drm_property_unreference_blob(
- *prp_blob);
- *prp_blob = blob;
- }
+ /* save blobs for later */
+ pr_blob = &pstate->property_blobs[idx];
+ /* need to clear previous reference */
+ if (*pr_blob)
+ drm_property_unreference_blob(*pr_blob);
+ *pr_blob = blob;
}
- pstate->property_values[idx] = val;
- ret = 0;
}
+ pstate->property_values[idx] = val;
+ ret = 0;
}
- if (ret == -EINVAL)
- DRM_ERROR("Invalid property set\n");
-
return ret;
}
@@ -955,6 +976,10 @@
int rc;
DBG("");
+
+ if (!plane)
+ return -EINVAL;
+
rc = sde_plane_atomic_set_property(plane, plane->state, property, val);
return rc;
}
@@ -963,26 +988,24 @@
const struct drm_plane_state *state,
struct drm_property *property, uint64_t *val)
{
- struct drm_device *dev = plane->dev;
struct sde_plane_state *pstate;
- struct msm_drm_private *dev_priv = dev->dev_private;
int idx, ret = -EINVAL;
DBG("");
- pstate = to_sde_plane_state(state);
- for (idx = 0; idx < PLANE_PROP_COUNT; ++idx) {
- if (dev_priv->plane_property[idx] == property) {
- *val = pstate->property_values[idx];
- DBG("Get property %d %lld", idx, *val);
- ret = 0;
- break;
- }
+ idx = _sde_plane_get_property_index(plane, property);
+ if (!state) {
+ DRM_ERROR("Invalid state\n");
+ } else if (!val) {
+ DRM_ERROR("Value pointer is NULL\n");
+ } else if (idx < PLANE_PROP_COUNT) {
+ pstate = to_sde_plane_state(state);
+
+ *val = pstate->property_values[idx];
+ DBG("Get property %d %lld", idx, *val);
+ ret = 0;
}
- if (ret == -EINVAL)
- DRM_ERROR("Invalid property get\n");
-
return ret;
}
@@ -997,14 +1020,14 @@
debugfs_remove_recursive(psde->debugfs_root);
- if (psde->pipe_hw)
- sde_hw_sspp_destroy(psde->pipe_hw);
-
drm_plane_helper_disable(plane);
/* this will destroy the states as well */
drm_plane_cleanup(plane);
+ if (psde->pipe_hw)
+ sde_hw_sspp_destroy(psde->pipe_hw);
+
kfree(psde);
}
}
@@ -1075,7 +1098,6 @@
/* assign default blend parameters */
pstate->property_values[PLANE_PROP_ALPHA] = 255;
- pstate->property_values[PLANE_PROP_PREMULTIPLIED] = 0;
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
pstate->property_values[PLANE_PROP_ZPOS] = STAGE_BASE;
@@ -1131,7 +1153,7 @@
sde_debugfs_get_root(kms));
if (psde->debugfs_root) {
/* don't error check these */
- debugfs_create_x32("features", 0444,
+ debugfs_create_x32("features", 0644,
psde->debugfs_root, &psde->features);
/* add register dump support */
@@ -1162,15 +1184,19 @@
/* initialize plane */
struct drm_plane *sde_plane_init(struct drm_device *dev,
- uint32_t pipe, bool private_plane)
+ uint32_t pipe, bool primary_plane)
{
struct drm_plane *plane = NULL;
struct sde_plane *psde;
struct msm_drm_private *priv;
struct sde_kms *kms;
- struct sde_mdss_cfg *sde_cat;
- int ret;
enum drm_plane_type type;
+ int ret = -EINVAL;
+
+ if (!dev) {
+ DRM_ERROR("[%u]Device is NULL\n", pipe);
+ goto exit;
+ }
priv = dev->dev_private;
if (!priv) {
@@ -1184,61 +1210,80 @@
}
kms = to_sde_kms(priv->kms);
+ if (!kms->catalog) {
+ DRM_ERROR("[%u]Invalid catalog reference\n", pipe);
+ goto exit;
+ }
+
/* create and zero local structure */
psde = kzalloc(sizeof(*psde), GFP_KERNEL);
if (!psde) {
+ DRM_ERROR("[%u]Failed to allocate local plane struct\n", pipe);
ret = -ENOMEM;
- goto fail;
+ goto exit;
}
+ /* cache local stuff for later */
plane = &psde->base;
-
psde->pipe = pipe;
+ psde->mmu_id = kms->mmu_id;
- if (kms) {
- /* mmu id for buffer mapping */
- psde->mmu_id = kms->mmu_id;
-
- /* check catalog for features mask */
- sde_cat = kms->catalog;
- if (sde_cat)
- psde->features = sde_cat->sspp[pipe].features;
+ /* initialize underlying h/w driver */
+ psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, kms->catalog);
+ if (IS_ERR(psde->pipe_hw)) {
+ DRM_ERROR("[%u]SSPP init failed\n", pipe);
+ ret = PTR_ERR(psde->pipe_hw);
+ goto clean_plane;
+ } else if (!psde->pipe_hw->cap || !psde->pipe_hw->cap->sblk) {
+ DRM_ERROR("[%u]SSPP init returned invalid cfg\n", pipe);
+ goto clean_sspp;
}
+
+ /* cache features mask for later */
+ psde->features = psde->pipe_hw->cap->features;
+ psde->pipe_sblk = psde->pipe_hw->cap->sblk;
+
+ /* add plane to DRM framework */
psde->nformats = mdp_get_formats(psde->formats,
ARRAY_SIZE(psde->formats),
!(psde->features & BIT(SDE_SSPP_CSC)) ||
!(psde->features & SDE_SSPP_SCALER));
- type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+ if (!psde->nformats) {
+ DRM_ERROR("[%u]No valid formats for plane\n", pipe);
+ goto clean_sspp;
+ }
+
+ if (psde->features & BIT(SDE_SSPP_CURSOR))
+ type = DRM_PLANE_TYPE_CURSOR;
+ else if (primary_plane)
+ type = DRM_PLANE_TYPE_PRIMARY;
+ else
+ type = DRM_PLANE_TYPE_OVERLAY;
ret = drm_universal_plane_init(dev, plane, 0xff, &sde_plane_funcs,
psde->formats, psde->nformats,
type);
if (ret)
- goto fail;
+ goto clean_sspp;
+ /* success! finalize initialization */
drm_plane_helper_add(plane, &sde_plane_helper_funcs);
- psde->pipe_hw = sde_hw_sspp_init(pipe, kms->mmio, sde_cat);
- if (IS_ERR(psde->pipe_hw)) {
- ret = PTR_ERR(psde->pipe_hw);
- psde->pipe_hw = NULL;
- goto fail;
- }
-
- _sde_plane_install_properties(plane, &plane->base);
+ _sde_plane_install_properties(plane, &plane->base, kms->catalog);
/* save user friendly pipe name for later */
snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);
_sde_plane_init_debugfs(psde, kms);
- DRM_INFO("Successfully created plane for %s\n", psde->pipe_name);
+ DRM_INFO("[%u]Successfully created %s\n", pipe, psde->pipe_name);
return plane;
-fail:
- DRM_ERROR("Plane creation failed\n");
- if (plane)
- sde_plane_destroy(plane);
+clean_sspp:
+ if (psde && psde->pipe_hw)
+ sde_hw_sspp_destroy(psde->pipe_hw);
+clean_plane:
+ kfree(psde);
exit:
return ERR_PTR(ret);
}