diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-11-13 13:51:10 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-11-13 13:51:09 -0800 |
| commit | 24d0c1f91eb2850889cb27ef6fdcadc0c8ff2834 (patch) | |
| tree | d67616ca5e112e3fb9673cf46697c4fe51e73aad /drivers/video | |
| parent | 23bb5f214ec5b929b321a8c27e24cb4257da2a31 (diff) | |
| parent | 44b187a8c5a21f13d0791c3b257e532d5523d589 (diff) | |
Merge "msm: mdss: dp: handle fast attention events"
Diffstat (limited to 'drivers/video')
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.c | 144 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp.h | 5 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp_aux.c | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp_util.c | 56 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dp_util.h | 11 |
5 files changed, 169 insertions, 49 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index 75e42ca8cd88..29fc4e6fd65b 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -45,6 +45,11 @@ #define VDDA_UA_ON_LOAD 100000 /* uA units */ #define VDDA_UA_OFF_LOAD 100 /* uA units */ +struct mdss_dp_attention_node { + u32 vdo; + struct list_head list; +}; + #define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3 static u32 supported_modes[] = { HDMI_VFRMT_640x480p60_4_3, @@ -60,6 +65,7 @@ static u32 supported_modes[] = { static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata); static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp); +static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp_drv); static void mdss_dp_put_dt_clk_data(struct device *dev, struct dss_module_power *module_power) @@ -1133,7 +1139,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp, mdss_dp_fill_link_cfg(dp); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); mdss_dp_config_ctrl(dp); - mdss_dp_sw_mvid_nvid(&dp->ctrl_io); + mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io); mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info); } @@ -1290,7 +1296,6 @@ link_training: dp_drv->cont_splash = 0; dp_drv->power_on = true; - mdss_dp_ack_state(dp_drv, true); pr_debug("End-\n"); exit: @@ -1559,6 +1564,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) goto edid_error; } + mdss_dp_update_cable_status(dp_drv, true); mdss_dp_notify_clients(dp_drv, true); dp_drv->dp_initialized = true; @@ -1883,8 +1889,13 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp) } /* update internal data about hdcp */ - dp->hdcp.data = fd; - dp->hdcp.ops = ops; + if (dp->hdcp.hdcp2_present || dp->hdcp.hdcp1_present) { + dp->hdcp.data = fd; + dp->hdcp.ops = ops; + } else { + dp->hdcp.data = NULL; + dp->hdcp.ops = NULL; + } } static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv) @@ -1920,6 +1931,8 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, if (dp->hdcp.ops && dp->hdcp.ops->authenticate) rc = dp->hdcp.ops->authenticate(dp->hdcp.data); + + mdss_dp_ack_state(dp, true); break; case MDSS_EVENT_PANEL_OFF: rc = mdss_dp_off(pdata); @@ -2041,6 +2054,12 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev, return rc; } + if (msm_dss_ioremap_byname(pdev, &dp_drv->dp_cc_io, "dp_mmss_cc")) { + pr_err("%d unable to remap dp MMSS_CC resources\n", + __LINE__); + return rc; + } + if (msm_dss_ioremap_byname(pdev, &dp_drv->qfprom_io, "qfprom_physical")) pr_warn("unable to remap dp qfprom resources\n"); @@ -2117,6 +2136,9 @@ static void mdss_dp_event_work(struct work_struct *work) case EV_IDLE_PATTERNS_SENT: mdss_dp_idle_patterns_sent(dp); break; + case EV_USBPD_ATTENTION: + mdss_dp_handle_attention(dp); + break; case EV_USBPD_DISCOVER_MODES: usbpd_send_svdm(dp->pd, USB_C_DP_SID, USBPD_SVDM_DISCOVER_MODES, SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0); @@ -2225,6 +2247,7 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp) INIT_WORK(&dp->work, mdss_dp_event_work); INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work); + INIT_LIST_HEAD(&dp->attention_head); return 0; } @@ -2508,6 +2531,7 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, const u32 *vdos, int num_vdos) { struct mdss_dp_drv_pdata *dp_drv; + struct mdss_dp_attention_node *node; dp_drv = container_of(hdlr, struct mdss_dp_drv_pdata, svid_handler); if (!dp_drv->pd) { @@ -2535,45 +2559,14 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, dp_send_events(dp_drv, EV_USBPD_DP_STATUS); break; case USBPD_SVDM_ATTENTION: - dp_drv->alt_mode.dp_status.response = *vdos; - mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status); - - dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on != - dp_drv->alt_mode.dp_status.hpd_irq; + node = kzalloc(sizeof(*node), GFP_KERNEL); + node->vdo = *vdos; - if (dp_drv->alt_mode.dp_status.hpd_irq) { - pr_debug("Attention: hpd_irq high\n"); - - if (dp_drv->power_on && dp_drv->hdcp.ops && - dp_drv->hdcp.ops->cp_irq) - dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data); - - if (!mdss_dp_process_hpd_irq_high(dp_drv)) - break; - } else if (dp_drv->hpd_irq_toggled) { - if (!mdss_dp_process_hpd_irq_low(dp_drv)) - break; - } - - if (!dp_drv->alt_mode.dp_status.hpd_high) { - pr_debug("Attention: HPD low\n"); - mdss_dp_update_cable_status(dp_drv, false); - mdss_dp_notify_clients(dp_drv, false); - pr_debug("Attention: Notified clients\n"); - break; - } - - pr_debug("Attention: HPD high\n"); - - mdss_dp_update_cable_status(dp_drv, true); - - dp_drv->alt_mode.current_state |= DP_STATUS_DONE; - - if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) - mdss_dp_host_init(&dp_drv->panel_data); - else - dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); + mutex_lock(&dp_drv->attention_lock); + list_add_tail(&node->list, &dp_drv->attention_head); + mutex_unlock(&dp_drv->attention_lock); + dp_send_events(dp_drv, EV_USBPD_ATTENTION); break; case DP_VDM_STATUS: dp_drv->alt_mode.dp_status.response = *vdos; @@ -2597,6 +2590,74 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, } } +static void mdss_dp_process_attention(struct mdss_dp_drv_pdata *dp_drv) +{ + dp_drv->hpd_irq_toggled = dp_drv->hpd_irq_on != + dp_drv->alt_mode.dp_status.hpd_irq; + + if (dp_drv->alt_mode.dp_status.hpd_irq) { + pr_debug("Attention: hpd_irq high\n"); + + if (dp_drv->power_on && dp_drv->hdcp.ops && + dp_drv->hdcp.ops->cp_irq) + dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data); + + if (!mdss_dp_process_hpd_irq_high(dp_drv)) + return; + } else if (dp_drv->hpd_irq_toggled) { + if (!mdss_dp_process_hpd_irq_low(dp_drv)) + return; + } + + if (!dp_drv->alt_mode.dp_status.hpd_high) { + pr_debug("Attention: HPD low\n"); + mdss_dp_update_cable_status(dp_drv, false); + mdss_dp_notify_clients(dp_drv, false); + pr_debug("Attention: Notified clients\n"); + return; + } + + pr_debug("Attention: HPD high\n"); + + mdss_dp_update_cable_status(dp_drv, true); + + dp_drv->alt_mode.current_state |= DP_STATUS_DONE; + + if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE) + mdss_dp_host_init(&dp_drv->panel_data); + else + dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); + + pr_debug("exit\n"); +} + +static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp) +{ + int i = 0; + + while (!list_empty_careful(&dp->attention_head)) { + struct mdss_dp_attention_node *node; + u32 vdo; + + pr_debug("processing item %d in the list\n", ++i); + + mutex_lock(&dp->attention_lock); + node = list_first_entry(&dp->attention_head, + struct mdss_dp_attention_node, list); + + vdo = node->vdo; + list_del(&node->list); + mutex_unlock(&dp->attention_lock); + + kzfree(node); + + dp->alt_mode.dp_status.response = vdo; + mdss_dp_usbpd_ext_dp_status(&dp->alt_mode.dp_status); + mdss_dp_process_attention(dp); + }; + +} + static int mdss_dp_usbpd_setup(struct mdss_dp_drv_pdata *dp_drv) { int ret = 0; @@ -2670,6 +2731,7 @@ static int mdss_dp_probe(struct platform_device *pdev) dp_drv->mask2 = EDP_INTR_MASK2; mutex_init(&dp_drv->emutex); mutex_init(&dp_drv->pd_msg_mutex); + mutex_init(&dp_drv->attention_lock); mutex_init(&dp_drv->hdcp_mutex); spin_lock_init(&dp_drv->lock); diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index e801eceeef1b..04abe9221acc 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -205,6 +205,7 @@ struct dp_alt_mode { #define EV_USBPD_DP_CONFIGURE BIT(10) #define EV_USBPD_CC_PIN_POLARITY BIT(11) #define EV_USBPD_EXIT_MODE BIT(12) +#define EV_USBPD_ATTENTION BIT(13) /* dp state ctrl */ #define ST_TRAIN_PATTERN_1 BIT(0) @@ -406,6 +407,7 @@ struct mdss_dp_drv_pdata { struct dss_io_data ctrl_io; struct dss_io_data phy_io; struct dss_io_data tcsr_reg_io; + struct dss_io_data dp_cc_io; struct dss_io_data qfprom_io; struct dss_io_data hdcp_io; int base_size; @@ -454,6 +456,7 @@ struct mdss_dp_drv_pdata { struct mutex aux_mutex; struct mutex train_mutex; struct mutex pd_msg_mutex; + struct mutex attention_lock; struct mutex hdcp_mutex; bool cable_connected; u32 s3d_mode; @@ -497,6 +500,8 @@ struct mdss_dp_drv_pdata { struct dpcd_test_request test_data; struct dpcd_sink_count sink_count; + + struct list_head attention_head; }; enum dp_lane_count { diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index f9dba99a653d..e396dfff60ef 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -1647,6 +1647,8 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp) clear: dp_clear_training_pattern(dp); if (ret != -EINVAL) { + mdss_dp_config_misc_settings(&dp->ctrl_io, + &dp->panel_data.panel_info); mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate, dp->lane_cnt, dp->vic); mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO); diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 2d24d8499105..86edc4492599 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -253,10 +253,48 @@ void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, writel_relaxed(data, ctrl_io->base + DP_ACTIVE_HOR_VER); } -void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io) +void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io, + char lrate, struct dss_io_data *dp_cc_io) { - writel_relaxed(0x37, ctrl_io->base + DP_SOFTWARE_MVID); - writel_relaxed(0x3c, ctrl_io->base + DP_SOFTWARE_NVID); + u32 pixel_m, pixel_n; + u32 mvid, nvid; + + pixel_m = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_M); + pixel_n = readl_relaxed(dp_cc_io->base + MMSS_DP_PIXEL_N); + pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", + pixel_m, pixel_n); + + mvid = (pixel_m & 0xFFFF) * 5; + nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); + if (lrate == DP_LINK_RATE_540) + nvid = nvid * 2; + pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); + writel_relaxed(mvid, ctrl_io->base + DP_SOFTWARE_MVID); + writel_relaxed(nvid, ctrl_io->base + DP_SOFTWARE_NVID); +} + +void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io, + struct mdss_panel_info *pinfo) +{ + u32 bpp = pinfo->bpp; + u32 misc_val = 0x0; + + switch (bpp) { + case 18: + misc_val |= (0x0 << 5); + break; + case 30: + misc_val |= (0x2 << 5); + break; + case 24: + default: + misc_val |= (0x1 << 5); + } + + misc_val |= BIT(0); /* Configure clock to synchronous mode */ + + pr_debug("Misc settings = 0x%x\n", misc_val); + writel_relaxed(misc_val, ctrl_io->base + DP_MISC1_MISC0); } void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, @@ -267,8 +305,6 @@ void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, u32 valid_boundary2 = 0x0; struct dp_vc_tu_mapping_table const *tu_entry = tu_table; - writel_relaxed(0x21, ctrl_io->base + DP_MISC1_MISC0); - for (; tu_entry != tu_table + ARRAY_SIZE(tu_table); ++tu_entry) { if ((tu_entry->vic == res) && (tu_entry->lanes == ln_cnt) && @@ -454,8 +490,14 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp) pin_cfg = dp->alt_mode.dp_cap.dlink_pin_config; for (pin = PIN_ASSIGNMENT_A; pin < PIN_ASSIGNMENT_MAX; pin++) { - if (pin_cfg & BIT(pin)) - break; + if (pin_cfg & BIT(pin)) { + if (dp->alt_mode.dp_status.multi_func) { + if (pin == PIN_ASSIGNMENT_D) + break; + } else { + break; + } + } } if (pin == PIN_ASSIGNMENT_MAX) diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index 334c0071050d..4b28d98177be 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -164,6 +164,12 @@ #define TCSR_USB3_DP_PHYMODE 0x48 #define EDID_START_ADDRESS 0x50 +/* DP MMSS_CC registers */ +#define MMSS_DP_LINK_CMD_RCGR 0x0000 +#define MMSS_DP_LINK_CFG_RCGR 0x0004 +#define MMSS_DP_PIXEL_M 0x0048 +#define MMSS_DP_PIXEL_N 0x004C + /* DP HDCP 1.3 registers */ #define DP_HDCP_CTRL (0x0A0) #define DP_HDCP_STATUS (0x0A4) @@ -271,6 +277,8 @@ void mdss_dp_switch_usb3_phy_to_dp_mode(struct dss_io_data *tcsr_reg_io); void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert); void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, u8 ln_cnt, u32 res); +void mdss_dp_config_misc_settings(struct dss_io_data *ctrl_io, + struct mdss_panel_info *pinfo); void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io); void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable); @@ -285,7 +293,8 @@ void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data); int mdss_dp_irq_setup(struct mdss_dp_drv_pdata *dp_drv); void mdss_dp_irq_enable(struct mdss_dp_drv_pdata *dp_drv); void mdss_dp_irq_disable(struct mdss_dp_drv_pdata *dp_drv); -void mdss_dp_sw_mvid_nvid(struct dss_io_data *ctrl_io); +void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io, + char lrate, struct dss_io_data *dp_cc_io); void mdss_dp_usbpd_ext_capabilities(struct usbpd_dp_capabilities *dp_cap); void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status); u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp); |
