Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a68a69ae authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: program dither based on input data"

parents 0a650460 9b15aa8e
Loading
Loading
Loading
Loading
+27 −81
Original line number Diff line number Diff line
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -34,9 +34,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"},
@@ -240,60 +237,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",
@@ -311,54 +260,51 @@ static void _sde_connector_install_dither_property(struct drm_device *dev,
		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 */
	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);
	/* 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;
		/*
		 * 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;
+4 −2
Original line number Diff line number Diff line
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -808,10 +808,12 @@ static inline bool sde_connector_needs_offset(struct drm_connector *connector)
 * @state: Pointer to drm_connector_state struct
 * @cfg: Pointer to pointer to dither cfg
 * @len: length of the dither data
 * @idle_pc: flag to indicate idle_pc_restore happened
 * Returns: Zero on success
 */
int sde_connector_get_dither_cfg(struct drm_connector *conn,
		struct drm_connector_state *state, void **cfg, size_t *len);
		struct drm_connector_state *state, void **cfg,
		size_t *len, bool idle_pc);

/**
 * sde_connector_set_blob_data - set connector blob property data
+3 −2
Original line number Diff line number Diff line
@@ -4196,7 +4196,7 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc)

static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
{
	void *dither_cfg;
	void *dither_cfg = NULL;
	int ret = 0, rc, i = 0;
	size_t len = 0;
	enum sde_rm_topology_name topology;
@@ -4231,7 +4231,8 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
	}

	ret = sde_connector_get_dither_cfg(phys->connector,
			phys->connector->state, &dither_cfg, &len);
			phys->connector->state, &dither_cfg,
			&len, sde_enc->idle_pc_restore);
	if (ret)
		return;