aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-10-14 02:24:03 -0500
committerIliyan Malchev <malchev@google.com>2011-10-17 18:53:54 -0700
commit828f971d600f53a5f7690b10975cc6c1939071a0 (patch)
tree0ba1d0d9aa3a87d9d7e73c22b2476baf84823c2e
parent92f0b3028d9e9b94a54968303e09ae3b33e4ad1e (diff)
downloadkernel_samsung_tuna-828f971d600f53a5f7690b10975cc6c1939071a0.zip
kernel_samsung_tuna-828f971d600f53a5f7690b10975cc6c1939071a0.tar.gz
kernel_samsung_tuna-828f971d600f53a5f7690b10975cc6c1939071a0.tar.bz2
OMAP4: HDMI: Reprogram video wrapper after wrapper reset
For loading HDCP keys HDMI wrapper is reset before HDMI is powered on either during an hpd 1 or set_mode when hdmi is being enabled. HDCP authetication is started only when the HDMI wrapper reset is completed and HDCP keys are loaded. Also, when changing the HDMI modes, avoid HDCP recovery by turning off HDCP in hdmi_power_off, instead of only for an hpd 0 interrupt. Change-Id: I9a683f7a671c22969cbeed4d12d10bbb77d9d109 Signed-off-by: Lajos Molnar <molnar@ti.com> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
-rw-r--r--drivers/video/omap2/dss/dss.h3
-rw-r--r--drivers/video/omap2/dss/hdmi.c36
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c1
-rw-r--r--drivers/video/omap2/hdcp/hdcp_top.c14
4 files changed, 33 insertions, 21 deletions
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 30290e7..22cd979 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -548,14 +548,13 @@ void omapdss_hdmi_set_deepcolor(int val);
int hdmi_get_current_hpd(void);
void hdmi_get_monspecs(struct fb_monspecs *specs);
u8 *hdmi_read_edid(struct omap_video_timings *);
-void hdmi_load_hdcp_keys(struct omap_dss_device *dssdev);
int hdmi_panel_init(void);
void hdmi_panel_exit(void);
void hdmi_dump_regs(struct seq_file *s);
int omapdss_hdmi_register_hdcp_callbacks(void (*hdmi_start_frame_cb)(void),
void (*hdmi_irq_cb)(int status),
- void (*hdmi_power_on_cb)(void));
+ bool (*hdmi_power_on_cb)(void));
int omap_dss_ovl_set_info(struct omap_overlay *ovl,
struct omap_overlay_info *info);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index c244634..fa98966 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -83,10 +83,11 @@ static struct {
int runtime_count;
int enabled;
bool set_mode;
+ bool wp_reset_done;
void (*hdmi_start_frame_cb)(void);
void (*hdmi_irq_cb)(int);
- void (*hdmi_power_on_cb)(void);
+ bool (*hdmi_power_on_cb)(void);
} hdmi;
static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
@@ -421,7 +422,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 1);
- if (hdmi.hdmi_start_frame_cb && hdmi.custom_set)
+ if (hdmi.hdmi_start_frame_cb &&
+ hdmi.custom_set &&
+ hdmi.wp_reset_done)
(*hdmi.hdmi_start_frame_cb)();
return 0;
@@ -432,6 +435,9 @@ err:
static void hdmi_power_off(struct omap_dss_device *dssdev)
{
+ if (hdmi.hdmi_irq_cb)
+ hdmi.hdmi_irq_cb(HDMI_HPD_LOW);
+
hdmi_ti_4xxx_wp_video_start(&hdmi.hdmi_data, 0);
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, dssdev->type, 0);
@@ -441,12 +447,16 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi.deep_color = HDMI_DEEP_COLOR_24BIT;
}
-void hdmi_load_hdcp_keys(struct omap_dss_device *dssdev)
+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.hdmi_power_on_cb();
- hdmi_ti_4xxx_set_wait_soft_reset(&hdmi.hdmi_data);
+ 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");
+ }
}
}
@@ -462,7 +472,7 @@ int omapdss_hdmi_get_mode(void)
int omapdss_hdmi_register_hdcp_callbacks(void (*hdmi_start_frame_cb)(void),
void (*hdmi_irq_cb)(int status),
- void (*hdmi_power_on_cb)(void))
+ bool (*hdmi_power_on_cb)(void))
{
hdmi.hdmi_start_frame_cb = hdmi_start_frame_cb;
hdmi.hdmi_irq_cb = hdmi_irq_cb;
@@ -492,8 +502,6 @@ static irqreturn_t hpd_irq_handler(int irq, void *ptr)
int hpd = hdmi_get_current_hpd();
pr_info("hpd %d\n", hpd);
- if (!hpd && hdmi.hdmi_irq_cb)
- hdmi.hdmi_irq_cb(HDMI_HPD_LOW);
hdmi_panel_hpd_handler(hpd);
return IRQ_HANDLED;
@@ -534,6 +542,7 @@ int omapdss_hdmi_display_set_mode(struct omap_dss_device *dssdev,
struct fb_videomode *vm)
{
int r1, r2;
+ DSSINFO("Enter omapdss_hdmi_display_set_mode\n");
/* turn the hdmi off and on to get new timings to use */
hdmi.set_mode = true;
dssdev->driver->disable(dssdev);
@@ -564,7 +573,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
{
int r = 0;
- DSSDBG("ENTER hdmi_display_enable\n");
+ DSSINFO("ENTER hdmi_display_enable\n");
mutex_lock(&hdmi.lock);
@@ -598,6 +607,8 @@ 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");
@@ -625,7 +636,7 @@ err0:
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
{
- DSSDBG("Enter hdmi_display_disable\n");
+ DSSINFO("Enter hdmi_display_disable\n");
mutex_lock(&hdmi.lock);
@@ -633,6 +644,8 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
goto done;
hdmi.enabled = false;
+ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
+ hdmi.wp_reset_done = false;
hdmi_power_off(dssdev);
if (dssdev->sync_lost_error == 0)
@@ -753,6 +766,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi.hdmi_data.hdmi_core_av_offset = HDMI_CORE_AV;
hdmi.hdmi_data.hdmi_pll_offset = HDMI_PLLCTRL;
hdmi.hdmi_data.hdmi_phy_offset = HDMI_PHY;
+ hdmi.wp_reset_done = false;
hdmi_panel_init();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index c17fad5..0fa5dea 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -224,7 +224,6 @@ static void hdmi_hotplug_detect_worker(struct work_struct *work)
dssdev->panel.monspecs.max_x * 10000;
dssdev->panel.height_in_um =
dssdev->panel.monspecs.max_y * 10000;
- hdmi_load_hdcp_keys(dssdev);
switch_set_state(&hdmi.hpd_switch, 1);
goto done;
} else if (state == HPD_STATE_EDID_TRYLAST){
diff --git a/drivers/video/omap2/hdcp/hdcp_top.c b/drivers/video/omap2/hdcp/hdcp_top.c
index f23605a..c9151a2 100644
--- a/drivers/video/omap2/hdcp/hdcp_top.c
+++ b/drivers/video/omap2/hdcp/hdcp_top.c
@@ -466,21 +466,22 @@ static void hdcp_cancel_work(struct delayed_work **work)
* Function: hdcp_3des_cb
*-----------------------------------------------------------------------------
*/
-static void hdcp_3des_cb(void)
+static bool hdcp_3des_cb(void)
{
DBG("hdcp_3des_cb() %u", jiffies_to_msecs(jiffies));
if (!hdcp.hdcp_keys_loaded) {
- DBG("%s: hdcp_keys not loaded = %d",
- __func__, hdcp.hdcp_keys_loaded);
- return;
+ printk(KERN_ERR "%s: hdcp_keys not loaded = %d",
+ __func__, hdcp.hdcp_keys_loaded);
+ return false;
}
/* Load 3DES key */
if (hdcp_3des_load_key(hdcp.en_ctrl->key) != HDCP_OK) {
printk(KERN_ERR "Error Loading HDCP keys\n");
- return;
+ return false;
}
+ return true;
}
/*-----------------------------------------------------------------------------
@@ -504,8 +505,7 @@ static void hdcp_start_frame_cb(void)
hdcp.hpd_low = 0;
hdcp.pending_disable = 0;
hdcp.retry_cnt = hdcp.en_ctrl->nb_retry;
- hdcp.pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
- HDCP_ENABLE_DELAY);
+ hdcp.pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT, 0);
}
/*-----------------------------------------------------------------------------