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

Commit c42ce055 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/sde: add 4k hdmi support"

parents 92ad29f0 68b757f5
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
Qualcomm Technologies,Inc. Adreno/Snapdragon display controller

Required properties:

Optional properties:
- qcom,sde-plane-id-map: plane id mapping for virtual plane.
- qcom,sde-plane-id: each virtual plane mapping node.
- reg: reg property.
- qcom,display-type: display type this plane is mapped to. It could be
 "primary", "secondary" and "tertiary".
- qcom,plane-name: plane name array for this virtual plane. It could be
 "rgb0", "rgb1", "rgb2", "rgb3", "vig0", "vig1", "vig2", "vig3", "dma0", "dma1",
 "dma2", "dma3", "cursor0", "cursor1".
- qcom,plane-type: virtual plane type. It could be "primary", "overlay",
 "cursor".

Example:

&mdss_mdp {
	qcom,sde-plane-id-map {
		qcom,sde-plane-id@0 {
			reg = <0x0>;
			qcom,display-type = "primary";
			qcom,plane-name = "rgb0", "rgb1";
			qcom,plane-type = "primary";
		};

		qcom,sde-plane-id@1 {
			reg = <0x1>;
			qcom,display-type = "primary";
			qcom,plane-name = "vig0", "vig1";
			qcom,plane-type = "overlay";
		};

		qcom,sde-plane-id@2 {
			reg = <0x2>;
			qcom,display-type = "primary";
			qcom,plane-name = "cursor0", "cursor1";
			qcom,plane-type = "cursor";
		};
	};
};
+5 −2
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ static LIST_HEAD(sde_hdmi_list);
#define HDMI_SCDC_ERR_DET_2_H           0x55
#define HDMI_SCDC_ERR_DET_CHECKSUM      0x56

#define HDMI_DISPLAY_MAX_WIDTH          4096
#define HDMI_DISPLAY_MAX_HEIGHT         2160

