diff options
author | Dan Murphy <dmurphy@ti.com> | 2011-10-24 07:41:03 -0500 |
---|---|---|
committer | Dan Murphy <dmurphy@ti.com> | 2011-10-24 07:41:03 -0500 |
commit | 211e9ff0454602ea092135f477e5c472a8f0aa99 (patch) | |
tree | 342f76f77bc1e02704c76888d55c7ecff2b648d9 | |
parent | 00fd50e342cb085dbab41ea525973920dfd61e61 (diff) | |
parent | 3974bebcea6efce02c75482c3a868c35e38956e4 (diff) | |
download | kernel_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.c | 24 | ||||
-rw-r--r-- | drivers/video/hdmi_ti_4xxx_ip.h | 1 | ||||
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 33 | ||||
-rw-r--r-- | drivers/video/omap2/hdcp/hdcp_top.c | 20 | ||||
-rw-r--r-- | include/video/hdmi_ti_4xxx_ip.h | 1 | ||||
-rw-r--r-- | sound/soc/omap/omap4-hdmi-card.c | 10 |
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; |