disp: msm: sde: program dither based on input data

This change programs dither based on user mode input data and
reprograms the dither when device comes out of power collapse.

Change-Id: I83be20c8eb2dc2221cc57cd2395f6512338ff6ef
Signed-off-by: Narendra Muppalla <NarendraM@codeaurora.org>
This commit is contained in:
Narendra Muppalla
2019-07-05 18:28:49 -07:00
parent 52161a09b6
commit f402d8e542
7 changed files with 118 additions and 141 deletions

View File

@@ -29,9 +29,6 @@
#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
static u32 dither_matrix[DITHER_MATRIX_SZ] = {
15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
};
static const struct drm_prop_enum_list e_topology_name[] = {
{SDE_RM_TOPOLOGY_NONE, "sde_none"},
@@ -245,60 +242,12 @@ void sde_connector_unregister_event(struct drm_connector *connector,
(void)sde_connector_register_event(connector, event_idx, 0, 0);
}
static int _sde_connector_get_default_dither_cfg_v1(
struct sde_connector *c_conn, void *cfg)
{
struct drm_msm_dither *dither_cfg = (struct drm_msm_dither *)cfg;
enum dsi_pixel_format dst_format = DSI_PIXEL_FORMAT_MAX;
if (!c_conn || !cfg) {
SDE_ERROR("invalid argument(s), c_conn %pK, cfg %pK\n",
c_conn, cfg);
return -EINVAL;
}
if (!c_conn->ops.get_dst_format) {
SDE_DEBUG("get_dst_format is unavailable\n");
return 0;
}
dst_format = c_conn->ops.get_dst_format(&c_conn->base, c_conn->display);
switch (dst_format) {
case DSI_PIXEL_FORMAT_RGB888:
dither_cfg->c0_bitdepth = 8;
dither_cfg->c1_bitdepth = 8;
dither_cfg->c2_bitdepth = 8;
dither_cfg->c3_bitdepth = 8;
break;
case DSI_PIXEL_FORMAT_RGB666:
case DSI_PIXEL_FORMAT_RGB666_LOOSE:
dither_cfg->c0_bitdepth = 6;
dither_cfg->c1_bitdepth = 6;
dither_cfg->c2_bitdepth = 6;
dither_cfg->c3_bitdepth = 6;
break;
default:
SDE_DEBUG("no default dither config for dst_format %d\n",
dst_format);
return -ENODATA;
}
memcpy(&dither_cfg->matrix, dither_matrix,
sizeof(u32) * DITHER_MATRIX_SZ);
dither_cfg->temporal_en = 0;
return 0;
}
static void _sde_connector_install_dither_property(struct drm_device *dev,
struct sde_kms *sde_kms, struct sde_connector *c_conn)
{
char prop_name[DRM_PROP_NAME_LEN];
struct sde_mdss_cfg *catalog = NULL;
struct drm_property_blob *blob_ptr;
void *cfg;
int ret = 0;
u32 version = 0, len = 0;
bool defalut_dither_needed = false;
u32 version = 0;
if (!dev || !sde_kms || !c_conn) {
SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n",
@@ -313,57 +262,55 @@ static void _sde_connector_install_dither_property(struct drm_device *dev,
"SDE_PP_DITHER_V", version);
switch (version) {
case 1:
case 2:
msm_property_install_blob(&c_conn->property_info, prop_name,
DRM_MODE_PROP_BLOB,
CONNECTOR_PROP_PP_DITHER);
len = sizeof(struct drm_msm_dither);
cfg = kzalloc(len, GFP_KERNEL);
if (!cfg)
return;
ret = _sde_connector_get_default_dither_cfg_v1(c_conn, cfg);
if (!ret)
defalut_dither_needed = true;
break;
default:
SDE_ERROR("unsupported dither version %d\n", version);
return;
}
if (defalut_dither_needed) {
blob_ptr = drm_property_create_blob(dev, len, cfg);
if (IS_ERR_OR_NULL(blob_ptr))
goto exit;
c_conn->blob_dither = blob_ptr;
}
exit:
kfree(cfg);
}
int sde_connector_get_dither_cfg(struct drm_connector *conn,
struct drm_connector_state *state, void **cfg,
size_t *len)
size_t *len, bool idle_pc)
{
struct sde_connector *c_conn = NULL;
struct sde_connector_state *c_state = NULL;
size_t dither_sz = 0;
bool is_dirty;
u32 *p = (u32 *)cfg;
if (!conn || !state || !p)
if (!conn || !state || !p) {
SDE_ERROR("invalid arguments\n");
return -EINVAL;
}
c_conn = to_sde_connector(conn);
c_state = to_sde_connector_state(state);
/* try to get user config data first */
*cfg = msm_property_get_blob(&c_conn->property_info,
&c_state->property_state,
&dither_sz,
CONNECTOR_PROP_PP_DITHER);
/* if user config data doesn't exist, use default dither blob */
if (*cfg == NULL && c_conn->blob_dither) {
*cfg = &c_conn->blob_dither->data;
dither_sz = c_conn->blob_dither->length;
is_dirty = msm_property_is_dirty(&c_conn->property_info,
&c_state->property_state,
CONNECTOR_PROP_PP_DITHER);
if (!is_dirty && !idle_pc) {
return -ENODATA;
} else if (is_dirty || idle_pc) {
*cfg = msm_property_get_blob(&c_conn->property_info,
&c_state->property_state,
&dither_sz,
CONNECTOR_PROP_PP_DITHER);
/*
* in idle_pc use case return early,
* when dither is already disabled.
*/
if (idle_pc && *cfg == NULL)
return -ENODATA;
/* disable dither based on user config data */
else if (*cfg == NULL)
return 0;
}
*len = dither_sz;
return 0;