static const struct of_device_id sde_hdmi_dt_match[] = {
	{.compatible = "qcom,hdmi-display"},
	{}
@@ -1454,8 +1457,8 @@ int sde_hdmi_get_info(struct msm_display_info *info,
				MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_VID_MODE;
	}
	info->is_connected = hdmi_display->connected;
	info->max_width = 4096;
	info->max_height = 2160;
	info->max_width = HDMI_DISPLAY_MAX_WIDTH;
	info->max_height = HDMI_DISPLAY_MAX_HEIGHT;
	info->compression = MSM_DISPLAY_COMPRESS_NONE;

	mutex_unlock(&hdmi_display->display_lock);
+9 −9
Original line number Diff line number Diff line
@@ -466,13 +466,13 @@ static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
#define REG_HDMI_CEC_RD_FILTER					0x000002b0

#define REG_HDMI_ACTIVE_HSYNC					0x000002b4
#define HDMI_ACTIVE_HSYNC_START__MASK				0x00000fff
#define HDMI_ACTIVE_HSYNC_START__MASK				0x00001fff
#define HDMI_ACTIVE_HSYNC_START__SHIFT				0
static inline uint32_t HDMI_ACTIVE_HSYNC_START(uint32_t val)
{
	return ((val) << HDMI_ACTIVE_HSYNC_START__SHIFT) & HDMI_ACTIVE_HSYNC_START__MASK;
}
#define HDMI_ACTIVE_HSYNC_END__MASK				0x0fff0000
#define HDMI_ACTIVE_HSYNC_END__MASK				0x1fff0000
#define HDMI_ACTIVE_HSYNC_END__SHIFT				16
static inline uint32_t HDMI_ACTIVE_HSYNC_END(uint32_t val)
{
@@ -480,13 +480,13 @@ static inline uint32_t HDMI_ACTIVE_HSYNC_END(uint32_t val)
}

#define REG_HDMI_ACTIVE_VSYNC					0x000002b8
#define HDMI_ACTIVE_VSYNC_START__MASK				0x00000fff
#define HDMI_ACTIVE_VSYNC_START__MASK				0x00001fff
#define HDMI_ACTIVE_VSYNC_START__SHIFT				0
static inline uint32_t HDMI_ACTIVE_VSYNC_START(uint32_t val)
{
	return ((val) << HDMI_ACTIVE_VSYNC_START__SHIFT) & HDMI_ACTIVE_VSYNC_START__MASK;
}
#define HDMI_ACTIVE_VSYNC_END__MASK				0x0fff0000
#define HDMI_ACTIVE_VSYNC_END__MASK				0x1fff0000
#define HDMI_ACTIVE_VSYNC_END__SHIFT				16
static inline uint32_t HDMI_ACTIVE_VSYNC_END(uint32_t val)
{
@@ -494,13 +494,13 @@ static inline uint32_t HDMI_ACTIVE_VSYNC_END(uint32_t val)
}

#define REG_HDMI_VSYNC_ACTIVE_F2				0x000002bc
#define HDMI_VSYNC_ACTIVE_F2_START__MASK			0x00000fff
#define HDMI_VSYNC_ACTIVE_F2_START__MASK			0x00001fff
#define HDMI_VSYNC_ACTIVE_F2_START__SHIFT			0
static inline uint32_t HDMI_VSYNC_ACTIVE_F2_START(uint32_t val)
{
	return ((val) << HDMI_VSYNC_ACTIVE_F2_START__SHIFT) & HDMI_VSYNC_ACTIVE_F2_START__MASK;
}
#define HDMI_VSYNC_ACTIVE_F2_END__MASK				0x0fff0000
#define HDMI_VSYNC_ACTIVE_F2_END__MASK				0x1fff0000
#define HDMI_VSYNC_ACTIVE_F2_END__SHIFT				16
static inline uint32_t HDMI_VSYNC_ACTIVE_F2_END(uint32_t val)
{
@@ -508,13 +508,13 @@ static inline uint32_t HDMI_VSYNC_ACTIVE_F2_END(uint32_t val)
}

#define REG_HDMI_TOTAL						0x000002c0
#define HDMI_TOTAL_H_TOTAL__MASK				0x00000fff
#define HDMI_TOTAL_H_TOTAL__MASK				0x00001fff
#define HDMI_TOTAL_H_TOTAL__SHIFT				0
static inline uint32_t HDMI_TOTAL_H_TOTAL(uint32_t val)
{
	return ((val) << HDMI_TOTAL_H_TOTAL__SHIFT) & HDMI_TOTAL_H_TOTAL__MASK;
}
#define HDMI_TOTAL_V_TOTAL__MASK				0x0fff0000
#define HDMI_TOTAL_V_TOTAL__MASK				0x1fff0000
#define HDMI_TOTAL_V_TOTAL__SHIFT				16
static inline uint32_t HDMI_TOTAL_V_TOTAL(uint32_t val)
{
@@ -522,7 +522,7 @@ static inline uint32_t HDMI_TOTAL_V_TOTAL(uint32_t val)
}

#define REG_HDMI_VSYNC_TOTAL_F2					0x000002c4
#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK			0x00000fff
#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK			0x00001fff
#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__SHIFT			0
static inline uint32_t HDMI_VSYNC_TOTAL_F2_V_TOTAL(uint32_t val)
{
+36 −9
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc)
{
	struct msm_drm_private *priv = crtc->dev->dev_private;

	return to_sde_kms(priv->kms);
}

@@ -183,9 +184,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,

		pstate = to_sde_plane_state(plane->state);

		flush_mask = ctl->ops.get_bitmask_sspp(ctl,
							sde_plane_pipe(plane));

		/* always stage plane on either left or right lm */
		if (plane->state->crtc_x >= crtc_split_width) {
			lm_idx = RIGHT_MIXER;
@@ -195,20 +193,36 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
			idx = left_crtc_zpos_cnt[pstate->stage]++;
		}

		/*
		 * program each mixer with two hw pipes in dual mixer mode,
		 */
		if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS) {
			stage_cfg->stage[LEFT_MIXER][pstate->stage][1] =
				sde_plane_pipe(plane, 1);

			flush_mask = ctl->ops.get_bitmask_sspp(ctl,
				sde_plane_pipe(plane, 1));
		}

		flush_mask |= ctl->ops.get_bitmask_sspp(ctl,
				sde_plane_pipe(plane, lm_idx ? 1 : 0));

		/* stage plane on right LM if it crosses the boundary */
		lm_right = (lm_idx == LEFT_MIXER) &&
		   (plane->state->crtc_x + plane->state->crtc_w >
							crtc_split_width);

		stage_cfg->stage[lm_idx][pstate->stage][idx] =
							sde_plane_pipe(plane);
					sde_plane_pipe(plane, lm_idx ? 1 : 0);

		mixer[lm_idx].flush_mask |= flush_mask;

		SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
				crtc->base.id,
				pstate->stage,
				plane->base.id,
				sde_plane_pipe(plane) - SSPP_VIG0,
				sde_plane_pipe(plane,
					lm_idx ? 1 : 0) - SSPP_VIG0,
				plane->state->fb ?
				plane->state->fb->base.id : -1);

