summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2015-10-08 14:37:52 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:46:30 -0700
commit7f60965397e5eb2516a47aa0c6311e0e4e7968b9 (patch)
treea2a1247dc5cce466e2bb2060d65148dfd93f4ac9
parent233a722f7f0626c85477d040c63f34afc2ae5369 (diff)
msm: mdss: hdmi: load hdcp1.x app only at bootup
Do not load hdcp1.x app at runtime and keep the app status for future use. Whenever cable is connected and hdcp 1.x needs to be started, just set keys using app. This avoids any possible app load - unload issues in some corner cases. Change-Id: Ic7f55ab74d6cb6b9ff654eb32c0bed8a44f70007 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
-rw-r--r--drivers/misc/hdcp.c30
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c154
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.h3
-rw-r--r--include/linux/hdcp_qseecom.h1
4 files changed, 89 insertions, 99 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index f19f8425c237..74449d8186d9 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -365,6 +365,9 @@ struct hdcp_lib_message_map {
const char *msg_name;
};
+static struct qseecom_handle *hdcp1_handle;
+static bool hdcp1_supported = true;
+
static const char *hdcp_lib_message_name(int msg_id)
{
/*
@@ -1168,24 +1171,35 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
}
}
+bool hdcp1_check_if_supported_load_app(void)
+{
+ int rc = 0;
+
+ /* start hdcp1 app */
+ if (hdcp1_supported && !hdcp1_handle) {
+ rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME,
+ QSEECOM_SBUFF_SIZE);
+ if (rc) {
+ pr_err("qseecom_start_app failed %d\n", rc);
+ hdcp1_supported = false;
+ }
+ }
+
+ return hdcp1_supported;
+}
+
/* APIs exposed to all clients */
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
{
int rc = 0;
struct hdcp1_key_set_req *key_set_req;
struct hdcp1_key_set_rsp *key_set_rsp;
- struct qseecom_handle *hdcp1_handle = NULL;
if (aksv_msb == NULL || aksv_lsb == NULL)
return -EINVAL;
- /* start hdcp1 app */
- rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME,
- QSEECOM_SBUFF_SIZE);
- if (rc) {
- pr_err("qseecom_start_app failed %d\n", rc);
- return -ENOSYS;
- }
+ if (!hdcp1_supported || !hdcp1_handle)
+ return -EINVAL;
/* set keys and request aksv */
key_set_req = (struct hdcp1_key_set_req *)hdcp1_handle->sbuf;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 0655c4971442..aa3f4db5c30a 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -397,24 +397,9 @@ static bool hdmi_tx_is_cea_format(int mode)
static inline bool hdmi_tx_is_hdcp_enabled(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- bool ret = false;
-
- if (hdmi_ctrl->hdcp_feature_on) {
- if (hdmi_ctrl->hdcp14_present) {
- /* Check to see if sw keys are available */
- if (hdmi_ctrl->hdcp14_sw_keys) {
- u32 m_aksv, l_aksv;
-
- ret = !hdcp1_set_keys(&m_aksv, &l_aksv);
- } else {
- ret = true;
- }
- }
- if (hdmi_ctrl->hdcp22_present)
- ret = true;
- }
-
- return ret;
+ return hdmi_ctrl->hdcp_feature_on &&
+ (hdmi_ctrl->hdcp14_present || hdmi_ctrl->hdcp22_present) &&
+ hdmi_ctrl->hdcp_ops;
}
static const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
@@ -1245,7 +1230,7 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work)
if (hdmi_ctrl->hpd_state && hdmi_ctrl->panel_power_on) {
DEV_DBG("%s: Reauthenticating\n", __func__);
rc = hdmi_ctrl->hdcp_ops->hdmi_hdcp_reauthenticate(
- hdmi_ctrl->hdcp_feature_data);
+ hdmi_ctrl->hdcp_data);
if (rc)
DEV_ERR("%s: HDCP reauth failed. rc=%d\n",
__func__, rc);
@@ -1421,6 +1406,7 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
struct hdmi_hdcp_init_data hdcp_init_data;
struct hdmi_cec_init_data cec_init_data;
struct resource *res = NULL;
+ void *fd = NULL;
if (!hdmi_ctrl || !fbi) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1432,23 +1418,21 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
edid_init_data.ds_data = &hdmi_ctrl->ds_data;
edid_init_data.max_pclk_khz = hdmi_ctrl->max_pclk_khz;
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] =
- hdmi_edid_init(&edid_init_data);
- if (!hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) {
+ fd = hdmi_edid_init(&edid_init_data);
+ if (!fd) {
DEV_ERR("%s: hdmi_edid_init failed\n", __func__);
return -EPERM;
}
- hdmi_ctrl->panel_data.panel_info.edid_data =
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID];
+ hdmi_ctrl->panel_data.panel_info.edid_data = fd;
/* get edid buffer from edid parser */
hdmi_ctrl->edid_buf = edid_init_data.buf;
hdmi_ctrl->edid_buf_size = edid_init_data.buf_size;
- hdmi_edid_set_video_resolution(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID],
- hdmi_ctrl->vid_cfg.vic, true);
+ hdmi_edid_set_video_resolution(fd, hdmi_ctrl->vid_cfg.vic, true);
+
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = fd;
/* Initialize HDCP features */
res = platform_get_resource_byname(hdmi_ctrl->pdev,
@@ -1459,62 +1443,49 @@ static int hdmi_tx_init_features(struct hdmi_tx_ctrl *hdmi_ctrl,
return -ENODEV;
}
- hdcp_init_data.phy_addr = res->start;
- hdcp_init_data.core_io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
- hdcp_init_data.qfprom_io =
- &hdmi_ctrl->pdata.io[HDMI_TX_QFPROM_IO];
- hdcp_init_data.hdcp_io =
- &hdmi_ctrl->pdata.io[HDMI_TX_HDCP_IO];
- hdcp_init_data.mutex = &hdmi_ctrl->mutex;
- hdcp_init_data.sysfs_kobj = hdmi_ctrl->kobj;
- hdcp_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
- hdcp_init_data.workq = hdmi_ctrl->workq;
+ hdcp_init_data.phy_addr = res->start;
+ hdcp_init_data.core_io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ hdcp_init_data.qfprom_io = &hdmi_ctrl->pdata.io[HDMI_TX_QFPROM_IO];
+ hdcp_init_data.hdcp_io = &hdmi_ctrl->pdata.io[HDMI_TX_HDCP_IO];
+ hdcp_init_data.mutex = &hdmi_ctrl->mutex;
+ hdcp_init_data.sysfs_kobj = hdmi_ctrl->kobj;
+ hdcp_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
+ hdcp_init_data.workq = hdmi_ctrl->workq;
hdcp_init_data.notify_status = hdmi_tx_hdcp_cb;
- hdcp_init_data.cb_data = (void *)hdmi_ctrl;
- hdcp_init_data.hdmi_tx_ver = hdmi_ctrl->hdmi_tx_ver;
- hdcp_init_data.timing = &hdmi_ctrl->vid_cfg.timing;
+ hdcp_init_data.cb_data = (void *)hdmi_ctrl;
+ hdcp_init_data.hdmi_tx_ver = hdmi_ctrl->hdmi_tx_ver;
+ hdcp_init_data.timing = &hdmi_ctrl->vid_cfg.timing;
- /*
- * Try to initialize both HDCP 1.4 and 2.2 features, decide which one
- * to use at HPD time
- */
if (hdmi_ctrl->hdcp14_present) {
+ fd = hdmi_hdcp_init(&hdcp_init_data);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] =
- hdmi_hdcp_init(&hdcp_init_data);
-
- if (IS_ERR_OR_NULL(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP])) {
- DEV_ERR("%s: hdmi_hdcp_init failed\n", __func__);
- hdmi_edid_deinit(hdmi_ctrl->feature_data[
- HDMI_TX_FEAT_EDID]);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID] = NULL;
- return -EPERM;
+ if (IS_ERR_OR_NULL(fd)) {
+ DEV_WARN("%s: hdmi_hdcp_init failed\n", __func__);
+ } else {
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP] = fd;
+ DEV_DBG("%s: HDCP 1.4 configured\n", __func__);
}
- DEV_DBG("%s: HDCP 1.4 feature initialized\n", __func__);
}
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] =
- hdmi_hdcp2p2_init(&hdcp_init_data);
+ fd = hdmi_hdcp2p2_init(&hdcp_init_data);
- if (IS_ERR_OR_NULL(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2])) {
+ if (IS_ERR_OR_NULL(fd)) {
DEV_WARN("%s: hdmi_hdcp2p2_init failed\n", __func__);
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] = NULL;
} else {
- DEV_DBG("%s: HDCP 2.2 feature initialized\n", __func__);
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2] = fd;
+ DEV_DBG("%s: HDCP 2.2 configured\n", __func__);
}
-
/* Initialize CEC feature */
cec_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
cec_init_data.sysfs_kobj = hdmi_ctrl->kobj;
cec_init_data.workq = hdmi_ctrl->workq;
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC] =
- hdmi_cec_init(&cec_init_data);
- if (!hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC])
+ fd = hdmi_cec_init(&cec_init_data);
+ if (!fd)
DEV_WARN("%s: hdmi_cec_init failed\n", __func__);
+ else
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC] = fd;
return 0;
} /* hdmi_tx_init_features */
@@ -1622,13 +1593,19 @@ static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
else
hdmi_ctrl->hdcp22_present = false;
- if (!hdmi_ctrl->hdcp22_present && hdmi_ctrl->hdcp14_present) {
- fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
- ops = hdmi_hdcp_start(fd);
+ if (!hdmi_ctrl->hdcp22_present) {
+ if (hdmi_ctrl->hdcp1_use_sw_keys)
+ hdmi_ctrl->hdcp14_present =
+ hdcp1_check_if_supported_load_app();
+
+ if (hdmi_ctrl->hdcp14_present) {
+ fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
+ ops = hdmi_hdcp_start(fd);
+ }
}
/* update internal data about hdcp */
- hdmi_ctrl->hdcp_feature_data = fd;
+ hdmi_ctrl->hdcp_data = fd;
hdmi_ctrl->hdcp_ops = ops;
}
@@ -1678,20 +1655,23 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
{
u32 hdmi_disabled, hdcp_disabled, reg_val;
- bool sw_keys = false;
struct dss_io_data *io = NULL;
+ int ret = 0;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
io = &hdmi_ctrl->pdata.io[HDMI_TX_QFPROM_IO];
if (!io->base) {
DEV_ERR("%s: QFPROM io is not initialized\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
+ /* check if hdmi and hdcp are disabled */
if (hdmi_ctrl->hdmi_tx_ver < HDMI_TX_VERSION_4) {
hdcp_disabled = DSS_REG_R_ND(io,
QFPROM_RAW_FEAT_CONFIG_ROW0_LSB) & BIT(31);
@@ -1703,6 +1683,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
QFPROM_RAW_FEAT_CONFIG_ROW0_LSB + QFPROM_RAW_VERSION_4);
hdcp_disabled = reg_val & BIT(12);
hdmi_disabled = reg_val & BIT(13);
+
reg_val = DSS_REG_R_ND(io, SEC_CTRL_HW_VERSION);
/*
* With HDCP enabled on capable hardware, check if HW
@@ -1713,7 +1694,7 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
QFPROM_RAW_FEAT_CONFIG_ROW0_MSB +
QFPROM_RAW_VERSION_4);
if (!(reg_val & BIT(23)))
- sw_keys = true;
+ hdmi_ctrl->hdcp1_use_sw_keys = true;
}
}
@@ -1722,19 +1703,13 @@ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl)
if (hdmi_disabled) {
DEV_ERR("%s: HDMI disabled\n", __func__);
- return -ENODEV;
- }
-
- if (hdcp_disabled) {
- hdmi_ctrl->hdcp14_present = 0;
- DEV_WARN("%s: HDCP disabled\n", __func__);
- } else {
- hdmi_ctrl->hdcp14_present = 1;
- hdmi_ctrl->hdcp14_sw_keys = sw_keys;
- DEV_DBG("%s: Device is HDCP enabled\n", __func__);
+ ret = -ENODEV;
+ goto end;
}
- return 0;
+ hdmi_ctrl->hdcp14_present = !hdcp_disabled;
+end:
+ return ret;
} /* hdmi_tx_check_capability */
static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl,
@@ -3779,10 +3754,10 @@ static irqreturn_t hdmi_tx_isr(int irq, void *data)
if (hdmi_cec_isr(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]))
DEV_ERR("%s: hdmi_cec_isr failed\n", __func__);
- if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_feature_data) {
+ if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_data) {
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr) {
if (hdmi_ctrl->hdcp_ops->hdmi_hdcp_isr(
- hdmi_ctrl->hdcp_feature_data))
+ hdmi_ctrl->hdcp_data))
DEV_ERR("%s: hdmi_hdcp_isr failed\n",
__func__);
}
@@ -3815,7 +3790,7 @@ static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
}
hdmi_ctrl->hdcp_ops = NULL;
- hdmi_ctrl->hdcp_feature_data = NULL;
+ hdmi_ctrl->hdcp_data = NULL;
if (hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) {
hdmi_edid_deinit(hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]);
@@ -3940,8 +3915,7 @@ static int hdmi_tx_start_hdcp(struct hdmi_tx_ctrl *hdmi_ctrl)
return -ENODEV;
}
- rc = hdmi_ctrl->hdcp_ops->hdmi_hdcp_authenticate(
- hdmi_ctrl->hdcp_feature_data);
+ rc = hdmi_ctrl->hdcp_ops->hdmi_hdcp_authenticate(hdmi_ctrl->hdcp_data);
if (rc)
DEV_ERR("%s: hdcp auth failed. rc=%d\n", __func__, rc);
@@ -4085,7 +4059,7 @@ static int hdmi_tx_panel_event_handler(struct mdss_panel_data *panel_data,
if (hdmi_tx_is_hdcp_enabled(hdmi_ctrl)) {
DEV_DBG("%s: Turning off HDCP\n", __func__);
hdmi_ctrl->hdcp_ops->hdmi_hdcp_off(
- hdmi_ctrl->hdcp_feature_data);
+ hdmi_ctrl->hdcp_data);
hdmi_ctrl->hdcp_ops = NULL;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
index 99151afc725d..c24dc169eea2 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h
@@ -174,6 +174,7 @@ struct hdmi_tx_ctrl {
bool ds_registered;
bool scrambler_enabled;
u32 hdcp14_present;
+ bool hdcp1_use_sw_keys;
bool audio_ack_enabled;
atomic_t audio_ack_pending;
bool hdcp14_sw_keys;
@@ -188,7 +189,7 @@ struct hdmi_tx_ctrl {
void *feature_data[HDMI_TX_FEAT_MAX];
struct hdmi_hdcp_ops *hdcp_ops;
- void *hdcp_feature_data;
+ void *hdcp_data;
bool hdcp22_present;
u8 *edid_buf;
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 1258a7b2f3e8..94caf29cba9f 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -109,6 +109,7 @@ int hdcp_library_register(void **pphdcpcontext,
struct hdcp_client_ops *client_ops,
struct hdcp_txmtr_ops *txmtr_ops, void *client_ctx);
void hdcp_library_deregister(void *phdcpcontext);
+bool hdcp1_check_if_supported_load_app(void);
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);
#endif /* __HDCP_QSEECOM_H */