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

Commit 7c1f3156 authored by Abhinav Kumar's avatar Abhinav Kumar
Browse files

drm/msm: add support for parsing hdmi/hdcp capabilities



Add support to parse the HDMI TX version and
HDCP support from the HDMI and QFPROM registers.

This information is used to decide which HDCP driver
module is to be initialized at boot time.

Change-Id: Ib598f3867f1cd2ef9adb7503c5907cbb1e4ba758
Signed-off-by: default avatarAbhinav Kumar <abhinavk@codeaurora.org>
parent e998aabf
Loading
Loading
Loading
Loading
+83 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
#include "sde_connector.h"
#include "sde_connector.h"
#include "msm_drv.h"
#include "msm_drv.h"
#include "sde_hdmi.h"
#include "sde_hdmi.h"
#include "sde_hdmi_regs.h"


static DEFINE_MUTEX(sde_hdmi_list_lock);
static DEFINE_MUTEX(sde_hdmi_list_lock);
static LIST_HEAD(sde_hdmi_list);
static LIST_HEAD(sde_hdmi_list);
@@ -1547,6 +1548,86 @@ int sde_hdmi_connector_pre_deinit(struct drm_connector *connector,
	return 0;
	return 0;
}
}


static void _sde_hdmi_get_tx_version(struct sde_hdmi *sde_hdmi)
{
	struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;

	sde_hdmi->hdmi_tx_version = hdmi_read(hdmi, REG_HDMI_VERSION);
	sde_hdmi->hdmi_tx_major_version =
		SDE_GET_MAJOR_VER(sde_hdmi->hdmi_tx_version);

	switch (sde_hdmi->hdmi_tx_major_version) {
	case (HDMI_TX_VERSION_3):
		sde_hdmi->max_pclk_khz = HDMI_TX_3_MAX_PCLK_RATE;
		break;
	case (HDMI_TX_VERSION_4):
		sde_hdmi->max_pclk_khz = HDMI_TX_4_MAX_PCLK_RATE;
		break;
	default:
		sde_hdmi->max_pclk_khz = HDMI_DEFAULT_MAX_PCLK_RATE;
		break;
	}
	SDE_DEBUG("sde_hdmi->hdmi_tx_version = 0x%x\n",
		sde_hdmi->hdmi_tx_version);
	SDE_DEBUG("sde_hdmi->hdmi_tx_major_version = 0x%x\n",
		sde_hdmi->hdmi_tx_major_version);
	SDE_DEBUG("sde_hdmi->max_pclk_khz = 0x%x\n",
		sde_hdmi->max_pclk_khz);
}

static int sde_hdmi_tx_check_capability(struct sde_hdmi *sde_hdmi)
{
	u32 hdmi_disabled, hdcp_disabled, reg_val;
	int ret = 0;
	struct hdmi *hdmi = sde_hdmi->ctrl.ctrl;

	/* check if hdmi and hdcp are disabled */
	if (sde_hdmi->hdmi_tx_major_version < HDMI_TX_VERSION_4) {
		hdcp_disabled = hdmi_qfprom_read(hdmi,
		QFPROM_RAW_FEAT_CONFIG_ROW0_LSB) & BIT(31);

		hdmi_disabled = hdmi_qfprom_read(hdmi,
		QFPROM_RAW_FEAT_CONFIG_ROW0_MSB) & BIT(0);
	} else {
		reg_val = hdmi_qfprom_read(hdmi,
		QFPROM_RAW_FEAT_CONFIG_ROW0_LSB + QFPROM_RAW_VERSION_4);
		hdcp_disabled = reg_val & BIT(12);

		hdmi_disabled = reg_val & BIT(13);

		reg_val = hdmi_qfprom_read(hdmi, SEC_CTRL_HW_VERSION);

		SDE_DEBUG("SEC_CTRL_HW_VERSION reg_val = 0x%x\n", reg_val);
		/*
		 * With HDCP enabled on capable hardware, check if HW
		 * or SW keys should be used.
		 */
		if (!hdcp_disabled && (reg_val >= HDCP_SEL_MIN_SEC_VERSION)) {
			reg_val = hdmi_qfprom_read(hdmi,
			QFPROM_RAW_FEAT_CONFIG_ROW0_MSB +
			QFPROM_RAW_VERSION_4);

			if (!(reg_val & BIT(23)))
				sde_hdmi->hdcp1_use_sw_keys = true;
		}
	}

	SDE_DEBUG("%s: Features <HDMI:%s, HDCP:%s>\n", __func__,
			hdmi_disabled ? "OFF" : "ON",
			hdcp_disabled ? "OFF" : "ON");

	if (hdmi_disabled) {
		DEV_ERR("%s: HDMI disabled\n", __func__);
		ret = -ENODEV;
		goto end;
	}

	sde_hdmi->hdcp14_present = !hdcp_disabled;

 end:
	return ret;
} /* hdmi_tx_check_capability */

