aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Murphy <dmurphy@ti.com>2011-10-24 07:41:03 -0500
committerDan Murphy <dmurphy@ti.com>2011-10-24 07:41:03 -0500
commit211e9ff0454602ea092135f477e5c472a8f0aa99 (patch)
tree342f76f77bc1e02704c76888d55c7ecff2b648d9
parent00fd50e342cb085dbab41ea525973920dfd61e61 (diff)
parent3974bebcea6efce02c75482c3a868c35e38956e4 (diff)
downloadkernel_samsung_espresso10-211e9ff0454602ea092135f477e5c472a8f0aa99.zip
kernel_samsung_espresso10-211e9ff0454602ea092135f477e5c472a8f0aa99.tar.gz
kernel_samsung_espresso10-211e9ff0454602ea092135f477e5c472a8f0aa99.tar.bz2
Merge branch 'android-omap-3.0' into p-android-omap-3.0
* android-omap-3.0: OMAP4: HDCP: Fix crash on cancel_delayed_work OMAP4: HDMI: Audio: poll HDMI display before returning error OMAP4: HDMI: Check AKSV registers before resetting HDMI Wrapper Change-Id: I42af064593ddecbcf93f948b3f7816240ba9bd3e Signed-off-by: Dan Murphy <dmurphy@ti.com>
-rw-r--r--drivers/video/hdmi_ti_4xxx_ip.c24
-rw-r--r--drivers/video/hdmi_ti_4xxx_ip.h1
-rw-r--r--drivers/video/omap2/dss/hdmi.c33
-rw-r--r--drivers/video/omap2/hdcp/hdcp_top.c20
-rw-r--r--include/video/hdmi_ti_4xxx_ip.h1
-rw-r--r--sound/soc/omap/omap4-hdmi-card.c10
6 files changed, 63 insertions, 26 deletions
diff --git a/drivers/video/hdmi_ti_4xxx_ip.c b/drivers/video/hdmi_ti_4xxx_ip.c
index 3cbcbe3..fb2bbb2 100644
--- a/drivers/video/hdmi_ti_4xxx_ip.c
+++ b/drivers/video/hdmi_ti_4xxx_ip.c
@@ -1316,6 +1316,30 @@ void hdmi_ti_4xxx_audio_enable(struct hdmi_ip_data *ip_data, bool enable)
}
EXPORT_SYMBOL(hdmi_ti_4xxx_audio_enable);
+bool hdmi_ti_4xx_check_aksv_data(struct hdmi_ip_data *ip_data)
+{
+ u32 aksv_data[5];
+ int i, j;
+ int one = 0, zero = 0;
+ /* check if HDCP AKSV registers are populated.
+ * If not load the keys and reset the wrapper.
+ */
+ for (i = 0; i < 5; i++) {
+ aksv_data[i] = hdmi_read_reg(hdmi_core_sys_base(ip_data),
+ HDMI_CORE_AKSV(i));
+ /* Count number of zero / one */
+ for (j = 0; j < 8; j++)
+ (aksv_data[i] & (0x01 << j)) ? one++ : zero++;
+ pr_debug("%x ", aksv_data[i] & 0xFF);
+ }
+
+ if (one == zero)
+ return true;
+ else
+ return false;
+
+}
+EXPORT_SYMBOL(hdmi_ti_4xx_check_aksv_data);
static int __init hdmi_ti_4xxx_init(void)
{
diff --git a/drivers/video/hdmi_ti_4xxx_ip.h b/drivers/video/hdmi_ti_4xxx_ip.h
index 4572d66..7c486fd 100644
--- a/drivers/video/hdmi_ti_4xxx_ip.h
+++ b/drivers/video/hdmi_ti_4xxx_ip.h
@@ -76,6 +76,7 @@ struct hdmi_reg { u16 idx; };
#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC)
#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0)
#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4)
+#define HDMI_CORE_AKSV(n) HDMI_CORE_SYS_REG(n*4 + 0x74)
#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 029d01a..6c458fc 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -330,6 +330,21 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}
+static void hdmi_load_hdcp_keys(struct omap_dss_device *dssdev)
+{
+ DSSDBG("hdmi_load_hdcp_keys\n");
+ /* load the keys and reset the wrapper to populate the AKSV registers*/
+ if (hdmi.hdmi_power_on_cb) {
+ if (!hdmi_ti_4xx_check_aksv_data(&hdmi.hdmi_data) &&
+ hdmi.custom_set &&
+ hdmi.hdmi_power_on_cb()) {
+ hdmi_ti_4xxx_set_wait_soft_reset(&hdmi.hdmi_data);
+ hdmi.wp_reset_done = true;
+ DSSINFO("HDMI_WRAPPER RESET DONE\n");
+ }
+ }
+}
+
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
int r;
@@ -341,6 +356,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
if (r)
return r;
+ /* Load the HDCP keys if not already loaded*/
+ hdmi_load_hdcp_keys(dssdev);
+
hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 0);
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, dssdev->type, 0);
@@ -447,19 +465,6 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi.deep_color = HDMI_DEEP_COLOR_24BIT;
}
-static void hdmi_load_hdcp_keys(struct omap_dss_device *dssdev)
-{
- DSSDBG("hdmi_load_hdcp_keys\n");
- /* load the keys and reset the wrapper to populate the AKSV registers*/
- if (hdmi.hdmi_power_on_cb && !hdmi.wp_reset_done) {
- if (hdmi.hdmi_power_on_cb()) {
- hdmi_ti_4xxx_set_wait_soft_reset(&hdmi.hdmi_data);
- hdmi.wp_reset_done = true;
- DSSINFO("HDMI_WRAPPER RESET DONE\n");
- }
- }
-}
-
int omapdss_hdmi_get_pixel_clock(void)
{
return PICOS2KHZ(hdmi.cfg.timings.pixclock);
@@ -607,8 +612,6 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
goto err3;
}
- /* Load the HDCP keys if not already loaded*/
- hdmi_load_hdcp_keys(dssdev);
r = hdmi_power_on(dssdev);
if (r) {
DSSERR("failed to power on device\n");
diff --git a/drivers/video/omap2/hdcp/hdcp_top.c b/drivers/video/omap2/hdcp/hdcp_top.c
index c9151a2..d6a71b5 100644
--- a/drivers/video/omap2/hdcp/hdcp_top.c
+++ b/drivers/video/omap2/hdcp/hdcp_top.c
@@ -250,7 +250,7 @@ static void hdcp_wq_authentication_failure(void)
hdcp_lib_disable();
hdcp.pending_disable = 0;
- if (hdcp.retry_cnt) {
+ if (hdcp.retry_cnt && (hdcp.hdmi_state != HDMI_STOPPED)) {
if (hdcp.retry_cnt < HDCP_INFINITE_REAUTH) {
hdcp.retry_cnt--;
printk(KERN_INFO "HDCP: authentication failed - "
@@ -395,6 +395,13 @@ static void hdcp_work_queue(struct work_struct *work)
}
kfree(hdcp_w);
+ hdcp_w = 0;
+ if (event == HDCP_START_FRAME_EVENT)
+ hdcp.pending_start = 0;
+ if (event == HDCP_KSV_LIST_RDY_EVENT ||
+ event == HDCP_R0_EXP_EVENT) {
+ hdcp.pending_wq_event = 0;
+ }
DBG("hdcp_work_queue() - END - %u hdmi=%d hdcp=%d auth=%d evt=%x %d ",
jiffies_to_msecs(jiffies),
@@ -442,16 +449,11 @@ static void hdcp_cancel_work(struct delayed_work **work)
if (*work) {
ret = cancel_delayed_work(*work);
-#if 0 /* cancel_work_sync is only exported to GPL code
- * as HDCP is not GPL, will not wait for work to finish
- * but avoid freeing the work which is on-going
- */
if (ret != 1) {
ret = cancel_work_sync(&((*work)->work));
printk(KERN_INFO "Canceling work failed - "
"cancel_work_sync done %d\n", ret);
}
-#endif
kfree(*work);
*work = 0;
}
@@ -499,8 +501,10 @@ static void hdcp_start_frame_cb(void)
}
/* Cancel any pending work */
- hdcp_cancel_work(&hdcp.pending_start);
- hdcp_cancel_work(&hdcp.pending_wq_event);
+ if (hdcp.pending_start)
+ hdcp_cancel_work(&hdcp.pending_start);
+ if (hdcp.pending_wq_event)
+ hdcp_cancel_work(&hdcp.pending_wq_event);
hdcp.hpd_low = 0;
hdcp.pending_disable = 0;
diff --git a/include/video/hdmi_ti_4xxx_ip.h b/include/video/hdmi_ti_4xxx_ip.h
index 992c704..a1224a4 100644
--- a/include/video/hdmi_ti_4xxx_ip.h
+++ b/include/video/hdmi_ti_4xxx_ip.h
@@ -382,4 +382,5 @@ void hdmi_ti_4xxx_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_infoframe_audio *info_aud);
void hdmi_ti_4xxx_audio_enable(struct hdmi_ip_data *ip_data, bool idle);
int hdmi_ti_4xxx_set_wait_soft_reset(struct hdmi_ip_data *ip_data);
+bool hdmi_ti_4xx_check_aksv_data(struct hdmi_ip_data *ip_data);
#endif
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
index 86c4832..9024735 100644
--- a/sound/soc/omap/omap4-hdmi-card.c
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <asm/mach-types.h>
@@ -31,7 +32,7 @@
static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- int i;
+ int i, count = 0;
struct omap_overlay_manager *mgr = NULL;
struct device *dev = substream->pcm->card->dev;
@@ -49,9 +50,12 @@ static int omap4_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
}
/* Make sure HDMI is power-on to avoid L3 interconnect errors */
- if (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ while (mgr->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ msleep(50);
+ if (count > 5)
+ return -EIO;
dev_err(dev, "HDMI display is not active!\n");
- return -EIO;
+ count++;
}
return 0;