diff --git a/Documentation/devicetree/bindings/fb/mdss-dp.txt b/Documentation/devicetree/bindings/fb/mdss-dp.txt index 27516d3b54a5..c9c882154c39 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dp.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dp.txt @@ -27,6 +27,7 @@ Required properties - qcom,aux-en-gpio: Specifies the aux-channel enable gpio. - qcom,aux-sel-gpio: Specifies the aux-channel select gpio. - qcom,usbplug-cc-gpio: Specifies the usbplug orientation gpio. +- qcom,aux-cfg-settings: An array that specifies the DP AUX configuration settings. Optional properties: - qcom,-supply-entries: A node that lists the elements of the supply used by the @@ -51,6 +52,7 @@ Optional properties: - pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin controller. These pin configurations are installed in the pinctrl device node. Refer to pinctrl-bindings.txt +- qcom,logical2physical-lane-map: An array that specifies the DP logical to physical lane map setting. Example: mdss_dp_ctrl: qcom,dp_ctrl@c990000 { @@ -83,6 +85,9 @@ Example: "core_aux_clk", "core_cfg_ahb_clk", "ctrl_link_clk", "ctrl_link_iface_clk", "ctrl_crypto_clk", "ctrl_pixel_clk"; + qcom,aux-cfg-settings = [00 13 00 10 0a 26 0a 03 8b 03]; + qcom,logical2physical-lane-map = [02 03 01 00]; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi index 845c96eb5ef4..05566d8fd263 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -500,6 +500,9 @@ qcom,msm_ext_disp = <&msm_ext_disp>; + qcom,aux-cfg-settings = [00 13 00 10 0a 26 0a 03 8b 03]; + qcom,logical2physical-lane-map = [02 03 01 00]; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index f3c36c5c6b5a..16ec948df5a9 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -129,6 +129,40 @@ static int mdss_dp_is_clk_prefix(const char *clk_prefix, const char *clk_name) return !strncmp(clk_name, clk_prefix, strlen(clk_prefix)); } +static int mdss_dp_parse_prop(struct platform_device *pdev, + struct mdss_dp_drv_pdata *dp_drv) +{ + int len = 0, i = 0; + const char *data; + + data = of_get_property(pdev->dev.of_node, + "qcom,aux-cfg-settings", &len); + if ((!data) || (len != AUX_CFG_LEN)) { + pr_err("%s:%d, Unable to read DP AUX CFG settings", + __func__, __LINE__); + return -EINVAL; + } + + for (i = 0; i < len; i++) + dp_drv->aux_cfg[i] = data[i]; + + data = of_get_property(pdev->dev.of_node, + "qcom,logical2physical-lane-map", &len); + if ((!data) || (len != DP_MAX_PHY_LN)) { + pr_debug("%s:%d, lane mapping not defined, use default", + __func__, __LINE__); + dp_drv->l_map[DP_PHY_LN0] = DP_ML0; + dp_drv->l_map[DP_PHY_LN1] = DP_ML1; + dp_drv->l_map[DP_PHY_LN2] = DP_ML2; + dp_drv->l_map[DP_PHY_LN3] = DP_ML3; + } else { + for (i = 0; i < len; i++) + dp_drv->l_map[i] = data[i]; + } + + return 0; +} + static int mdss_dp_init_clk_power_data(struct device *dev, struct mdss_dp_drv_pdata *pdata) { @@ -1151,10 +1185,9 @@ static inline void mdss_dp_ack_state(struct mdss_dp_drv_pdata *dp, int val) * given usb plug orientation. */ static int mdss_dp_get_lane_mapping(struct mdss_dp_drv_pdata *dp, - enum plug_orientation orientation, - struct lane_mapping *lane_map) + enum plug_orientation orientation, char *lane_map) { - int ret = 0; + int ret = 0, i = 0, j = 0; pr_debug("enter: orientation = %d\n", orientation); @@ -1164,22 +1197,35 @@ static int mdss_dp_get_lane_mapping(struct mdss_dp_drv_pdata *dp, goto exit; } - /* Set the default lane mapping */ - lane_map->lane0 = 2; - lane_map->lane1 = 3; - lane_map->lane2 = 1; - lane_map->lane3 = 0; - + /* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */ if (orientation == ORIENTATION_CC2) { - lane_map->lane0 = 1; - lane_map->lane1 = 0; - lane_map->lane2 = 2; - lane_map->lane3 = 3; + for (i = 0; i < DP_MAX_PHY_LN; i++) { + if (dp->l_map[i] == DP_ML0) { + for (j = 0; j < DP_MAX_PHY_LN; j++) { + if (dp->l_map[j] == DP_ML3) { + lane_map[i] = DP_ML3; + lane_map[j] = DP_ML0; + break; + } + } + } else if (dp->l_map[i] == DP_ML1) { + for (j = 0; j < DP_MAX_PHY_LN; j++) { + if (dp->l_map[j] == DP_ML2) { + lane_map[i] = DP_ML2; + lane_map[j] = DP_ML1; + break; + } + } + } + } + } else { + /* Normal orientation */ + for (i = 0; i < DP_MAX_PHY_LN; i++) + lane_map[i] = dp->l_map[i]; } pr_debug("lane0 = %d, lane1 = %d, lane2 =%d, lane3 =%d\n", - lane_map->lane0, lane_map->lane1, lane_map->lane2, - lane_map->lane3); + lane_map[0], lane_map[1], lane_map[2], lane_map[3]); exit: return ret; @@ -1248,9 +1294,9 @@ static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv) * configuration, output format and sink/panel timing information. */ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp, - struct lane_mapping *lane_map) + char *lane_map) { - mdss_dp_ctrl_lane_mapping(&dp->ctrl_io, *lane_map); + mdss_dp_ctrl_lane_mapping(&dp->ctrl_io, lane_map); mdss_dp_fill_link_cfg(dp); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); mdss_dp_config_ctrl(dp); @@ -1318,7 +1364,7 @@ end: static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) { int ret = 0; - struct lane_mapping ln_map; + char ln_map[4]; /* wait until link training is completed */ pr_debug("enter, lt_needed=%s\n", lt_needed ? "true" : "false"); @@ -1331,7 +1377,7 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) dp_init_panel_info(dp_drv, dp_drv->vic); ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, - &ln_map); + ln_map); if (ret) goto exit_loop; @@ -1352,7 +1398,7 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) goto exit_loop; } - mdss_dp_configure_source_params(dp_drv, &ln_map); + mdss_dp_configure_source_params(dp_drv, ln_map); reinit_completion(&dp_drv->idle_comp); @@ -1385,7 +1431,7 @@ exit_loop: int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) { int ret = 0; - struct lane_mapping ln_map; + char ln_map[4]; /* wait until link training is completed */ mutex_lock(&dp_drv->train_mutex); @@ -1404,7 +1450,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) } mdss_dp_hpd_configure(&dp_drv->ctrl_io, true); - ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, &ln_map); + ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, ln_map); if (ret) goto exit; @@ -1427,7 +1473,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) reinit_completion(&dp_drv->idle_comp); - mdss_dp_configure_source_params(dp_drv, &ln_map); + mdss_dp_configure_source_params(dp_drv, ln_map); if (dp_drv->psm_enabled) { ret = mdss_dp_aux_send_psm_request(dp_drv, false); @@ -1689,7 +1735,7 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io), mdss_dp_get_phy_hw_version(&dp_drv->phy_io)); - mdss_dp_phy_aux_setup(&dp_drv->phy_io); + mdss_dp_phy_aux_setup(&dp_drv->phy_io, dp_drv->aux_cfg); mdss_dp_irq_enable(dp_drv); dp_drv->dp_initialized = true; @@ -3704,6 +3750,13 @@ static int mdss_dp_probe(struct platform_device *pdev) goto probe_err; } + ret = mdss_dp_parse_prop(pdev, dp_drv); + if (ret) { + DEV_ERR("DP properties parsing failed.ret=%d\n", + ret); + goto probe_err; + } + ret = mdss_dp_irq_setup(dp_drv); if (ret) goto probe_err; diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index bf74a8a4d7df..76ad0b6e6061 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -36,6 +36,8 @@ #define AUX_CMD_MAX 16 #define AUX_CMD_I2C_MAX 128 +#define AUX_CFG_LEN 10 + #define EDP_PORT_MAX 1 #define EDP_SINK_CAP_LEN 16 @@ -536,6 +538,10 @@ struct mdss_dp_drv_pdata { struct mdss_dp_event_data dp_event; struct task_struct *ev_thread; + /* dt settings */ + char l_map[4]; + u32 aux_cfg[AUX_CFG_LEN]; + struct workqueue_struct *workq; struct delayed_work hdcp_cb_work; spinlock_t lock; @@ -554,6 +560,21 @@ struct mdss_dp_drv_pdata { struct list_head attention_head; }; +enum dp_phy_lane_num { + DP_PHY_LN0 = 0, + DP_PHY_LN1 = 1, + DP_PHY_LN2 = 2, + DP_PHY_LN3 = 3, + DP_MAX_PHY_LN = 4, +}; + +enum dp_mainlink_lane_num { + DP_ML0 = 0, + DP_ML1 = 1, + DP_ML2 = 2, + DP_ML3 = 3, +}; + enum dp_lane_count { DP_LANE_COUNT_1 = 1, DP_LANE_COUNT_2 = 2, diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 1dcf83f094c1..98e76a578c08 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -859,30 +859,34 @@ void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, pr_debug("dp_tu=0x%x\n", dp_tu); } -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map) +void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map) { u8 bits_per_lane = 2; - u32 lane_map = ((l_map.lane0 << (bits_per_lane * 0)) - | (l_map.lane1 << (bits_per_lane * 1)) - | (l_map.lane2 << (bits_per_lane * 2)) - | (l_map.lane3 << (bits_per_lane * 3))); + u32 lane_map = ((l_map[0] << (bits_per_lane * 0)) + | (l_map[1] << (bits_per_lane * 1)) + | (l_map[2] << (bits_per_lane * 2)) + | (l_map[3] << (bits_per_lane * 3))); pr_debug("%s: lane mapping reg = 0x%x\n", __func__, lane_map); writel_relaxed(lane_map, ctrl_io->base + DP_LOGICAL2PHYSCIAL_LANE_MAPPING); } -void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io) +void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io, u32 *aux_cfg) { writel_relaxed(0x3d, phy_io->base + DP_PHY_PD_CTL); - writel_relaxed(0x13, phy_io->base + DP_PHY_AUX_CFG1); - writel_relaxed(0x10, phy_io->base + DP_PHY_AUX_CFG3); - writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG4); - writel_relaxed(0x26, phy_io->base + DP_PHY_AUX_CFG5); - writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG6); - writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG7); - writel_relaxed(0x8b, phy_io->base + DP_PHY_AUX_CFG8); - writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG9); + + /* DP AUX CFG register programming */ + writel_relaxed(aux_cfg[0], phy_io->base + DP_PHY_AUX_CFG0); + writel_relaxed(aux_cfg[1], phy_io->base + DP_PHY_AUX_CFG1); + writel_relaxed(aux_cfg[2], phy_io->base + DP_PHY_AUX_CFG2); + writel_relaxed(aux_cfg[3], phy_io->base + DP_PHY_AUX_CFG3); + writel_relaxed(aux_cfg[4], phy_io->base + DP_PHY_AUX_CFG4); + writel_relaxed(aux_cfg[5], phy_io->base + DP_PHY_AUX_CFG5); + writel_relaxed(aux_cfg[6], phy_io->base + DP_PHY_AUX_CFG6); + writel_relaxed(aux_cfg[7], phy_io->base + DP_PHY_AUX_CFG7); + writel_relaxed(aux_cfg[8], phy_io->base + DP_PHY_AUX_CFG8); + writel_relaxed(aux_cfg[9], phy_io->base + DP_PHY_AUX_CFG9); + writel_relaxed(0x1f, phy_io->base + DP_PHY_AUX_INTERRUPT_MASK); } diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index cb62d145960f..e944b8b78d7f 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -206,13 +206,6 @@ #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) -struct lane_mapping { - char lane0; - char lane1; - char lane2; - char lane3; -}; - struct edp_cmd { char read; /* 1 == read, 0 == write */ char i2c; /* 1 == i2c cmd, 0 == native cmd */ @@ -292,12 +285,11 @@ 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, struct mdss_panel_info *pinfo); void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc); -void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io); +void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io, u32 *aux_cfg); 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); void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable); -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map); +void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map); int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which); void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, struct mdss_panel_info *pinfo); @@ -311,8 +303,6 @@ void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_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); -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map); void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io, u8 orientation, u8 ln_cnt); void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,