aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/tvout
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/tvout')
-rw-r--r--drivers/media/video/samsung/tvout/Kconfig10
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hdcp.c20
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hdmi.c56
-rw-r--r--drivers/media/video/samsung/tvout/hw_if/hw_if.h26
-rw-r--r--drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c76
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c89
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout.c38
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h10
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h4
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_fb.c16
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_hpd.c80
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c115
-rw-r--r--drivers/media/video/samsung/tvout/s5p_vp_ctrl.c20
13 files changed, 447 insertions, 113 deletions
diff --git a/drivers/media/video/samsung/tvout/Kconfig b/drivers/media/video/samsung/tvout/Kconfig
index 176efeb..da7bda7 100644
--- a/drivers/media/video/samsung/tvout/Kconfig
+++ b/drivers/media/video/samsung/tvout/Kconfig
@@ -62,6 +62,16 @@ config HDMI_CONTROLLED_BY_EXT_IC
For example, the H/W has HDMI level shifter then it should be turned
on when HPD interrupt comes.
+config HDMI_TX_STRENGTH
+ bool "Tuning TX amplitude"
+ depends on VIDEO_TVOUT && ARCH_EXYNOS4
+ default n
+ ---help---
+ Say y here if the H/W needs to be tuned for TX amplitude.
+ HDMI driver will take the values registered at board file
+ and apply them through HDMI phy i2c according to the requested
+ channel number.
+
config HDMI_SWITCH_HPD
bool "HDMI HPD switch uevent driver support"
depends on HDMI_HPD
diff --git a/drivers/media/video/samsung/tvout/hw_if/hdcp.c b/drivers/media/video/samsung/tvout/hw_if/hdcp.c
index 569de28..41caf19 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hdcp.c
+++ b/drivers/media/video/samsung/tvout/hw_if/hdcp.c
@@ -379,7 +379,9 @@ static int s5p_hdcp_read_bcaps(void)
if (s5p_ddc_read(HDCP_Bcaps, BCAPS_SIZE, &bcaps) < 0)
goto bcaps_read_err;
- if (s5p_hdmi_ctrl_status() == false || !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ if (s5p_hdmi_ctrl_status() == false ||
+ !s5p_hdmi_reg_get_hpd_status() ||
+ on_stop_process)
goto bcaps_read_err;
writeb(bcaps, hdmi_base + S5P_HDMI_HDCP_BCAPS);
@@ -532,7 +534,8 @@ static void s5p_hdcp_reset_auth(void)
unsigned long spin_flags;
if (s5p_hdmi_ctrl_status() == false ||
- !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ !s5p_hdmi_reg_get_hpd_status() ||
+ on_stop_process)
return;
spin_lock_irqsave(&hdcp_info.reset_lock, spin_flags);
@@ -956,9 +959,12 @@ check_ri_err:
static void s5p_hdcp_work(void *arg)
{
+ s5p_tvout_mutex_lock();
if (!hdcp_info.hdcp_enable || s5p_hdmi_ctrl_status() == false ||
- !s5p_hdmi_reg_get_hpd_status() || on_stop_process)
+ !s5p_hdmi_reg_get_hpd_status() || on_stop_process) {
+ s5p_tvout_mutex_unlock();
return;
+ }
if (hdcp_info.event & HDCP_EVENT_READ_BKSV_START) {
if (s5p_hdcp_bksv() < 0)
@@ -987,13 +993,16 @@ static void s5p_hdcp_work(void *arg)
else
hdcp_info.event &= ~HDCP_EVENT_CHECK_RI_START;
}
+ s5p_tvout_mutex_unlock();
return;
work_err:
if (!hdcp_info.hdcp_enable || s5p_hdmi_ctrl_status() == false ||
!s5p_hdmi_reg_get_hpd_status() || on_stop_process) {
+ s5p_tvout_mutex_unlock();
return;
}
s5p_hdcp_reset_auth();
+ s5p_tvout_mutex_unlock();
}
irqreturn_t s5p_hdcp_irq_handler(int irq, void *dev_id)
@@ -1121,3 +1130,8 @@ int s5p_hdcp_encrypt_stop(bool on)
return 0;
}
+
+void s5p_hdcp_flush_work(void)
+{
+ flush_workqueue(hdcp_wq);
+}
diff --git a/drivers/media/video/samsung/tvout/hw_if/hdmi.c b/drivers/media/video/samsung/tvout/hw_if/hdmi.c
index dfb3152..67099af 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hdmi.c
+++ b/drivers/media/video/samsung/tvout/hw_if/hdmi.c
@@ -871,10 +871,10 @@ static void s5p_hdmi_print_phy_config(void)
printk(KERN_WARNING "read buffer :\n");
- for (i = 1; i < size; i++) {
+ for (i = 0; i < size; i++) {
printk("0x%02x", read_buffer[i]);
- if (i % 8)
+ if ((i+1) % 8)
printk(" ");
else
printk("\n");
@@ -1146,6 +1146,58 @@ void s5p_hdmi_reg_sw_reset(void)
s5p_hdmi_ctrl_clock(0);
}
+#ifdef CONFIG_HDMI_TX_STRENGTH
+int s5p_hdmi_phy_set_tx_strength(u8 ch, u8 *value)
+{
+ u8 buff[2];
+
+ if (ch & TX_EMP_LVL) { /* REG10 BIT7:4 */
+ buff[0] = HDMI_PHY_I2C_REG10;
+ buff[1] = (value[TX_EMP_LVL_VAL] & 0x0f) << 4;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_AMP_LVL) { /* REG10 BIT3:0, REG0F BIT7 */
+ buff[0] = HDMI_PHY_I2C_REG10;
+ buff[1] = (value[TX_AMP_LVL_VAL] & 0x0e) >> 1;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ buff[0] = HDMI_PHY_I2C_REG0F;
+ buff[1] = (value[TX_AMP_LVL_VAL] & 0x01) << 7;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH0) { /* REG04 BIT7:6 */
+ buff[0] = HDMI_PHY_I2C_REG04;
+ buff[1] = (value[TX_LVL_CH0_VAL] & 0x3) << 6;
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH1) { /* REG13 BIT1:0 */
+ buff[0] = HDMI_PHY_I2C_REG13;
+ buff[1] = (value[TX_LVL_CH1_VAL] & 0x3);
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ if (ch & TX_LVL_CH2) { /* REG17 BIT1:0 */
+ buff[0] = HDMI_PHY_I2C_REG17;
+ buff[1] = (value[TX_LVL_CH2_VAL] & 0x3);
+ if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ pr_err("%s: failed to set tx strength\n", __func__);
+ return -1;
+}
+#endif
+
int s5p_hdmi_phy_power(bool on)
{
u32 size;
diff --git a/drivers/media/video/samsung/tvout/hw_if/hw_if.h b/drivers/media/video/samsung/tvout/hw_if/hw_if.h
index 11bda99..e437b0a 100644
--- a/drivers/media/video/samsung/tvout/hw_if/hw_if.h
+++ b/drivers/media/video/samsung/tvout/hw_if/hw_if.h
@@ -364,6 +364,27 @@ struct s5p_hdmi_v_format {
u8 mhl_vsync;
};
+#ifdef CONFIG_HDMI_TX_STRENGTH
+#define HDMI_PHY_I2C_REG10 0x10
+#define HDMI_PHY_I2C_REG0F 0x0F
+#define HDMI_PHY_I2C_REG04 0x04
+#define HDMI_PHY_I2C_REG13 0x13
+#define HDMI_PHY_I2C_REG17 0x17
+
+#define TX_EMP_LVL 0x10
+#define TX_AMP_LVL 0x08
+#define TX_LVL_CH0 0x04
+#define TX_LVL_CH1 0x02
+#define TX_LVL_CH2 0x01
+
+#define TX_EMP_LVL_VAL 0
+#define TX_AMP_LVL_VAL 1
+#define TX_LVL_CH0_VAL 2
+#define TX_LVL_CH1_VAL 3
+#define TX_LVL_CH2_VAL 4
+
+extern int s5p_hdmi_phy_set_tx_strength(u8 ch, u8 *value);
+#endif
extern int s5p_hdmi_phy_power(bool on);
extern s32 s5p_hdmi_phy_config(
enum phy_freq freq, enum s5p_hdmi_color_depth cd);
@@ -750,6 +771,7 @@ extern int s5p_hdcp_encrypt_stop(bool on);
extern int __init s5p_hdcp_init(void);
extern int s5p_hdcp_start(void);
extern int s5p_hdcp_stop(void);
+extern void s5p_hdcp_flush_work(void);
/****************************************
* Definitions for sdo ctrl class
@@ -1000,6 +1022,10 @@ struct s5p_tvif_ctrl_private_data {
struct device *bus_dev; /* for BusFreq with Opp */
#endif
struct device *dev; /* hpd device pointer */
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ u8 tx_ch;
+ u8 *tx_val;
+#endif
};
#endif /* _SAMSUNG_TVOUT_HW_IF_H_ */
diff --git a/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c b/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
index a0169cb..5e78a3c 100644
--- a/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_mixer_ctrl.c
@@ -241,7 +241,7 @@ static void s5p_mixer_ctrl_clock(bool on)
clk_enable(s5p_mixer_ctrl_private.clk[ACLK].ptr);
- // Restore mixer_base address
+ /* Restore mixer_base address */
s5p_mixer_init(s5p_mixer_ctrl_private.reg_mem.base);
} else {
clk_disable(s5p_mixer_ctrl_private.clk[ACLK].ptr);
@@ -252,7 +252,7 @@ static void s5p_mixer_ctrl_clock(bool on)
clk_disable(s5p_mixer_ctrl_private.clk[MUX].ptr);
- // Set mixer_base address to NULL
+ /* Set mixer_base address to NULL */
s5p_mixer_init(NULL);
}
}
@@ -267,7 +267,7 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
{
struct s5ptvfb_user_scaling scaling;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -278,12 +278,16 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
s5p_mixer_set_priority(layer,
s5p_mixer_ctrl_private.layer[layer].priority);
s5p_mixer_set_pre_mul_mode(layer,
- s5p_mixer_ctrl_private.layer[layer].pre_mul_mode);
+ s5p_mixer_ctrl_private.layer[layer].
+ pre_mul_mode);
s5p_mixer_set_chroma_key(layer,
- s5p_mixer_ctrl_private.layer[layer].chroma_enable,
- s5p_mixer_ctrl_private.layer[layer].chroma_key);
+ s5p_mixer_ctrl_private.layer[layer].
+ chroma_enable,
+ s5p_mixer_ctrl_private.layer[layer].
+ chroma_key);
s5p_mixer_set_layer_blend(layer,
- s5p_mixer_ctrl_private.layer[layer].layer_blend);
+ s5p_mixer_ctrl_private.layer[layer].
+ layer_blend);
s5p_mixer_set_alpha(layer,
s5p_mixer_ctrl_private.layer[layer].alpha);
s5p_mixer_set_grp_layer_dst_pos(layer,
@@ -299,7 +303,8 @@ void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer)
}
}
-int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 trans_len)
+int s5p_mixer_ctrl_set_pixel_format(
+ enum s5p_mixer_layer layer, u32 bpp, u32 trans_len)
{
enum s5p_mixer_color_fmt format;
@@ -322,7 +327,7 @@ int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 tra
s5p_mixer_ctrl_private.layer[layer].format = format;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -351,7 +356,7 @@ int s5p_mixer_ctrl_enable_layer(enum s5p_mixer_layer layer)
tvout_err("invalid layer\n");
return -1;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -384,7 +389,7 @@ int s5p_mixer_ctrl_disable_layer(enum s5p_mixer_layer layer)
return -1;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -523,7 +528,7 @@ int s5p_mixer_ctrl_set_dst_win_pos(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].dst_x = (u32)dst_x;
s5p_mixer_ctrl_private.layer[layer].dst_y = (u32)dst_y;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -551,7 +556,7 @@ int s5p_mixer_ctrl_set_src_win_pos(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].width = w;
s5p_mixer_ctrl_private.layer[layer].height = h;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -559,7 +564,8 @@ int s5p_mixer_ctrl_set_src_win_pos(enum s5p_mixer_layer layer,
#endif
{
if (s5p_mixer_ctrl_private.running)
- s5p_mixer_set_grp_layer_src_pos(layer, src_x, src_y, w, w, h);
+ s5p_mixer_set_grp_layer_src_pos(
+ layer, src_x, src_y, w, w, h);
}
return 0;
@@ -577,7 +583,7 @@ int s5p_mixer_ctrl_set_buffer_address(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].fb_addr = start_addr;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -602,7 +608,7 @@ int s5p_mixer_ctrl_set_chroma_key(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].chroma_enable = enabled;
s5p_mixer_ctrl_private.layer[layer].chroma_key = chroma.key;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -709,7 +715,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
case PIXEL_BLENDING:
tvout_dbg("pixel blending\n");
s5p_mixer_ctrl_private.layer[layer].pixel_blend = true;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -723,7 +729,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
tvout_dbg("layer blending : alpha value = 0x%x\n", alpha);
s5p_mixer_ctrl_private.layer[layer].layer_blend = true;
s5p_mixer_ctrl_private.layer[layer].alpha = alpha;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -739,7 +745,7 @@ int s5p_mixer_ctrl_set_alpha_blending(enum s5p_mixer_layer layer,
tvout_dbg("alpha blending off\n");
s5p_mixer_ctrl_private.layer[layer].pixel_blend = false;
s5p_mixer_ctrl_private.layer[layer].layer_blend = false;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -780,7 +786,7 @@ int s5p_mixer_ctrl_scaling(enum s5p_mixer_layer layer,
s5p_mixer_ctrl_private.layer[layer].ver = scaling.ver;
s5p_mixer_ctrl_private.layer[layer].hor = scaling.hor;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return 0;
@@ -796,7 +802,8 @@ int s5p_mixer_ctrl_mux_clk(struct clk *ptr)
{
if (clk_set_parent(s5p_mixer_ctrl_private.clk[MUX].ptr, ptr)) {
tvout_err("unable to set parent %s of clock %s.\n",
- ptr->name, s5p_mixer_ctrl_private.clk[MUX].ptr->name);
+ ptr->name,
+ s5p_mixer_ctrl_private.clk[MUX].ptr->name);
return -1;
}
@@ -828,6 +835,12 @@ bool s5p_mixer_ctrl_get_vsync_interrupt()
return s5p_mixer_ctrl_private.vsync_interrupt_enable;
}
+void s5p_mixer_ctrl_disable_vsync_interrupt()
+{
+ if (s5p_mixer_ctrl_private.running)
+ s5p_mixer_set_vsync_interrupt(false);
+}
+
void s5p_mixer_ctrl_clear_pend_all(void)
{
if (s5p_mixer_ctrl_private.running)
@@ -840,7 +853,7 @@ void s5p_mixer_ctrl_stop(void)
tvout_dbg("running(%d)\n", s5p_mixer_ctrl_private.running);
if (s5p_mixer_ctrl_private.running) {
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -848,11 +861,12 @@ void s5p_mixer_ctrl_stop(void)
{
s5p_mixer_set_vsync_interrupt(false);
- for (i = 0; i < S5PTV_VP_BUFF_CNT -1; i++)
+ for (i = 0; i < S5PTV_VP_BUFF_CNT-1; i++)
s5ptv_vp_buff.copy_buff_idxs[i] = i;
s5ptv_vp_buff.curr_copy_idx = 0;
- s5ptv_vp_buff.vp_access_buff_idx = S5PTV_VP_BUFF_CNT - 1;
+ s5ptv_vp_buff.vp_access_buff_idx =
+ S5PTV_VP_BUFF_CNT - 1;
s5p_mixer_stop();
s5p_mixer_ctrl_clock(0);
@@ -1006,10 +1020,24 @@ int s5p_mixer_ctrl_start(
s5p_mixer_init_csc_coef_default(csc_for_coeff);
s5p_mixer_init_display_mode(disp, out, csc);
+#ifndef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
if (!s5p_tvif_get_q_range() || out == TVOUT_HDMI_RGB)
mixer_video_limiter = true;
else
mixer_video_limiter = false;
+#else
+ /* full range */
+ if ((out == TVOUT_HDMI_RGB && disp == TVOUT_480P_60_4_3) ||
+ (out != TVOUT_HDMI_RGB && s5p_tvif_get_q_range())) {
+ mixer_video_limiter = false;
+ for (i = MIXER_BG_COLOR_0; i <= MIXER_BG_COLOR_2; i++)
+ s5p_mixer_ctrl_private.bg_color[i].color_y = 0;
+ } else { /* limited range */
+ mixer_video_limiter = true;
+ for (i = MIXER_BG_COLOR_0; i <= MIXER_BG_COLOR_2; i++)
+ s5p_mixer_ctrl_private.bg_color[i].color_y = 16;
+ }
+#endif
s5p_mixer_set_video_limiter(s5p_mixer_ctrl_private.v_layer.y_min,
s5p_mixer_ctrl_private.v_layer.y_max,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c b/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
index 93cb640..43e7a1f 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
@@ -49,6 +49,12 @@
#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
#include <mach/dev.h>
#endif
+#include <mach/regs-hdmi.h>
+
+#ifdef CONFIG_HDMI_TX_STRENGTH
+#include <plat/tvout.h>
+#endif
+
#include "s5p_tvout_common_lib.h"
#include "hw_if/hw_if.h"
@@ -1758,7 +1764,7 @@ static void s5p_sdo_ctrl_clock(bool on)
#ifdef CONFIG_ARCH_EXYNOS4
s5p_tvout_pm_runtime_get();
#endif
- // Restore sdo_base address
+ /* Restore sdo_base address */
s5p_sdo_init(s5p_sdo_ctrl_private.reg_mem.base);
clk_enable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
@@ -1771,7 +1777,7 @@ static void s5p_sdo_ctrl_clock(bool on)
clk_disable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
- // Set sdo_base address to NULL
+ /* Set sdo_base address to NULL */
s5p_sdo_init(NULL);
}
@@ -2362,8 +2368,10 @@ static void s5p_hdmi_ctrl_internal_stop(void)
#ifdef CONFIG_HDMI_HPD
s5p_hpd_set_eint();
#endif
- if (ctrl->hdcp_en)
+ if (ctrl->hdcp_en) {
s5p_hdcp_stop();
+ s5p_hdcp_flush_work();
+ }
s5p_hdmi_reg_enable(false);
@@ -2376,10 +2384,16 @@ int s5p_hdmi_ctrl_phy_power(bool on)
if (on) {
/* on */
clk_enable(s5ptv_status.i2c_phy_clk);
- // Restore i2c_hdmi_phy_base address
+ /* Restore i2c_hdmi_phy_base address */
s5p_hdmi_phy_init(s5p_hdmi_ctrl_private.reg_mem[HDMI_PHY].base);
s5p_hdmi_phy_power(true);
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ if (s5p_tvif_ctrl_private.tx_val)
+ s5p_hdmi_phy_set_tx_strength(
+ s5p_tvif_ctrl_private.tx_ch,
+ s5p_tvif_ctrl_private.tx_val);
+#endif
} else {
/*
@@ -2398,7 +2412,7 @@ int s5p_hdmi_ctrl_phy_power(bool on)
s5p_hdmi_phy_power(false);
clk_disable(s5ptv_status.i2c_phy_clk);
- // Set i2c_hdmi_phy_base to NULL
+ /* Set i2c_hdmi_phy_base to NULL */
s5p_hdmi_phy_init(NULL);
}
@@ -2419,7 +2433,7 @@ void s5p_hdmi_ctrl_clock(bool on)
#endif
clk_enable(clk[HDMI_PCLK].ptr);
- // Restore hdmi_base address
+ /* Restore hdmi_base address */
s5p_hdmi_init(s5p_hdmi_ctrl_private.reg_mem[HDMI].base);
} else {
clk_disable(clk[HDMI_PCLK].ptr);
@@ -2430,7 +2444,7 @@ void s5p_hdmi_ctrl_clock(bool on)
clk_disable(clk[HDMI_MUX].ptr);
- // Set hdmi_base to NULL
+ /* Set hdmi_base to NULL */
s5p_hdmi_init(NULL);
}
}
@@ -2447,7 +2461,7 @@ void s5p_hdmi_ctrl_stop(void)
tvout_dbg("running(%d)\n", ctrl->running);
if (ctrl->running) {
ctrl->running = false;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2681,7 +2695,7 @@ static int s5p_tvif_ctrl_internal_stop(void)
case TVOUT_HDMI:
case TVOUT_HDMI_RGB:
s5p_hdmi_ctrl_stop();
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2705,6 +2719,10 @@ static void s5p_tvif_ctrl_internal_start(
enum s5p_tvout_o_mode inf)
{
tvout_dbg("\n");
+#ifdef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+#endif
s5p_mixer_ctrl_set_int_enable(false);
/* Clear All Interrupt Pending */
@@ -2724,6 +2742,47 @@ static void s5p_tvif_ctrl_internal_start(
case TVOUT_HDMI:
case TVOUT_HDMI_RGB:
case TVOUT_DVI:
+#ifdef __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+ switch (std) {
+ case TVOUT_480P_60_4_3:
+ if (inf == TVOUT_HDMI_RGB) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else if (s5p_tvif_get_q_range()) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_YPBPR;
+ break;
+ case TVOUT_480P_60_16_9:
+ case TVOUT_480P_59:
+ case TVOUT_576P_50_16_9:
+ case TVOUT_576P_50_4_3:
+ case TVOUT_720P_60:
+ case TVOUT_720P_50:
+ case TVOUT_720P_59:
+ case TVOUT_1080I_60:
+ case TVOUT_1080I_59:
+ case TVOUT_1080I_50:
+ case TVOUT_1080P_60:
+ case TVOUT_1080P_30:
+ case TVOUT_1080P_59:
+ case TVOUT_1080P_50:
+ if (inf == TVOUT_HDMI_RGB) /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_RGB;
+ else if (s5p_tvif_get_q_range()) /* full range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_BYPASS;
+ else /* limited range */
+ s5p_hdmi_output[inf].reg.pxl_limit =
+ S5P_HDMI_PX_LMT_CTRL_YPBPR;
+ break;
+ default:
+ break;
+ }
+#endif
s5p_hdmi_ctrl_phy_power(1);
if (s5p_mixer_ctrl_start(std, inf) < 0)
@@ -2854,7 +2913,7 @@ int s5p_tvif_ctrl_start(
goto cannot_change;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -2889,6 +2948,16 @@ void s5p_tvif_ctrl_stop(void)
int s5p_tvif_ctrl_constructor(struct platform_device *pdev)
{
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ struct s5p_platform_tvout *pdata = to_tvout_plat(&pdev->dev);
+ s5p_tvif_ctrl_private.tx_ch = 0x00;
+ s5p_tvif_ctrl_private.tx_val = NULL;
+ if ((pdata) && (pdata->tx_tune)) {
+ s5p_tvif_ctrl_private.tx_ch = pdata->tx_tune->tx_ch;
+ s5p_tvif_ctrl_private.tx_val = pdata->tx_tune->tx_val;
+ }
+#endif
+
#ifdef CONFIG_ANALOG_TVENC
if (s5p_sdo_ctrl_constructor(pdev))
goto err;
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout.c b/drivers/media/video/samsung/tvout/s5p_tvout.c
index 7407670..5f00ebc 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/delay.h>
#if defined(CONFIG_S5P_SYSMMU_TV)
#include <plat/sysmmu.h>
@@ -25,6 +26,10 @@
#include <mach/media.h>
#endif
+#if defined(CONFIG_HDMI_TX_STRENGTH) && !defined(CONFIG_USER_ALLOC_TVOUT)
+#include <plat/tvout.h>
+#endif
+
#include "s5p_tvout_common_lib.h"
#include "s5p_tvout_ctrl.h"
#include "s5p_tvout_fb.h"
@@ -291,6 +296,12 @@ static int __devinit s5p_tvout_probe(struct platform_device *pdev)
struct device *hdmi_audio_dev;
#endif
+#if defined(CONFIG_HDMI_TX_STRENGTH) && !defined(CONFIG_USER_ALLOC_TVOUT)
+ struct s5p_platform_tvout *pdata;
+ u8 tx_ch;
+ u8 *tx_val;
+#endif
+
#ifdef CONFIG_TVOUT_DEBUG
struct class *sec_tvout;
tvout_dbg_flag = 1 << DBG_FLAG_HPD;
@@ -339,6 +350,15 @@ static int __devinit s5p_tvout_probe(struct platform_device *pdev)
s5p_hdmi_phy_power(true);
if (s5p_tvif_ctrl_start(TVOUT_720P_60, TVOUT_HDMI) < 0)
goto err_tvif_start;
+#ifdef CONFIG_HDMI_TX_STRENGTH
+ pdata = to_tvout_plat(&pdev->dev);
+ if (pdata && pdata->tx_tune) {
+ tx_ch = pdata->tx_tune->tx_ch;
+ tx_val = pdata->tx_tune->tx_val;
+ }
+ if (tx_ch && tx_val)
+ s5p_hdmi_phy_set_tx_strength(tx_ch, tx_val);
+#endif
#endif
/* prepare memory */
@@ -495,14 +515,19 @@ static int s5p_tvout_remove(struct platform_device *pdev)
static void s5p_tvout_early_suspend(struct early_suspend *h)
{
tvout_dbg("\n");
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
mutex_lock(&s5p_tvout_mutex);
- s5p_mixer_ctrl_set_vsync_interrupt(false);
+ /* disable vsync interrupt during early suspend */
+ s5p_mixer_ctrl_disable_vsync_interrupt();
s5p_vp_ctrl_suspend();
s5p_mixer_ctrl_suspend();
s5p_tvif_ctrl_suspend();
suspend_status = 1;
tvout_dbg("suspend_status is true\n");
mutex_unlock(&s5p_tvout_mutex);
+#else
+ suspend_status = 1;
+#endif
return;
}
@@ -511,6 +536,7 @@ static void s5p_tvout_late_resume(struct early_suspend *h)
{
tvout_dbg("\n");
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
mutex_lock(&s5p_tvout_mutex);
#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
@@ -521,11 +547,17 @@ static void s5p_tvout_late_resume(struct early_suspend *h)
#endif
suspend_status = 0;
tvout_dbg("suspend_status is false\n");
+
s5p_tvif_ctrl_resume();
s5p_mixer_ctrl_resume();
s5p_vp_ctrl_resume();
- s5p_mixer_ctrl_set_vsync_interrupt(s5p_mixer_ctrl_get_vsync_interrupt());
+ /* restore vsync interrupt setting */
+ s5p_mixer_ctrl_set_vsync_interrupt(
+ s5p_mixer_ctrl_get_vsync_interrupt());
mutex_unlock(&s5p_tvout_mutex);
+#else
+ suspend_status = 0;
+#endif
return;
}
@@ -562,8 +594,10 @@ static int s5p_tvout_suspend(struct device *dev)
static int s5p_tvout_resume(struct device *dev)
{
tvout_dbg("\n");
+#if defined(CLOCK_GATING_ON_EARLY_SUSPEND)
#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412)
flag_after_resume = true;
+#endif
#else
queue_work_on(0, tvout_resume_wq, &tvout_resume_work);
#endif
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h b/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
index e43b9c7..467ab1d 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_common_lib.h
@@ -45,6 +45,12 @@ do { \
#endif
#endif
+/*
+#if defined(CONFIG_MACH_T0) || defined(CONFIG_MACH_M3)
+#define __CONFIG_HDMI_SUPPORT_FULL_RANGE__
+#endif
+*/
+
#define S5PTV_FB_CNT 2
#define S5PTV_VP_BUFF_CNT 4
#define S5PTV_VP_BUFF_SIZE (4*1024*1024)
@@ -53,6 +59,10 @@ do { \
#define HDMI_START_NUM 0x1000
+#ifdef CONFIG_CPU_EXYNOS4210
+#define CLOCK_GATING_ON_EARLY_SUSPEND
+#endif
+
enum s5p_tvout_disp_mode {
TVOUT_NTSC_M = 0,
TVOUT_PAL_BDGHI,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h b/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
index 43043b4..b330a95 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_ctrl.h
@@ -29,7 +29,8 @@
extern void s5p_mixer_ctrl_init_fb_addr_phy(enum s5p_mixer_layer layer,
dma_addr_t fb_addr);
extern void s5p_mixer_ctrl_init_grp_layer(enum s5p_mixer_layer layer);
-extern int s5p_mixer_ctrl_set_pixel_format(enum s5p_mixer_layer layer, u32 bpp, u32 trans_len);
+extern int s5p_mixer_ctrl_set_pixel_format(
+ enum s5p_mixer_layer layer, u32 bpp, u32 trans_len);
extern int s5p_mixer_ctrl_enable_layer(enum s5p_mixer_layer layer);
extern int s5p_mixer_ctrl_disable_layer(enum s5p_mixer_layer layer);
extern int s5p_mixer_ctrl_set_priority(enum s5p_mixer_layer layer, u32 prio);
@@ -52,6 +53,7 @@ extern int s5p_mixer_ctrl_mux_clk(struct clk *ptr);
extern void s5p_mixer_ctrl_set_int_enable(bool en);
extern void s5p_mixer_ctrl_set_vsync_interrupt(bool en);
extern bool s5p_mixer_ctrl_get_vsync_interrupt(void);
+extern void s5p_mixer_ctrl_disable_vsync_interrupt(void);
extern void s5p_mixer_ctrl_clear_pend_all(void);
extern void s5p_mixer_ctrl_stop(void);
extern void s5p_mixer_ctrl_internal_start(void);
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_fb.c b/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
index 5a2ce5a..c0a3508 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_fb.c
@@ -303,7 +303,7 @@ static int s5p_tvout_fb_blank(int blank_mode, struct fb_info *fb)
tvout_dbg("change blank mode\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (fb->node) {
@@ -336,12 +336,12 @@ static int s5p_tvout_fb_blank(int blank_mode, struct fb_info *fb)
goto err_fb_blank;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 1;
err_fb_blank:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -356,7 +356,7 @@ static int s5p_tvout_fb_set_par(struct fb_info *fb)
tvout_dbg("[fb%d] set_par\n", win->id);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
if (!fb->fix.smem_start) {
@@ -390,7 +390,7 @@ static int s5p_tvout_fb_set_par(struct fb_info *fb)
s5p_mixer_ctrl_set_src_win_pos(layer, src_x, src_y, w, h);
s5p_mixer_ctrl_set_alpha_blending(layer, win->alpha.mode,
win->alpha.value);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -472,7 +472,7 @@ static int s5p_tvout_fb_ioctl(struct fb_info *fb, unsigned int cmd,
} p;
tvout_dbg("\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (fb->node) {
@@ -552,13 +552,13 @@ static int s5p_tvout_fb_ioctl(struct fb_info *fb, unsigned int cmd,
s5p_mixer_ctrl_scaling(layer, p.user_scaling);
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
err_fb_ioctl:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c b/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
index 4f35a91..1c98453 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_hpd.c
@@ -67,6 +67,12 @@ struct hpd_struct {
#endif
};
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+static work_func_t ext_ic_control_func(void) ;
+static DECLARE_DELAYED_WORK(ext_ic_control_dwork,
+ (work_func_t)ext_ic_control_func);
+#endif
+
static struct hpd_struct hpd_struct;
static int last_hpd_state;
@@ -81,6 +87,10 @@ static ssize_t s5p_hpd_read(struct file *file, char __user *buffer,
static unsigned int s5p_hpd_poll(struct file *file, poll_table *wait);
static long s5p_hpd_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+void mhl_hpd_handler(bool onoff);
+bool (*is_mhl_power_state_on)(void);
+#endif
static const struct file_operations hpd_fops = {
.owner = THIS_MODULE,
@@ -139,6 +149,7 @@ static void s5p_hpd_kobject_uevent(void)
if (hpd_state) {
if (last_uevent_state == -1 || last_uevent_state == HPD_LO) {
#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ HPDPRINTK("ext_ic power ON\n");
hpd_struct.ext_ic_control(true);
msleep(20);
#endif
@@ -154,9 +165,13 @@ static void s5p_hpd_kobject_uevent(void)
KOBJ_CHANGE, envp);
#endif
HPDPRINTK("[HDMI] HPD event -connect!!!\n");
- on_start_process = true;
+ if (atomic_read(&hdmi_status) == HDMI_OFF) {
+ on_start_process = true;
+ } else {
+ on_start_process = false;
+ }
HPDIFPRINTK("%s() on_start_process(%d)\n",
- __func__, on_start_process);
+ __func__, on_start_process);
}
last_uevent_state = HPD_HI;
} else {
@@ -176,10 +191,14 @@ static void s5p_hpd_kobject_uevent(void)
KOBJ_CHANGE, envp);
#endif
HPDPRINTK("[HDMI] HPD event -disconnet!!!\n");
- on_stop_process = true;
-#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
- hpd_struct.ext_ic_control(false);
-#endif
+ if (atomic_read(&hdmi_status) == HDMI_ON) {
+ on_stop_process = true;
+ } else {
+ on_stop_process = false;
+ }
+ HPDIFPRINTK("%s() on_stop_process(%d)\n",
+ __func__, on_stop_process);
+
}
last_uevent_state = HPD_LO;
}
@@ -233,9 +252,16 @@ static unsigned int s5p_hpd_poll(struct file *file, poll_table * wait)
void hdmi_send_audio_ch_num(
int supported_ch_num, struct switch_dev *p_audio_ch_switch)
{
- printk(KERN_INFO "%s() hdmi_send_audio_ch_num :: "
- "HDMI Audio supported ch = %d",
- __func__, supported_ch_num);
+ if (last_uevent_state == HPD_LO) {
+ printk(KERN_INFO "[WARNING] %s() "
+ "HDMI Audio ch = %d but not send\n",
+ __func__, supported_ch_num);
+ return;
+ } else
+ printk(KERN_INFO "%s() "
+ "HDMI Audio ch = %d\n",
+ __func__, supported_ch_num);
+
p_audio_ch_switch->state = 0;
switch_set_state(p_audio_ch_switch, (int)supported_ch_num);
}
@@ -366,7 +392,16 @@ static int s5p_hpd_irq_eint(int irq)
atomic_set(&poll_state, 1);
last_hpd_state = HPD_LO;
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+ if (is_mhl_power_state_on != NULL)
+ if (!is_mhl_power_state_on())
+ mhl_hpd_handler(false);
+#endif
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ schedule_delayed_work(&ext_ic_control_dwork ,
+ msecs_to_jiffies(1000));
+#endif
wake_up_interruptible(&hpd_struct.waitq);
}
schedule_work(&hpd_work);
@@ -438,6 +473,15 @@ static int s5p_hpd_irq_hdmi(int irq)
atomic_set(&poll_state, 1);
last_hpd_state = HPD_LO;
+#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
+ if (is_mhl_power_state_on != NULL)
+ if (!is_mhl_power_state_on())
+ mhl_hpd_handler(false);
+#endif
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ schedule_delayed_work(&ext_ic_control_dwork ,
+ msecs_to_jiffies(1000));
+#endif
wake_up_interruptible(&hpd_struct.waitq);
}
@@ -474,6 +518,20 @@ static irqreturn_t s5p_hpd_irq_handler(int irq, void *dev_id)
return ret;
}
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+static work_func_t ext_ic_control_func(void)
+{
+ if (!hpd_struct.read_gpio()) {
+ hpd_struct.ext_ic_control(false);
+ HPDPRINTK("HDMI_EXT_IC Power Off\n");
+ } else {
+ HPDPRINTK("HDMI_EXT_IC Delay work do nothing\n");
+ }
+ return 0;
+}
+#endif
+
+
#ifdef CONFIG_SAMSUNG_WORKAROUND_HPD_GLANCE
static irqreturn_t s5p_hpd_irq_default_handler(int irq, void *dev_id)
{
@@ -566,6 +624,9 @@ static int __devinit s5p_hpd_probe(struct platform_device *pdev)
if (hpd_struct.read_gpio()) {
atomic_set(&hpd_struct.state, HPD_HI);
last_hpd_state = HPD_HI;
+#ifdef CONFIG_HDMI_CONTROLLED_BY_EXT_IC
+ hpd_struct.ext_ic_control(true);
+#endif
} else {
atomic_set(&hpd_struct.state, HPD_LO);
last_hpd_state = HPD_LO;
@@ -575,6 +636,7 @@ static int __devinit s5p_hpd_probe(struct platform_device *pdev)
hpd_struct.hpd_switch.name = "hdmi";
switch_dev_register(&hpd_struct.hpd_switch);
#endif
+ switch_set_state(&hpd_struct.hpd_switch, last_hpd_state);
irq_set_irq_type(hpd_struct.irq_n, IRQ_TYPE_EDGE_BOTH);
ret = request_irq(hpd_struct.irq_n, (irq_handler_t) s5p_hpd_irq_handler,
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
index 68508e7..3fa6e55 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
@@ -369,7 +369,7 @@ static int s5p_tvout_tvif_s_std(
int i;
v4l2_std_id std_id = *norm;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
for (i = 0; i < S5P_TVOUT_TVIF_NO_OF_STANDARD; i++) {
@@ -379,7 +379,8 @@ static int s5p_tvout_tvif_s_std(
if (i == S5P_TVOUT_TVIF_NO_OF_STANDARD) {
tvout_err("There is no TV standard(0x%08Lx)\n", std_id);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -EINVAL;
@@ -390,7 +391,7 @@ static int s5p_tvout_tvif_s_std(
tvout_dbg("standard id=0x%X, name=\"%s\"\n",
(u32) std_id, s5p_tvout_tvif_standard[i].name);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
@@ -437,7 +438,7 @@ static int s5p_tvout_tvif_s_output(
return -EINVAL;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_lock();
#endif
on_start_process = true;
@@ -582,12 +583,12 @@ static int s5p_tvout_tvif_s_output(
s5p_tvif_ctrl_start(tv_std, tv_if);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
error_on_tvif_s_output:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -749,7 +750,7 @@ long s5p_tvout_tvif_ioctl(
void *argp = (void *) arg;
int i = 0;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
@@ -916,13 +917,13 @@ long s5p_tvout_tvif_ioctl(
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return video_ioctl2(file, cmd, arg);
end_tvif_ioctl:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return ret;
@@ -1035,7 +1036,7 @@ static int s5p_tvout_vo_s_fmt_type_private(
(u32) vparam.base_y, (u32) vparam.base_c,
pix_fmt->field);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
/* check progressive or not */
@@ -1133,52 +1134,72 @@ static int s5p_tvout_vo_s_fmt_type_private(
pix_fmt->height, color, field);
#else
if (pix_fmt->priv) {
- copy_buff_idx = s5ptv_vp_buff.copy_buff_idxs[s5ptv_vp_buff.curr_copy_idx];
-
- if ((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base == NULL) {
- s5p_vp_ctrl_set_src_plane((u32) vparam.base_y, (u32) vparam.base_c,
- pix_fmt->width, pix_fmt->height, color, field);
+ copy_buff_idx =
+ s5ptv_vp_buff.
+ copy_buff_idxs[s5ptv_vp_buff.curr_copy_idx];
+
+ if ((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base
+ == NULL) {
+ s5p_vp_ctrl_set_src_plane(
+ (u32) vparam.base_y, (u32) vparam.base_c,
+ pix_fmt->width, pix_fmt->height, color, field);
} else {
- if (pix_fmt->pixelformat == V4L2_PIX_FMT_NV12T
- || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) {
- y_size = ALIGN(ALIGN(pix_fmt->width, 128) * ALIGN(pix_fmt->height, 32), SZ_8K);
- cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) * ALIGN(pix_fmt->height >> 1, 32), SZ_8K);
+ if (pix_fmt->pixelformat ==
+ V4L2_PIX_FMT_NV12T
+ || pix_fmt->pixelformat == V4L2_PIX_FMT_NV21T) {
+ y_size = ALIGN(ALIGN(pix_fmt->width, 128) *
+ ALIGN(pix_fmt->height, 32), SZ_8K);
+ cbcr_size = ALIGN(ALIGN(pix_fmt->width, 128) *
+ ALIGN(pix_fmt->height >> 1, 32), SZ_8K);
} else {
y_size = pix_fmt->width * pix_fmt->height;
- cbcr_size = pix_fmt->width * (pix_fmt->height >> 1);
+ cbcr_size =
+ pix_fmt->width * (pix_fmt->height >> 1);
}
- src_vir_y_addr = (unsigned int)phys_to_virt((unsigned long)vparam.base_y);
- src_vir_cb_addr = (unsigned int)phys_to_virt((unsigned long)vparam.base_c);
+ src_vir_y_addr = (unsigned int)phys_to_virt(
+ (unsigned long)vparam.base_y);
+ src_vir_cb_addr = (unsigned int)phys_to_virt(
+ (unsigned long)vparam.base_c);
- memcpy((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base,
- (void *)src_vir_y_addr, y_size);
- memcpy((void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base + y_size,
- (void *)src_vir_cb_addr, cbcr_size);
+ memcpy(
+ (void *)
+ s5ptv_vp_buff.vp_buffs[copy_buff_idx].vir_base,
+ (void *)src_vir_y_addr, y_size);
+ memcpy(
+ (void *)s5ptv_vp_buff.vp_buffs[copy_buff_idx].
+ vir_base + y_size,
+ (void *)src_vir_cb_addr, cbcr_size);
flush_all_cpu_caches();
outer_flush_all();
- s5p_vp_ctrl_set_src_plane((u32) s5ptv_vp_buff.vp_buffs[copy_buff_idx].phy_base,
- (u32) s5ptv_vp_buff.vp_buffs[copy_buff_idx].phy_base + y_size,
- pix_fmt->width, pix_fmt->height, color, field);
+ s5p_vp_ctrl_set_src_plane(
+ (u32) s5ptv_vp_buff.
+ vp_buffs[copy_buff_idx].phy_base,
+ (u32) s5ptv_vp_buff.
+ vp_buffs[copy_buff_idx].phy_base
+ + y_size,
+ pix_fmt->width, pix_fmt->height, color, field);
s5ptv_vp_buff.curr_copy_idx++;
- if (s5ptv_vp_buff.curr_copy_idx >= S5PTV_VP_BUFF_CNT - 1)
+ if (s5ptv_vp_buff.curr_copy_idx >=
+ S5PTV_VP_BUFF_CNT - 1)
s5ptv_vp_buff.curr_copy_idx = 0;
}
} else {
- s5p_vp_ctrl_set_src_plane((u32) vparam.base_y, (u32) vparam.base_c,
- pix_fmt->width, pix_fmt->height, color, field);
+ s5p_vp_ctrl_set_src_plane(
+ (u32) vparam.base_y, (u32) vparam.base_c,
+ pix_fmt->width, pix_fmt->height, color, field);
}
#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
error_on_s_fmt_type_private:
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return -1;
@@ -1201,7 +1222,7 @@ static int s5p_tvout_vo_s_fmt_vid_overlay(
rect->left, rect->top, rect->width, rect->height,
a->fmt.win.global_alpha);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
s5p_tvout_v4l2_private.vo_dst_fmt = a->fmt.win;
@@ -1211,7 +1232,7 @@ static int s5p_tvout_vo_s_fmt_vid_overlay(
rect->left, rect->top,
rect->width, rect->height);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1237,7 +1258,7 @@ static int s5p_tvout_vo_s_crop(
struct file *file, void *fh, struct v4l2_crop *a)
{
tvout_dbg("\n");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
switch (a->type) {
@@ -1260,7 +1281,7 @@ static int s5p_tvout_vo_s_crop(
tvout_err("Invalid buf type(0x%08x)\n", a->type);
break;
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1285,7 +1306,7 @@ static int s5p_tvout_vo_s_fbuf(
(a->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0,
a->fmt.priv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
@@ -1294,7 +1315,7 @@ static int s5p_tvout_vo_s_fbuf(
s5p_vp_ctrl_set_dest_win_priority(a->fmt.priv);
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
@@ -1305,15 +1326,21 @@ static int s5p_tvout_vo_overlay(
{
tvout_dbg("%s\n", (i) ? "start" : "stop");
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_lock();
#endif
- if (i)
+ if (i) {
s5p_vp_ctrl_start();
- else
+ /* restore vsync interrupt setting */
+ s5p_mixer_set_vsync_interrupt(
+ s5p_mixer_ctrl_get_vsync_interrupt());
+ } else {
+ /* disable vsync interrupt when VP is disabled */
+ s5p_mixer_ctrl_disable_vsync_interrupt();
s5p_vp_ctrl_stop();
+ }
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CLOCK_GATING_ON_EARLY_SUSPEND)
s5p_tvout_mutex_unlock();
#endif
return 0;
diff --git a/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c b/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
index d074da3..148e3e9 100644
--- a/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
+++ b/drivers/media/video/samsung/tvout/s5p_vp_ctrl.c
@@ -279,7 +279,7 @@ static int s5p_vp_ctrl_set_reg(void)
struct s5p_vp_ctrl_pp_param *pp_param = &s5p_vp_ctrl_private.pp_param;
struct s5p_vp_ctrl_op_mode *op_mode = &s5p_vp_ctrl_private.op_mode;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -362,7 +362,7 @@ static int s5p_vp_ctrl_set_reg(void)
static void s5p_vp_ctrl_internal_stop(void)
{
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -409,7 +409,7 @@ void s5p_vp_ctrl_set_src_plane(
src_plane->w = width;
src_plane->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -434,7 +434,7 @@ void s5p_vp_ctrl_set_src_win(u32 left, u32 top, u32 width, u32 height)
src_win->w = width;
src_win->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -466,7 +466,7 @@ void s5p_vp_ctrl_set_dest_win(u32 left, u32 top, u32 width, u32 height)
dst_win->y = top;
dst_win->w = width;
dst_win->h = height;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -493,7 +493,7 @@ void s5p_vp_ctrl_set_dest_win(u32 left, u32 top, u32 width, u32 height)
void s5p_vp_ctrl_set_dest_win_alpha_val(u32 alpha)
{
s5p_vp_ctrl_private.mixer_param.alpha = alpha;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -505,7 +505,7 @@ void s5p_vp_ctrl_set_dest_win_alpha_val(u32 alpha)
void s5p_vp_ctrl_set_dest_win_blend(bool enable)
{
s5p_vp_ctrl_private.mixer_param.blend = enable;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -518,7 +518,7 @@ void s5p_vp_ctrl_set_dest_win_blend(bool enable)
void s5p_vp_ctrl_set_dest_win_priority(u32 prio)
{
s5p_vp_ctrl_private.mixer_param.prio = prio;
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
return;
@@ -531,7 +531,7 @@ void s5p_vp_ctrl_stop(void)
{
if (s5p_vp_ctrl_private.running) {
s5p_vp_ctrl_internal_stop();
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else
@@ -647,7 +647,7 @@ int s5p_vp_ctrl_start(void)
if (s5p_vp_ctrl_private.running)
s5p_vp_ctrl_internal_stop();
else {
-#ifdef CONFIG_HAS_EARLYSUSPEND
+#ifdef CLOCK_GATING_ON_EARLY_SUSPEND
if (suspend_status) {
tvout_dbg("driver is suspend_status\n");
} else