@@ -230,8 +244,19 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,

		if (lm_right) {
			idx = right_crtc_zpos_cnt[pstate->stage]++;
			stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] =
							sde_plane_pipe(plane);

			/*
			 * program each mixer with two hw pipes
			   in dual mixer mode,
			 */
			if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS) {
				stage_cfg->stage[RIGHT_MIXER][pstate->stage][1]
					= sde_plane_pipe(plane, 0);
			}

			stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx]
				= sde_plane_pipe(plane, 1);

			mixer[RIGHT_MIXER].flush_mask |= flush_mask;

			/* blend config update */
@@ -1256,7 +1281,8 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
	return 0;
}

void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc,
	struct drm_file *file)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);

@@ -1675,7 +1701,8 @@ static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc,
#endif

/* initialize crtc */
struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
struct drm_crtc *sde_crtc_init(struct drm_device *dev,
	struct drm_plane *plane)
{
	struct drm_crtc *crtc = NULL;
	struct sde_crtc *sde_crtc = NULL;
+118 −5
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/slab.h>
#include <linux/of_address.h>

#include <linux/of_platform.h>

#include "sde_hw_mdss.h"
#include "sde_hw_catalog.h"
#include "sde_hw_catalog_format.h"
@@ -715,6 +717,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
		sblk->pcc_blk.len = 0;
		set_bit(SDE_SSPP_PCC, &sspp->features);
	}
	snprintf(sspp->name, sizeof(sspp->name), "vig%d", *vig_count-1);
}

static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
@@ -753,6 +756,7 @@ static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
		sblk->pcc_blk.len = 0;
		set_bit(SDE_SSPP_PCC, &sspp->features);
	}
	snprintf(sspp->name, sizeof(sspp->name), "rgb%d", *rgb_count-1);
}