int sde_hdmi_connector_post_init(struct drm_connector *connector,
int sde_hdmi_connector_post_init(struct drm_connector *connector,
		void *info,
		void *info,
		void *display)
		void *display)
@@ -1579,6 +1660,8 @@ int sde_hdmi_connector_post_init(struct drm_connector *connector,
	if (rc)
	if (rc)
		SDE_ERROR("failed to enable HPD: %d\n", rc);
		SDE_ERROR("failed to enable HPD: %d\n", rc);


	_sde_hdmi_get_tx_version(sde_hdmi);
	sde_hdmi_tx_check_capability(sde_hdmi);
	return rc;
	return rc;
}
}


+14 −1
Original line number Original line Diff line number Diff line
@@ -36,6 +36,10 @@
#define SDE_HDMI_DEBUG(fmt, args...)   SDE_DEBUG(fmt, ##args)
#define SDE_HDMI_DEBUG(fmt, args...)   SDE_DEBUG(fmt, ##args)
#endif
#endif


/* HW Revisions for different SDE targets */
#define SDE_GET_MAJOR_VER(rev)((rev) >> 28)
#define SDE_GET_MINOR_VER(rev)(((rev) >> 16) & 0xFFF)

/**
/**
 * struct sde_hdmi_info - defines hdmi display properties
 * struct sde_hdmi_info - defines hdmi display properties
 * @display_type:      Display type as defined by device tree.
 * @display_type:      Display type as defined by device tree.
@@ -121,7 +125,11 @@ struct sde_hdmi {
	struct drm_display_mode mode;
	struct drm_display_mode mode;
	bool connected;
	bool connected;
	bool is_tpg_enabled;
	bool is_tpg_enabled;

	u32 hdmi_tx_version;
	u32 hdmi_tx_major_version;
	u32 max_pclk_khz;
	bool hdcp1_use_sw_keys;
	u32 hdcp14_present;
	struct work_struct hpd_work;
	struct work_struct hpd_work;
	bool codec_ready;
	bool codec_ready;
	bool client_notify_pending;
	bool client_notify_pending;
@@ -154,6 +162,11 @@ enum hdmi_tx_scdc_access_type {


#define HDMI_KHZ_TO_HZ 1000
#define HDMI_KHZ_TO_HZ 1000
#define HDMI_MHZ_TO_HZ 1000000
#define HDMI_MHZ_TO_HZ 1000000

/* Maximum pixel clock rates for hdmi tx */
#define HDMI_DEFAULT_MAX_PCLK_RATE	148500
#define HDMI_TX_3_MAX_PCLK_RATE		297000
#define HDMI_TX_4_MAX_PCLK_RATE		600000
/**
/**
 * hdmi_tx_ddc_timer_type() - hdmi DDC timer functionalities.
 * hdmi_tx_ddc_timer_type() - hdmi DDC timer functionalities.
 */
 */