diff options
| author | Ujwal Patel <ujwalp@codeaurora.org> | 2012-11-19 16:23:58 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:13:33 -0700 |
| commit | 8d57ffc14a23c3bd3810df181f18ea39c569a7fb (patch) | |
| tree | e34273fbf9b7367d253bf8136f807efe263709be | |
| parent | 98a86e9d90ee0ec39a6c4ed5c594c7e9f2a115df (diff) | |
msm: mdss: hdmi: Add dimension overflow check for video resolutions
MDSS based HDMI Tx controller can output 13bit h_total and v_total
compare to 12bit wide from previous generation chipsets. Add overflow
check to insure that controller is not programmed for incorrect dimension.
Change-Id: I6c3906020da6f4aad3f1fcf8a5633731515a7569
Signed-off-by: Ujwal Patel <ujwalp@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_tx.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index f316eac2875d..d9ce757aff7c 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -636,7 +636,7 @@ static int hdmi_tx_set_video_fmt(struct hdmi_tx_ctrl *hdmi_ctrl, return 0; } /* hdmi_tx_set_video_fmt */ -static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl, +static int hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl, int video_format) { u32 total_v = 0; @@ -652,47 +652,53 @@ static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl, if (timing == NULL) { DEV_ERR("%s: video format not supported: %d\n", __func__, video_format); - return; + return -EPERM; } if (!hdmi_ctrl) { DEV_ERR("%s: invalid input\n", __func__); - return; + return -EINVAL; } io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; if (!io->base) { DEV_ERR("%s: Core io is not initialized\n", __func__); - return; + return -EPERM; } total_h = timing->active_h + timing->front_porch_h + timing->back_porch_h + timing->pulse_width_h - 1; total_v = timing->active_v + timing->front_porch_v + timing->back_porch_v + timing->pulse_width_v - 1; - DSS_REG_W(io, HDMI_TOTAL, - ((total_v << 16) & 0x0FFF0000) | - ((total_h << 0) & 0x00000FFF)); + if (((total_v << 16) & 0xE0000000) || (total_h & 0xFFFFE000)) { + DEV_ERR("%s: total v=%d or h=%d is larger than supported\n", + __func__, total_v, total_h); + return -EPERM; + } + DSS_REG_W(io, HDMI_TOTAL, (total_v << 16) | (total_h << 0)); start_h = timing->back_porch_h + timing->pulse_width_h; end_h = (total_h + 1) - timing->front_porch_h; - DSS_REG_W(io, HDMI_ACTIVE_H, - ((end_h << 16) & 0x0FFF0000) | - ((start_h << 0) & 0x00000FFF)); + if (((end_h << 16) & 0xE0000000) || (start_h & 0xFFFFE000)) { + DEV_ERR("%s: end_h=%d or start_h=%d is larger than supported\n", + __func__, end_h, start_h); + return -EPERM; + } + DSS_REG_W(io, HDMI_ACTIVE_H, (end_h << 16) | (start_h << 0)); start_v = timing->back_porch_v + timing->pulse_width_v - 1; end_v = total_v - timing->front_porch_v; - DSS_REG_W(io, HDMI_ACTIVE_V, - ((end_v << 16) & 0x0FFF0000) | - ((start_v << 0) & 0x00000FFF)); + if (((end_v << 16) & 0xE0000000) || (start_v & 0xFFFFE000)) { + DEV_ERR("%s: end_v=%d or start_v=%d is larger than supported\n", + __func__, end_v, start_v); + return -EPERM; + } + DSS_REG_W(io, HDMI_ACTIVE_V, (end_v << 16) | (start_v << 0)); if (timing->interlaced) { - DSS_REG_W(io, HDMI_V_TOTAL_F2, - ((total_v + 1) << 0) & 0x00000FFF); - + DSS_REG_W(io, HDMI_V_TOTAL_F2, (total_v + 1) << 0); DSS_REG_W(io, HDMI_ACTIVE_V_F2, - (((start_v + 1) << 0) & 0x00000FFF) | - (((end_v + 1) << 16) & 0x0FFF0000)); + ((end_v + 1) << 16) | ((start_v + 1) << 0)); } else { DSS_REG_W(io, HDMI_V_TOTAL_F2, 0); DSS_REG_W(io, HDMI_ACTIVE_V_F2, 0); @@ -702,6 +708,8 @@ static void hdmi_tx_video_setup(struct hdmi_tx_ctrl *hdmi_ctrl, ((timing->interlaced << 31) & 0x80000000) | ((timing->active_low_h << 29) & 0x20000000) | ((timing->active_low_v << 28) & 0x10000000)); + + return 0; } /* hdmi_tx_video_setup */ static void hdmi_tx_set_avi_infoframe(struct hdmi_tx_ctrl *hdmi_ctrl) @@ -1610,7 +1618,13 @@ static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_tx_set_mode(hdmi_ctrl, true); - hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution); + rc = hdmi_tx_video_setup(hdmi_ctrl, hdmi_ctrl->video_resolution); + if (rc) { + DEV_ERR("%s: hdmi_tx_video_setup failed. rc=%d\n", + __func__, rc); + hdmi_tx_set_mode(hdmi_ctrl, false); + return rc; + } if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) { rc = hdmi_tx_audio_setup(hdmi_ctrl); |
