|
@@ -29,9 +29,6 @@
|
|
|
|
|
|
#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
|
|
#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
|
|
(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
|
|
(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[] = {
|
|
static const struct drm_prop_enum_list e_topology_name[] = {
|
|
{SDE_RM_TOPOLOGY_NONE, "sde_none"},
|
|
{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);
|
|
(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,
|
|
static void _sde_connector_install_dither_property(struct drm_device *dev,
|
|
struct sde_kms *sde_kms, struct sde_connector *c_conn)
|
|
struct sde_kms *sde_kms, struct sde_connector *c_conn)
|
|
{
|
|
{
|
|
char prop_name[DRM_PROP_NAME_LEN];
|
|
char prop_name[DRM_PROP_NAME_LEN];
|
|
struct sde_mdss_cfg *catalog = NULL;
|
|
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) {
|
|
if (!dev || !sde_kms || !c_conn) {
|
|
SDE_ERROR("invld args (s), dev %pK, sde_kms %pK, c_conn %pK\n",
|
|
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);
|
|
"SDE_PP_DITHER_V", version);
|
|
switch (version) {
|
|
switch (version) {
|
|
case 1:
|
|
case 1:
|
|
|
|
+ case 2:
|
|
msm_property_install_blob(&c_conn->property_info, prop_name,
|
|
msm_property_install_blob(&c_conn->property_info, prop_name,
|
|
DRM_MODE_PROP_BLOB,
|
|
DRM_MODE_PROP_BLOB,
|
|
CONNECTOR_PROP_PP_DITHER);
|
|
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;
|
|
break;
|
|
default:
|
|
default:
|
|
SDE_ERROR("unsupported dither version %d\n", version);
|
|
SDE_ERROR("unsupported dither version %d\n", version);
|
|
return;
|
|
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,
|
|
int sde_connector_get_dither_cfg(struct drm_connector *conn,
|
|
struct drm_connector_state *state, void **cfg,
|
|
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 *c_conn = NULL;
|
|
struct sde_connector_state *c_state = NULL;
|
|
struct sde_connector_state *c_state = NULL;
|
|
size_t dither_sz = 0;
|
|
size_t dither_sz = 0;
|
|
|
|
+ bool is_dirty;
|
|
u32 *p = (u32 *)cfg;
|
|
u32 *p = (u32 *)cfg;
|
|
|
|
|
|
- if (!conn || !state || !p)
|
|
|
|
|
|
+ if (!conn || !state || !p) {
|
|
|
|
+ SDE_ERROR("invalid arguments\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
+ }
|
|
|
|
|
|
c_conn = to_sde_connector(conn);
|
|
c_conn = to_sde_connector(conn);
|
|
c_state = to_sde_connector_state(state);
|
|
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;
|
|
*len = dither_sz;
|
|
return 0;
|
|
return 0;
|