revise widebus timing engine programming and enable widebus feature base on chip
Kuogee Hsieh (4): drm/msm/dpu: revise timing engine programming to support widebus feature drm/msm/dpu: delete DATA_HCTL_EN from sc7280 hw feature drm/msm/dpu: replace BIT(x) with correspond marco define string drm/msm/dp: enable widebus feature for display port
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 + .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 +++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 61 ++++++++++++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 2 + drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++++++++++- drivers/gpu/drm/msm/dp/dp_catalog.h | 3 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +++-- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 32 ++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 + drivers/gpu/drm/msm/dp/dp_panel.c | 4 +- drivers/gpu/drm/msm/dp/dp_panel.h | 2 +- drivers/gpu/drm/msm/msm_drv.h | 6 +++ 15 files changed, 165 insertions(+), 27 deletions(-)
Widebus feature will transmit two pixel data per pixel clock to interface. Timing engine provides driving force for this purpose. This patch base on HPG (Hardware Programming Guide) to revise timing engine register setting to accommodate both widebus and non widebus application. Also horizontal width parameters need to be reduced by half since two pixel data are clocked out per pixel clock when widebus feature enabled.
Widebus can be enabled individually at DP. However at DSI, widebus have to be enabled along with DSC to achieve pixel clock rate be scaled down with same ratio as compression ratio when 10 bits per source component. Therefore this patch add no supports of DSI related widebus and compression.
Changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp
Changes in v3: -- split patch into 3 patches
Changes in v4: -- rework timing engine to not interfere with dsi/hdmi -- cover both widebus and compression
Changes in v5: -- remove supports of DSI widebus and compression
Changes in v7: -- split this patch into 3 patches -- add Tested-by
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com Tested-by: Bjorn Andersson bjorn.andersson@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 + .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 55 ++++++++++++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 2 + 5 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db..2b2dbb7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -208,6 +208,8 @@ struct dpu_encoder_virt {
u32 idle_timeout;
+ bool wide_bus_en; + struct msm_dp *dp; };
@@ -217,6 +219,14 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 };
+ +bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); + + return dpu_enc->wide_bus_en; +} + static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914..0d73550 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -168,4 +168,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc); */ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
+bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc); + #endif /* __DPU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89..04ac2dc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -110,6 +110,20 @@ static void drm_mode_to_intf_timing_params( timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; } + + timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); + + /* + * for DP, divide the horizonal parameters by 2 when + * widebus is enabled + */ + if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { + timing->width = timing->width >> 1; + timing->xres = timing->xres >> 1; + timing->h_back_porch = timing->h_back_porch >> 1; + timing->h_front_porch = timing->h_front_porch >> 1; + timing->hsync_pulse_width = timing->hsync_pulse_width >> 1; + } }
static u32 get_horizontal_total(const struct intf_timing_params *timing) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 116e2b5..b68e696 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -33,6 +33,7 @@ #define INTF_TP_COLOR1 0x05C #define INTF_CONFIG2 0x060 #define INTF_DISPLAY_DATA_HCTL 0x064 +#define INTF_ACTIVE_DATA_HCTL 0x068 #define INTF_FRAME_LINE_COUNT_EN 0x0A8 #define INTF_FRAME_COUNT 0x0AC #define INTF_LINE_COUNT 0x0B0 @@ -90,15 +91,23 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, u32 hsync_period, vsync_period; u32 display_v_start, display_v_end; u32 hsync_start_x, hsync_end_x; + u32 hsync_data_start_x, hsync_data_end_x; u32 active_h_start, active_h_end; u32 active_v_start, active_v_end; u32 active_hctl, display_hctl, hsync_ctl; u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity; u32 panel_format; - u32 intf_cfg, intf_cfg2 = 0, display_data_hctl = 0; + u32 intf_cfg, intf_cfg2 = 0; + u32 display_data_hctl = 0, active_data_hctl = 0; + u32 data_width; + bool dp_intf = false;
/* read interface_cfg */ intf_cfg = DPU_REG_READ(c, INTF_CONFIG); + + if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) + dp_intf = true; + hsync_period = p->hsync_pulse_width + p->h_back_porch + p->width + p->h_front_porch; vsync_period = p->vsync_pulse_width + p->v_back_porch + p->height + @@ -112,7 +121,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, hsync_start_x = p->h_back_porch + p->hsync_pulse_width; hsync_end_x = hsync_period - p->h_front_porch - 1;
- if (p->width != p->xres) { + if (p->width != p->xres) { /* border fill added */ active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; } else { @@ -120,7 +129,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_h_end = 0; }
- if (p->height != p->yres) { + if (p->height != p->yres) { /* border fill added */ active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1; } else { @@ -130,27 +139,47 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start; - intf_cfg |= BIT(29); /* ACTIVE_H_ENABLE */ + intf_cfg |= BIT(29); } else { active_hctl = 0; }
if (active_v_end) - intf_cfg |= BIT(30); /* ACTIVE_V_ENABLE */ + intf_cfg |= BIT(30);
hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x;
- if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) { + /* + * DATA_HCTL_EN controls data timing which can be different from + * video timing. It is recommended to enable it for all cases, except + * if compression is enabled in 1 pixel per clock mode + */ + if (p->wide_bus_en) + intf_cfg2 |= (BIT(0) | BIT(4)); + + data_width = p->width; + + hsync_data_start_x = hsync_start_x; + hsync_data_end_x = hsync_start_x + data_width - 1; + + display_data_hctl = (hsync_data_end_x << 16) | hsync_data_start_x; + + if (dp_intf) { + /* DP timing adjustment */ + display_v_start += p->hsync_pulse_width + p->h_back_porch; + display_v_end -= p->h_front_porch; + active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1;
- display_v_start += p->hsync_pulse_width + p->h_back_porch; - active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl; + + intf_cfg |= BIT(29); + intf_cfg |= BIT(30); }
den_polarity = 0; @@ -180,13 +209,6 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, (COLOR_8BIT << 4) | (0x21 << 8));
- if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) { - intf_cfg2 |= BIT(4); - display_data_hctl = display_hctl; - DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); - DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl); - } - DPU_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl); DPU_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); DPU_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0, @@ -204,6 +226,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, DPU_REG_WRITE(c, INTF_FRAME_LINE_COUNT_EN, 0x3); DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg); DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format); + DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); + DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl); + DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl); }
static void dpu_hw_intf_enable_timing_engine( diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 3568be8..e4a518a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -30,6 +30,8 @@ struct intf_timing_params { u32 border_clr; u32 underflow_clr; u32 hsync_skew; + + bool wide_bus_en; };
struct intf_prog_fetch {
On 17/02/2022 01:05, Kuogee Hsieh wrote:
Widebus feature will transmit two pixel data per pixel clock to interface. Timing engine provides driving force for this purpose. This patch base on HPG (Hardware Programming Guide) to revise timing engine register setting to accommodate both widebus and non widebus application. Also horizontal width parameters need to be reduced by half since two pixel data are clocked out per pixel clock when widebus feature enabled.
Widebus can be enabled individually at DP. However at DSI, widebus have to be enabled along with DSC to achieve pixel clock rate be scaled down with same ratio as compression ratio when 10 bits per source component. Therefore this patch add no supports of DSI related widebus and compression.
Changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp
Changes in v3: -- split patch into 3 patches
Changes in v4: -- rework timing engine to not interfere with dsi/hdmi -- cover both widebus and compression
Changes in v5: -- remove supports of DSI widebus and compression
Changes in v7: -- split this patch into 3 patches -- add Tested-by
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com Tested-by: Bjorn Andersson bjorn.andersson@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 + .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 55 ++++++++++++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 2 + 5 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db..2b2dbb7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -208,6 +208,8 @@ struct dpu_encoder_virt {
u32 idle_timeout;
- bool wide_bus_en;
- struct msm_dp *dp; };
@@ -217,6 +219,14 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 };
+bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc) +{
- struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- return dpu_enc->wide_bus_en;
+}
- static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914..0d73550 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -168,4 +168,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc); */ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
+bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc);
- #endif /* __DPU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89..04ac2dc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -110,6 +110,20 @@ static void drm_mode_to_intf_timing_params( timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; }
timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
/*
* for DP, divide the horizonal parameters by 2 when
* widebus is enabled
*/
if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) {
timing->width = timing->width >> 1;
timing->xres = timing->xres >> 1;
timing->h_back_porch = timing->h_back_porch >> 1;
timing->h_front_porch = timing->h_front_porch >> 1;
timing->hsync_pulse_width = timing->hsync_pulse_width >> 1;
} }
static u32 get_horizontal_total(const struct intf_timing_params *timing)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 116e2b5..b68e696 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -33,6 +33,7 @@ #define INTF_TP_COLOR1 0x05C #define INTF_CONFIG2 0x060 #define INTF_DISPLAY_DATA_HCTL 0x064 +#define INTF_ACTIVE_DATA_HCTL 0x068 #define INTF_FRAME_LINE_COUNT_EN 0x0A8 #define INTF_FRAME_COUNT 0x0AC #define INTF_LINE_COUNT 0x0B0 @@ -90,15 +91,23 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, u32 hsync_period, vsync_period; u32 display_v_start, display_v_end; u32 hsync_start_x, hsync_end_x;
- u32 hsync_data_start_x, hsync_data_end_x; u32 active_h_start, active_h_end; u32 active_v_start, active_v_end; u32 active_hctl, display_hctl, hsync_ctl; u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity; u32 panel_format;
- u32 intf_cfg, intf_cfg2 = 0, display_data_hctl = 0;
u32 intf_cfg, intf_cfg2 = 0;
u32 display_data_hctl = 0, active_data_hctl = 0;
u32 data_width;
bool dp_intf = false;
/* read interface_cfg */ intf_cfg = DPU_REG_READ(c, INTF_CONFIG);
if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP)
dp_intf = true;
hsync_period = p->hsync_pulse_width + p->h_back_porch + p->width + p->h_front_porch; vsync_period = p->vsync_pulse_width + p->v_back_porch + p->height +
@@ -112,7 +121,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, hsync_start_x = p->h_back_porch + p->hsync_pulse_width; hsync_end_x = hsync_period - p->h_front_porch - 1;
- if (p->width != p->xres) {
- if (p->width != p->xres) { /* border fill added */ active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; } else {
@@ -120,7 +129,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_h_end = 0; }
- if (p->height != p->yres) {
- if (p->height != p->yres) { /* border fill added */ active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1; } else {
@@ -130,27 +139,47 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start;
intf_cfg |= BIT(29); /* ACTIVE_H_ENABLE */
intf_cfg |= BIT(29);
} else { active_hctl = 0; }
if (active_v_end)
intf_cfg |= BIT(30); /* ACTIVE_V_ENABLE */
intf_cfg |= BIT(30);
hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x;
- if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) {
- /*
* DATA_HCTL_EN controls data timing which can be different from
* video timing. It is recommended to enable it for all cases, except
* if compression is enabled in 1 pixel per clock mode
*/
- if (p->wide_bus_en)
intf_cfg2 |= (BIT(0) | BIT(4));
Previously the HCTL_EN was set even for non-wide-bus cases. Was this incorrect? Should we set it only for the wide bus case?
- data_width = p->width;
- hsync_data_start_x = hsync_start_x;
- hsync_data_end_x = hsync_start_x + data_width - 1;
- display_data_hctl = (hsync_data_end_x << 16) | hsync_data_start_x;
- if (dp_intf) {
/* DP timing adjustment */
display_v_start += p->hsync_pulse_width + p->h_back_porch;
display_v_end -= p->h_front_porch;
Quoting a question to v4: So, this changes the display_v_end. Is there a mistake currently (and so this change should be backported to stable kernels) or is it just unoptimal?
- active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1;
display_v_start += p->hsync_pulse_width + p->h_back_porch;
- active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl;
intf_cfg |= BIT(29);
intf_cfg |= BIT(30);
Could you please add defines for _new_ bits in this patch.
}
den_polarity = 0; @@ -180,13 +209,6 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, (COLOR_8BIT << 4) | (0x21 << 8));
- if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
intf_cfg2 |= BIT(4);
display_data_hctl = display_hctl;
DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl);
- }
- DPU_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl); DPU_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); DPU_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0,
@@ -204,6 +226,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, DPU_REG_WRITE(c, INTF_FRAME_LINE_COUNT_EN, 0x3); DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg); DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format);
- DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
- DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl);
- DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
Which generations received these registers? I'd be more comfortable if the driver didn't write into the registers that are not handled by the hardware. The rest of DPU driver does exactly that.
Could you please add a check in the beginning of this function to print and error message if wide bus is enabled, but DPU_DATA_HCTL_EN is not supported. And move these writes under features check.
}
static void dpu_hw_intf_enable_timing_engine( diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 3568be8..e4a518a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -30,6 +30,8 @@ struct intf_timing_params { u32 border_clr; u32 underflow_clr; u32 hsync_skew;
bool wide_bus_en; };
struct intf_prog_fetch {
On 2/16/2022 10:34 PM, Dmitry Baryshkov wrote:
On 17/02/2022 01:05, Kuogee Hsieh wrote:
Widebus feature will transmit two pixel data per pixel clock to interface. Timing engine provides driving force for this purpose. This patch base on HPG (Hardware Programming Guide) to revise timing engine register setting to accommodate both widebus and non widebus application. Also horizontal width parameters need to be reduced by half since two pixel data are clocked out per pixel clock when widebus feature enabled.
Widebus can be enabled individually at DP. However at DSI, widebus have to be enabled along with DSC to achieve pixel clock rate be scaled down with same ratio as compression ratio when 10 bits per source component. Therefore this patch add no supports of DSI related widebus and compression.
Changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp
Changes in v3: -- split patch into 3 patches
Changes in v4: -- rework timing engine to not interfere with dsi/hdmi -- cover both widebus and compression
Changes in v5: -- remove supports of DSI widebus and compression
Changes in v7: -- split this patch into 3 patches -- add Tested-by
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com Tested-by: Bjorn Andersson bjorn.andersson@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ++++ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 + .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 ++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 55 ++++++++++++++++------ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h | 2 + 5 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1e648db..2b2dbb7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -208,6 +208,8 @@ struct dpu_encoder_virt { u32 idle_timeout; + bool wide_bus_en;
struct msm_dp *dp; }; @@ -217,6 +219,14 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = { 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10 }; + +bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc) +{ + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+ return dpu_enc->wide_bus_en; +}
static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc) { struct dpu_hw_dither_cfg dither_cfg = { 0 }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h index e241914..0d73550 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h @@ -168,4 +168,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc); */ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc); +bool dpu_encoder_is_widebus_enabled(struct drm_encoder *drm_enc);
#endif /* __DPU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index ddd9d89..04ac2dc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -110,6 +110,20 @@ static void drm_mode_to_intf_timing_params( timing->v_back_porch += timing->v_front_porch; timing->v_front_porch = 0; }
+ timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
+ /* + * for DP, divide the horizonal parameters by 2 when + * widebus is enabled + */ + if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { + timing->width = timing->width >> 1; + timing->xres = timing->xres >> 1; + timing->h_back_porch = timing->h_back_porch >> 1; + timing->h_front_porch = timing->h_front_porch >> 1; + timing->hsync_pulse_width = timing->hsync_pulse_width >> 1; + } } static u32 get_horizontal_total(const struct intf_timing_params *timing) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 116e2b5..b68e696 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -33,6 +33,7 @@ #define INTF_TP_COLOR1 0x05C #define INTF_CONFIG2 0x060 #define INTF_DISPLAY_DATA_HCTL 0x064 +#define INTF_ACTIVE_DATA_HCTL 0x068 #define INTF_FRAME_LINE_COUNT_EN 0x0A8 #define INTF_FRAME_COUNT 0x0AC #define INTF_LINE_COUNT 0x0B0 @@ -90,15 +91,23 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, u32 hsync_period, vsync_period; u32 display_v_start, display_v_end; u32 hsync_start_x, hsync_end_x; + u32 hsync_data_start_x, hsync_data_end_x; u32 active_h_start, active_h_end; u32 active_v_start, active_v_end; u32 active_hctl, display_hctl, hsync_ctl; u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity; u32 panel_format; - u32 intf_cfg, intf_cfg2 = 0, display_data_hctl = 0; + u32 intf_cfg, intf_cfg2 = 0; + u32 display_data_hctl = 0, active_data_hctl = 0; + u32 data_width; + bool dp_intf = false; /* read interface_cfg */ intf_cfg = DPU_REG_READ(c, INTF_CONFIG);
+ if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) + dp_intf = true;
hsync_period = p->hsync_pulse_width + p->h_back_porch + p->width + p->h_front_porch; vsync_period = p->vsync_pulse_width + p->v_back_porch + p->height + @@ -112,7 +121,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, hsync_start_x = p->h_back_porch + p->hsync_pulse_width; hsync_end_x = hsync_period - p->h_front_porch - 1; - if (p->width != p->xres) { + if (p->width != p->xres) { /* border fill added */ active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; } else { @@ -120,7 +129,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_h_end = 0; } - if (p->height != p->yres) { + if (p->height != p->yres) { /* border fill added */ active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1; } else { @@ -130,27 +139,47 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start; - intf_cfg |= BIT(29); /* ACTIVE_H_ENABLE */ + intf_cfg |= BIT(29); } else { active_hctl = 0; } if (active_v_end) - intf_cfg |= BIT(30); /* ACTIVE_V_ENABLE */ + intf_cfg |= BIT(30); hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x; - if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) { + /* + * DATA_HCTL_EN controls data timing which can be different from + * video timing. It is recommended to enable it for all cases, except + * if compression is enabled in 1 pixel per clock mode + */ + if (p->wide_bus_en) + intf_cfg2 |= (BIT(0) | BIT(4));
Previously the HCTL_EN was set even for non-wide-bus cases. Was this incorrect? Should we set it only for the wide bus case?
When widebus enable, then DATA_HCTL_EN must be enabled, since data and video timing is different.
DATA_HCTL_EN can be enabled at other case too as long as data and video timing are same.
the only except is at compression is enabled in 1 pixel per clock mode as comment said
+ data_width = p->width;
+ hsync_data_start_x = hsync_start_x; + hsync_data_end_x = hsync_start_x + data_width - 1;
+ display_data_hctl = (hsync_data_end_x << 16) | hsync_data_start_x;
+ if (dp_intf) { + /* DP timing adjustment */ + display_v_start += p->hsync_pulse_width + p->h_back_porch; + display_v_end -= p->h_front_porch;
Quoting a question to v4: So, this changes the display_v_end. Is there a mistake currently (and so this change should be backported to stable kernels) or is it just unoptimal?
I think previous does not have display_v_end adjusted for DP.
I will add a patch to fix this, then this patch can be back ported to stable kernel.
active_h_start = hsync_start_x; active_h_end = active_h_start + p->xres - 1; active_v_start = display_v_start; active_v_end = active_v_start + (p->yres * hsync_period) - 1; - display_v_start += p->hsync_pulse_width + p->h_back_porch;
active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl;
+ intf_cfg |= BIT(29); + intf_cfg |= BIT(30);
Could you please add defines for _new_ bits in this patch.
} den_polarity = 0; @@ -180,13 +209,6 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, (COLOR_8BIT << 4) | (0x21 << 8)); - if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) { - intf_cfg2 |= BIT(4); - display_data_hctl = display_hctl; - DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); - DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl); - }
DPU_REG_WRITE(c, INTF_HSYNC_CTL, hsync_ctl); DPU_REG_WRITE(c, INTF_VSYNC_PERIOD_F0, vsync_period * hsync_period); DPU_REG_WRITE(c, INTF_VSYNC_PULSE_WIDTH_F0, @@ -204,6 +226,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, DPU_REG_WRITE(c, INTF_FRAME_LINE_COUNT_EN, 0x3); DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg); DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format); + DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2); + DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl); + DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
Which generations received these registers? I'd be more comfortable if the driver didn't write into the registers that are not handled by the hardware. The rest of DPU driver does exactly that.
Could you please add a check in the beginning of this function to print and error message if wide bus is enabled, but DPU_DATA_HCTL_EN is not supported. And move these writes under features check.
ok
} static void dpu_hw_intf_enable_timing_engine( diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h index 3568be8..e4a518a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h @@ -30,6 +30,8 @@ struct intf_timing_params { u32 border_clr; u32 underflow_clr; u32 hsync_skew;
+ bool wide_bus_en; }; struct intf_prog_fetch {
DPTA_HCTL_EN controls data timing which can be different from video timing. It only required to be enabled either widebus or compression enabled.
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index aa75991..53bfb22 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -55,7 +55,7 @@
#define INTF_SC7180_MASK BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE)
-#define INTF_SC7280_MASK INTF_SC7180_MASK | BIT(DPU_DATA_HCTL_EN) +#define INTF_SC7280_MASK INTF_SC7180_MASK
#define IRQ_SDM845_MASK (BIT(MDP_SSPP_TOP0_INTR) | \ BIT(MDP_SSPP_TOP0_INTR2) | \
To improve code readability, this patch replace BIT(x) with correspond register bit define string
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index b68e696..8f10aab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -61,6 +61,12 @@
#define INTF_MUX 0x25C
+#define INTF_CFG_ACTIVE_H_EN BIT(29) +#define INTF_CFG_ACTIVE_V_EN BIT(30) + +#define INTF_CFG2_DATABUS_WIDEN BIT(0) +#define INTF_CFG2_DATA_HCTL_EN BIT(4) + static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, const struct dpu_mdss_cfg *m, void __iomem *addr, @@ -139,13 +145,13 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start; - intf_cfg |= BIT(29); + intf_cfg |= INTF_CFG_ACTIVE_H_EN; } else { active_hctl = 0; }
if (active_v_end) - intf_cfg |= BIT(30); + intf_cfg |= INTF_CFG_ACTIVE_V_EN;
hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x; @@ -156,7 +162,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, * if compression is enabled in 1 pixel per clock mode */ if (p->wide_bus_en) - intf_cfg2 |= (BIT(0) | BIT(4)); + intf_cfg2 |= (INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN);
data_width = p->width;
@@ -178,8 +184,8 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl;
- intf_cfg |= BIT(29); - intf_cfg |= BIT(30); + intf_cfg |= INTF_CFG_ACTIVE_H_EN; + intf_cfg |= INTF_CFG_ACTIVE_V_EN; }
den_polarity = 0;
On 17/02/2022 01:05, Kuogee Hsieh wrote:
To improve code readability, this patch replace BIT(x) with correspond register bit define string
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com
This patch should come first.
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index b68e696..8f10aab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -61,6 +61,12 @@
#define INTF_MUX 0x25C
+#define INTF_CFG_ACTIVE_H_EN BIT(29) +#define INTF_CFG_ACTIVE_V_EN BIT(30)
+#define INTF_CFG2_DATABUS_WIDEN BIT(0) +#define INTF_CFG2_DATA_HCTL_EN BIT(4)
- static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf, const struct dpu_mdss_cfg *m, void __iomem *addr,
@@ -139,13 +145,13 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
if (active_h_end) { active_hctl = (active_h_end << 16) | active_h_start;
intf_cfg |= BIT(29);
intf_cfg |= INTF_CFG_ACTIVE_H_EN;
} else { active_hctl = 0; }
if (active_v_end)
intf_cfg |= BIT(30);
intf_cfg |= INTF_CFG_ACTIVE_V_EN;
hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width; display_hctl = (hsync_end_x << 16) | hsync_start_x;
@@ -156,7 +162,7 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, * if compression is enabled in 1 pixel per clock mode */ if (p->wide_bus_en)
intf_cfg2 |= (BIT(0) | BIT(4));
intf_cfg2 |= (INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN);
data_width = p->width;
@@ -178,8 +184,8 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx, active_hctl = (active_h_end << 16) | active_h_start; display_hctl = active_hctl;
intf_cfg |= BIT(29);
intf_cfg |= BIT(30);
intf_cfg |= INTF_CFG_ACTIVE_H_EN;
intf_cfg |= INTF_CFG_ACTIVE_V_EN;
}
den_polarity = 0;
Widebus feature will transmit two pixel data per pixel clock to interface. This feature now is required to be enabled to easy migrant to higher resolution applications in future. However since some legacy chipsets does not support this feature, this feature is enabled base on chip's hardware revision.
changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp
Changes in v3: -- split patch into 3 patches -- enable widebus feature base on chip hardware revision
Changes in v5: -- DP_INTF_CONFIG_DATABUS_WIDEN
Changes in v6: -- fix Reported-bya issue -- fix static inline bool msm_dp_wide_bus_enable() at msm_drv.h
Changes in v7: -- add Tested-by
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com Reported-by: kernel test robot lkp@intel.com Tested-by: Bjorn Andersson bjorn.andersson@linaro.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 +++- drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++++++++++++++++++++++++++-- drivers/gpu/drm/msm/dp/dp_catalog.h | 3 ++- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +++++++---- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 32 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_panel.h | 2 +- drivers/gpu/drm/msm/msm_drv.h | 6 +++++ 10 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 2b2dbb7..1e96cede 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2138,8 +2138,10 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(&dpu_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); - else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) + else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) { dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; + dpu_enc->wide_bus_en = msm_dp_wide_bus_enable(dpu_enc->dp); + }
INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 6ae9b29..524eccc 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -24,6 +24,8 @@ #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 #define DP_INTERRUPT_STATUS_MASK_SHIFT 2
+#define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4) + #define DP_INTERRUPT_STATUS1 \ (DP_INTR_AUX_I2C_DONE| \ DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ @@ -483,6 +485,22 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, }
/** + * dp_catalog_hw_revision() - retrieve DP hw revision + * + * @dp_catalog: DP catalog structure + * + * Return: DP controller hw revision + * + */ +u32 dp_catalog_hw_revision(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + return dp_read_ahb(catalog, REG_DP_HW_VERSION); +} + +/** * dp_catalog_ctrl_reset() - reset DP controller * * @dp_catalog: DP catalog structure @@ -739,10 +757,11 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) }
/* panel related catalog functions */ -int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, bool wide_bus_en) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); + u32 reg;
dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, dp_catalog->total); @@ -751,7 +770,18 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, dp_catalog->width_blanking); dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); - dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0); + + reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG); + + if (wide_bus_en) + reg |= DP_INTF_CONFIG_DATABUS_WIDEN; + else + reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN; + + + DRM_DEBUG_DP("wide_bus_en=%d reg=%x\n", wide_bus_en, reg); + + dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg); return 0; }
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 6965afa..2ba1ea4 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -95,6 +95,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb); void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate, u32 stream_rate_khz, bool fixed_nvid); int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern); +u32 dp_catalog_hw_revision(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); @@ -115,7 +116,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog);
/* DP Panel APIs */ -int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog); +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, bool wide_bus_en); void dp_catalog_dump_regs(struct dp_catalog *dp_catalog); void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, struct drm_display_mode *drm_mode); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c724cb0..b07574c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -154,7 +154,7 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_config_ctrl(ctrl->catalog, config); }
-static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) +static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl, bool wide_bus_en) { u32 cc, tb;
@@ -167,7 +167,7 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) ctrl->panel->dp_mode.bpp); cc = dp_link_get_colorimetry_config(ctrl->link); dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb); - dp_panel_timing_cfg(ctrl->panel); + dp_panel_timing_cfg(ctrl->panel, wide_bus_en); }
/* @@ -1799,6 +1799,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) int ret = 0; bool mainlink_ready = false; struct dp_ctrl_private *ctrl; + u32 pixel_rate_orig;
if (!dp_ctrl) return -EINVAL; @@ -1807,6 +1808,10 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+ pixel_rate_orig = ctrl->dp_ctrl.pixel_rate; + if (dp_ctrl->wide_bus_en) + ctrl->dp_ctrl.pixel_rate >>= 1; + DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n", ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate); @@ -1842,11 +1847,11 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) */ reinit_completion(&ctrl->video_comp);
- dp_ctrl_configure_source_params(ctrl); + dp_ctrl_configure_source_params(ctrl, dp_ctrl->wide_bus_en);
dp_catalog_ctrl_config_msa(ctrl->catalog, ctrl->link->link_params.rate, - ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl)); + pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
dp_ctrl_setup_tr_unit(ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 2363a2d..a0a5fbb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -17,6 +17,7 @@ struct dp_ctrl { bool orientation; atomic_t aborted; u32 pixel_rate; + bool wide_bus_en; };
int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 7cc4d21..8ecccf2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -115,6 +115,8 @@ struct dp_display_private { struct dp_event event_list[DP_EVENT_Q_MAX]; spinlock_t event_lock;
+ bool wide_bus_en; + struct dp_audio *audio; };
@@ -848,6 +850,8 @@ static int dp_display_enable(struct dp_display_private *dp, u32 data) return 0; }
+ dp->ctrl->wide_bus_en = dp->wide_bus_en; + rc = dp_ctrl_on_stream(dp->ctrl); if (!rc) dp_display->power_on = true; @@ -972,6 +976,7 @@ int dp_display_get_modes(struct msm_dp *dp, dp->connector, dp_mode); if (dp_mode->drm_mode.clock) dp->max_pclk_khz = dp_mode->drm_mode.clock; + return ret; }
@@ -1437,6 +1442,28 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); }
+bool msm_dp_wide_bus_enable(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + u32 revision, major, minor; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + /* for the time being widebus only support on DP */ + if (dp_display->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + revision = dp_catalog_hw_revision(dp->catalog); + major = ((revision >> 28) & 0x0ff); + minor = ((revision >> 16) & 0x0fff); + + DRM_DEBUG_DP("id=%d major=%d minor=%d\n", dp->id, major, minor); + + if (major >= 1 && minor >= 2) + return true; + } + + return false; +} + void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) { struct dp_display_private *dp; @@ -1460,6 +1487,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { struct msm_drm_private *priv; + struct dp_display_private *dp_priv; int ret;
if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev)) @@ -1468,6 +1496,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, priv = dev->dev_private; dp_display->drm_dev = dev;
+ dp_priv = container_of(dp_display, struct dp_display_private, dp_display); + ret = dp_display_request_irq(dp_display); if (ret) { DRM_ERROR("request_irq failed, ret=%d\n", ret); @@ -1498,6 +1528,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
priv->bridges[priv->num_bridges++] = dp_display->bridge;
+ dp_priv->wide_bus_en = msm_dp_wide_bus_enable(dp_display); + return 0; }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index e3adcd5..b718cc9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -24,6 +24,8 @@ struct msm_dp {
hdmi_codec_plugged_cb plugged_cb;
+ bool wide_bus_en; + u32 max_pclk_khz;
u32 max_dp_lanes; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 71db10c..71deb1e 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -353,7 +353,7 @@ void dp_panel_dump_regs(struct dp_panel *dp_panel) dp_catalog_dump_regs(catalog); }
-int dp_panel_timing_cfg(struct dp_panel *dp_panel) +int dp_panel_timing_cfg(struct dp_panel *dp_panel, bool wide_bus_en) { u32 data, total_ver, total_hor; struct dp_catalog *catalog; @@ -404,7 +404,7 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
catalog->dp_active = data;
- dp_catalog_panel_timing_cfg(catalog); + dp_catalog_panel_timing_cfg(catalog, wide_bus_en); panel->panel_on = true;
return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 9023e5b..5ec341a 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -57,7 +57,7 @@ struct dp_panel {
int dp_panel_init_panel_info(struct dp_panel *dp_panel); int dp_panel_deinit(struct dp_panel *dp_panel); -int dp_panel_timing_cfg(struct dp_panel *dp_panel); +int dp_panel_timing_cfg(struct dp_panel *dp_panel, bool wide_bus_en); void dp_panel_dump_regs(struct dp_panel *dp_panel); int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d7574e6..4f9c24e 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -399,6 +399,7 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display); void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor); +bool msm_dp_wide_bus_enable(struct msm_dp *dp_display);
#else static inline int __init msm_dp_register(void) @@ -449,6 +450,11 @@ static inline void msm_dp_debugfs_init(struct msm_dp *dp_display, { }
+static inline bool msm_dp_wide_bus_enable(struct msm_dp *dp_display) +{ + return false; +} + #endif
void __init msm_mdp_register(void);
On 17/02/2022 01:05, Kuogee Hsieh wrote:
Widebus feature will transmit two pixel data per pixel clock to interface. This feature now is required to be enabled to easy migrant to higher resolution applications in future. However since some legacy chipsets does not support this feature, this feature is enabled base on chip's hardware revision.
changes in v2: -- remove compression related code from timing -- remove op_info from struct msm_drm_private -- remove unnecessary wide_bus_en variables -- pass wide_bus_en into timing configuration by struct msm_dp
Changes in v3: -- split patch into 3 patches -- enable widebus feature base on chip hardware revision
Changes in v5: -- DP_INTF_CONFIG_DATABUS_WIDEN
Changes in v6: -- fix Reported-bya issue -- fix static inline bool msm_dp_wide_bus_enable() at msm_drv.h
Changes in v7: -- add Tested-by
Signed-off-by: Kuogee Hsieh quic_khsieh@quicinc.com Reported-by: kernel test robot lkp@intel.com Tested-by: Bjorn Andersson bjorn.andersson@linaro.org
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 +++- drivers/gpu/drm/msm/dp/dp_catalog.c | 34 +++++++++++++++++++++++++++-- drivers/gpu/drm/msm/dp/dp_catalog.h | 3 ++- drivers/gpu/drm/msm/dp/dp_ctrl.c | 13 +++++++---- drivers/gpu/drm/msm/dp/dp_ctrl.h | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 32 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 2 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 4 ++-- drivers/gpu/drm/msm/dp/dp_panel.h | 2 +- drivers/gpu/drm/msm/msm_drv.h | 6 +++++ 10 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 2b2dbb7..1e96cede 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2138,8 +2138,10 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(&dpu_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0);
- else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS)
else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) { dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]];
dpu_enc->wide_bus_en = msm_dp_wide_bus_enable(dpu_enc->dp);
}
INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work);
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 6ae9b29..524eccc 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -24,6 +24,8 @@ #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 #define DP_INTERRUPT_STATUS_MASK_SHIFT 2
+#define DP_INTF_CONFIG_DATABUS_WIDEN BIT(4)
- #define DP_INTERRUPT_STATUS1 \ (DP_INTR_AUX_I2C_DONE| \ DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
@@ -483,6 +485,22 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, }
/**
- dp_catalog_hw_revision() - retrieve DP hw revision
- @dp_catalog: DP catalog structure
- Return: DP controller hw revision
- */
+u32 dp_catalog_hw_revision(struct dp_catalog *dp_catalog) +{
- struct dp_catalog_private *catalog = container_of(dp_catalog,
struct dp_catalog_private, dp_catalog);
- return dp_read_ahb(catalog, REG_DP_HW_VERSION);
+}
+/**
- dp_catalog_ctrl_reset() - reset DP controller
- @dp_catalog: DP catalog structure
@@ -739,10 +757,11 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) }
/* panel related catalog functions */ -int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, bool wide_bus_en) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
u32 reg;
dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, dp_catalog->total);
@@ -751,7 +770,18 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, dp_catalog->width_blanking); dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active);
- dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0);
- reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG);
- if (wide_bus_en)
reg |= DP_INTF_CONFIG_DATABUS_WIDEN;
- else
reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN;
- DRM_DEBUG_DP("wide_bus_en=%d reg=%x\n", wide_bus_en, reg);
- dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg); return 0; }
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 6965afa..2ba1ea4 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -95,6 +95,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb); void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate, u32 stream_rate_khz, bool fixed_nvid); int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern); +u32 dp_catalog_hw_revision(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); @@ -115,7 +116,7 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog);
/* DP Panel APIs */ -int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog); +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog, bool wide_bus_en); void dp_catalog_dump_regs(struct dp_catalog *dp_catalog); void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, struct drm_display_mode *drm_mode); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index c724cb0..b07574c 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -154,7 +154,7 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_config_ctrl(ctrl->catalog, config); }
-static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) +static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl, bool wide_bus_en) { u32 cc, tb;
@@ -167,7 +167,7 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) ctrl->panel->dp_mode.bpp); cc = dp_link_get_colorimetry_config(ctrl->link); dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb);
- dp_panel_timing_cfg(ctrl->panel);
dp_panel_timing_cfg(ctrl->panel, wide_bus_en); }
/*
@@ -1799,6 +1799,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) int ret = 0; bool mainlink_ready = false; struct dp_ctrl_private *ctrl;
u32 pixel_rate_orig;
if (!dp_ctrl) return -EINVAL;
@@ -1807,6 +1808,10 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
- pixel_rate_orig = ctrl->dp_ctrl.pixel_rate;
- if (dp_ctrl->wide_bus_en)
ctrl->dp_ctrl.pixel_rate >>= 1;
- DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n", ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate);
@@ -1842,11 +1847,11 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) */ reinit_completion(&ctrl->video_comp);
- dp_ctrl_configure_source_params(ctrl);
dp_ctrl_configure_source_params(ctrl, dp_ctrl->wide_bus_en);
dp_catalog_ctrl_config_msa(ctrl->catalog, ctrl->link->link_params.rate,
ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
dp_ctrl_setup_tr_unit(ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 2363a2d..a0a5fbb 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -17,6 +17,7 @@ struct dp_ctrl { bool orientation; atomic_t aborted; u32 pixel_rate;
bool wide_bus_en; };
int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 7cc4d21..8ecccf2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -115,6 +115,8 @@ struct dp_display_private { struct dp_event event_list[DP_EVENT_Q_MAX]; spinlock_t event_lock;
- bool wide_bus_en;
- struct dp_audio *audio; };
@@ -848,6 +850,8 @@ static int dp_display_enable(struct dp_display_private *dp, u32 data) return 0; }
- dp->ctrl->wide_bus_en = dp->wide_bus_en;
- rc = dp_ctrl_on_stream(dp->ctrl); if (!rc) dp_display->power_on = true;
@@ -972,6 +976,7 @@ int dp_display_get_modes(struct msm_dp *dp, dp->connector, dp_mode); if (dp_mode->drm_mode.clock) dp->max_pclk_khz = dp_mode->drm_mode.clock;
- return ret; }
@@ -1437,6 +1442,28 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); }
+bool msm_dp_wide_bus_enable(struct msm_dp *dp_display) +{
- struct dp_display_private *dp;
- u32 revision, major, minor;
- dp = container_of(dp_display, struct dp_display_private, dp_display);
- /* for the time being widebus only support on DP */
- if (dp_display->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
revision = dp_catalog_hw_revision(dp->catalog);
major = ((revision >> 28) & 0x0ff);
minor = ((revision >> 16) & 0x0fff);
DRM_DEBUG_DP("id=%d major=%d minor=%d\n", dp->id, major, minor);
if (major >= 1 && minor >= 2)
return true;
- }
Please add an excplicit boolean to msm_dp_config instead. You can save it into dp_parser or dp_display, whichever works for you.
Having such function doesn't help to determine if wide bus is available on a random platform supported by this driver or not.
- return false;
+}
- void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) { struct dp_display_private *dp;
@@ -1460,6 +1487,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { struct msm_drm_private *priv;
struct dp_display_private *dp_priv; int ret;
if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
@@ -1468,6 +1496,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, priv = dev->dev_private; dp_display->drm_dev = dev;
- dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
- ret = dp_display_request_irq(dp_display); if (ret) { DRM_ERROR("request_irq failed, ret=%d\n", ret);
@@ -1498,6 +1528,8 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
priv->bridges[priv->num_bridges++] = dp_display->bridge;
- dp_priv->wide_bus_en = msm_dp_wide_bus_enable(dp_display);
- return 0; }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index e3adcd5..b718cc9 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -24,6 +24,8 @@ struct msm_dp {
hdmi_codec_plugged_cb plugged_cb;
bool wide_bus_en;
u32 max_pclk_khz;
u32 max_dp_lanes;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 71db10c..71deb1e 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -353,7 +353,7 @@ void dp_panel_dump_regs(struct dp_panel *dp_panel) dp_catalog_dump_regs(catalog); }
-int dp_panel_timing_cfg(struct dp_panel *dp_panel) +int dp_panel_timing_cfg(struct dp_panel *dp_panel, bool wide_bus_en) { u32 data, total_ver, total_hor; struct dp_catalog *catalog; @@ -404,7 +404,7 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
catalog->dp_active = data;
- dp_catalog_panel_timing_cfg(catalog);
dp_catalog_panel_timing_cfg(catalog, wide_bus_en); panel->panel_on = true;
return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index 9023e5b..5ec341a 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -57,7 +57,7 @@ struct dp_panel {
int dp_panel_init_panel_info(struct dp_panel *dp_panel); int dp_panel_deinit(struct dp_panel *dp_panel); -int dp_panel_timing_cfg(struct dp_panel *dp_panel); +int dp_panel_timing_cfg(struct dp_panel *dp_panel, bool wide_bus_en); void dp_panel_dump_regs(struct dp_panel *dp_panel); int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index d7574e6..4f9c24e 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -399,6 +399,7 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display); void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor); +bool msm_dp_wide_bus_enable(struct msm_dp *dp_display);
#else static inline int __init msm_dp_register(void) @@ -449,6 +450,11 @@ static inline void msm_dp_debugfs_init(struct msm_dp *dp_display, { }
+static inline bool msm_dp_wide_bus_enable(struct msm_dp *dp_display) +{
- return false;
+}
#endif
void __init msm_mdp_register(void);
dri-devel@lists.freedesktop.org