summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c83
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h15
2 files changed, 97 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 2e0665274199..4d93b631c53b 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -29,6 +29,7 @@
#include "sde_connector.h"
#include "msm_drv.h"
#include "sde_hdmi.h"
+#include "sde_hdmi_regs.h"
static DEFINE_MUTEX(sde_hdmi_list_lock);
static LIST_HEAD(sde_hdmi_list);
@@ -1547,6 +1548,86 @@ int sde_hdmi_connector_pre_deinit(struct drm_connector *connector,
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,
void *info,
void *display)
@@ -1579,6 +1660,8 @@ int sde_hdmi_connector_post_init(struct drm_connector *connector,
if (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;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index a50f9533bd62..38ab1da08196 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -36,6 +36,10 @@
#define SDE_HDMI_DEBUG(fmt, args...) SDE_DEBUG(fmt, ##args)
#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
* @display_type: Display type as defined by device tree.
@@ -121,7 +125,11 @@ struct sde_hdmi {
struct drm_display_mode mode;
bool connected;
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;
bool codec_ready;
bool client_notify_pending;
@@ -154,6 +162,11 @@ enum hdmi_tx_scdc_access_type {
#define HDMI_KHZ_TO_HZ 1000
#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.
*/