From ac8bc2905a1655ba36191a699c3cc102978ef36a Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Sat, 20 Aug 2016 14:07:53 -0700 Subject: [PATCH 1/3] msm: mdss: dp: fix hdcp 1.x interrupt and aux issues Do not reset interrupt in Display Port driver as HDCP module also uses same register for interrupts. Use proper parameters for AUX APIs to avoid communication failures. CRs-Fixed: 1050304 Change-Id: Ib7b046ca5a0071e571758fd656c86a3fd3be51af Signed-off-by: Ajay Singh Parmar Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 10 +++---- drivers/video/fbdev/msm/mdss_dp_aux.c | 8 ++++-- drivers/video/fbdev/msm/mdss_dp_util.h | 2 -- drivers/video/fbdev/msm/mdss_hdcp_1x.c | 39 +++++++++++++------------- drivers/video/fbdev/msm/mdss_hdcp_1x.h | 1 - 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index c8b415df4bce..43b102feb2a4 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1730,7 +1730,7 @@ irqreturn_t dp_isr(int irq, void *ptr) { struct mdss_dp_drv_pdata *dp = (struct mdss_dp_drv_pdata *)ptr; unsigned char *base = dp->base; - u32 isr1, isr2, mask1, mask2; + u32 isr1, isr2, mask1; u32 ack; spin_lock(&dp->lock); @@ -1738,13 +1738,11 @@ irqreturn_t dp_isr(int irq, void *ptr) isr2 = dp_read(base + DP_INTR_STATUS2); mask1 = isr1 & dp->mask1; - mask2 = isr2 & dp->mask2; isr1 &= ~mask1; /* remove masks bit */ - isr2 &= ~mask2; - pr_debug("isr=%x mask=%x isr2=%x mask2=%x\n", - isr1, mask1, isr2, mask2); + pr_debug("isr=%x mask=%x isr2=%x\n", + isr1, mask1, isr2); ack = isr1 & EDP_INTR_STATUS1; ack <<= 1; /* ack bits */ @@ -1753,7 +1751,7 @@ irqreturn_t dp_isr(int irq, void *ptr) ack = isr2 & EDP_INTR_STATUS2; ack <<= 1; /* ack bits */ - ack |= mask2; + ack |= isr2; dp_write(base + DP_INTR_STATUS2, ack); spin_unlock(&dp->lock); diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index 0bbcd0c9041e..584d2edc364e 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -230,7 +230,9 @@ static int dp_aux_write_cmds(struct mdss_dp_drv_pdata *ep, int dp_aux_write(void *ep, struct edp_cmd *cmd) { - return dp_aux_write_cmds(ep, cmd); + int rc = dp_aux_write_cmds(ep, cmd); + + return rc < 0 ? -EINVAL : 0; } static int dp_aux_read_cmds(struct mdss_dp_drv_pdata *ep, @@ -291,7 +293,9 @@ static int dp_aux_read_cmds(struct mdss_dp_drv_pdata *ep, int dp_aux_read(void *ep, struct edp_cmd *cmds) { - return dp_aux_read_cmds(ep, cmds); + int rc = dp_aux_read_cmds(ep, cmds); + + return rc < 0 ? -EINVAL : 0; } void dp_aux_native_handler(struct mdss_dp_drv_pdata *ep, u32 isr) diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index 96664d1f9954..9f2b9f2df250 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -181,8 +181,6 @@ #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) -#define DP_INTERRUPT_STATUS_2 (0x024) - struct lane_mapping { char lane0; char lane1; diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c index 7f26007fab13..f5ad305535b5 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c +++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c @@ -41,14 +41,14 @@ #define HDCP_INT_CLR (isr->auth_success_ack | isr->auth_fail_ack | \ isr->auth_fail_info_ack | isr->tx_req_ack | \ isr->encryption_ready_ack | \ - isr->encryption_not_ready | isr->tx_req_done_ack) + isr->encryption_not_ready_ack | isr->tx_req_done_ack) #define HDCP_INT_EN (isr->auth_success_mask | isr->auth_fail_mask | \ isr->encryption_ready_mask | \ isr->encryption_not_ready_mask) #define HDCP_POLL_SLEEP_US (20 * 1000) -#define HDCP_POLL_TIMEOUT_US (HDCP_POLL_SLEEP_US * 1000) +#define HDCP_POLL_TIMEOUT_US (HDCP_POLL_SLEEP_US * 100) #define reg_set_data(x) \ (hdcp_ctrl->init_data.sec_access ? reg_set->sec_data##x : \ @@ -215,7 +215,7 @@ struct hdcp_reg_set { BIT(0), BIT(4), 0, 0, 0, 0} #define HDCP_DP_INT_SET \ - {DP_INTERRUPT_STATUS_2, \ + {DP_INTR_STATUS2, \ BIT(17), BIT(20), BIT(24), BIT(27), 0, 0, \ BIT(16), BIT(19), BIT(21), BIT(23), BIT(26), 0, 0, \ BIT(15), BIT(18), BIT(22), BIT(25), 0, 0} @@ -554,7 +554,7 @@ static int hdcp_1x_read(struct hdcp_1x_ctrl *hdcp_ctrl, cmd.out_buf = buf; cmd.len = sink->len; - rc = dp_aux_read(hdcp_ctrl->init_data.dp_data, &cmd); + rc = dp_aux_read(hdcp_ctrl->init_data.cb_data, &cmd); if (rc) DEV_ERR("%s: %s: %s read failed\n", __func__, HDCP_STATE_NAME, sink->name); @@ -564,7 +564,7 @@ static int hdcp_1x_read(struct hdcp_1x_ctrl *hdcp_ctrl, } static int hdcp_1x_write(struct hdcp_1x_ctrl *hdcp_ctrl, - u32 offset, u32 len, u8 *buf, char *name) + struct hdcp_sink_addr *sink, u8 *buf) { int rc = 0; struct hdmi_tx_ddc_data ddc_data; @@ -573,28 +573,28 @@ static int hdcp_1x_write(struct hdcp_1x_ctrl *hdcp_ctrl, memset(&ddc_data, 0, sizeof(ddc_data)); ddc_data.dev_addr = 0x74; - ddc_data.offset = offset; + ddc_data.offset = sink->addr; ddc_data.data_buf = buf; - ddc_data.data_len = len; - ddc_data.what = name; + ddc_data.data_len = sink->len; + ddc_data.what = sink->name; hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl); if (rc) DEV_ERR("%s: %s: %s write failed\n", __func__, - HDCP_STATE_NAME, name); + HDCP_STATE_NAME, sink->name); } else if (IS_ENABLED(CONFIG_FB_MSM_MDSS_DP_PANEL) && hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) { struct edp_cmd cmd = {0}; - cmd.addr = offset; - cmd.len = len; + cmd.addr = sink->addr; + cmd.len = sink->len; cmd.datap = buf; - rc = dp_aux_write(hdcp_ctrl->init_data.dp_data, &cmd); + rc = dp_aux_write(hdcp_ctrl->init_data.cb_data, &cmd); if (rc) DEV_ERR("%s: %s: %s read failed\n", __func__, - HDCP_STATE_NAME, name); + HDCP_STATE_NAME, sink->name); } return rc; @@ -754,13 +754,13 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl) an[6] = (link0_an_1 >> 16) & 0xFF; an[7] = (link0_an_1 >> 24) & 0xFF; - rc = hdcp_1x_write(hdcp_ctrl, 0x18, 8, an, "an"); + rc = hdcp_1x_write(hdcp_ctrl, &hdcp_ctrl->sink_addr.an, an); if (IS_ERR_VALUE(rc)) { DEV_ERR("%s: error writing an to sink\n", __func__); goto error; } - rc = hdcp_1x_write(hdcp_ctrl, 0x10, 5, aksv, "aksv"); + rc = hdcp_1x_write(hdcp_ctrl, &hdcp_ctrl->sink_addr.aksv, aksv); if (IS_ERR_VALUE(rc)) { DEV_ERR("%s: error writing aksv to sink\n", __func__); goto error; @@ -1325,10 +1325,12 @@ static void hdcp_1x_auth_work(struct work_struct *work) } io = hdcp_ctrl->init_data.core_io; - /* Enabling Software DDC */ + /* Enabling Software DDC for HDMI and REF timer for DP */ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI) DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION, DSS_REG_R(io, HDMI_DDC_ARBITRATION) & ~(BIT(4))); + else if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) + DSS_REG_W(io, DP_DP_HPD_REFTIMER, 0x10013); rc = hdcp_1x_authentication_part1(hdcp_ctrl); if (rc) { @@ -1774,9 +1776,8 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data) }; if (!init_data || !init_data->core_io || !init_data->qfprom_io || - !init_data->mutex || !init_data->ddc_ctrl || - !init_data->notify_status || !init_data->workq || - !init_data->cb_data) { + !init_data->mutex || !init_data->notify_status || + !init_data->workq || !init_data->cb_data) { DEV_ERR("%s: invalid input\n", __func__); goto error; } diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.h b/drivers/video/fbdev/msm/mdss_hdcp_1x.h index dbe91b459a9f..426b13a340f4 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp_1x.h +++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.h @@ -42,7 +42,6 @@ struct hdcp_init_data { void *cb_data; void (*notify_status)(void *cb_data, enum hdcp_states status); struct hdmi_tx_ddc_ctrl *ddc_ctrl; - void *dp_data; u32 phy_addr; u32 hdmi_tx_ver; struct msm_hdmi_mode_timing_info *timing; From 16e3ac406c5c8d8d81bb4e7be8c7617e4b9571b3 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Thu, 8 Sep 2016 13:31:24 -0700 Subject: [PATCH 2/3] msm: mdss: hdcp: fix hdcp sink address and random number read Fix the hdcp 1.x sink address where the random number for the first part of authentication protocol will be written. Furthermore, fix the read of random number as generated on the device before it is sent during authentication. Change-Id: I665008509a2c00d6627e49a5806069747e00eafd CRs-Fixed: 1050304 Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_hdcp_1x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c index f5ad305535b5..9d067c97bfa5 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c +++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c @@ -198,15 +198,15 @@ struct hdcp_reg_set { {{"bcaps", 0x40, 1}, {"bksv", 0x00, 5}, {"r0'", 0x08, 2}, \ {"bstatus", 0x41, 2}, {"ksv-fifo", 0x43, 0}, {"v_h0", 0x20, 4}, \ {"v_h1", 0x24, 4}, {"v_h2", 0x28, 4}, {"v_h3", 0x2c, 4}, \ - {"v_h4", 0x30, 4}, {"an", 0x16, 8}, {"aksv", 0x10, 5}, \ - {"repater", 0x00, 0} } + {"v_h4", 0x30, 4}, {"an", 0x18, 8}, {"aksv", 0x10, 5}, \ + {"repeater", 0x00, 0} } #define HDCP_DP_SINK_ADDR_MAP \ {{"bcaps", 0x68028, 1}, {"bksv", 0x68000, 5}, {"r0'", 0x68005, 2}, \ {"bstatus", 0x6802A, 2}, {"ksv-fifo", 0x6802A, 0}, \ {"v_h0", 0x68014, 4}, {"v_h1", 0x68018, 4}, {"v_h2", 0x6801C, 4}, \ {"v_h3", 0x68020, 4}, {"v_h4", 0x68024, 4}, {"an", 0x6800C, 8}, \ - {"aksv", 0x68007, 5}, {"repater", 0x68028, 1} } + {"aksv", 0x68007, 5}, {"repeater", 0x68028, 1} } #define HDCP_HDMI_INT_SET \ {HDMI_HDCP_INT_CTRL, \ @@ -731,7 +731,7 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x_ctrl *hdcp_ctrl) link0_an_1 = DSS_REG_R(io, reg_set->data6); if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) { udelay(1); - link0_an_0 = DSS_REG_R(io, reg_set->data6); + link0_an_1 = DSS_REG_R(io, reg_set->data6); } /* Read AKSV */ From f0b8cc92837076eb5ff43e70f7ae536bf45cea3b Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Thu, 8 Sep 2016 13:51:04 -0700 Subject: [PATCH 3/3] msm: mdss: make hdcp 1.x data part of fb panel hdcp 1.x can be used by different interfaces attached to different frame buffers. Add hdcp 1.x data to the panel specific data so that hdcp 1.x module can access the corresponding data. Change-Id: I19917582aa1a52b11eb04e2031403c09bc0aba9b CRs-Fixed: 1050304 Signed-off-by: Tatenda Chipeperekwa --- drivers/video/fbdev/msm/mdss_dp.c | 2 + drivers/video/fbdev/msm/mdss_hdcp_1x.c | 44 +++++++++++++-- drivers/video/fbdev/msm/mdss_hdmi_panel.c | 69 ----------------------- drivers/video/fbdev/msm/mdss_hdmi_panel.h | 3 - drivers/video/fbdev/msm/mdss_hdmi_tx.c | 11 ++-- drivers/video/fbdev/msm/mdss_hdmi_util.c | 68 ++++++++++++++++++++++ drivers/video/fbdev/msm/mdss_hdmi_util.h | 4 ++ drivers/video/fbdev/msm/mdss_panel.h | 1 + 8 files changed, 118 insertions(+), 84 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 43b102feb2a4..c7c75dcb69b3 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1394,6 +1394,8 @@ static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata) goto error; } + dp_drv->panel_data.panel_info.hdcp_1x_data = dp_drv->hdcp_data; + pr_debug("HDCP 1.3 initialized\n"); dp_drv->hdcp_ops = hdcp_1x_start(dp_drv->hdcp_data); diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c index 9d067c97bfa5..5b490ad67e65 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c +++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c @@ -19,6 +19,7 @@ #include #include #include "mdss_hdcp_1x.h" +#include "mdss_fb.h" #include "mdss_dp_util.h" #include "video/msm_hdmi_hdcp_mgr.h" @@ -1630,12 +1631,45 @@ error: return rc; } /* hdcp_1x_isr */ +static struct hdcp_1x_ctrl *hdcp_1x_get_ctrl(struct device *dev) +{ + struct fb_info *fbi; + struct msm_fb_data_type *mfd; + struct mdss_panel_info *pinfo; + + if (!dev) { + pr_err("invalid input\n"); + goto error; + } + + fbi = dev_get_drvdata(dev); + if (!fbi) { + pr_err("invalid fbi\n"); + goto error; + } + + mfd = fbi->par; + if (!mfd) { + pr_err("invalid mfd\n"); + goto error; + } + + pinfo = mfd->panel_info; + if (!pinfo) { + pr_err("invalid pinfo\n"); + goto error; + } + + return pinfo->hdcp_1x_data; + +error: + return NULL; +} static ssize_t hdcp_1x_sysfs_rda_status(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret; - struct hdcp_1x_ctrl *hdcp_ctrl = - hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP); + struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev); if (!hdcp_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -1654,8 +1688,7 @@ static ssize_t hdcp_1x_sysfs_rda_tp(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; - struct hdcp_1x_ctrl *hdcp_ctrl = - hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP); + struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev); if (!hdcp_ctrl) { DEV_ERR("%s: invalid input\n", __func__); @@ -1689,8 +1722,7 @@ static ssize_t hdcp_1x_sysfs_wta_tp(struct device *dev, { int msgid = 0; ssize_t ret = count; - struct hdcp_1x_ctrl *hdcp_ctrl = - hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP); + struct hdcp_1x_ctrl *hdcp_ctrl = hdcp_1x_get_ctrl(dev); if (!hdcp_ctrl || !buf) { DEV_ERR("%s: invalid input\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.c b/drivers/video/fbdev/msm/mdss_hdmi_panel.c index 0335bf900866..522debfba8ce 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.c @@ -150,74 +150,6 @@ enum hdmi_scaling_info { HDMI_SCALING_HORZ_VERT, }; -int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, - struct hdmi_util_ds_data *ds_data) -{ - int new_vic = -1; - u32 h_total, v_total; - struct msm_hdmi_mode_timing_info timing; - - if (!pinfo) { - pr_err("invalid panel data\n"); - return -EINVAL; - } - - if (pinfo->vic) { - struct msm_hdmi_mode_timing_info info = {0}; - u32 ret = hdmi_get_supported_mode(&info, ds_data, pinfo->vic); - u32 supported = info.supported; - - if (!ret && supported) { - new_vic = pinfo->vic; - } else { - pr_err("invalid or not supported vic %d\n", - pinfo->vic); - return -EPERM; - } - } else { - timing.active_h = pinfo->xres; - timing.back_porch_h = pinfo->lcdc.h_back_porch; - timing.front_porch_h = pinfo->lcdc.h_front_porch; - timing.pulse_width_h = pinfo->lcdc.h_pulse_width; - - h_total = timing.active_h + timing.back_porch_h + - timing.front_porch_h + timing.pulse_width_h; - - pr_debug("ah=%d bph=%d fph=%d pwh=%d ht=%d\n", - timing.active_h, timing.back_porch_h, - timing.front_porch_h, timing.pulse_width_h, - h_total); - - timing.active_v = pinfo->yres; - timing.back_porch_v = pinfo->lcdc.v_back_porch; - timing.front_porch_v = pinfo->lcdc.v_front_porch; - timing.pulse_width_v = pinfo->lcdc.v_pulse_width; - - v_total = timing.active_v + timing.back_porch_v + - timing.front_porch_v + timing.pulse_width_v; - - pr_debug("av=%d bpv=%d fpv=%d pwv=%d vt=%d\n", - timing.active_v, timing.back_porch_v, - timing.front_porch_v, timing.pulse_width_v, v_total); - - timing.pixel_freq = ((unsigned long int)pinfo->clk_rate / 1000); - if (h_total && v_total) { - timing.refresh_rate = ((timing.pixel_freq * 1000) / - (h_total * v_total)) * 1000; - } else { - pr_err("cannot cal refresh rate\n"); - return -EPERM; - } - - pr_debug("pixel_freq=%d refresh_rate=%d\n", - timing.pixel_freq, timing.refresh_rate); - - new_vic = hdmi_get_video_id_code(&timing, ds_data); - } - - return new_vic; -} - static void hdmi_panel_update_dfps_data(struct hdmi_panel *panel) { struct mdss_panel_info *pinfo = panel->data->pinfo; @@ -916,7 +848,6 @@ void *hdmi_panel_init(struct hdmi_panel_init_data *data) if (data->ops) { data->ops->on = hdmi_panel_power_on; data->ops->off = hdmi_panel_power_off; - data->ops->get_vic = hdmi_panel_get_vic; data->ops->vendor = hdmi_panel_set_vendor_specific_infoframe; data->ops->update_fps = hdmi_panel_update_fps; } diff --git a/drivers/video/fbdev/msm/mdss_hdmi_panel.h b/drivers/video/fbdev/msm/mdss_hdmi_panel.h index e5cc1486f222..6fa9af13d46e 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_panel.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_panel.h @@ -48,15 +48,12 @@ struct hdmi_panel_data { * @off: pointer to a function which powers off the panel * @vendor: pointer to a function which programs vendor specific infoframe * @update_fps: pointer to a function which updates fps - * @get_vic: pointer to a function which get the vic from panel information. */ struct hdmi_panel_ops { int (*on)(void *input); int (*off)(void *input); void (*vendor)(void *input); int (*update_fps)(void *input, u32 fps); - int (*get_vic)(struct mdss_panel_info *pinfo, - struct hdmi_util_ds_data *ds_data); }; /** diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index 37081e5e4a0b..ace796163fa4 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -1814,6 +1814,8 @@ static int hdmi_tx_init_hdcp(struct hdmi_tx_ctrl *hdmi_ctrl) goto end; } else { hdmi_tx_set_fd(HDMI_TX_FEAT_HDCP, hdcp_data); + hdmi_ctrl->panel_data.panel_info.hdcp_1x_data = + hdcp_data; DEV_DBG("%s: HDCP 1.4 initialized\n", __func__); } } @@ -3115,9 +3117,8 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl) void *pdata = hdmi_tx_get_fd(HDMI_TX_FEAT_PANEL); void *edata = hdmi_tx_get_fd(HDMI_TX_FEAT_EDID); - if (hdmi_ctrl->panel_ops.get_vic) - hdmi_ctrl->vic = hdmi_ctrl->panel_ops.get_vic( - &panel_data->panel_info, &hdmi_ctrl->ds_data); + hdmi_panel_get_vic(&panel_data->panel_info, + &hdmi_ctrl->ds_data); if (hdmi_ctrl->vic <= 0) { DEV_ERR("%s: invalid vic\n", __func__); @@ -3703,9 +3704,7 @@ static int hdmi_tx_evt_handle_check_param(struct hdmi_tx_ctrl *hdmi_ctrl) int new_vic = -1; int rc = 0; - if (hdmi_ctrl->panel_ops.get_vic) - new_vic = hdmi_ctrl->panel_ops.get_vic( - hdmi_ctrl->evt_arg, &hdmi_ctrl->ds_data); + new_vic = hdmi_panel_get_vic(hdmi_ctrl->evt_arg, &hdmi_ctrl->ds_data); if ((new_vic < 0) || (new_vic > HDMI_VFRMT_MAX)) { DEV_ERR("%s: invalid or not supported vic\n", __func__); diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.c b/drivers/video/fbdev/msm/mdss_hdmi_util.c index 555ba1ba5b1c..9ed909e9a387 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.c @@ -33,6 +33,74 @@ enum trigger_mode { TRIGGER_READ }; +int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, + struct hdmi_util_ds_data *ds_data) +{ + int new_vic = -1; + u32 h_total, v_total; + struct msm_hdmi_mode_timing_info timing; + + if (!pinfo) { + pr_err("invalid panel data\n"); + return -EINVAL; + } + + if (pinfo->vic) { + struct msm_hdmi_mode_timing_info info = {0}; + u32 ret = hdmi_get_supported_mode(&info, ds_data, pinfo->vic); + u32 supported = info.supported; + + if (!ret && supported) { + new_vic = pinfo->vic; + } else { + pr_err("invalid or not supported vic %d\n", + pinfo->vic); + return -EPERM; + } + } else { + timing.active_h = pinfo->xres; + timing.back_porch_h = pinfo->lcdc.h_back_porch; + timing.front_porch_h = pinfo->lcdc.h_front_porch; + timing.pulse_width_h = pinfo->lcdc.h_pulse_width; + + h_total = timing.active_h + timing.back_porch_h + + timing.front_porch_h + timing.pulse_width_h; + + pr_debug("ah=%d bph=%d fph=%d pwh=%d ht=%d\n", + timing.active_h, timing.back_porch_h, + timing.front_porch_h, timing.pulse_width_h, + h_total); + + timing.active_v = pinfo->yres; + timing.back_porch_v = pinfo->lcdc.v_back_porch; + timing.front_porch_v = pinfo->lcdc.v_front_porch; + timing.pulse_width_v = pinfo->lcdc.v_pulse_width; + + v_total = timing.active_v + timing.back_porch_v + + timing.front_porch_v + timing.pulse_width_v; + + pr_debug("av=%d bpv=%d fpv=%d pwv=%d vt=%d\n", + timing.active_v, timing.back_porch_v, + timing.front_porch_v, timing.pulse_width_v, v_total); + + timing.pixel_freq = ((unsigned long int)pinfo->clk_rate / 1000); + if (h_total && v_total) { + timing.refresh_rate = ((timing.pixel_freq * 1000) / + (h_total * v_total)) * 1000; + } else { + pr_err("cannot cal refresh rate\n"); + return -EPERM; + } + + pr_debug("pixel_freq=%d refresh_rate=%d\n", + timing.pixel_freq, timing.refresh_rate); + + new_vic = hdmi_get_video_id_code(&timing, ds_data); + } + + return new_vic; +} + int hdmi_utils_get_timeout_in_hysnc(struct msm_hdmi_mode_timing_info *timing, u32 timeout_ms) { diff --git a/drivers/video/fbdev/msm/mdss_hdmi_util.h b/drivers/video/fbdev/msm/mdss_hdmi_util.h index ceb171417822..e65cf915fe92 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_util.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_util.h @@ -15,6 +15,8 @@ #include #include "video/msm_hdmi_modes.h" +#include "mdss_panel.h" + /* HDMI_TX Registers */ #define HDMI_CTRL (0x00000000) #define HDMI_TEST_PATTERN (0x00000010) @@ -489,6 +491,8 @@ const char *msm_hdmi_mode_2string(u32 mode); int hdmi_set_resv_timing_info(struct msm_hdmi_mode_timing_info *mode); bool hdmi_is_valid_resv_timing(int mode); void hdmi_reset_resv_timing_info(void); +int hdmi_panel_get_vic(struct mdss_panel_info *pinfo, + struct hdmi_util_ds_data *ds_data); /* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */ void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 1137c4475cab..f91d83a3bdfe 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -688,6 +688,7 @@ struct mdss_panel_info { void *edid_data; void *dba_data; void *cec_data; + void *hdcp_1x_data; char panel_name[MDSS_MAX_PANEL_LEN]; struct mdss_mdp_pp_tear_check te;