summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h36
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c25
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c57
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h3
5 files changed, 96 insertions, 29 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index a74bf6f60774..7d4578b08244 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -1455,7 +1455,7 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
mdss_dp_config_misc(dp,
mdss_dp_bpp_to_test_bit_depth(mdss_dp_get_bpp(dp)),
mdss_dp_get_colorimetry_config(dp));
- mdss_dp_sw_config_msa(&dp->ctrl_io, dp->link_rate, &dp->dp_cc_io);
+ mdss_dp_sw_config_msa(dp);
mdss_dp_timing_cfg(&dp->ctrl_io, &dp->panel_data.panel_info);
}
@@ -1715,7 +1715,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
static bool mdss_dp_is_ds_bridge(struct mdss_dp_drv_pdata *dp)
{
- return dp->dpcd.downstream_port.dfp_present;
+ return dp->dpcd.downstream_port.dsp_present;
}
static bool mdss_dp_is_ds_bridge_sink_count_zero(struct mdss_dp_drv_pdata *dp)
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index f358aad8a667..afa8e3db590f 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -230,14 +230,38 @@ struct dp_alt_mode {
#define DP_LINK_RATE_MULTIPLIER 27000000
#define DP_KHZ_TO_HZ 1000
#define DP_MAX_PIXEL_CLK_KHZ 675000
+
+enum downstream_port_type {
+ DSP_TYPE_DP = 0x00,
+ DSP_TYPE_VGA,
+ DSP_TYPE_DVI_HDMI_DPPP,
+ DSP_TYPE_OTHER,
+};
+
+static inline char *mdss_dp_dsp_type_to_string(u32 dsp_type)
+{
+ switch (dsp_type) {
+ case DSP_TYPE_DP:
+ return DP_ENUM_STR(DSP_TYPE_DP);
+ case DSP_TYPE_VGA:
+ return DP_ENUM_STR(DSP_TYPE_VGA);
+ case DSP_TYPE_DVI_HDMI_DPPP:
+ return DP_ENUM_STR(DSP_TYPE_DVI_HDMI_DPPP);
+ case DSP_TYPE_OTHER:
+ return DP_ENUM_STR(DSP_TYPE_OTHER);
+ default:
+ return "unknown";
+ }
+}
+
struct downstream_port_config {
/* Byte 02205h */
- bool dfp_present;
- u32 dfp_type;
+ bool dsp_present;
+ enum downstream_port_type dsp_type;
bool format_conversion;
bool detailed_cap_info_available;
/* Byte 02207h */
- u32 dfp_count;
+ u32 dsp_count;
bool msa_timing_par_ignored;
bool oui_support;
};
@@ -1139,6 +1163,12 @@ static inline void mdss_dp_reset_frame_crc_data(struct mdss_dp_crc_data *crc)
crc->en = false;
}
+static inline bool mdss_dp_is_dsp_type_vga(struct mdss_dp_drv_pdata *dp)
+{
+ return (dp->dpcd.downstream_port.dsp_present &&
+ (dp->dpcd.downstream_port.dsp_type == DSP_TYPE_VGA));
+}
+
void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
int mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index 37209c161366..23a63121b78c 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -633,7 +633,8 @@ void dp_extract_edid_video_support(struct edp_edid *edid, char *buf)
pr_debug("Digital Video intf=%d color_depth=%d\n",
edid->video_intf, edid->color_depth);
} else {
- pr_err("Error, Analog video interface\n");
+ pr_debug("Analog video interface, set color depth to 8\n");
+ edid->color_depth = DP_TEST_BIT_DEPTH_8;
}
};
@@ -1140,13 +1141,13 @@ int mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *ep)
pr_debug("rx_ports=%d", cap->num_rx_port);
data = *bp++; /* Byte 5: DOWN_STREAM_PORT_PRESENT */
- cap->downstream_port.dfp_present = data & BIT(0);
- cap->downstream_port.dfp_type = data & 0x6;
+ cap->downstream_port.dsp_present = data & BIT(0);
+ cap->downstream_port.dsp_type = (data & 0x6) >> 1;
cap->downstream_port.format_conversion = data & BIT(3);
cap->downstream_port.detailed_cap_info_available = data & BIT(4);
- pr_debug("dfp_present = %d, dfp_type = %d\n",
- cap->downstream_port.dfp_present,
- cap->downstream_port.dfp_type);
+ pr_debug("dsp_present = %d, dsp_type = %d\n",
+ cap->downstream_port.dsp_present,
+ cap->downstream_port.dsp_type);
pr_debug("format_conversion = %d, detailed_cap_info_available = %d\n",
cap->downstream_port.format_conversion,
cap->downstream_port.detailed_cap_info_available);
@@ -1154,16 +1155,16 @@ int mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *ep)
bp += 1; /* Skip Byte 6 */
data = *bp++; /* Byte 7: DOWN_STREAM_PORT_COUNT */
- cap->downstream_port.dfp_count = data & 0x7;
- if (cap->downstream_port.dfp_count > DP_MAX_DS_PORT_COUNT) {
+ cap->downstream_port.dsp_count = data & 0x7;
+ if (cap->downstream_port.dsp_count > DP_MAX_DS_PORT_COUNT) {
pr_debug("DS port count %d greater that max (%d) supported\n",
- cap->downstream_port.dfp_count, DP_MAX_DS_PORT_COUNT);
- cap->downstream_port.dfp_count = DP_MAX_DS_PORT_COUNT;
+ cap->downstream_port.dsp_count, DP_MAX_DS_PORT_COUNT);
+ cap->downstream_port.dsp_count = DP_MAX_DS_PORT_COUNT;
}
cap->downstream_port.msa_timing_par_ignored = data & BIT(6);
cap->downstream_port.oui_support = data & BIT(7);
- pr_debug("dfp_count = %d, msa_timing_par_ignored = %d\n",
- cap->downstream_port.dfp_count,
+ pr_debug("dsp_count = %d, msa_timing_par_ignored = %d\n",
+ cap->downstream_port.dsp_count,
cap->downstream_port.msa_timing_par_ignored);
pr_debug("oui_support = %d\n", cap->downstream_port.oui_support);
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index e8c3fe9f4957..f7b3d4664e86 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -786,19 +786,56 @@ 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_config_msa(struct dss_io_data *ctrl_io,
- char lrate, struct dss_io_data *dp_cc_io)
+static bool use_fixed_nvid(struct mdss_dp_drv_pdata *dp)
+{
+ /*
+ * For better interop experience, used a fixed NVID=0x8000
+ * whenever connected to a VGA dongle downstream
+ */
+ return mdss_dp_is_dsp_type_vga(dp);
+}
+
+void mdss_dp_sw_config_msa(struct mdss_dp_drv_pdata *dp)
{
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);
+ u64 mvid_calc;
+ u32 const nvid_fixed = 0x8000;
+ struct dss_io_data *ctrl_io = &dp->ctrl_io;
+ struct dss_io_data *dp_cc_io = &dp->dp_cc_io;
+ u32 lrate_kbps;
+ u64 stream_rate_khz;
+
+ if (use_fixed_nvid(dp)) {
+ pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
+ nvid = nvid_fixed;
+
+ lrate_kbps = dp->link_rate * DP_LINK_RATE_MULTIPLIER /
+ DP_KHZ_TO_HZ;
+ stream_rate_khz = div_u64(dp->panel_data.panel_info.clk_rate,
+ DP_KHZ_TO_HZ);
+ pr_debug("link rate=%dkbps, stream_rate_khz=%lluKhz",
+ lrate_kbps, stream_rate_khz);
+
+ /*
+ * For intermediate results, use 64 bit arithmetic to avoid
+ * loss of precision.
+ */
+ mvid_calc = stream_rate_khz * nvid;
+ mvid_calc = div_u64(mvid_calc, lrate_kbps);
+
+ /*
+ * truncate back to 32 bits as this final divided value will
+ * always be within the range of a 32 bit unsigned int.
+ */
+ mvid = (u32) mvid_calc;
+ } else {
+ 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);
+ }
pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
writel_relaxed(mvid, ctrl_io->base + DP_SOFTWARE_MVID);
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index 4c93e48e97dc..4970f5bc3a47 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -316,8 +316,7 @@ 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_config_msa(struct dss_io_data *ctrl_io,
- char lrate, struct dss_io_data *dp_cc_io);
+void mdss_dp_sw_config_msa(struct mdss_dp_drv_pdata *dp);
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);