static void _sde_sspp_setup_cursor(struct sde_mdss_cfg *sde_cfg,
@@ -766,6 +770,7 @@ static void _sde_sspp_setup_cursor(struct sde_mdss_cfg *sde_cfg,
	sspp->clk_ctrl = SDE_CLK_CTRL_CURSOR0 + *cursor_count;
	sblk->format_list = plane_formats;
	(*cursor_count)++;
	snprintf(sspp->name, sizeof(sspp->name), "cursor%d", *cursor_count-1);
}

static void _sde_sspp_setup_dma(struct sde_mdss_cfg *sde_cfg,
@@ -779,6 +784,7 @@ static void _sde_sspp_setup_dma(struct sde_mdss_cfg *sde_cfg,
	sblk->format_list = plane_formats;
	set_bit(SDE_SSPP_QOS, &sspp->features);
	(*dma_count)++;
	snprintf(sspp->name, sizeof(sspp->name), "dma%d", *dma_count-1);
}

static int sde_sspp_parse_dt(struct device_node *np,
@@ -1200,7 +1206,8 @@ end:
	return rc;
}

static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
static int sde_wb_parse_dt(struct device_node *np,
	struct sde_mdss_cfg *sde_cfg)
{
	int rc, prop_count[WB_PROP_MAX], i, j;
	struct sde_prop_value *prop_value = NULL;
@@ -1686,7 +1693,8 @@ end:
	return rc;
}

static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
static int sde_pp_parse_dt(struct device_node *np,
	struct sde_mdss_cfg *sde_cfg)
{
	int rc, prop_count[PP_PROP_MAX], i;
	struct sde_prop_value *prop_value = NULL;
@@ -1760,6 +1768,94 @@ end:
	return rc;
}

static inline u32 _sde_parse_sspp_id(struct sde_mdss_cfg *cfg,
	const char *name)
{
	int i;

	for (i = 0; i < cfg->sspp_count; i++) {
		if (!strcmp(cfg->sspp[i].name, name))
			return cfg->sspp[i].id;
	}

	return SSPP_NONE;
}

static int _sde_vp_parse_dt(struct device_node *np,
	struct sde_mdss_cfg *cfg)
{
	int rc = 0, i = 0;
	struct device_node *node = NULL;
	struct device_node *root_node = NULL;
	struct sde_vp_cfg *vp;
	struct sde_vp_sub_blks *vp_sub, *vp_sub_next;
	struct property *prop;
	const char *cname;

	root_node = of_get_child_by_name(np, "qcom,sde-plane-id-map");
	if (!root_node) {
		root_node = of_parse_phandle(np, "qcom,sde-plane-id-map", 0);
		if (!root_node) {
			SDE_ERROR("No entry present for qcom,sde-plane-id-map");
			rc = -EINVAL;
			goto end;
		}
	}

	for_each_child_of_node(root_node, node) {
		if (i >= MAX_BLOCKS) {
			SDE_ERROR("num of nodes(%d) is bigger than max(%d)\n",
					i, MAX_BLOCKS);
			rc = -EINVAL;
			goto end;
		}
		cfg->vp_count++;
		vp = &(cfg->vp[i]);
		vp->id = i;
		rc = of_property_read_string(node, "qcom,display-type",
						&(vp->display_type));
		if (rc) {
			SDE_ERROR("failed to read display-type, rc = %d\n", rc);
			goto end;
		}

		rc = of_property_read_string(node, "qcom,plane-type",
						&(vp->plane_type));
		if (rc) {
			SDE_ERROR("failed to read plane-type, rc = %d\n", rc);
			goto end;
		}

		INIT_LIST_HEAD(&vp->sub_blks);
		of_property_for_each_string(node, "qcom,plane-name",
						prop, cname) {
			vp_sub = kzalloc(sizeof(*vp_sub), GFP_KERNEL);
			if (!vp_sub) {
				rc = -ENOMEM;
				goto end;
			}
			vp_sub->sspp_id = _sde_parse_sspp_id(cfg, cname);
			list_add_tail(&vp_sub->pipeid_list, &vp->sub_blks);
		}
		i++;
	}

end:
	if (rc && cfg->vp_count) {
		vp = &(cfg->vp[i]);
		for (i = 0; i < cfg->vp_count; i++) {
			list_for_each_entry_safe(vp_sub, vp_sub_next,
				&vp->sub_blks, pipeid_list) {
				list_del(&vp_sub->pipeid_list);
				kfree(vp_sub);
			}
		}
		memset(&(cfg->vp[0]), 0, sizeof(cfg->vp));
		cfg->vp_count = 0;
	}
	return rc;
}

static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
{
	int rc, len, prop_count[SDE_PROP_MAX];
@@ -1851,7 +1947,8 @@ end:
	return rc;
}

static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
static int sde_perf_parse_dt(struct device_node *np,
	struct sde_mdss_cfg *cfg)
{
	int rc, len, prop_count[PERF_PROP_MAX];
	struct sde_prop_value *prop_value = NULL;
@@ -1891,7 +1988,8 @@ end:
	return rc;
}

static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg,
	uint32_t hw_rev)
{
	switch (hw_rev) {
	case SDE_HW_VER_170:
@@ -1909,6 +2007,7 @@ static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
{
	int i;
	struct sde_vp_sub_blks *vp_sub, *vp_sub_next;

	if (!sde_cfg)
		return;
@@ -1932,13 +2031,23 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
		kfree(sde_cfg->vbif[i].dynamic_ot_rd_tbl.cfg);
		kfree(sde_cfg->vbif[i].dynamic_ot_wr_tbl.cfg);
	}

	for (i = 0; i < sde_cfg->vp_count; i++) {
		list_for_each_entry_safe(vp_sub, vp_sub_next,
			&sde_cfg->vp[i].sub_blks, pipeid_list) {
			list_del(&vp_sub->pipeid_list);
			kfree(vp_sub);
		}
	}

	kfree(sde_cfg);
}

/*************************************************************
 * hardware catalog init
 *************************************************************/
struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev,
	u32 hw_rev)
{
	int rc;
	struct sde_mdss_cfg *sde_cfg;
@@ -1996,6 +2105,10 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
	if (rc)
		goto end;

	rc = _sde_vp_parse_dt(np, sde_cfg);
	if (rc)
		SDE_DEBUG("virtual plane is not supported.\n");

	sde_hardware_caps(sde_cfg, hw_rev);

	return sde_cfg;
Loading