summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClarence Ip <cip@codeaurora.org>2016-09-23 15:03:34 -0400
committerClarence Ip <cip@codeaurora.org>2016-10-05 10:54:00 -0400
commit1f819168bd4460619d250e1053886ffa7175d724 (patch)
tree03dfb8707c161254c41d35b6adce0be24298ebad
parente3d64dab54a86784d7e7dab4dfd576febbef1996 (diff)
drm/msm/sde: update csc property definition and type
Blob properties under DRM require a new blob to be created for each unique set of incoming data. By changing the csc property to accept an incoming user space pointer and using copy_from_user to explicitly copy out the structure data each time the property is set, the user space client avoids the need to create new DRM blob objects when the csc configuration needs to be updated. Change-Id: I7586d407ef9d65a927c93b59cdd0128cef498378 Signed-off-by: Clarence Ip <cip@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/msm_prop.c37
-rw-r--r--drivers/gpu/drm/msm/msm_prop.h26
-rw-r--r--drivers/gpu/drm/msm/sde/sde_plane.c145
-rw-r--r--include/uapi/drm/sde_drm.h16
5 files changed, 129 insertions, 97 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 30aea910bee8..2266d2ab2f00 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -81,7 +81,7 @@ struct msm_file_private {
enum msm_mdp_plane_property {
/* blob properties, always put these first */
PLANE_PROP_SCALER,
- PLANE_PROP_CSC,
+ PLANE_PROP_CSC_V1,
PLANE_PROP_INFO,
/* # of blob properties */
diff --git a/drivers/gpu/drm/msm/msm_prop.c b/drivers/gpu/drm/msm/msm_prop.c
index 90310fb6369e..5a9e472ea59b 100644
--- a/drivers/gpu/drm/msm/msm_prop.c
+++ b/drivers/gpu/drm/msm/msm_prop.c
@@ -134,9 +134,20 @@ static void _msm_property_set_dirty_no_lock(
&info->dirty_list);
}
-void msm_property_install_range(struct msm_property_info *info,
+/**
+ * _msm_property_install_integer - install standard drm range property
+ * @info: Pointer to property info container struct
+ * @name: Property name
+ * @flags: Other property type flags, e.g. DRM_MODE_PROP_IMMUTABLE
+ * @min: Min property value
+ * @max: Max property value
+ * @init: Default Property value
+ * @property_idx: Property index
+ * @force_dirty: Whether or not to filter 'dirty' status on unchanged values
+ */
+static void _msm_property_install_integer(struct msm_property_info *info,
const char *name, int flags, uint64_t min, uint64_t max,
- uint64_t init, uint32_t property_idx)
+ uint64_t init, uint32_t property_idx, bool force_dirty)
{
struct drm_property **prop;
@@ -162,6 +173,7 @@ void msm_property_install_range(struct msm_property_info *info,
/* save init value for later */
info->property_data[property_idx].default_value = init;
+ info->property_data[property_idx].force_dirty = force_dirty;
/* always attach property, if created */
if (*prop) {
@@ -171,6 +183,22 @@ void msm_property_install_range(struct msm_property_info *info,
}
}
+void msm_property_install_range(struct msm_property_info *info,
+ const char *name, int flags, uint64_t min, uint64_t max,
+ uint64_t init, uint32_t property_idx)
+{
+ _msm_property_install_integer(info, name, flags,
+ min, max, init, property_idx, false);
+}
+
+void msm_property_install_volatile_range(struct msm_property_info *info,
+ const char *name, int flags, uint64_t min, uint64_t max,
+ uint64_t init, uint32_t property_idx)
+{
+ _msm_property_install_integer(info, name, flags,
+ min, max, init, property_idx, true);
+}
+
void msm_property_install_rotation(struct msm_property_info *info,
unsigned int supported_rotations, uint32_t property_idx)
{
@@ -198,6 +226,7 @@ void msm_property_install_rotation(struct msm_property_info *info,
/* save init value for later */
info->property_data[property_idx].default_value = 0;
+ info->property_data[property_idx].force_dirty = false;
/* always attach property, if created */
if (*prop) {
@@ -244,6 +273,7 @@ void msm_property_install_enum(struct msm_property_info *info,
/* save init value for later */
info->property_data[property_idx].default_value = 0;
+ info->property_data[property_idx].force_dirty = false;
/* always attach property, if created */
if (*prop) {
@@ -281,6 +311,7 @@ void msm_property_install_blob(struct msm_property_info *info,
/* save init value for later */
info->property_data[property_idx].default_value = 0;
+ info->property_data[property_idx].force_dirty = true;
/* always attach property, if created */
if (*prop) {
@@ -377,7 +408,7 @@ int msm_property_atomic_set(struct msm_property_info *info,
/* update value and flag as dirty */
if (property_values[property_idx] != val ||
- property_idx < info->blob_count) {
+ info->property_data[property_idx].force_dirty) {
property_values[property_idx] = val;
_msm_property_set_dirty_no_lock(info, property_idx);
diff --git a/drivers/gpu/drm/msm/msm_prop.h b/drivers/gpu/drm/msm/msm_prop.h
index f065cbffda09..dbe28bdf5638 100644
--- a/drivers/gpu/drm/msm/msm_prop.h
+++ b/drivers/gpu/drm/msm/msm_prop.h
@@ -23,10 +23,13 @@
* drm-object per property stuff
* @default_value: Default property value for this drm object
* @dirty_node: Linked list node to track if property is dirty or not
+ * @force_dirty: Always dirty property on incoming sets, rather than checking
+ * for modified values
*/
struct msm_property_data {
uint64_t default_value;
struct list_head dirty_node;
+ bool force_dirty;
};
/**
@@ -172,7 +175,7 @@ void msm_property_destroy(struct msm_property_info *info);
* @flags: Other property type flags, e.g. DRM_MODE_PROP_IMMUTABLE
* @min: Min property value
* @max: Max property value
- * @init: Default property value
+ * @init: Default Property value
* @property_idx: Property index
*/
void msm_property_install_range(struct msm_property_info *info,
@@ -184,6 +187,27 @@ void msm_property_install_range(struct msm_property_info *info,
uint32_t property_idx);
/**
+ * msm_property_install_volatile_range - install drm range property
+ * This function is similar to msm_property_install_range, but assumes
+ * that the property is meant for holding user pointers or descriptors
+ * that may reference volatile data without having an updated value.
+ * @info: Pointer to property info container struct
+ * @name: Property name
+ * @flags: Other property type flags, e.g. DRM_MODE_PROP_IMMUTABLE
+ * @min: Min property value
+ * @max: Max property value
+ * @init: Default Property value
+ * @property_idx: Property index
+ */
+void msm_property_install_volatile_range(struct msm_property_info *info,
+ const char *name,
+ int flags,
+ uint64_t min,
+ uint64_t max,
+ uint64_t init,
+ uint32_t property_idx);
+
+/**
* msm_property_install_rotation - install standard drm rotation property
* @info: Pointer to property info container struct
* @supported_rotations: Bitmask of supported rotation values (see
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index dbc531b68d66..661695eaf72d 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -58,6 +58,12 @@ enum sde_plane_qos {
SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
};
+/*
+ * struct sde_plane - local sde plane structure
+ * @csc_cfg: Decoded user configuration for csc
+ * @csc_usr_ptr: Points to csc_cfg if valid user config available
+ * @csc_ptr: Points to sde_csc_cfg structure to use for current
+ */
struct sde_plane {
struct drm_plane base;
@@ -81,6 +87,7 @@ struct sde_plane {
bool is_rt_pipe;
struct sde_csc_cfg csc_cfg;
+ struct sde_csc_cfg *csc_usr_ptr;
struct sde_csc_cfg *csc_ptr;
const struct sde_sspp_sub_blks *pipe_sblk;
@@ -736,9 +743,7 @@ static int _sde_plane_verify_blob(void *blob_ptr,
return -EINVAL;
}
-static void _sde_plane_setup_csc(struct sde_plane *psde,
- struct sde_plane_state *pstate,
- const struct sde_format *fmt)
+static inline void _sde_plane_setup_csc(struct sde_plane *psde)
{
static const struct sde_csc_cfg sde_csc_YUV2RGB_601L = {
{
@@ -754,78 +759,22 @@ static void _sde_plane_setup_csc(struct sde_plane *psde,
{ 0x10, 0xeb, 0x10, 0xf0, 0x10, 0xf0,},
{ 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,},
};
- static const struct sde_csc_cfg sde_csc_NOP = {
- {
- /* identity matrix, S15.16 format */
- 0x10000, 0x00000, 0x00000,
- 0x00000, 0x10000, 0x00000,
- 0x00000, 0x00000, 0x10000,
- },
- /* signed bias */
- { 0x0, 0x0, 0x0,},
- { 0x0, 0x0, 0x0,},
- /* unsigned clamp */
- { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,},
- { 0x0, 0xff, 0x0, 0xff, 0x0, 0xff,},
- };
- struct sde_drm_csc *csc = NULL;
- size_t csc_size = 0;
- int i;
- if (!psde || !pstate || !fmt) {
- SDE_ERROR("invalid arguments\n");
- return;
- }
- if (!psde->pipe_hw || !psde->pipe_hw->ops.setup_csc)
+ if (!psde) {
+ SDE_ERROR("invalid plane\n");
return;
-
- /* check for user space override */
- psde->csc_ptr = NULL;
- csc = msm_property_get_blob(&psde->property_info,
- pstate->property_blobs,
- &csc_size,
- PLANE_PROP_CSC);
- if (csc) {
- /* user space override */
- memcpy(&psde->csc_cfg,
- &sde_csc_NOP,
- sizeof(struct sde_csc_cfg));
- switch (csc->version) {
- case SDE_DRM_CSC_V1:
- if (!_sde_plane_verify_blob(csc,
- csc_size,
- &csc->v1,
- sizeof(struct sde_drm_csc_v1))) {
- for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
- psde->csc_cfg.csc_mv[i] =
- csc->v1.ctm_coeff[i] >> 16;
- for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
- psde->csc_cfg.csc_pre_bv[i] =
- csc->v1.pre_bias[i];
- psde->csc_cfg.csc_post_bv[i] =
- csc->v1.post_bias[i];
- }
- for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
- psde->csc_cfg.csc_pre_lv[i] =
- csc->v1.pre_clamp[i];
- psde->csc_cfg.csc_post_lv[i] =
- csc->v1.post_clamp[i];
- }
- psde->csc_ptr = &psde->csc_cfg;
- }
- break;
- default:
- break;
- }
- if (!psde->csc_ptr)
- SDE_ERROR("invalid csc blob, v%lld\n", csc->version);
}
/* revert to kernel default if override not available */
- if (psde->csc_ptr)
- SDE_DEBUG("user blob override for csc\n");
- else if (SDE_FORMAT_IS_YUV(fmt))
+ if (psde->csc_usr_ptr)
+ psde->csc_ptr = psde->csc_usr_ptr;
+ else
psde->csc_ptr = (struct sde_csc_cfg *)&sde_csc_YUV2RGB_601L;
+
+ SDE_DEBUG("using 0x%X 0x%X 0x%X...\n",
+ psde->csc_ptr->csc_mv[0],
+ psde->csc_ptr->csc_mv[1],
+ psde->csc_ptr->csc_mv[2]);
}
static void _sde_plane_setup_scaler(struct sde_plane *psde,
@@ -1096,7 +1045,7 @@ static int _sde_plane_mode_set(struct drm_plane *plane,
case PLANE_PROP_SCALER:
pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
break;
- case PLANE_PROP_CSC:
+ case PLANE_PROP_CSC_V1:
pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
break;
case PLANE_PROP_COLOR_FILL:
@@ -1203,7 +1152,7 @@ static int _sde_plane_mode_set(struct drm_plane *plane,
/* update csc */
if (SDE_FORMAT_IS_YUV(fmt))
- _sde_plane_setup_csc(psde, pstate, fmt);
+ _sde_plane_setup_csc(psde);
else
psde->csc_ptr = 0;
}
@@ -1587,6 +1536,11 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
msm_property_install_range(&psde->property_info, "input_fence",
0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
+ if (psde->features & BIT(SDE_SSPP_CSC)) {
+ msm_property_install_volatile_range(&psde->property_info,
+ "csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
+ }
+
/* standard properties */
msm_property_install_rotation(&psde->property_info,
BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);
@@ -1605,10 +1559,6 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
msm_property_install_blob(&psde->property_info, "scaler", 0,
PLANE_PROP_SCALER);
- if (psde->features & BIT(SDE_SSPP_CSC))
- msm_property_install_blob(&psde->property_info, "csc", 0,
- PLANE_PROP_CSC);
-
info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
if (!info)
return;
@@ -1645,6 +1595,40 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
kfree(info);
}
+static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)
+{
+ struct sde_drm_csc_v1 csc_v1;
+ int i;
+
+ if (!psde) {
+ SDE_ERROR("invalid plane\n");
+ return;
+ }
+
+ psde->csc_usr_ptr = NULL;
+ if (!usr_ptr) {
+ SDE_DEBUG("csc data removed\n");
+ return;
+ }
+
+ if (copy_from_user(&csc_v1, usr_ptr, sizeof(csc_v1))) {
+ SDE_ERROR("failed to copy csc data\n");
+ return;
+ }
+
+ for (i = 0; i < SDE_CSC_MATRIX_COEFF_SIZE; ++i)
+ psde->csc_cfg.csc_mv[i] = csc_v1.ctm_coeff[i] >> 16;
+ for (i = 0; i < SDE_CSC_BIAS_SIZE; ++i) {
+ psde->csc_cfg.csc_pre_bv[i] = csc_v1.pre_bias[i];
+ psde->csc_cfg.csc_post_bv[i] = csc_v1.post_bias[i];
+ }
+ for (i = 0; i < SDE_CSC_CLAMP_SIZE; ++i) {
+ psde->csc_cfg.csc_pre_lv[i] = csc_v1.pre_clamp[i];
+ psde->csc_cfg.csc_post_lv[i] = csc_v1.post_clamp[i];
+ }
+ psde->csc_usr_ptr = &psde->csc_cfg;
+}
+
static int sde_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state, struct drm_property *property,
uint64_t val)
@@ -1668,8 +1652,17 @@ static int sde_plane_atomic_set_property(struct drm_plane *plane,
if (!ret) {
idx = msm_property_index(&psde->property_info,
property);
- if (idx == PLANE_PROP_INPUT_FENCE)
+ switch (idx) {
+ case PLANE_PROP_INPUT_FENCE:
_sde_plane_set_input_fence(plane, pstate, val);
+ break;
+ case PLANE_PROP_CSC_V1:
+ _sde_plane_set_csc_v1(psde, (void *)val);
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
}
}
diff --git a/include/uapi/drm/sde_drm.h b/include/uapi/drm/sde_drm.h
index bcd64c23eb14..35b3bc782921 100644
--- a/include/uapi/drm/sde_drm.h
+++ b/include/uapi/drm/sde_drm.h
@@ -188,10 +188,6 @@ struct sde_drm_scaler {
#define SDE_CSC_CLAMP_SIZE 6
#define SDE_CSC_BIAS_SIZE 3
-/* CSC version definition, see top of file for guidelines */
-#define SDE_DRM_CSC_V1 0x1
-#define SDE_DRM_CSC_VERSION SDE_DRM_CSC_V1
-
/**
* struct sde_drm_csc_v1 - version 1 of struct sde_drm_csc
* @ctm_coeff: Matrix coefficients, in S31.32 format
@@ -208,18 +204,6 @@ struct sde_drm_csc_v1 {
uint32_t post_clamp[SDE_CSC_CLAMP_SIZE];
};
-/**
- * struct sde_drm_csc - CSC configuration structure
- * @version: Structure version, set to SDE_DRM_CSC_VERSION
- * @v1: Version 1 of csc structure
- */
-struct sde_drm_csc {
- uint64_t version;
- union {
- struct sde_drm_csc_v1 v1;
- };
-};
-
/* Writeback Config version definition */
#define SDE_DRM_WB_CFG 0x1