Re: [Intel-gfx] [PATCH] drm/i915/icl: MBUS B credit change
Hi, LGTM Reviewed-by: Mahesh Kumar On 10/4/2018 8:48 PM, Rodrigo Vivi wrote: No functional change. But just a minor change to keep up with Spec, since it has changed since commit c3cc39c539d4 ("drm/i915/icl: program mbus during pipe enable") The instructions previously said to program pipe's B credit = 24 / number of pipes, which is 8 for ICL. Now the spec gives us direct values independent of number of pipes. Let's keep in sync. Also just a reorder on fields to make easier to compare against spec's sequence: A -> BW -> B. Cc: Lucas De Marchi Cc: Paulo Zanoni Cc: Mahesh Kumar Cc: Arthur J Runyan Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_display.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 36434c5359b1..eb2250a984a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5683,10 +5683,9 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc) enum pipe pipe = crtc->pipe; uint32_t val; - val = MBUS_DBOX_BW_CREDIT(1) | MBUS_DBOX_A_CREDIT(2); - - /* Program B credit equally to all pipes */ - val |= MBUS_DBOX_B_CREDIT(24 / INTEL_INFO(dev_priv)->num_pipes); + val = MBUS_DBOX_A_CREDIT(2); + val |= MBUS_DBOX_BW_CREDIT(1); + val |= MBUS_DBOX_B_CREDIT(8); I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val); } ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4] drm/i915: use for_each_pipe loop to assign crtc_mask
Hi, just a ping for review :) -Mahesh On 9/8/2018 11:40 AM, Mahesh Kumar wrote: This cleanup patch makes changes to use for_each_pipe loop during bit-mask assignment of allowed crtc with encoder. changes: - use BIT(i) macro instead of (1 << i) (Chris) changes from V2: - use int for consistency (Jani) changes from V3: - instead use enum pipe (Ville) Cc: Jani Nikula Cc: Rodrigo Vivi Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_ddi.c | 4 +++- drivers/gpu/drm/i915/intel_dp.c | 5 - drivers/gpu/drm/i915/intel_hdmi.c | 5 - 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cd01a09c5e0f..0ef2448fd350 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3751,6 +3751,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) struct intel_encoder *intel_encoder; struct drm_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; + enum pipe pipe; init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || @@ -3801,8 +3802,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->type = INTEL_OUTPUT_DDI; intel_encoder->power_domain = intel_port_to_power_domain(port); intel_encoder->port = port; - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; + for_each_pipe(dev_priv, pipe) + intel_encoder->crtc_mask |= BIT(pipe); if (INTEL_GEN(dev_priv) >= 11) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 436c22de33b6..7302b5807884 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6709,7 +6709,10 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, else intel_encoder->crtc_mask = (1 << 0) | (1 << 1); } else { - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) + intel_encoder->crtc_mask |= BIT(pipe); } intel_encoder->cloneable = 0; intel_encoder->port = port; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index a2dab0b6bde6..0d4c6f565d65 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2468,7 +2468,10 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, else intel_encoder->crtc_mask = (1 << 0) | (1 << 1); } else { - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) + intel_encoder->crtc_mask |= BIT(pipe); } intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG; /* ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v2] drm/i915: use for_each_pipe loop to assign crtc_mask
Hi, I used u8 because internally num_pipes variable used by for_each_pipe macro is of u8 type. If you think it's good to have int for consistency I can update the patch. Regards, -Mahesh On 9/7/2018 6:34 PM, Jani Nikula wrote: On Fri, 07 Sep 2018, Mahesh Kumar wrote: This cleanup patch makes changes to use for_each_pipe loop during bit-mask assignment of allowed crtc with encoder. changes: - use BIT(i) macro instead of (1 << i) (Chris) Cc: Jani Nikula Cc: Rodrigo Vivi Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_ddi.c | 4 +++- drivers/gpu/drm/i915/intel_dp.c | 5 - drivers/gpu/drm/i915/intel_hdmi.c | 5 - 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cd01a09c5e0f..88dfca245099 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3751,6 +3751,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) struct intel_encoder *intel_encoder; struct drm_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; + u8 i; Please use int instead of u8 throughout. u8 only makes sense when you actually need the specific size, or need to be concerned about the size. BR, Jani. init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || @@ -3801,8 +3802,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->type = INTEL_OUTPUT_DDI; intel_encoder->power_domain = intel_port_to_power_domain(port); intel_encoder->port = port; - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; + for_each_pipe(dev_priv, i) + intel_encoder->crtc_mask |= BIT(i); if (INTEL_GEN(dev_priv) >= 11) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 436c22de33b6..1f954debdc55 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6709,7 +6709,10 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, else intel_encoder->crtc_mask = (1 << 0) | (1 << 1); } else { - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + u8 i; + + for_each_pipe(dev_priv, i) + intel_encoder->crtc_mask |= BIT(i); } intel_encoder->cloneable = 0; intel_encoder->port = port; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index a2dab0b6bde6..647e38de7980 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2468,7 +2468,10 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, else intel_encoder->crtc_mask = (1 << 0) | (1 << 1); } else { - intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + u8 i; + + for_each_pipe(dev_priv, i) + intel_encoder->crtc_mask |= BIT(i); } intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG; /* ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/4] drm/i915: Enable Y210, Y212, Y216 format for primary and sprite planes
On 8/27/2018 12:17 PM, Swati Sharma wrote: From: Vidya Srinivas In this patch, a list for icl specific pixel formats is created in which Y210, Y212 and Y216 pixel formats are added along with legacy pixel formats for primary and sprite plane. Signed-off-by: Swati Sharma Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/i915/intel_display.c | 25 +++-- drivers/gpu/drm/i915/intel_sprite.c | 22 -- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91aa8cc..30065e3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -104,6 +104,24 @@ DRM_FORMAT_NV12, }; +static const uint32_t icl_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB, + DRM_FORMAT_XBGR, + DRM_FORMAT_ARGB, + DRM_FORMAT_ABGR, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, +}; + static const uint64_t skl_format_modifiers_noccs[] = { I915_FORMAT_MOD_Yf_TILED, I915_FORMAT_MOD_Y_TILED, @@ -13718,8 +13736,11 @@ bool skl_plane_has_planar(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) >= 9) { primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY); - - if (skl_plane_has_planar(dev_priv, pipe, PLANE_PRIMARY)) { + if (INTEL_GEN(dev_priv) >= 11) { + intel_primary_formats = icl_primary_formats; + num_formats = ARRAY_SIZE(icl_primary_formats); + } else if (skl_plane_has_planar(dev_priv, pipe, + PLANE_PRIMARY)) { intel_primary_formats = skl_pri_planar_formats; num_formats = ARRAY_SIZE(skl_pri_planar_formats); } else { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 417501f..2abdd85 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1281,6 +1281,21 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, DRM_FORMAT_NV12, }; +static uint32_t icl_plane_formats[] = { + DRM_FORMAT_RGB565, + DRM_FORMAT_ABGR, + DRM_FORMAT_ARGB, + DRM_FORMAT_XBGR, + DRM_FORMAT_XRGB, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_Y210, + DRM_FORMAT_Y212, + DRM_FORMAT_Y216, +}; + static const uint64_t skl_plane_format_modifiers_noccs[] = { I915_FORMAT_MOD_Yf_TILED, I915_FORMAT_MOD_Y_TILED, @@ -1536,8 +1551,11 @@ struct intel_plane * intel_plane->disable_plane = skl_disable_plane; intel_plane->get_hw_state = skl_plane_get_hw_state; - if (skl_plane_has_planar(dev_priv, pipe, -PLANE_SPRITE0 + plane)) { + if (INTEL_GEN(dev_priv) >= 11) { + plane_formats = icl_plane_formats; + num_plane_formats = ARRAY_SIZE(icl_plane_formats); 64 bits pixel formats are supported only with HDR planes. -Mahesh + } else if (skl_plane_has_planar(dev_priv, pipe, + PLANE_SPRITE0 + plane)) { plane_formats = skl_planar_formats; num_plane_formats = ARRAY_SIZE(skl_planar_formats); } else { ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/4] drm/i915: Preparations for enabling Y210, Y212, Y216 formats
Hi, On 8/27/2018 12:17 PM, Swati Sharma wrote: From: Vidya Srinivas Signed-off-by: Swati Sharma Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/i915/intel_display.c | 15 +++ drivers/gpu/drm/i915/intel_sprite.c | 3 +++ 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 30fdfd1..91aa8cc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3511,6 +3511,12 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format) return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY; case DRM_FORMAT_NV12: return PLANE_CTL_FORMAT_NV12; + case DRM_FORMAT_Y210: + return PLANE_CTL_FORMAT_Y210; + case DRM_FORMAT_Y212: + return PLANE_CTL_FORMAT_Y212; + case DRM_FORMAT_Y216: + return PLANE_CTL_FORMAT_Y216; While programming YUV pixel format, you also need to program order of samples in bits [17:16] BTW 64 bits pixel format are not supported in all the planes, these are supported only in HDR planes. You should handle that as well. -Mahesh default: MISSING_CASE(pixel_format); } @@ -4959,6 +4965,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, case DRM_FORMAT_UYVY: case DRM_FORMAT_VYUY: case DRM_FORMAT_NV12: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: break; default: DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", @@ -13413,6 +13422,9 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: case DRM_FORMAT_VYUY: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: case DRM_FORMAT_NV12: if (modifier == I915_FORMAT_MOD_Yf_TILED) return true; @@ -14544,6 +14556,9 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, case DRM_FORMAT_UYVY: case DRM_FORMAT_YVYU: case DRM_FORMAT_VYUY: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) { DRM_DEBUG_KMS("unsupported pixel format: %s\n", drm_get_format_name(mode_cmd->pixel_format, _name)); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index c286dda..417501f 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1419,6 +1419,9 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: case DRM_FORMAT_VYUY: + case DRM_FORMAT_Y210: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: case DRM_FORMAT_NV12: if (modifier == I915_FORMAT_MOD_Yf_TILED) return true; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/4] drm: Add Y210, Y212, Y216 format definitions and fourcc
On 8/27/2018 12:47 PM, Kumar, Mahesh wrote: Hi, On 8/27/2018 12:17 PM, Swati Sharma wrote: From: Vidya Srinivas The following pixel formats are packed format that follows 4:2:2 chroma sampling. For memory represenation each component is allocated 16 bits each. Thus each pixel occupies a DWORD. Y210: Valid data occupies MSB 10 bits. LSB 6 bits are filled with zeroes. Y212: Valid data occupies MSB 12 bits. LSB 4 bits are filled with zeroes. Y216: Valid data occupies 16 bits, doesn't require any padding bits. First 16 bits stores the Y value and the next 16 bits stores one of the chroma samples alternatively. The first luma sample will be accompanied by first U sample and second luma sample is accompanied by the first V sample. Signed-off-by: Swati Sharma Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/drm_fourcc.c | 3 +++ include/uapi/drm/drm_fourcc.h | 4 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 35c1e27..4bf04a5 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -173,6 +173,9 @@ const struct drm_format_info *__drm_format_info(u32 format) { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, + { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_Y212, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_Y216, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, }; you should also set is_yuv to true. Apart from this there can be different order for YUV samples, Are you going to add those as well? -Mahesh unsigned int i; diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 2ed46e9..6a03e6d 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -149,6 +149,10 @@ #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Y0:Cb0:Y1:Cr1 10:10:10:10 little endian */ +#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Y0:Cb0:Y1:Cr1 12:12:12:12 little endian */ +#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Y0:Cb0:Y1:Cr1 16:16:16:16 little endian */ + /* * 2 plane RGB + A * index 0 = RGB plane, same format as the corresponding non _A8 format has ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 2/4] drm/i915: Add Y210, Y212, Y216 plane control definitions
Hi, Please include platform name in subject line: On 8/27/2018 12:17 PM, Swati Sharma wrote: From: Vidya Srinivas Added needed plane control flag definitions for Y210, Y212 and Y216 formats. may be, add more info in commit message -Mahesh Signed-off-by: Swati Sharma Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8534f88..926e42d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6504,6 +6504,9 @@ enum { #define PLANE_CTL_FORMAT_RGB_565(14 << 24) #define ICL_PLANE_CTL_FORMAT_MASK (0x1f << 23) #define PLANE_CTL_PIPE_CSC_ENABLE (1 << 23) /* Pre-GLK */ +#define PLANE_CTL_FORMAT_Y210(1 << 23) +#define PLANE_CTL_FORMAT_Y212(3 << 23) +#define PLANE_CTL_FORMAT_Y216(5 << 23) #define PLANE_CTL_KEY_ENABLE_MASK (0x3 << 21) #define PLANE_CTL_KEY_ENABLE_SOURCE (1 << 21) #define PLANE_CTL_KEY_ENABLE_DESTINATION(2 << 21) ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/4] drm: Add Y210, Y212, Y216 format definitions and fourcc
Hi, On 8/27/2018 12:17 PM, Swati Sharma wrote: From: Vidya Srinivas The following pixel formats are packed format that follows 4:2:2 chroma sampling. For memory represenation each component is allocated 16 bits each. Thus each pixel occupies a DWORD. Y210: Valid data occupies MSB 10 bits. LSB 6 bits are filled with zeroes. Y212: Valid data occupies MSB 12 bits. LSB 4 bits are filled with zeroes. Y216: Valid data occupies 16 bits, doesn't require any padding bits. First 16 bits stores the Y value and the next 16 bits stores one of the chroma samples alternatively. The first luma sample will be accompanied by first U sample and second luma sample is accompanied by the first V sample. Signed-off-by: Swati Sharma Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/drm_fourcc.c | 3 +++ include/uapi/drm/drm_fourcc.h | 4 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 35c1e27..4bf04a5 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -173,6 +173,9 @@ const struct drm_format_info *__drm_format_info(u32 format) { .format = DRM_FORMAT_UYVY,.depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, { .format = DRM_FORMAT_VYUY,.depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, { .format = DRM_FORMAT_AYUV,.depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, + { .format = DRM_FORMAT_Y210,.depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_Y212,.depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_Y216,.depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 2, .vsub = 1 }, }; you should also set is_yuv to true. -Mahesh unsigned int i; diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 2ed46e9..6a03e6d 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -149,6 +149,10 @@ #define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ +#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Y0:Cb0:Y1:Cr1 10:10:10:10 little endian */ +#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Y0:Cb0:Y1:Cr1 12:12:12:12 little endian */ +#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Y0:Cb0:Y1:Cr1 16:16:16:16 little endian */ + /* * 2 plane RGB + A * index 0 = RGB plane, same format as the corresponding non _A8 format has ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 4/5] drm/i915/kbl+: Enable IPC only for symmetric memory configurations
Hi, On 8/22/2018 12:26 AM, Rodrigo Vivi wrote: On Tue, Aug 21, 2018 at 09:30:21PM +0530, Kumar, Mahesh wrote: Hi, On 8/21/2018 8:27 PM, Kumar, Mahesh wrote: Hi, On 8/17/2018 11:50 PM, Rodrigo Vivi wrote: On Thu, Jul 26, 2018 at 07:44:09PM +0530, Mahesh Kumar wrote: IPC may cause underflows if not used with dual channel symmetric memory configuration. Disable IPC for non symmetric configurations in affected platforms. Display WA #1141 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 43 - drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 86bc2e685522..2273664166bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1141,21 +1141,47 @@ skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) return 0; } +static bool +intel_is_dram_ipc_capable(struct drm_i915_private *dev_priv, + u32 val_ch0, u32 val_ch1, + struct dram_channel_info *ch0) what about intel_is_dram_symmetric() ? sounds good. +{ + /* Display WA #1141: SKL:all KBL:all CNL:A CNL:B */ move this to the wa call, not the the function check... + if (INTEL_GEN(dev_priv) > 9 && + !IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) please don't add CNL pre-prod wa ok sure + return true; + + if (!IS_KABYLAKE(dev_priv) && !IS_SKYLAKE(dev_priv)) + return true; actually remove all platforms checks here... Agree will remove these checks, function will just return if memory is symmetric. + + if (val_ch0 != val_ch1) + return false; + + if (ch0->s_info.size == 0) + return true; + if (ch0->l_info.size == ch0->s_info.size && + ch0->l_info.width == ch0->s_info.width && + ch0->l_info.rank == ch0->s_info.rank) + return true; + + return false; return (val_ch0 == val_ch1 && (ch0->s_info.size == 0 || (ch0->l_info.size == ch0->s_info.size && ch0->l_info.width == ch0->s_info.width && ch0->l_info.rank == ch0->s_info.rank))) +} + static int skl_dram_get_channels_info(struct drm_i915_private *dev_priv) { struct dram_info *dram_info = _priv->dram_info; struct dram_channel_info ch0, ch1; - u32 val; + u32 val_ch0, val_ch1; int ret; - val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch0); if (ret == 0) dram_info->num_channels++; - val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch1); if (ret == 0) dram_info->num_channels++; @@ -1185,6 +1211,13 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) dram_info->is_16gb_dimm = true; + if (intel_is_dram_ipc_capable(dev_priv, val_ch0, val_ch1, )) + dev_priv->ipc_capable_mem = true; + else + dev_priv->ipc_capable_mem = false; + + DRM_DEBUG_KMS("memory configuration is %sIPC capable\n", + dev_priv->ipc_capable_mem ? "" : "not "); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 854f3c828e01..036d6554c017 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2112,6 +2112,7 @@ struct drm_i915_private { bool chv_phy_assert[2]; bool ipc_enabled; + bool ipc_capable_mem; I don't think we need to stage this... With above changes storing this info is not needed, But we need to keep a flag in dram_info to check if "memory is symmetric", Otherwise we need to compute all the memory related info again. -Mahesh /* Used to save the pipe-to-encoder mapping for audio */ struct intel_encoder *av_enc_map[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2446f53adf21..39e400d5f555 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6097,7 +6097,7 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) u32 val; /* Display WA #0477 WaDisableIPC: skl */ - if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv) || !dev_priv->ipc_capable_mem) { dev_priv->ipc_enabled = false; This is not the WA 1141 for other platforms than SKL. Please only keep skl here. For the other WA add 4us across all watermark levels
Re: [Intel-gfx] [PATCH 4/5] drm/i915/kbl+: Enable IPC only for symmetric memory configurations
Hi, On 8/21/2018 8:27 PM, Kumar, Mahesh wrote: Hi, On 8/17/2018 11:50 PM, Rodrigo Vivi wrote: On Thu, Jul 26, 2018 at 07:44:09PM +0530, Mahesh Kumar wrote: IPC may cause underflows if not used with dual channel symmetric memory configuration. Disable IPC for non symmetric configurations in affected platforms. Display WA #1141 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 43 - drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 86bc2e685522..2273664166bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1141,21 +1141,47 @@ skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) return 0; } +static bool +intel_is_dram_ipc_capable(struct drm_i915_private *dev_priv, + u32 val_ch0, u32 val_ch1, + struct dram_channel_info *ch0) what about intel_is_dram_symmetric() ? sounds good. +{ + /* Display WA #1141: SKL:all KBL:all CNL:A CNL:B */ move this to the wa call, not the the function check... + if (INTEL_GEN(dev_priv) > 9 && + !IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) please don't add CNL pre-prod wa ok sure + return true; + + if (!IS_KABYLAKE(dev_priv) && !IS_SKYLAKE(dev_priv)) + return true; actually remove all platforms checks here... Agree will remove these checks, function will just return if memory is symmetric. + + if (val_ch0 != val_ch1) + return false; + + if (ch0->s_info.size == 0) + return true; + if (ch0->l_info.size == ch0->s_info.size && + ch0->l_info.width == ch0->s_info.width && + ch0->l_info.rank == ch0->s_info.rank) + return true; + + return false; return (val_ch0 == val_ch1 && (ch0->s_info.size == 0 || (ch0->l_info.size == ch0->s_info.size && ch0->l_info.width == ch0->s_info.width && ch0->l_info.rank == ch0->s_info.rank))) +} + static int skl_dram_get_channels_info(struct drm_i915_private *dev_priv) { struct dram_info *dram_info = _priv->dram_info; struct dram_channel_info ch0, ch1; - u32 val; + u32 val_ch0, val_ch1; int ret; - val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch0); if (ret == 0) dram_info->num_channels++; - val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch1); if (ret == 0) dram_info->num_channels++; @@ -1185,6 +1211,13 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) dram_info->is_16gb_dimm = true; + if (intel_is_dram_ipc_capable(dev_priv, val_ch0, val_ch1, )) + dev_priv->ipc_capable_mem = true; + else + dev_priv->ipc_capable_mem = false; + + DRM_DEBUG_KMS("memory configuration is %sIPC capable\n", + dev_priv->ipc_capable_mem ? "" : "not "); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 854f3c828e01..036d6554c017 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2112,6 +2112,7 @@ struct drm_i915_private { bool chv_phy_assert[2]; bool ipc_enabled; + bool ipc_capable_mem; I don't think we need to stage this... With above changes storing this info is not needed, But we need to keep a flag in dram_info to check if "memory is symmetric", Otherwise we need to compute all the memory related info again. -Mahesh /* Used to save the pipe-to-encoder mapping for audio */ struct intel_encoder *av_enc_map[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2446f53adf21..39e400d5f555 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6097,7 +6097,7 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) u32 val; /* Display WA #0477 WaDisableIPC: skl */ - if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv) || !dev_priv->ipc_capable_mem) { dev_priv->ipc_enabled = false; This is not the WA 1141 for other platforms than SKL. Please only keep skl here. For the other WA add 4us across all watermark levels /* Display WA #1141: skl,kbl,cfl */ if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && intel_is_
Re: [Intel-gfx] [PATCH 4/5] drm/i915/kbl+: Enable IPC only for symmetric memory configurations
Hi, On 8/17/2018 11:50 PM, Rodrigo Vivi wrote: On Thu, Jul 26, 2018 at 07:44:09PM +0530, Mahesh Kumar wrote: IPC may cause underflows if not used with dual channel symmetric memory configuration. Disable IPC for non symmetric configurations in affected platforms. Display WA #1141 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 43 - drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 +- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 86bc2e685522..2273664166bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1141,21 +1141,47 @@ skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) return 0; } +static bool +intel_is_dram_ipc_capable(struct drm_i915_private *dev_priv, + u32 val_ch0, u32 val_ch1, + struct dram_channel_info *ch0) what about intel_is_dram_symmetric() ? sounds good. +{ + /* Display WA #1141: SKL:all KBL:all CNL:A CNL:B */ move this to the wa call, not the the function check... + if (INTEL_GEN(dev_priv) > 9 && + !IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) please don't add CNL pre-prod wa ok sure + return true; + + if (!IS_KABYLAKE(dev_priv) && !IS_SKYLAKE(dev_priv)) + return true; actually remove all platforms checks here... Agree will remove these checks, function will just return if memory is symmetric. + + if (val_ch0 != val_ch1) + return false; + + if (ch0->s_info.size == 0) + return true; + if (ch0->l_info.size == ch0->s_info.size && + ch0->l_info.width == ch0->s_info.width && + ch0->l_info.rank == ch0->s_info.rank) + return true; + + return false; return (val_ch0 == val_ch1 && (ch0->s_info.size == 0 || (ch0->l_info.size == ch0->s_info.size && ch0->l_info.width == ch0->s_info.width && ch0->l_info.rank == ch0->s_info.rank))) +} + static int skl_dram_get_channels_info(struct drm_i915_private *dev_priv) { struct dram_info *dram_info = _priv->dram_info; struct dram_channel_info ch0, ch1; - u32 val; + u32 val_ch0, val_ch1; int ret; - val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch0); if (ret == 0) dram_info->num_channels++; - val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(, val); + val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val_ch1); if (ret == 0) dram_info->num_channels++; @@ -1185,6 +1211,13 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) dram_info->is_16gb_dimm = true; + if (intel_is_dram_ipc_capable(dev_priv, val_ch0, val_ch1, )) + dev_priv->ipc_capable_mem = true; + else + dev_priv->ipc_capable_mem = false; + + DRM_DEBUG_KMS("memory configuration is %sIPC capable\n", + dev_priv->ipc_capable_mem ? "" : "not "); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 854f3c828e01..036d6554c017 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2112,6 +2112,7 @@ struct drm_i915_private { bool chv_phy_assert[2]; bool ipc_enabled; + bool ipc_capable_mem; I don't think we need to stage this... With above changes storing this info is not needed, But we need to keep a flag in dram_info to check if "memory is symmetric", Otherwise we need to compute all the memory related info again. -Mahesh /* Used to save the pipe-to-encoder mapping for audio */ struct intel_encoder *av_enc_map[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2446f53adf21..39e400d5f555 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6097,7 +6097,7 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) u32 val; /* Display WA #0477 WaDisableIPC: skl */ - if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv) || !dev_priv->ipc_capable_mem) { dev_priv->ipc_enabled = false; This is not the WA 1141 for other platforms than SKL. Please only keep skl here. For the other WA add 4us across all watermark levels /* Display WA #1141: skl,kbl,cfl */ if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && intel_is_dram_symmetric()) levels += 4;
Re: [Intel-gfx] [PATCH 2/5] drm/i915/skl+: Decode memory bandwidth and parameters
Hi, On 8/17/2018 4:05 AM, Rodrigo Vivi wrote: On Thu, Jul 26, 2018 at 07:44:07PM +0530, Mahesh Kumar wrote: This patch adds support to decode system memory bandwidth and other parameters for skylake and Gen9+ platforms, which will be used for arbitrated display memory bandwidth calculation in GEN9 based platforms and WM latency level-0 Work-around calculation on GEN9+. Changes Since V1: - s/memdev_info/dram_info - create a struct to hold channel info Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 131 ++-- drivers/gpu/drm/i915/i915_drv.h | 7 +++ drivers/gpu/drm/i915/i915_reg.h | 21 +++ 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 16629601c9f4..ddf6bf9b500a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1070,6 +1070,118 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static int +skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) +{ + u8 l_rank, s_rank; + u8 l_size, s_size; + u8 l_width, s_width; + enum dram_rank rank; + + if (!val) + return -1; -SOMEERRNO? ok sure. + + l_size = (val >> SKL_DRAM_SIZE_L_SHIFT) & SKL_DRAM_SIZE_MASK; + s_size = (val >> SKL_DRAM_SIZE_S_SHIFT) & SKL_DRAM_SIZE_MASK; + l_width = (val >> SKL_DRAM_WIDTH_L_SHIFT) & SKL_DRAM_WIDTH_MASK; + s_width = (val >> SKL_DRAM_WIDTH_S_SHIFT) & SKL_DRAM_WIDTH_MASK; + l_rank = (val >> SKL_DRAM_RANK_L_SHIFT) & SKL_DRAM_RANK_MASK; + s_rank = (val >> SKL_DRAM_RANK_S_SHIFT) & SKL_DRAM_RANK_MASK; + + if (l_size == 0 && s_size == 0) + return -1; ditto + + DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n", + l_size, (1 << l_width) * 8, l_rank ? "dual" : "single", + s_size, (1 << s_width) * 8, s_rank ? "dual" : "single"); + + if (l_rank == SKL_DRAM_RANK_DUAL || s_rank == SKL_DRAM_RANK_DUAL) + rank = I915_DRAM_RANK_DUAL; + else if ((l_size && l_rank == SKL_DRAM_RANK_SINGLE) && +(s_size && s_rank == SKL_DRAM_RANK_SINGLE)) + rank = I915_DRAM_RANK_DUAL; + else + rank = I915_DRAM_RANK_SINGLE; + + ch->l_info.size = l_size; + ch->s_info.size = s_size; + ch->l_info.width = l_width; + ch->s_info.width = s_width; + ch->l_info.rank = l_rank; + ch->s_info.rank = s_rank; + ch->rank = rank; could we do this directly without intermediates? not clear if we change in the middle after printing... This information is needed later while checking is memories are symmetric, that's why we need to keep this as well. + + return 0; +} + +static int +skl_dram_get_channels_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = _priv->dram_info; + struct dram_channel_info ch0, ch1; + u32 val; + int ret; + + val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val); + if (ret == 0) + dram_info->num_channels++; + + val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(, val); + if (ret == 0) + dram_info->num_channels++; + + if (dram_info->num_channels == 0) { + DRM_INFO("Number of memory channels is zero\n"); + return -EINVAL; + } + + /* +* If any of the channel is single rank channel, worst case output +* will be same as if single rank memory, so consider single rank +* memory. +*/ + if (ch0.rank == I915_DRAM_RANK_SINGLE || + ch1.rank == I915_DRAM_RANK_SINGLE) + dram_info->rank = I915_DRAM_RANK_SINGLE; + else + dram_info->rank = max(ch0.rank, ch1.rank); + + if (dram_info->rank == I915_DRAM_RANK_INVALID) { + DRM_INFO("couldn't get memory rank information\n"); + return -EINVAL; + } + return 0; +} + +static int +skl_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = _priv->dram_info; + u32 mem_freq_khz, val; + int ret; + + ret = skl_dram_get_channels_info(dev_priv); + if (ret) + return ret; + + val = I915_READ(SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); + mem_freq_khz = DIV_ROUND_UP((val & SKL_REQ_DATA_MASK) * + SKL_MEMORY_FREQ_MULTIPLIER_HZ, 1000); + + dram_info->bandwidth_kbps = dram_info->num_channels * + mem_freq_khz * 8; + + if (dram_info->bandwidth_kbps == 0) { + DRM_INFO("Couldn't get system memory bandwidth\n"); + return -EINVAL; +
Re: [Intel-gfx] [PATCH 1/5] drm/i915/bxt: Decode memory bandwidth and parameters
Hi, On 8/17/2018 11:13 PM, Rodrigo Vivi wrote: On Thu, Jul 26, 2018 at 07:44:06PM +0530, Mahesh Kumar wrote: This patch adds support to decode system memory bandwidth and other parameters for broxton platform, which will be used for arbitrated display memory bandwidth calculation in GEN9 based platforms and WM latency level-0 Work-around calculation on GEN9+ platforms. Changes since V1: - s/memdev_info/dram_info Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 116 drivers/gpu/drm/i915/i915_drv.h | 11 drivers/gpu/drm/i915/i915_reg.h | 30 +++ 3 files changed, 157 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 18a45e7a3d7c..16629601c9f4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1070,6 +1070,116 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static int +bxt_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = _priv->dram_info; + u32 dram_channels; + u32 mem_freq_khz, val; + u8 num_active_channels; + int i; + + val = I915_READ(BXT_P_CR_MC_BIOS_REQ_0_0_0); + mem_freq_khz = DIV_ROUND_UP((val & BXT_REQ_DATA_MASK) * + BXT_MEMORY_FREQ_MULTIPLIER_HZ, 1000); + + dram_channels = (val >> BXT_DRAM_CHANNEL_ACTIVE_SHIFT) & + BXT_DRAM_CHANNEL_ACTIVE_MASK; + num_active_channels = hweight32(dram_channels); + + /* Each active bit represents 4-byte channel */ + dram_info->bandwidth_kbps = (mem_freq_khz * num_active_channels * 4); + + if (dram_info->bandwidth_kbps == 0) { + DRM_INFO("Couldn't get system memory bandwidth\n"); + return -EINVAL; + } + + /* +* Now read each DUNIT8/9/10/11 to check the rank of each dimms. +*/ + for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { + u8 rank, size, width; + enum dram_rank ch_rank; + + val = I915_READ(BXT_D_CR_DRP0_DUNIT(i)); + if (val == 0x) + continue; + + dram_info->num_channels++; + rank = val & BXT_DRAM_RANK_MASK; + width = (val >> BXT_DRAM_WIDTH_SHIFT) & BXT_DRAM_WIDTH_MASK; + size = (val >> BXT_DRAM_SIZE_SHIFT) & BXT_DRAM_SIZE_MASK; + if (rank == BXT_DRAM_RANK_SINGLE) + ch_rank = I915_DRAM_RANK_SINGLE; + else if (rank == BXT_DRAM_RANK_DUAL) + ch_rank = I915_DRAM_RANK_DUAL; + else + ch_rank = I915_DRAM_RANK_INVALID; + + if (size == BXT_DRAM_SIZE_4GB) + size = 4; + else if (size == BXT_DRAM_SIZE_6GB) + size = 6; + else if (size == BXT_DRAM_SIZE_8GB) + size = 8; + else if (size == BXT_DRAM_SIZE_12GB) + size = 12; + else if (size == BXT_DRAM_SIZE_16GB) + size = 16; + else + size = 0; + + width = (1 << width) * 8; + DRM_DEBUG_KMS("dram size:%dGB width:X%d rank:%s\n", size, + width, rank == BXT_DRAM_RANK_SINGLE ? "single" : + rank == BXT_DRAM_RANK_DUAL ? "dual" : "unknown"); + + /* +* If any of the channel is single rank channel, +* worst case output will be same as if single rank +* memory, so consider single rank memory. +*/ + if (dram_info->rank == I915_DRAM_RANK_INVALID) + dram_info->rank = ch_rank; + else if (ch_rank == I915_DRAM_RANK_SINGLE) + dram_info->rank = I915_DRAM_RANK_SINGLE; + } + + if (dram_info->rank == I915_DRAM_RANK_INVALID) { + DRM_INFO("couldn't get memory rank information\n"); + return -EINVAL; + } + + dram_info->valid = true; + return 0; +} + +static void +intel_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = _priv->dram_info; + int ret; + + dram_info->valid = false; + dram_info->rank = I915_DRAM_RANK_INVALID; + dram_info->bandwidth_kbps = 0; + dram_info->num_channels = 0; + + if (!IS_BROXTON(dev_priv)) + return; + + ret = bxt_get_dram_info(dev_priv); + if (ret) + return; + + DRM_DEBUG_KMS("DRAM bandwidth:%d KBps, total-channels: %u\n", + dram_info->bandwidth_kbps, dram_info->num_channels); + DRM_DEBUG_KMS("DRAM rank: %s rank\n", +
Re: [Intel-gfx] [PATCH V2 1/3] drm/vkms/crc: Implement verify_crc_source callback
Hi Haneen, On 8/21/2018 4:09 AM, Haneen Mohammed wrote: On Tue, Aug 14, 2018 at 08:31:03AM +0530, Mahesh Kumar wrote: This patch implements "verify_crc_source" callback function for Virtual KMS drm driver. Changes Since V1: - update values_cnt in verify_crc_source Cc: Haneen Mohammed Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/vkms/vkms_crc.c | 38 ++ drivers/gpu/drm/vkms/vkms_crtc.c | 1 + drivers/gpu/drm/vkms/vkms_drv.h | 2 ++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c index 37d717f38e3c..b2a484b4e2ad 100644 --- a/drivers/gpu/drm/vkms/vkms_crc.c +++ b/drivers/gpu/drm/vkms/vkms_crc.c @@ -70,6 +70,37 @@ void vkms_crc_work_handle(struct work_struct *work) drm_crtc_add_crc_entry(crtc, true, crtc_state->n_frame, ); } +static int vkms_crc_parse_source(const char *src_name, bool *enabled) +{ + int ret = 0; + + if (!src_name) { + *enabled = false; + } else if (strcmp(src_name, "auto") == 0) { + *enabled = true; + } else { + *enabled = false; + ret = -EINVAL; + } + + return ret; +} + +int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, + size_t *values_cnt) +{ + bool enabled; + + if (vkms_crc_parse_source(src_name, ) < 0) { + DRM_DEBUG_DRIVER("unknown source %s\n", src_name); + return -EINVAL; + } + + *values_cnt = 1; + + return 0; +} + int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name, size_t *values_cnt) { @@ -78,10 +109,9 @@ int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name, unsigned long flags; int ret = 0; - if (src_name && strcmp(src_name, "auto") == 0) - enabled = true; - else if (src_name) - ret = -EINVAL; + ret = vkms_crc_parse_source(src_name, ); + if (ret) + return ret; I think the return value after vkms_crc_parse_source should be called once instead at the end of vkms_set_crc_source otherwise crc_enabled won't be updated? Here I'm assuming if src_name is wrong we don't need to proceed further, let the CRC generation to continue whatever it was doing (enabled or disabled). But anyway that is changing the original design, will remove above return to keep the behavior same. -Mahesh - Haneen *values_cnt = 1; diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index bfe6e0312cc4..9d0b1a325a78 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -140,6 +140,7 @@ static const struct drm_crtc_funcs vkms_crtc_funcs = { .enable_vblank = vkms_enable_vblank, .disable_vblank = vkms_disable_vblank, .set_crc_source = vkms_set_crc_source, + .verify_crc_source = vkms_verify_crc_source, }; static void vkms_crtc_atomic_enable(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index f156c930366a..090c5e4f5544 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -125,6 +125,8 @@ void vkms_gem_vunmap(struct drm_gem_object *obj); /* CRC Support */ int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name, size_t *values_cnt); +int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, + size_t *values_cnt); void vkms_crc_work_handle(struct work_struct *work); #endif /* _VKMS_DRV_H_ */ -- 2.16.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_pipe_crc_basic: expect setting bad source to fail
Hi, On 8/2/2018 4:13 PM, Maarten Lankhorst wrote: Op 02-08-18 om 12:42 schreef Maarten Lankhorst: Op 02-07-18 om 13:27 schreef Maarten Lankhorst: Op 02-07-18 om 13:16 schreef Mahesh Kumar: Now crc-core framework verifies the source string passed by the user. So setting bad-source will fail. Expect file write to fail in bad-source subtest of kms_pipe_crc_basic. Signed-off-by: Mahesh Kumar --- tests/kms_pipe_crc_basic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c index 235fdc38..2d4dfee8 100644 --- a/tests/kms_pipe_crc_basic.c +++ b/tests/kms_pipe_crc_basic.c @@ -48,8 +48,7 @@ static struct { static void test_bad_source(data_t *data) { - igt_assert(igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")); - igt_assert(openat(data->debugfs, "crtc-0/crc/data", O_WRONLY) == -1); + igt_assert(!igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")); } #define N_CRCS 3 New behavior makes more sense. Reviewed-by: Maarten Lankhorst Do you have igt commit rights? Any objections if we change this to allow both behaviors? diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c index 235fdc386ba2..91909fa42f2f 100644 --- a/tests/kms_pipe_crc_basic.c +++ b/tests/kms_pipe_crc_basic.c @@ -48,8 +48,11 @@ static struct { static void test_bad_source(data_t *data) { - igt_assert(igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")); - igt_assert(openat(data->debugfs, "crtc-0/crc/data", O_WRONLY) == -1); + errno = 0; + if (igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")) + igt_assert(openat(data->debugfs, "crtc-0/crc/data", O_WRONLY) == -1); + else + igt_assert_eq(errno, EINVAL); } #define N_CRCS 3 Hm without the else, errno should be EINVAL in any case.. agree, with this change Reviewed-by: Mahesh Kumar ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/icl: avoid unclaimed PLANE_NV12_BUF_CFG register
Hi, Reviewed-by: Mahesh Kumar -Mahesh On 8/1/2018 6:16 AM, Paulo Zanoni wrote: We don't have proper watermark NV12 support on ICL due to differences in how it should be implemented. In commit 234059da0f33 ("drm/i915/icl: NV12 y-plane ddb is not in same plane") we avoided writing the non-existent PLANE_NV12_BUF_CFG registers but we forgot to also avoid them on the hardware state readout. While the code is still not correct, at least now we can avoid unclaimed register error messages when dealing with RGB formats, which makes CI happier. Also add some FIXME comments in order to make it even more clear that there's still work to do. References: commit 234059da0f33 ("drm/i915/icl: NV12 y-plane ddb is not in same plane") Cc: Mahesh Kumar Signed-off-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_pm.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2531eb75bdce..04cef1369e8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3909,7 +3909,12 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, val & PLANE_CTL_ALPHA_MASK); val = I915_READ(PLANE_BUF_CFG(pipe, plane_id)); - val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); + /* +* FIXME: add proper NV12 support for ICL. Avoid reading unclaimed +* registers for now. +*/ + if (INTEL_GEN(dev_priv) < 11) + val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); if (fourcc == DRM_FORMAT_NV12) { skl_ddb_entry_init_from_hw(dev_priv, @@ -4977,6 +4982,7 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), >plane[pipe][plane_id]); + /* FIXME: add proper NV12 support for ICL. */ if (INTEL_GEN(dev_priv) >= 11) return skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/5] drm/i915: Implement 16GB dimm wa for latency level-0
Hi, On 7/28/2018 11:18 AM, Rodrigo Vivi wrote: On Fri, Jul 27, 2018 at 11:40:14AM +0530, Kumar, Mahesh wrote: Hi Matt, On 7/27/2018 9:21 AM, Matt Turner wrote: On Thu, Jul 26, 2018 at 7:14 AM, Mahesh Kumar wrote: Bspec: 4381 Do we know that these numbers are stable? yes these numbers are fixed in Bspec I don't know if this form is common in the kernel, but in Mesa we specify the name of the page which should always allow readers to find it. This is common practice in kernel to give Bspec Number reference instead of name of the page. Well, I believe Matt has a good point here. It is stable for now and for a while, but we had seen changes on the web interface in use. Also this number doesn't help devs who don't use the web interface. sure, will update this in next version. Will float updated series once receive review comments on other patches. -Mahesh -Mahesh ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/skl: distribute DDB based on panel resolution
Hi Chris, Thanks for review. On 7/30/2018 9:08 PM, Chris Wilson wrote: Quoting Mahesh Kumar (2018-07-30 15:12:02) We distribute DDB equally among all pipes irrespective of display buffer requirement of each pipe. This leads to a situation where high resolution y-tiled display can not be enabled with 2 low resolution displays. Main contributing factor for DDB requirement is width of the display. This patch make changes to distribute ddb based on display width. So display with higher width will get bigger chunk of DDB. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107113 Cc: raviraj.p.sita...@intel.com Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 55 +++-- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7312ecb73415..e092f0deb93d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3814,8 +3814,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_i915_private *dev_priv = to_i915(dev); struct drm_crtc *for_crtc = cstate->base.crtc; + enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe; + const struct drm_crtc_state *crtc_state; + const struct drm_crtc *crtc; + u32 pipe_width[I915_MAX_PIPES] = {0}; + u32 total_width = 0, width_before_pipe = 0; unsigned int pipe_size, ddb_size; - int nth_active_pipe; + u16 ddb_size_before_pipe; + u32 i; if (WARN_ON(!state) || !cstate->base.active) { alloc->start = 0; @@ -3833,14 +3839,14 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, *num_active, ddb); /* -* If the state doesn't change the active CRTC's, then there's -* no need to recalculate; the existing pipe allocation limits -* should remain unchanged. Note that we're safe from racing -* commits since any racing commit that changes the active CRTC -* list would need to grab _all_ crtc locks, including the one -* we currently hold. +* If the state doesn't change the active CRTC's or there is no +* modeset request, then there's no need to recalculate; +* the existing pipe allocation limits should remain unchanged. +* Note that we're safe from racing commits since any racing commit +* that changes the active CRTC list or do modeset would need to +* grab _all_ crtc locks, including the one we currently hold. */ - if (!intel_state->active_pipe_changes) { + if (!intel_state->active_pipe_changes && !intel_state->modeset) { /* * alloc may be cleared by clear_intel_crtc_state, * copy from old state to be sure @@ -3849,10 +3855,33 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, return; } - nth_active_pipe = hweight32(intel_state->active_crtcs & - (drm_crtc_mask(for_crtc) - 1)); - pipe_size = ddb_size / hweight32(intel_state->active_crtcs); - alloc->start = nth_active_pipe * ddb_size / *num_active; + /* +* Watermark/ddb requirement highly depends upon width of the +* framebuffer, So instead of allocating DDB equally among pipes +* distribute DDB based on resolution/width of the display. +*/ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + const struct drm_display_mode *adjusted_mode; + int hdisplay, vdisplay; + enum pipe pipe; + + if (!crtc_state->enable) + continue; + + pipe = to_intel_crtc(crtc)->pipe; + adjusted_mode = _state->adjusted_mode; + drm_mode_get_hv_timing(adjusted_mode, , ); + pipe_width[pipe] = hdisplay; + total_width += pipe_width[pipe]; + + if (pipe < for_pipe) + width_before_pipe += pipe_width[pipe]; + } + + ddb_size_before_pipe = div_u64(ddb_size * width_before_pipe, + total_width); ddb_size is unsigned int (u32) width_before_pipe is u32 ddb_size_before_pipe is u16 That mismash of types is itself perplexing, but u32*u16 is only u32, you need to cast it to u64 to avoid the overflow: i.e. div_u64(mul_u32_u32(ddb_size, width_before_pipe), total_width); But ddb_size_before_pipe obviously need to be the same type as ddb_size, and if u16 is good enough, then you do not need a 64b divide! hmm, ddb_size will not go beyond u16 as we have only 1024 blocks and in future also I'm not expecting it to overflow u16. I don't wanted to change already used data-types , anyway will clean this
Re: [Intel-gfx] [PATCH 3/5] drm/i915: Implement 16GB dimm wa for latency level-0
Hi Matt, On 7/27/2018 9:21 AM, Matt Turner wrote: On Thu, Jul 26, 2018 at 7:14 AM, Mahesh Kumar wrote: Bspec: 4381 Do we know that these numbers are stable? yes these numbers are fixed in Bspec I don't know if this form is common in the kernel, but in Mesa we specify the name of the page which should always allow readers to find it. This is common practice in kernel to give Bspec Number reference instead of name of the page. -Mahesh ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915: inline skl_copy_ddb_for_pipe() to its only caller
Hi, Patch LGTM. Reviewed-by: Mahesh Kumar thanks, -Mahesh On 6/8/2018 4:37 AM, Paulo Zanoni wrote: While things may have been different before, right now the function is very simple and has a single caller. IMHO any possible benefits from an abstraction here are gone and not worth the price of the current indirection while reading the code. Cc: Mahesh Kumar Signed-off-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_pm.c | 16 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 533e6886..018aae9f5769 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5141,17 +5141,6 @@ skl_compute_ddb(struct drm_atomic_state *state) return 0; } -static void -skl_copy_ddb_for_pipe(struct skl_ddb_values *dst, - struct skl_ddb_values *src, - enum pipe pipe) -{ - memcpy(dst->ddb.uv_plane[pipe], src->ddb.uv_plane[pipe], - sizeof(dst->ddb.uv_plane[pipe])); - memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], - sizeof(dst->ddb.plane[pipe])); -} - static void skl_print_wm_changes(const struct drm_atomic_state *state) { @@ -5381,7 +5370,10 @@ static void skl_initial_wm(struct intel_atomic_state *state, if (cstate->base.active_changed) skl_atomic_update_crtc_wm(state, cstate); - skl_copy_ddb_for_pipe(hw_vals, results, pipe); + memcpy(hw_vals->ddb.uv_plane[pipe], results->ddb.uv_plane[pipe], + sizeof(hw_vals->ddb.uv_plane[pipe])); + memcpy(hw_vals->ddb.plane[pipe], results->ddb.plane[pipe], + sizeof(hw_vals->ddb.plane[pipe])); mutex_unlock(_priv->wm.wm_mutex); } ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v4 10/10] drm/rcar-du/crc: Implement get_crc_sources callback
Hi Laurent! Thanks for the review. :) will update patch and resubmit -Mahesh On 7/19/2018 4:42 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patch. On Friday, 13 July 2018 16:59:42 EEST Mahesh Kumar wrote: This patch implements get_crc_sources callback, which returns list of all the crc sources supported by driver in current platform. Changes Since V1: - move sources list per-crtc - init sources-list only for gen3 Signed-off-by: Mahesh Kumar Cc: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 96 ++- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 3 ++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 6a29055a4ab0..bbe417e93fe3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -691,6 +691,79 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .atomic_disable = rcar_du_crtc_atomic_disable, }; +static void rcar_du_crtc_crc_sources_list_init(struct rcar_du_crtc *rcrtc) +{ + struct rcar_du_device *rcdu = rcrtc->group->dev; + struct drm_device *dev = rcrtc->crtc.dev; + struct drm_crtc *crtc = >crtc; + struct drm_plane *plane; + unsigned int count; + const char **sources; + u32 plane_mask; + int i = 0; i never takes negative values, it can be an unsigned int. + /* CRC available only on Gen3 HW */ Please capitalize sentences and end them with a period in comments to match the driver's style. This applies to other locations in this patch. + if (rcdu->info->gen < 3) + goto fail; You can just return here, sources_count and sources are initialized to 0 when the rcar_du_crtc structure is allocated. + drm_for_each_plane(plane, dev) { + if (drm_crtc_mask(crtc) & plane->possible_crtcs) { + count++; + plane_mask |= drm_plane_mask(plane); + } + } You can instead iterate over the planes of the associated VSP (hardware composer). /* Reserve 1 for "auto" source. */ count = rcrtc->vsp->num_planes + 1; and get rid of plane_mask. + /* reserve 1 for "auto" source */ + count += 1; + sources = kmalloc_array(count, sizeof(char *), GFP_KERNEL); s/sizeof(char *)/sizeof(*sources)/ + if (!sources) + goto fail; + + sources[i] = kstrdup("auto", GFP_KERNEL); + if (!sources[i]) + goto fail_no_mem; + + i++; + drm_for_each_plane_mask(plane, dev, plane_mask) { + char name[16]; + + sprintf(name, "plane%d", plane->base.id); The ID is an unsigned integer, you should use %u. + sources[i] = kstrdup(name, GFP_KERNEL); + if (!sources[i]) + goto fail_no_mem; As there will be a single error label, you can just name it "error". + i++; + } You can iterate over the VSP planes here too. for (i = 0; i < rcrtc->vsp->num_planes; ++i) { struct drm_plane *plane = >vsp->planes[i].plane; char name[16]; sprintf(name, "plane%u", plane->base.id); sources[i+1] = kstrdup(name, GFP_KERNEL); if (!sources[i+1]) goto error; } + rcrtc->sources = sources; + rcrtc->sources_count = count; + return; + +fail_no_mem: + while (i > 0) { + i--; + kfree(sources[i]); + } You'll have to adapt it based on the code above. + kfree(sources); +fail: + rcrtc->sources = NULL; + rcrtc->sources_count = 0; +} + +static void rcar_du_crtc_crc_sources_list_uninit(struct rcar_du_crtc *rcrtc) +{ + unsigned int i; + + if (!rcrtc->sources) + return; + + for (i = 0; i < rcrtc->sources_count; i++) + kfree(rcrtc->sources[i]); + kfree(rcrtc->sources); + + rcrtc->sources = NULL; + rcrtc->sources_count = 0; +} + static struct drm_crtc_state * rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { @@ -717,6 +790,15 @@ static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc, kfree(to_rcar_crtc_state(state)); } +static void rcar_du_crtc_cleanup(struct drm_crtc *crtc) +{ + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + + rcar_du_crtc_crc_sources_list_uninit(rcrtc); + + return drm_crtc_cleanup(crtc); +} + static void rcar_du_crtc_reset(struct drm_crtc *crtc) { struct rcar_du_crtc_state *state; @@ -811,6 +893,15 @@ static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc, return 0; } +const char *const *rcar_du_crtc_get_crc_sources(struct drm_crtc *crtc, + size_t *count) +{ + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + +
Re: [Intel-gfx] [PATCH 3/3] drm/i915: Implement 16GB dimm wa for latency level-0
Hi, On 7/18/2018 5:34 PM, Ville Syrjälä wrote: On Sat, Jul 14, 2018 at 07:40:43PM +0530, Kumar, Mahesh wrote: Hi, Thanks for review. On 7/13/2018 8:27 PM, Ville Syrjälä wrote: On Fri, Jul 13, 2018 at 07:41:24PM +0530, Mahesh Kumar wrote: Memory with 16GB dimms require an increase of 1us in level-0 latency. This patch implements the same. Bspec: 4381 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 35 +-- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 13 + 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b93194cbd820..c6d30653d70c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1063,6 +1063,29 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static void +intel_memdev_is_16gb_dimm(struct memdev_info *memdev_info, + u8 rank, u8 size, u8 width) +{ + bool found_16gb_dimm = false; + + if (size == 16 && width == SKL_DRAM_WIDTH_X8 && + rank == SKL_DRAM_RANK_SINGLE) + found_16gb_dimm = true; + else if (size == 32 && width == SKL_DRAM_WIDTH_X8 && +rank == SKL_DRAM_RANK_DUAL) + found_16gb_dimm = true; + else if (size == 8 && width == SKL_DRAM_WIDTH_X16 && +rank == SKL_DRAM_RANK_SINGLE) + found_16gb_dimm = true; + else if (size == 16 && width == SKL_DRAM_WIDTH_X16 && +rank == SKL_DRAM_RANK_DUAL) + found_16gb_dimm = true; + + if (!memdev_info->is_16gb_dimm) + memdev_info->is_16gb_dimm = found_16gb_dimm; +} Pure functions are generally more fun. Would also make the function name match the implementation. Are you suggesting to change the name to only "is_16gb_dimm" ? I'm suggesting making it pure. ok sure, got it. -Mahesh ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 0/3] Decode memdev info and bandwidth and implemnt latency WA
Hi, On 7/18/2018 5:33 PM, Ville Syrjälä wrote: On Sat, Jul 14, 2018 at 07:42:17PM +0530, Kumar, Mahesh wrote: On 7/13/2018 8:21 PM, Ville Syrjälä wrote: On Fri, Jul 13, 2018 at 07:41:21PM +0530, Mahesh Kumar wrote: This series adds support to calculate system memdev parameters and calculate What's "memdev"? memory device. Still not sure what that means. Makes me think of something akin to chardev or blockdev. I guess I'd just call it mem_info or something like that. It's in reality dram specification information, what about if we call it "dram_info"? If ok, will update all the occurrence to s/memdev_info/dram_info -Mahesh -Mahesh total system memory bandwidth. This parameters and BW will be used to enable WM level-0 latency workaround and display memory bandwidth related WA for gen9. Mahesh Kumar (3): drm/i915/bxt: Decode memory bandwidth and parameters drm/i915/skl+: Decode memory bandwidth and parameters drm/i915: Implement 16GB dimm wa for latency level-0 drivers/gpu/drm/i915/i915_drv.c | 261 drivers/gpu/drm/i915/i915_drv.h | 13 ++ drivers/gpu/drm/i915/i915_reg.h | 51 drivers/gpu/drm/i915/intel_pm.c | 13 ++ 4 files changed, 338 insertions(+) -- 2.16.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 00/10] Improve crc-core driver interface
Hi, thanks for the review. On 7/12/2018 4:38 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patches. When resubmitting patch series, could you please add a version number to the [PATCH] prefix ? Otherwise it gets difficult to figure out which version is the latest. This can be done automatically with the -v argument to git-format- patch. sure :), added patch prefix (now v4) and re-floated the series after addressing review comments in patches 03/10, 08/10 & 10/10. -Mahesh On Thursday, 12 July 2018 11:36:25 EEST Mahesh Kumar wrote: This series improves crc-core <-> driver interface. This series adds following functionality in the crc-core - Now control node will print all the available sources if implemented by driver along with current source. - Setting of sorce will fail if provided source is not supported - cleanup of crtc_crc_open function first allocate memory before enabling CRC generation - Don't block open() call instead wait in crc read call. Following IGT will fail due to crc-core <-> driver interface change igt@kms_pipe_crc_basic@bad-source ig@kms_pipe_crc_basic@nonblocking-crc-pipe-X ig@kms_pipe_crc_basic@nonblocking-crc-pipe-X-frame-sequence In nonblocking crc tests we'll get lesser crc's due to skipping crc AMD/Rockchip/rcar code path is not validated and need inputs Cc: dri-de...@lists.freedesktop.org Mahesh Kumar (10): drm: crc: Introduce verify_crc_source callback drm: crc: Introduce get_crc_sources callback drm/rockchip/crc: Implement verify_crc_source callback drm/amdgpu_dm/crc: Implement verify_crc_source callback drm/rcar-du/crc: Implement verify_crc_source callback drm/i915/crc: implement verify_crc_source callback drm/i915/crc: implement get_crc_sources callback drm/crc: Cleanup crtc_crc_open function Revert "drm: crc: Wait for a frame before returning from open()" drm/rcar-du/crc: Implement get_crc_sources callback drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 20 +++- drivers/gpu/drm/drm_debugfs_crc.c | 92 +--- drivers/gpu/drm/i915/intel_display.c | 2 + drivers/gpu/drm/i915/intel_drv.h | 9 +- drivers/gpu/drm/i915/intel_pipe_crc.c | 119 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 82 +++--- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 67 drivers/gpu/drm/rcar-du/rcar_du_kms.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 26 - include/drm/drm_crtc.h | 40 ++- 14 files changed, 396 insertions(+), 74 deletions(-) ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 0/3] Decode memdev info and bandwidth and implemnt latency WA
On 7/13/2018 8:21 PM, Ville Syrjälä wrote: On Fri, Jul 13, 2018 at 07:41:21PM +0530, Mahesh Kumar wrote: This series adds support to calculate system memdev parameters and calculate What's "memdev"? memory device. -Mahesh total system memory bandwidth. This parameters and BW will be used to enable WM level-0 latency workaround and display memory bandwidth related WA for gen9. Mahesh Kumar (3): drm/i915/bxt: Decode memory bandwidth and parameters drm/i915/skl+: Decode memory bandwidth and parameters drm/i915: Implement 16GB dimm wa for latency level-0 drivers/gpu/drm/i915/i915_drv.c | 261 drivers/gpu/drm/i915/i915_drv.h | 13 ++ drivers/gpu/drm/i915/i915_reg.h | 51 drivers/gpu/drm/i915/intel_pm.c | 13 ++ 4 files changed, 338 insertions(+) -- 2.16.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 3/3] drm/i915: Implement 16GB dimm wa for latency level-0
Hi, Thanks for review. On 7/13/2018 8:27 PM, Ville Syrjälä wrote: On Fri, Jul 13, 2018 at 07:41:24PM +0530, Mahesh Kumar wrote: Memory with 16GB dimms require an increase of 1us in level-0 latency. This patch implements the same. Bspec: 4381 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 35 +-- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 13 + 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b93194cbd820..c6d30653d70c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1063,6 +1063,29 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static void +intel_memdev_is_16gb_dimm(struct memdev_info *memdev_info, + u8 rank, u8 size, u8 width) +{ + bool found_16gb_dimm = false; + + if (size == 16 && width == SKL_DRAM_WIDTH_X8 && + rank == SKL_DRAM_RANK_SINGLE) + found_16gb_dimm = true; + else if (size == 32 && width == SKL_DRAM_WIDTH_X8 && +rank == SKL_DRAM_RANK_DUAL) + found_16gb_dimm = true; + else if (size == 8 && width == SKL_DRAM_WIDTH_X16 && +rank == SKL_DRAM_RANK_SINGLE) + found_16gb_dimm = true; + else if (size == 16 && width == SKL_DRAM_WIDTH_X16 && +rank == SKL_DRAM_RANK_DUAL) + found_16gb_dimm = true; + + if (!memdev_info->is_16gb_dimm) + memdev_info->is_16gb_dimm = found_16gb_dimm; +} Pure functions are generally more fun. Would also make the function name match the implementation. Are you suggesting to change the name to only "is_16gb_dimm" ? + static enum memdev_rank skl_memdev_get_channel_rank(struct memdev_info *memdev_info, u32 val) { @@ -1084,6 +1107,8 @@ skl_memdev_get_channel_rank(struct memdev_info *memdev_info, u32 val) if (l_size == 0 && s_size == 0) return I915_DRAM_RANK_INVALID; + memdev_info->valid_dimm = true; + DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n", l_size, (1 << l_width) * 8, l_rank ? "dual" : "single", s_size, (1 << s_width) * 8, s_rank ? "dual" : "single"); @@ -1096,6 +1121,9 @@ skl_memdev_get_channel_rank(struct memdev_info *memdev_info, u32 val) else rank = I915_DRAM_RANK_SINGLE; + intel_memdev_is_16gb_dimm(memdev_info, l_rank, l_size, l_width); + intel_memdev_is_16gb_dimm(memdev_info, s_rank, s_size, s_width); + return rank; } @@ -1247,6 +1275,7 @@ bxt_get_memdev_info(struct drm_i915_private *dev_priv) return -EINVAL; } + memdev_info->valid_dimm = true; memdev_info->valid = true; return 0; } @@ -1259,6 +1288,8 @@ intel_get_memdev_info(struct drm_i915_private *dev_priv) int ret; memdev_info->valid = false; + memdev_info->valid_dimm = false; + memdev_info->is_16gb_dimm = false; memdev_info->rank = I915_DRAM_RANK_INVALID; memdev_info->bandwidth_kbps = 0; memdev_info->num_channels = 0; @@ -1282,9 +1313,9 @@ intel_get_memdev_info(struct drm_i915_private *dev_priv) sprintf(bandwidth_str, "unknown"); DRM_DEBUG_KMS("DRAM bandwidth:%s, total-channels: %u\n", bandwidth_str, memdev_info->num_channels); - DRM_DEBUG_KMS("DRAM rank: %s rank\n", + DRM_DEBUG_KMS("DRAM rank: %s rank 16GB-dimm:%s\n", (memdev_info->rank == I915_DRAM_RANK_DUAL) ? - "dual" : "single"); + "dual" : "single", yesno(memdev_info->is_16gb_dimm)); } /** diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 845447d3806a..244adf8a30f1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1914,6 +1914,8 @@ struct drm_i915_private { struct memdev_info { bool valid; + bool valid_dimm; + bool is_16gb_dimm; u8 num_channels; enum memdev_rank { I915_DRAM_RANK_INVALID = 0, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 533e6886..f20f2f9118df 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2874,6 +2874,19 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, } } + /* +* WA Level-0 adjustment for 16GB DIMMs: SKL+ +* If we could not get dimm info enable this WA to prevent from +* any underrun. If not able to get Dimm info assume 16GB dimm +* to avoid any underrun. +*/ +
Re: [Intel-gfx] [PATCH 08/10] drm/crc: Cleanup crtc_crc_open function
Hi, Thanks for the review. On 7/10/2018 5:19 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patch. On Monday, 2 July 2018 14:07:27 EEST Mahesh Kumar wrote: This patch make changes to allocate crc-entries buffer before enabling CRC generation. It moves all the failure check early in the function before setting the source or memory allocation. Now set_crc_source takes only two variable inputs, values_cnt we already gets as part of verify_crc_source. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 4 +- drivers/gpu/drm/drm_debugfs_crc.c | 52 --- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_pipe_crc.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 6 +-- include/drm/drm_crtc.h | 3 +- 8 files changed, 30 insertions(+), 50 deletions(-) [snip] diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index f4d76528d24c..739a813b4b09 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -124,11 +124,9 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, if (source[len] == '\n') source[len] = '\0'; - if (crtc->funcs->verify_crc_source) { - ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); - if (ret) - return ret; - } + ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); + if (ret) + return ret; spin_lock_irq(>lock); @@ -193,12 +191,15 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) return ret; } - if (crtc->funcs->verify_crc_source) { - ret = crtc->funcs->verify_crc_source(crtc, crc->source, -_cnt); - if (ret) - return ret; - } + ret = crtc->funcs->verify_crc_source(crtc, crc->source, _cnt); + if (ret) + return ret; + + if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) + return -EINVAL; + + if (WARN_ON(values_cnt == 0)) + return -EINVAL; spin_lock_irq(>lock); if (!crc->opened) @@ -210,30 +211,22 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) if (ret) return ret; - ret = crtc->funcs->set_crc_source(crtc, crc->source, _cnt); - if (ret) - goto err; - - if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { - ret = -EINVAL; - goto err_disable; - } - - if (WARN_ON(values_cnt == 0)) { - ret = -EINVAL; - goto err_disable; - } - entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL); if (!entries) { ret = -ENOMEM; - goto err_disable; + goto err; } If you moved allocation before the !crc->opened check, you could group the two code blocks protected by the crc->lock. agree, will update in next version. -Mahesh spin_lock_irq(>lock); crc->entries = entries; crc->values_cnt = values_cnt; + spin_unlock_irq(>lock); + ret = crtc->funcs->set_crc_source(crtc, crc->source); + if (ret) + goto err; + + spin_lock_irq(>lock); /* * Only return once we got a first frame, so userspace doesn't have to * guess when this particular piece of HW will be ready to start @@ -250,7 +243,7 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) return 0; err_disable: - crtc->funcs->set_crc_source(crtc, NULL, _cnt); + crtc->funcs->set_crc_source(crtc, NULL); err: spin_lock_irq(>lock); crtc_crc_cleanup(crc); @@ -262,9 +255,8 @@ static int crtc_crc_release(struct inode *inode, struct file *filep) { struct drm_crtc *crtc = filep->f_inode->i_private; struct drm_crtc_crc *crc = >crc; - size_t values_cnt; - crtc->funcs->set_crc_source(crtc, NULL, _cnt); + crtc->funcs->set_crc_source(crtc, NULL); spin_lock_irq(>lock); crtc_crc_cleanup(crc); @@ -370,7 +362,7 @@ int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) { struct dentry *crc_ent, *ent; - if (!crtc->funcs->set_crc_source) + if (!crtc->funcs->set_crc_source || !crtc->funcs->verify_crc_source) return 0; crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry); [snip] ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 05/10] drm/rcar-du/crc: Implement verify_crc_source callback
Hi, thanks foe the review. On 7/10/2018 5:07 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patch. On Monday, 2 July 2018 14:07:24 EEST Mahesh Kumar wrote: This patch implements "verify_crc_source" callback function for rcar drm driver. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 40 +++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 15dc9caa128b..24eeaa7e14d7 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -756,6 +756,45 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc) rcrtc->vblank_enable = false; } +static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc, + const char *source_name, + size_t *values_cnt) +{ + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + unsigned int index = 0; + unsigned int i; + int ret; + + /* +* Parse the source name. Supported values are "plane%u" to compute the +* CRC on an input plane (%u is the plane ID), and "auto" to compute the +* CRC on the composer (VSP) output. +*/ + if (!source_name || !strcmp(source_name, "auto")) { + goto out; + } else if (strstarts(source_name, "plane")) { + ret = kstrtouint(source_name + strlen("plane"), 10, ); + if (ret < 0) + return ret; + + for (i = 0; i < rcrtc->vsp->num_planes; ++i) { + if (index == rcrtc->vsp->planes[i].plane.base.id) { + index = i; + break; + } + } + + if (i >= rcrtc->vsp->num_planes) + return -EINVAL; + } else { + return -EINVAL; + } + +out: + *values_cnt = 1; + return 0; This duplicates lots of code from the rcar_du_crtc_set_crc_source() function. Could you please extract it to a shared function ? Agree, it duplicates the code but "index" is needed by set_crc_source call anyway will create a wrapper to avoid duplication of code. Could you please also implement support for the .get_crc_sources() operation ? I think doing so might show limitations in the current API, namely the fact that the list will need to be dynamically created for this driver. for that I think rcar_du_crtc_create function can build a dynamic list during initializing crtc functions, unless plane can be dynamically allocated to any CRTC. this is the place where I need input from maintainer. -Mahesh +} + static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) @@ -861,6 +900,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { .enable_vblank = rcar_du_crtc_enable_vblank, .disable_vblank = rcar_du_crtc_disable_vblank, .set_crc_source = rcar_du_crtc_set_crc_source, + .verify_crc_source = rcar_du_crtc_verify_crc_source, }; /* ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 01/10] drm: crc: Introduce verify_crc_source callback
Hi, On 7/10/2018 5:40 PM, Laurent Pinchart wrote: Hi Mahesh, On Tuesday, 10 July 2018 14:54:11 EEST Kumar, Mahesh wrote: On 7/10/2018 4:56 PM, Laurent Pinchart wrote: On Monday, 2 July 2018 14:07:20 EEST Mahesh Kumar wrote: This patch adds a new callback function "verify_crc_source" which will be used during setting the crc source in control node and while opening data node for crc reading. This will help in avoiding setting of wrong string for source. Why do you need to verify the source in the open() operation ? Isn't it enough to verify it in the write() handler ? The answer to this question might lie in patch 08/10, in which case I'd add the .verify_crc_source() call in open() in that patch, not here. Yes, final goal is achieved by patch 08/10. But if crc_read is called before setting the source, it may have wrong source set in that case I wanted to return early at least for the drivers implemented verify_crc_source. If you still think otherwise I will modify accordingly in next series. I don't disagree with you, but I don't think this issue is new. As I got a bit confused as to why the call is needed in open() (there's no explanation in this patch), I think fixing the problem in 08/10 would be better. ok sure :) -Mahesh Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_debugfs_crc.c | 15 +++ include/drm/drm_crtc.h| 15 +++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 9f8312137cad..c6a725b79ac6 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -87,6 +87,8 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, struct drm_crtc *crtc = m->private; struct drm_crtc_crc *crc = >crc; char *source; + size_t values_cnt; + int ret = 0; if (len == 0) return 0; @@ -104,6 +106,12 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, if (source[len] == '\n') source[len] = '\0'; + if (crtc->funcs->verify_crc_source) { + ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); + if (ret) + return ret; + } + spin_lock_irq(>lock); if (crc->opened) { @@ -167,6 +175,13 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) return ret; } + if (crtc->funcs->verify_crc_source) { + ret = crtc->funcs->verify_crc_source(crtc, crc->source, +_cnt); + if (ret) + return ret; + } + spin_lock_irq(>lock); if (!crc->opened) crc->opened = true; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 23eddbccab10..1a6dcbf91744 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -661,6 +661,21 @@ struct drm_crtc_funcs { */ int (*set_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt); + /** +* @verify_crc_source: +* +* verifies the source of CRC checksums of frames before setting the +* source for CRC and during crc open. +* +* This callback is optional if the driver does not support any CRC +* generation functionality. +* +* RETURNS: +* +* 0 on success or a negative error code on failure. +*/ + int (*verify_crc_source)(struct drm_crtc *crtc, const char *source, +size_t *values_cnt); /** * @atomic_print_state: ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 02/10] drm: crc: Introduce get_crc_sources callback
Hi, On 7/10/2018 5:39 PM, Laurent Pinchart wrote: Hi Mahesh, On Tuesday, 10 July 2018 15:01:38 EEST Kumar, Mahesh wrote: On 7/10/2018 4:52 PM, Laurent Pinchart wrote: Hi Mahesh, On Monday, 2 July 2018 14:07:21 EEST Mahesh Kumar wrote: This patch introduce a callback function "get_crc_sources" which will be called during read of control node. It is an optional callback function and if driver implements this callback, driver should print list of available CRC sources in seq_file privided as an input to the callback. The commit message seems to be outdated, the callback doesn't take a seq_file anymore. ops, will update. Changes Since V1: (Daniel) - return const pointer to an array of crc sources list - do validation of sources in CRC-core Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_debugfs_crc.c | 20 +++- include/drm/drm_crtc.h| 16 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index c6a725b79ac6..f4d76528d24c 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -67,9 +67,27 @@ static int crc_control_show(struct seq_file *m, void *data) { struct drm_crtc *crtc = m->private; + size_t count; Count it only used within the if () {} block, you can declare it there. agree. + + if (crtc->funcs->get_crc_sources) { + const char *const *sources = crtc->funcs->get_crc_sources(crtc, + ); + size_t values_cnt; + int i; I only takes positive values, it can be an unsigned int. ok + + if (count <= 0 || !sources) count is a size_t, it can't be negative. The .get_crc_sources() documentation doesn't clearly specify whether sources should always be NULL when count is zero. I advise updating the documentation, and possibly updating this check accordingly. ok will update. + goto out; + + seq_puts(m, "["); + for (i = 0; i < count; i++) + if (!crtc->funcs->verify_crc_source(crtc, sources[i], + _cnt)) I assume that you verify sources one by one here to avoid having to create a list of sources dynamically in the .get_crc_sources() callback ? If so, I think the .get_crc_sources() callback should document that. You should also document that .verify_crc_source() is required when get_crc_sources() is provided. ok sure. + seq_printf(m, "%s ", sources[i]); + seq_puts(m, "] "); This assumes that source names can't include a space. Isn't that too restrictive ? Shouldn't a different separator be used ? How about one source name per line ? what about comma separated as I'm putting names inside square-brackets? Additionally, shouldn't the active source be marked ? active source is again printed by the code in next few lines. output will be of following format. [space separated list of valid sources] active_source I had missed that, my bad. The proposed format seems a bit hackish to me, in the sense that it forbids both spaces and brackets in source names. One source per line would fix both and be easy to parse. We would then need to mark the active source, which could be done by adding a marker to the corresponding line (maybe a * at the end of the line ?). sounds good, will do that. -Mahesh + } +out: seq_printf(m, "%s\n", crtc->crc.source); - return 0; } [snip] ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 02/10] drm: crc: Introduce get_crc_sources callback
Hi, thanks for the review. On 7/10/2018 4:52 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patch. On Monday, 2 July 2018 14:07:21 EEST Mahesh Kumar wrote: This patch introduce a callback function "get_crc_sources" which will be called during read of control node. It is an optional callback function and if driver implements this callback, driver should print list of available CRC sources in seq_file privided as an input to the callback. The commit message seems to be outdated, the callback doesn't take a seq_file anymore. ops, will update. Changes Since V1: (Daniel) - return const pointer to an array of crc sources list - do validation of sources in CRC-core Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_debugfs_crc.c | 20 +++- include/drm/drm_crtc.h| 16 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index c6a725b79ac6..f4d76528d24c 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -67,9 +67,27 @@ static int crc_control_show(struct seq_file *m, void *data) { struct drm_crtc *crtc = m->private; + size_t count; Count it only used within the if () {} block, you can declare it there. agree. + + if (crtc->funcs->get_crc_sources) { + const char *const *sources = crtc->funcs->get_crc_sources(crtc, + ); + size_t values_cnt; + int i; I only takes positive values, it can be an unsigned int. ok + + if (count <= 0 || !sources) count is a size_t, it can't be negative. The .get_crc_sources() documentation doesn't clearly specify whether sources should always be NULL when count is zero. I advise updating the documentation, and possibly updating this check accordingly. ok will update. + goto out; + + seq_puts(m, "["); + for (i = 0; i < count; i++) + if (!crtc->funcs->verify_crc_source(crtc, sources[i], + _cnt)) I assume that you verify sources one by one here to avoid having to create a list of sources dynamically in the .get_crc_sources() callback ? If so, I think the .get_crc_sources() callback should document that. You should also document that .verify_crc_source() is required when get_crc_sources() is provided. ok sure. + seq_printf(m, "%s ", sources[i]); + seq_puts(m, "] "); This assumes that source names can't include a space. Isn't that too restrictive ? Shouldn't a different separator be used ? How about one source name per line ? what about comma separated as I'm putting names inside square-brackets? Additionally, shouldn't the active source be marked ? active source is again printed by the code in next few lines. output will be of following format. [space separated list of valid sources] active_source -Mahesh + } +out: seq_printf(m, "%s\n", crtc->crc.source); - return 0; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1a6dcbf91744..ffaec138aeee 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -676,6 +676,22 @@ struct drm_crtc_funcs { */ int (*verify_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt); + /** +* @get_crc_sources: +* +* Driver callback for getting a list of all the available sources for +* CRC generation. +* +* This callback is optional if the driver does not support exporting of +* possible CRC sources list. CRC-core does the verification of sources. +* +* RETURNS: +* +* a constant character pointer to the list of all the available CRC +* sources +*/ + const char *const *(*get_crc_sources)(struct drm_crtc *crtc, + size_t *count); /** * @atomic_print_state: ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 01/10] drm: crc: Introduce verify_crc_source callback
Hi, Thanks for the review, On 7/10/2018 4:56 PM, Laurent Pinchart wrote: Hi Mahesh, Thank you for the patch. On Monday, 2 July 2018 14:07:20 EEST Mahesh Kumar wrote: This patch adds a new callback function "verify_crc_source" which will be used during setting the crc source in control node and while opening data node for crc reading. This will help in avoiding setting of wrong string for source. Why do you need to verify the source in the open() operation ? Isn't it enough to verify it in the write() handler ? The answer to this question might lie in patch 08/10, in which case I'd add the .verify_crc_source() call in open() in that patch, not here. Yes, final goal is achieved by patch 08/10. But if crc_read is called before setting the source, it may have wrong source set in that case I wanted to return early at least for the drivers implemented verify_crc_source. If you still think otherwise I will modify accordingly in next series. -Mahesh Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_debugfs_crc.c | 15 +++ include/drm/drm_crtc.h| 15 +++ 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 9f8312137cad..c6a725b79ac6 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -87,6 +87,8 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, struct drm_crtc *crtc = m->private; struct drm_crtc_crc *crc = >crc; char *source; + size_t values_cnt; + int ret = 0; if (len == 0) return 0; @@ -104,6 +106,12 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, if (source[len] == '\n') source[len] = '\0'; + if (crtc->funcs->verify_crc_source) { + ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); + if (ret) + return ret; + } + spin_lock_irq(>lock); if (crc->opened) { @@ -167,6 +175,13 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) return ret; } + if (crtc->funcs->verify_crc_source) { + ret = crtc->funcs->verify_crc_source(crtc, crc->source, +_cnt); + if (ret) + return ret; + } + spin_lock_irq(>lock); if (!crc->opened) crc->opened = true; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 23eddbccab10..1a6dcbf91744 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -661,6 +661,21 @@ struct drm_crtc_funcs { */ int (*set_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt); + /** +* @verify_crc_source: +* +* verifies the source of CRC checksums of frames before setting the +* source for CRC and during crc open. +* +* This callback is optional if the driver does not support any CRC +* generation functionality. +* +* RETURNS: +* +* 0 on success or a negative error code on failure. +*/ + int (*verify_crc_source)(struct drm_crtc *crtc, const char *source, +size_t *values_cnt); /** * @atomic_print_state: ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v2] drm/i915/skl+: ddb allocation algorithm optimization
Hi, On 7/3/2018 4:56 AM, Rodrigo Vivi wrote: On Fri, Jun 29, 2018 at 03:13:35PM +0530, Mahesh Kumar wrote: This patch implements new DDB allocation algorithm as per HW team recommendation. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each Usually "It also" in a commit message is a good indication that we should be doing more than one patch. Enabling same watermark level for each plane in CRTC is byproduct of this algorithm. But Agree will rework on patch and try to break it as much as possible. I think I should Add old cover letter as well to explain what is new algo optimization all about. plane in crtc, for efficient power saving. This algorithm uses fixed ddb allocation for cursor planes. Ealier version of this patch reverted due to regression. And it was root caused to following: New algorithm required more DDB for cursor plane but as cursor plane has fixed allocation it's DDB was not sufficient and WM level-0 was getting disabled, resulting in blank screen. Now we use old DDB allocation logic only for cursor plane. I really don't see on spec old and new DDB allocation logics. Actually now spec have 2 method for DDB allocation (Added based on our request). So new Algorithm is nothing but second method of allocation logic. Only thing different for cursor that I see there is that a workaround on watermark calculation where "For each plane, except cursor..." "Number of planes, except cursor..." This is not what I see in this patch, but maybe because the patch is too big. so for each plane we first calculate WM then try to find maximum level that can be enabled with available DDB for pipe and distribute DDB accordingly. but for cursor Now I'm allocating DDB first (8block or 32 blocks based on number of CRTC similar to old method) that is the difference from previous version of patch. Changes: - add reason for revert in commit msg (Maarten) - Fix checkpatch checks Testcase: igt/kms_plane_multiple Signed-off-by: Mahesh Kumar Cc: Rodrigo Vivi Well, since I'm on cc and I was the one that reverted that because I noticed on my own machine I opened this patch for review many times here already, but I gave up completely every time because this patch is hard to review. Agree, My bad, will try to split this patch but I'm afraid main patch still be lengthy please bare with me. So this time I won't fully give up and at least put some comments... So, overall it is hard to match the spec differences because this patch is trying to do all at once. Smaller patches should be better. --- drivers/gpu/drm/i915/i915_drv.h | 5 +- drivers/gpu/drm/i915/intel_pm.c | 376 +++- 2 files changed, 219 insertions(+), 162 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b684f431c60..f5d636a6d121 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1212,8 +1212,9 @@ struct skl_ddb_values { struct skl_wm_level { bool plane_en; - uint16_t plane_res_b; - uint8_t plane_res_l; + u16 plane_res_b; + u8 plane_res_l; + u16 min_dbuf_req; }; /* Stores plane specific WM parameters */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 533e6886..d1564a08a202 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3802,17 +3802,37 @@ static unsigned int intel_get_ddb_size(struct drm_i915_private *dev_priv, return ddb_size; } +static int +skl_get_num_pipes_active(struct drm_i915_private *dev_priv, +const struct intel_crtc_state *cstate) +{ + struct drm_atomic_state *state = cstate->base.state; + const struct intel_atomic_state *intel_state; + int num_active; + + if (WARN_ON(!state) || !cstate->base.active) + return hweight32(dev_priv->active_crtcs); + + intel_state = to_intel_atomic_state(state); + + if (intel_state->active_pipe_changes) + num_active = hweight32(intel_state->active_crtcs); + else + num_active = hweight32(dev_priv->active_crtcs); + + return num_active; +} This entire function here is something that should come in a separated patch. This is new change in this version. I should have created separate patch. will do so. + static void -skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, +skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, const struct intel_crtc_state *cstate, const unsigned int total_data_rate, struct skl_ddb_allocation *ddb, - struct skl_ddb_entry *alloc, /* out */ -
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_pipe_crc_basic: expect setting bad source to fail
Hi, On 7/2/2018 4:57 PM, Maarten Lankhorst wrote: Op 02-07-18 om 13:16 schreef Mahesh Kumar: Now crc-core framework verifies the source string passed by the user. So setting bad-source will fail. Expect file write to fail in bad-source subtest of kms_pipe_crc_basic. Signed-off-by: Mahesh Kumar --- tests/kms_pipe_crc_basic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c index 235fdc38..2d4dfee8 100644 --- a/tests/kms_pipe_crc_basic.c +++ b/tests/kms_pipe_crc_basic.c @@ -48,8 +48,7 @@ static struct { static void test_bad_source(data_t *data) { - igt_assert(igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")); - igt_assert(openat(data->debugfs, "crtc-0/crc/data", O_WRONLY) == -1); + igt_assert(!igt_sysfs_set(data->debugfs, "crtc-0/crc/control", "foo")); } #define N_CRCS 3 New behavior makes more sense. Reviewed-by: Maarten Lankhorst Do you have igt commit rights? thanks for review. I don't have commit rights -Mahesh ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 02/10] drm: crc: Introduce pre_crc_read function
Hi, On 6/27/2018 8:48 PM, Maarten Lankhorst wrote: Op 27-06-18 om 16:44 schreef Mahesh Kumar: This patch implements a callback function "pre_crc_read" which will be called before crc read. In this function driver can implement and preparation work required for successfully reading CRC data. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/drm_debugfs_crc.c | 8 include/drm/drm_crtc.h| 14 ++ 2 files changed, 22 insertions(+) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index c6a725b79ac6..2b4a737c5aeb 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -278,6 +278,14 @@ static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf, return 0; } + if (crtc->funcs->pre_crc_read) { + ret = crtc->funcs->pre_crc_read(crtc); + if (ret) { + spin_unlock_irq(>lock); + return ret; + } + } + /* Nothing to read? */ while (crtc_crc_data_count(crc) == 0) { if (filep->f_flags & O_NONBLOCK) { diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1a6dcbf91744..bae432469616 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -676,6 +676,20 @@ struct drm_crtc_funcs { */ int (*verify_crc_source)(struct drm_crtc *crtc, const char *source, size_t *values_cnt); + /** +* @pre_crc_read: +* +* Driver callback for performing any preparation work required by +* driver before reading CRC +* +* This callback is optional if the driver does not support CRC +* generation or no prework is required before reading the crc +* +* RETURNS: +* +* 0 on success or a negative error code on failure. +*/ + int (*pre_crc_read)(struct drm_crtc *crtc); /** * @atomic_print_state: I think this patch might have to be dropped, or reordered after the revert in 10/10, because else in theory open could block. :) Or maybe just drop until we have upstream kernel users? thanks, Can reorder it after patch-10 and if others also vote to drop it will take decision accordingly, atleast it should not block other patches :) -Mahesh ~Maarten ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 04/10] drm/rockchip/crc: Implement verify_crc_source callback
Hi, On 6/27/2018 5:30 PM, Jani Nikula wrote: On Tue, 26 Jun 2018, Mahesh Kumar wrote: This patch implements "verify_crc_source" callback function for rockchip drm driver. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c9222119767d..ea4884ac4cb0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1138,12 +1138,32 @@ static int vop_crtc_set_crc_source(struct drm_crtc *crtc, return ret; } + +static int +vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, + size_t *values_cnt) +{ + if ((source_name && strcmp(source_name, "auto") == 0) || !source_name) { Drive-by review: IOW, if (!source_name || strcmp(source_name, "auto") == 0) Better yet, reverse the logic, if (source_name && strcmp(source_name, "auto") != 0) return -EINVAL; *values_cnt = 3; return 0; thanks for review, Will reverse the logic as suggested. -Mahesh BR, Jani. + *values_cnt = 3; + return 0; + } + + return -EINVAL; +} + #else static int vop_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) { return -ENODEV; } + +static int +vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, + size_t *values_cnt) +{ + return -ENODEV; +} #endif static const struct drm_crtc_funcs vop_crtc_funcs = { @@ -1156,6 +1176,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = { .enable_vblank = vop_crtc_enable_vblank, .disable_vblank = vop_crtc_disable_vblank, .set_crc_source = vop_crtc_set_crc_source, + .verify_crc_source = vop_crtc_verify_crc_source, }; static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 08/10] drm/i915/crc: implement get_crc_sources callback
Hi, thanks for review. On 6/26/2018 1:59 PM, Daniel Vetter wrote: On Tue, Jun 26, 2018 at 11:52:57AM +0530, Mahesh Kumar wrote: This patch implements get_crc_sources callback, which returns list of all the valid crc sources supported by driver in current platform. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pipe_crc.c | 12 3 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c0eb752b0901..93b4be2eee32 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12894,6 +12894,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .atomic_destroy_state = intel_crtc_destroy_state, .set_crc_source = intel_crtc_set_crc_source, .verify_crc_source = intel_crtc_verify_crc_source, + .get_crc_sources = intel_crtc_get_crc_sources, }; struct wait_rps_boost { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 64e13adad9f5..17735cafdd72 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -2156,11 +2156,13 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt); int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt); +void intel_crtc_get_crc_sources(struct seq_file *m, struct drm_crtc *crtc); void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc); void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc); #else #define intel_crtc_set_crc_source NULL #define intel_crtc_verify_crc_source NULL +#define intel_crtc_get_crc_sources NULL static inline void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) { } diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index a37521380f94..d6807155a237 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -1001,6 +1001,18 @@ intel_is_valid_crc_source(struct drm_i915_private *dev_priv, return ivb_crc_source_valid(dev_priv, source); } +void intel_crtc_get_crc_sources(struct seq_file *m, struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + enum intel_pipe_crc_source source; + + seq_puts(m, "["); + for (source = 0; source < INTEL_PIPE_CRC_SOURCE_MAX; source++) + if (intel_is_valid_crc_source(dev_priv, source) == 0) + seq_printf(m, "%s,", pipe_crc_source_name(source)); + seq_puts(m, "auto] "); This seems to be a very quirky interface ... Can't you instead return a real array, and then also push validation into the core? Same we do with e.g. the per-plane drm_fourcc format support. Something like an array of const char * pointers should be good. sounds good, will make the changes and return constant pointer to an array. Will also push validation to the crc-core -Mahesh -Daniel +} + int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) { -- 2.16.2 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 09/10] drm/crc: Cleanup crtc_crc_open function
Cc: Laurent Pinchart On 6/26/2018 11:52 AM, Mahesh Kumar wrote: This patch make changes to allocate crc-entries buffer before enabling CRC generation. It moves all the failure check early in the function before setting the source or memory allocation. Now set_crc_source takes only two variable input, values_cnt we already gets as part of verify_crc_source. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 4 +- drivers/gpu/drm/drm_debugfs_crc.c | 52 +- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/i915/intel_pipe_crc.c | 4 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 5 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 6 +-- include/drm/drm_crtc.h | 3 +- 8 files changed, 30 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 79b0a16652b9..a7a5551fee1b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -261,8 +261,7 @@ amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector); /* amdgpu_dm_crc.c */ #ifdef CONFIG_DEBUG_FS -int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name, - size_t *values_cnt); +int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name); int amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name, size_t *values_cnt); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index dfcca594d52a..e7ad528f5853 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -62,8 +62,7 @@ amdgpu_dm_crtc_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } -int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name, - size_t *values_cnt) +int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) { struct dm_crtc_state *crtc_state = to_dm_crtc_state(crtc->state); struct dc_stream_state *stream_state = crtc_state->stream; @@ -99,7 +98,6 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name, return -EINVAL; } - *values_cnt = 3; /* Reset crc_skipped on dm state */ crtc_state->crc_skip_count = 0; return 0; diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 2751d124387d..834bc7ee5550 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -109,11 +109,9 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, if (source[len] == '\n') source[len] = '\0'; - if (crtc->funcs->verify_crc_source) { - ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); - if (ret) - return ret; - } + ret = crtc->funcs->verify_crc_source(crtc, source, _cnt); + if (ret) + return ret; spin_lock_irq(>lock); @@ -178,12 +176,15 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) return ret; } - if (crtc->funcs->verify_crc_source) { - ret = crtc->funcs->verify_crc_source(crtc, crc->source, -_cnt); - if (ret) - return ret; - } + ret = crtc->funcs->verify_crc_source(crtc, crc->source, _cnt); + if (ret) + return ret; + + if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) + return -EINVAL; + + if (WARN_ON(values_cnt == 0)) + return -EINVAL; spin_lock_irq(>lock); if (!crc->opened) @@ -195,30 +196,22 @@ static int crtc_crc_open(struct inode *inode, struct file *filep) if (ret) return ret; - ret = crtc->funcs->set_crc_source(crtc, crc->source, _cnt); - if (ret) - goto err; - - if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) { - ret = -EINVAL; - goto err_disable; - } - - if (WARN_ON(values_cnt == 0)) { - ret = -EINVAL; - goto err_disable; - } - entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL); if (!entries) { ret = -ENOMEM; - goto err_disable; + goto err; } spin_lock_irq(>lock); crc->entries
Re: [Intel-gfx] [PATCH 06/10] drm/rcar-du/crc: Implement verify_crc_source callback
Cc: Laurent Pinchart On 6/26/2018 11:52 AM, Mahesh Kumar wrote: This patch implements "verify_crc_source" callback function for rcar drm driver. Signed-off-by: Mahesh Kumar Cc: dri-de...@lists.freedesktop.org --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 40 ++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 15dc9caa128b..24eeaa7e14d7 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -756,6 +756,45 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc) rcrtc->vblank_enable = false; } +static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc, + const char *source_name, + size_t *values_cnt) +{ + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + unsigned int index = 0; + unsigned int i; + int ret; + + /* +* Parse the source name. Supported values are "plane%u" to compute the +* CRC on an input plane (%u is the plane ID), and "auto" to compute the +* CRC on the composer (VSP) output. +*/ + if (!source_name || !strcmp(source_name, "auto")) { + goto out; + } else if (strstarts(source_name, "plane")) { + ret = kstrtouint(source_name + strlen("plane"), 10, ); + if (ret < 0) + return ret; + + for (i = 0; i < rcrtc->vsp->num_planes; ++i) { + if (index == rcrtc->vsp->planes[i].plane.base.id) { + index = i; + break; + } + } + + if (i >= rcrtc->vsp->num_planes) + return -EINVAL; + } else { + return -EINVAL; + } + +out: + *values_cnt = 1; + return 0; +} + static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt) @@ -861,6 +900,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { .enable_vblank = rcar_du_crtc_enable_vblank, .disable_vblank = rcar_du_crtc_disable_vblank, .set_crc_source = rcar_du_crtc_set_crc_source, + .verify_crc_source = rcar_du_crtc_verify_crc_source, }; /* - ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 00/10] Improve crc-core driver interface
Cc:dri-de...@lists.freedesktop.org On 6/26/2018 11:52 AM, Mahesh Kumar wrote: This series improves crc-core <-> driver interface. This series adds following functionality in the crc-core - Now control node will print all the available sources if implemented by driver along with current source. - Setting of sorce will fail if provided source is not supported - cleanup of crtc_crc_open function first allocate memory before enabling CRC generation - Don't block open() call instead wait in crc read call. Following IGT will fail due to crc-core <-> driver interface change igt@kms_pipe_crc_basic@bad-source ig@kms_pipe_crc_basic@nonblocking-crc-pipe-X ig@kms_pipe_crc_basic@nonblocking-crc-pipe-X-frame-sequence In nonblocking crc tests we'll get lesser crc's due to skipping crc AMD/Rockchip/rcar code path is not validated and need inputs Changes: - Add dri-devel in Cc Mahesh Kumar (10): drm: crc: Introduce verify_crc_source callback drm: crc: Introduce pre_crc_read function drm: crc: Introduce get_crc_sources callback drm/rockchip/crc: Implement verify_crc_source callback drm/amdgpu_dm/crc: Implement verify_crc_source callback drm/rcar-du/crc: Implement verify_crc_source callback drm/i915/crc: implement verify_crc_source callback drm/i915/crc: implement get_crc_sources callback drm/crc: Cleanup crtc_crc_open function Revert "drm: crc: Wait for a frame before returning from open()" drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 20 +++- drivers/gpu/drm/drm_debugfs_crc.c | 62 ++- drivers/gpu/drm/i915/intel_display.c | 2 + drivers/gpu/drm/i915/intel_drv.h | 8 +- drivers/gpu/drm/i915/intel_pipe_crc.c | 124 - drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 45 +++- drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 27 - include/drm/drm_crtc.h | 42 ++- 10 files changed, 288 insertions(+), 50 deletions(-) ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/skl+: ddb allocation algorithm optimization
On 5/22/2018 1:27 PM, Maarten Lankhorst wrote: Hey, Op 21-05-18 om 13:36 schreef Mahesh Kumar: From: "Kumar, Mahesh" <mahesh1.ku...@intel.com> This patch implements new DDB allocation algorithm as per HW team recommendation. This algo takecare of scenario where we allocate less DDB takes care* for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane in crtc, for efficient power saving. This algorithm uses fix ddb allocation for cursor planes. fixed* Because this is a resubmit for a commit that has been reverted, the commit message should at least point out what the regression was, and what has been done to fix it. :) Thanks for review. agree, will add commit msg in next version of patch. Just to summarize, Regression was due to the Cursor-Plane WM for level-0 getting disabled even if cursor plane was enabled. With New algorithm WM requirement for cursor plane was more & this was resulting "8 blocks" not being sufficient. To solve above issue, earlier I proposed dynamic DDB allocation for cursor plane. There was no issue till now for cursor plane with fixed 8/32 block allocation, So later decided to use old approach of WM calculation *only* for cursor plane (first allocate DDB & later decide/calculate WM). -Mahesh I've added Rodrigo to cc, since he reverted the original commit. Signed-off-by: Mahesh Kumar <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 326 ++-- 2 files changed, 184 insertions(+), 143 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e33c380b43e3..5fc8fb67d5d1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1202,6 +1202,7 @@ struct skl_wm_level { bool plane_en; uint16_t plane_res_b; uint8_t plane_res_l; + uint16_t min_dbuf_req; }; /* Stores plane specific WM parameters */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b85229e153c4..32665c7fcb2b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4271,13 +4271,58 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); } +static void +skl_enable_plane_wm_levels(const struct drm_i915_private *dev_priv, + u16 plane_ddb, + u16 max_level, + struct skl_plane_wm *wm) +{ + int level; + /* +* Now enable all levels in WM structure which can be enabled +* using current DDB allocation +*/ + for (level = ilk_wm_max_level(dev_priv); level >= 0; level--) { + struct skl_wm_level *level_wm = >wm[level]; + + if (level > max_level || level_wm->min_dbuf_req > plane_ddb + || (level && level_wm->plane_res_l >= 31) + || level_wm->plane_res_b == 0) { + level_wm->plane_en = false; + level_wm->plane_res_b = 0; + level_wm->plane_res_l = 0; + } else { + level_wm->plane_en = true; + } + + /* +* Display WA #826 (SKL:ALL, BXT:ALL) & #1059 (CNL:A) +* disable wm level 1-7 on NV12 planes +*/ + if (wm->is_planar && level >= 1 && + (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || +IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0))) { + level_wm->plane_en = false; + level_wm->plane_res_b = 0; + level_wm->plane_res_l = 0; + } + } + + if (wm->trans_wm.plane_res_b && wm->trans_wm.plane_res_b < plane_ddb) + wm->trans_wm.plane_en = true; + else + wm->trans_wm.plane_en = false; +} + static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; struct drm_crtc *crtc = cstate->base.crtc; struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = >wm.skl.ddb; @@ -4290,6 +4335,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, unsigned int plane_data_rate[I915_MAX_PLANES] = {};
Re: [Intel-gfx] [PATCH 03/24] drm/i915/icl: introduce tc_port
Reviewed-by: Mahesh KumarOn 5/22/2018 5:55 AM, Paulo Zanoni wrote: Add and enum for TC ports and auxiliary functions to handle them. Icelake brings a lot of registers and other things that only apply to the TC ports and are indexed starting from 0, so having an enum for tc_ports that starts at 0 really helps the indexing. This patch is based on previous patches written by Dhinakaran Pandiyan and Mahesh Kumar. Cc: Dhinakaran Pandiyan Cc: Mahesh Kumar Signed-off-by: Paulo Zanoni --- drivers/gpu/drm/i915/intel_display.c | 16 drivers/gpu/drm/i915/intel_display.h | 11 +++ drivers/gpu/drm/i915/intel_drv.h | 3 +++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c9ec88acad9c..64593b0fbebd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5807,6 +5807,22 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } +bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port) +{ + if (IS_ICELAKE(dev_priv)) + return port >= PORT_C && port <= PORT_F; + + return false; +} + +enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port) +{ + if (!intel_port_is_tc(dev_priv, port)) + return PORT_TC_NONE; + + return port - PORT_C; +} + enum intel_display_power_domain intel_port_to_power_domain(enum port port) { switch (port) { diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h index 2ef31617614a..c88185ed7594 100644 --- a/drivers/gpu/drm/i915/intel_display.h +++ b/drivers/gpu/drm/i915/intel_display.h @@ -126,6 +126,17 @@ enum port { #define port_name(p) ((p) + 'A') +enum tc_port { + PORT_TC_NONE = -1, + + PORT_TC1 = 0, + PORT_TC2, + PORT_TC3, + PORT_TC4, + + I915_MAX_TC_PORTS +}; + enum dpio_channel { DPIO_CH0, DPIO_CH1 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 22af249393a4..a54232c270e1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1493,6 +1493,9 @@ void intel_connector_attach_encoder(struct intel_connector *connector, struct intel_encoder *encoder); struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder); +bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port); +enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, + enum port port); enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] ✗ Fi.CI.BAT: failure for Optimize use of DBuf slices (rev2)
Hi, On 4/26/2018 3:24 AM, Rodrigo Vivi wrote: On Wed, Apr 25, 2018 at 09:46:23PM -, Patchwork wrote: == Series Details == Series: Optimize use of DBuf slices (rev2) URL : https://patchwork.freedesktop.org/series/41180/ State : failure == Summary == Applying: drm/i915/icl: track dbuf slice-2 status error: Failed to merge in the changes. Using index info to reconstruct a base tree... M drivers/gpu/drm/i915/i915_drv.h M drivers/gpu/drm/i915/intel_display.c M drivers/gpu/drm/i915/intel_pm.c M drivers/gpu/drm/i915/intel_runtime_pm.c Falling back to patching base and 3-way merge... Auto-merging drivers/gpu/drm/i915/intel_runtime_pm.c Auto-merging drivers/gpu/drm/i915/intel_pm.c Auto-merging drivers/gpu/drm/i915/intel_display.c Auto-merging drivers/gpu/drm/i915/i915_drv.h CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_drv.h Patch failed at 0001 drm/i915/icl: track dbuf slice-2 status The copy of the patch that failed is found in: .git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". Mahesh, I'm really sorry for taking so long to review these patches Could you please send a rebased version so after CI giving the okay we push it. Thanks for review, Will resend the series after rebase. Regards, -Mahesh Thanks in advance, Rodrigo. == Logs == For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8588/issues.html ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH 1/3] drm/i915/icl: track dbuf slice-2 status
Hi, On 4/5/2018 1:55 PM, Jani Nikula wrote: On Thu, 05 Apr 2018, Mahesh Kumarwrote: This patch adds support to start tracking status of DBUF slices. This is foundation to introduce support for enabling/disabling second DBUF slice dynamically for ICL. Signed-off-by: Mahesh Kumar Reviewed-by: James Ausmus --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c| 5 + drivers/gpu/drm/i915/intel_pm.c | 20 drivers/gpu/drm/i915/intel_runtime_pm.c | 4 4 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5373b171bb96..e51da42297d8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1184,6 +1184,7 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, struct skl_ddb_allocation { struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; + uint8_t enabled_slices; /* GEN11 has configurable 2 slices */ Please prefer kernel types u8/u16/u32/u64 over uint8_t and friends. It's fine to use the stdint types when the context uses them, but please let's not add new ones. ok, sure will update in new version -Mahesh BR, Jani. }; struct skl_wm_values { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 415fb8cf2cf4..96a1e6a7f69e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11385,6 +11385,11 @@ static void verify_wm_state(struct drm_crtc *crtc, skl_ddb_get_hw_state(dev_priv, _ddb); sw_ddb = _priv->wm.skl_hw.ddb; + if (INTEL_GEN(dev_priv) >= 11) + if (hw_ddb.enabled_slices != sw_ddb->enabled_slices) + DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n", + sw_ddb->enabled_slices, + hw_ddb.enabled_slices); /* planes */ for_each_universal_plane(dev_priv, pipe, plane) { hw_plane_wm = _wm.planes[plane]; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 19e82aaa9863..3ff37d5ba353 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3567,6 +3567,23 @@ bool ilk_disable_lp_wm(struct drm_device *dev) return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); } +static uint8_t intel_enabled_dbuf_slices_num(struct drm_i915_private *dev_priv) +{ + uint8_t enabled_slices; + + /* Slice 1 will always be enabled */ + enabled_slices = 1; + + /* Gen prior to GEN11 have only one DBuf slice */ + if (INTEL_GEN(dev_priv) < 11) + return enabled_slices; + + if (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE) + enabled_slices++; + + return enabled_slices; +} + /* * FIXME: We still don't have the proper code detect if we need to apply the WA, * so assume we'll always need it in order to avoid underruns. @@ -3832,6 +3849,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, memset(ddb, 0, sizeof(*ddb)); + ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv); + for_each_intel_crtc(_priv->drm, crtc) { enum intel_display_power_domain power_domain; enum plane_id plane_id; @@ -5050,6 +5069,7 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, sizeof(dst->ddb.y_plane[pipe])); memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], sizeof(dst->ddb.plane[pipe])); + dst->ddb.enabled_slices = src->ddb.enabled_slices; } static void diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 53ea564f971e..58be542d660b 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2664,6 +2664,8 @@ static void icl_dbuf_enable(struct drm_i915_private *dev_priv) if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) DRM_ERROR("DBuf power enable timeout\n"); + else + dev_priv->wm.skl_hw.ddb.enabled_slices = 2; } static void icl_dbuf_disable(struct drm_i915_private *dev_priv) @@ -2677,6 +2679,8 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv) if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) DRM_ERROR("DBuf power disable timeout!\n"); + else + dev_priv->wm.skl_hw.ddb.enabled_slices = 0; } static void icl_mbus_init(struct drm_i915_private *dev_priv) ___ Intel-gfx mailing list
Re: [Intel-gfx] [PATCH 1/3] drm/i915/cnl; Add macro to get PORT_TX register
Hi, On 3/10/2018 2:21 AM, Lucas De Marchi wrote: On Fri, Mar 09, 2018 at 11:55:47AM -0800, Rodrigo Vivi wrote: On Fri, Mar 09, 2018 at 06:28:56PM +0530, Mahesh Kumar wrote: This patch creates a new macro to get PORT_TX register for any given DW. This will remove the need of defining register address for each port & DW. please squash patches 1 and 2. I had to open both simultaneously to review it what indicates that they should be 1 patch. ok, will merge. Signed-off-by: Mahesh Kumar--- drivers/gpu/drm/i915/i915_reg.h | 28 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e6a8c0ee7df1..30ef3513dc6f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1964,6 +1964,34 @@ enum i915_power_well_id { _CNL_PORT_PCS_DW1_LN0_F) #define COMMON_KEEPER_EN(1 << 26) +/* CNL Port TX registers */ +#define _CNL_PORT_TX_AE_GRP_OFFSET 0x162340 +#define _CNL_PORT_TX_B_GRP_OFFSET 0x1623C0 +#define _CNL_PORT_TX_C_GRP_OFFSET 0x162B40 +#define _CNL_PORT_TX_D_GRP_OFFSET 0x162BC0 +#define _CNL_PORT_TX_F_GRP_OFFSET 0x162A40 +#define _CNL_PORT_TX_AE_LN0_OFFSET 0x162440 +#define _CNL_PORT_TX_B_LN0_OFFSET 0x162640 +#define _CNL_PORT_TX_C_LN0_OFFSET 0x162C40 +#define _CNL_PORT_TX_D_LN0_OFFSET 0x162E40 +#define _CNL_PORT_TX_F_LN0_OFFSET 0x162840 +#define CNL_PORT_TX_DW_GRP(port, dw) (_PICK((port), \ + _CNL_PORT_TX_AE_GRP_OFFSET, \ + _CNL_PORT_TX_B_GRP_OFFSET, \ + _CNL_PORT_TX_B_GRP_OFFSET, \ + _CNL_PORT_TX_D_GRP_OFFSET, \ + _CNL_PORT_TX_AE_GRP_OFFSET, \ + _CNL_PORT_TX_F_GRP_OFFSET) + \ + 4*(dw)) the math is right. I'm glad someone could see some logic on all these numbers. I with we had a basic offset and math for all the port registers, but... +#define CNL_PORT_TX_DW_LN0(port, dw) (_PICK((port), \ who converts the offset to MMIO reg now? caller of this macro converts it to MMIO reg I don't think this is supposed to be used outside the header is it? I think it should have a underscore, because otherwise it's confusing that CNL_PORT_TX_DW_LN0 returns an offsed and CNL_PORT_TX_DW[0-5]_LN0 return an mmio reg. hmm, agree, will add underscore to the macros. And if it's used elsewhere, maybe append _OFFSET to the macro? this isn't intended to be used outside of header file. -Mahesh Lucas De Marchi + _CNL_PORT_TX_AE_LN0_OFFSET, \ + _CNL_PORT_TX_B_LN0_OFFSET, \ + _CNL_PORT_TX_B_LN0_OFFSET, \ + _CNL_PORT_TX_D_LN0_OFFSET, \ + _CNL_PORT_TX_AE_LN0_OFFSET, \ + _CNL_PORT_TX_F_LN0_OFFSET) + \ + 4*(dw)) + #define _CNL_PORT_TX_DW2_GRP_AE 0x162348 #define _CNL_PORT_TX_DW2_GRP_B0x1623C8 #define _CNL_PORT_TX_DW2_GRP_C0x162B48 -- 2.14.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH v3] drm/i915/icl: remove port A/E lane sharing limitation.
Please review. thanks, -Mahesh On 2/6/2018 11:38 AM, Mahesh Kumar wrote: Platforms before Gen11 were sharing lanes between port-A & port-E. This limitation is no more there. Changes since V1: - optimize the code (Shashank/Jani) - create helper function to get max lanes (ville) Changes since V2: - Include BIOS fail fix-up in same helper function (ville) Changes since V3: - remove confusing if/else (jani) - group intel_encoder initialization Signed-off-by: Mahesh Kumar--- drivers/gpu/drm/i915/intel_ddi.c | 85 ++-- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cfcd9cb37d5d..60fe2ba4b29c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2842,39 +2842,45 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) return false; } +static int +intel_ddi_max_lanes(struct intel_digital_port *intel_dport) +{ + struct drm_i915_private *dev_priv = to_i915(intel_dport->base.base.dev); + enum port port = intel_dport->base.port; + int max_lanes = 4; + + if (INTEL_GEN(dev_priv) >= 11) + return max_lanes; + + if (port == PORT_A || port == PORT_E) { + if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) + max_lanes = port == PORT_A ? 4 : 0; + else + /* Both A and E share 2 lanes */ + max_lanes = 2; + } + + /* +* Some BIOS might fail to set this bit on port A if eDP +* wasn't lit up at boot. Force this bit set when needed +* so we use the proper lane count for our calculations. +*/ + if (intel_ddi_a_force_4_lanes(intel_dport)) { + DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); + intel_dport->saved_port_bits |= DDI_A_4_LANES; + max_lanes = 4; + } + + return max_lanes; +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; struct drm_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; - int max_lanes; - if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { - switch (port) { - case PORT_A: - max_lanes = 4; - break; - case PORT_E: - max_lanes = 0; - break; - default: - max_lanes = 4; - break; - } - } else { - switch (port) { - case PORT_A: - max_lanes = 2; - break; - case PORT_E: - max_lanes = 2; - break; - default: - max_lanes = 4; - break; - } - } init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || dev_priv->vbt.ddi_port_info[port].supports_hdmi); @@ -2920,10 +2926,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->get_config = intel_ddi_get_config; intel_encoder->suspend = intel_dp_encoder_suspend; intel_encoder->get_power_domains = intel_ddi_get_power_domains; + intel_encoder->type = INTEL_OUTPUT_DDI; + intel_encoder->power_domain = intel_port_to_power_domain(port); + intel_encoder->port = port; + intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); + intel_encoder->cloneable = 0; intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + intel_dig_port->dp.output_reg = INVALID_MMIO_REG; + intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port); switch (port) { case PORT_A: @@ -2954,26 +2967,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) MISSING_CASE(port); } - /* -* Some BIOS might fail to set this bit on port A if eDP -* wasn't lit up at boot. Force this bit set when needed -* so we use the proper lane count for our calculations. -*/ - if (intel_ddi_a_force_4_lanes(intel_dig_port)) { - DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); - intel_dig_port->saved_port_bits |= DDI_A_4_LANES; - max_lanes = 4; - } - - intel_dig_port->dp.output_reg = INVALID_MMIO_REG; - intel_dig_port->max_lanes = max_lanes; - - intel_encoder->type = INTEL_OUTPUT_DDI; - intel_encoder->power_domain =
Re: [Intel-gfx] [PATCH 05/16] drm/i915/skl+: NV12 related changes for WM
Hi, On 2/7/2018 10:12 PM, Sharma, Shashank wrote: Regards Shashank On 2/6/2018 6:28 PM, Vidya Srinivas wrote: From: Mahesh KumarNV12 requires WM calculation for UV plane as well. UV plane WM should also fulfill all the WM related restrictions. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 54 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cca5414..778dc5a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1459,6 +1459,7 @@ struct skl_wm_level { struct skl_wm_params { bool x_tiled, y_tiled; bool rc_surface; + bool is_nv12; uint32_t width; uint8_t cpp; uint32_t plane_pixel_rate; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ed33840..65dac21 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -594,6 +594,7 @@ struct intel_pipe_wm { struct skl_plane_wm { struct skl_wm_level wm[8]; + struct skl_wm_level uv_wm[8]; struct skl_wm_level trans_wm; bool is_nv12; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4c9a811..b3d1bf7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4421,7 +4421,7 @@ static int skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, - struct skl_wm_params *wp) + struct skl_wm_params *wp, int plane_num) Is this plane_num intended for 'no of planes' or 'plane number' ? from the usage below looks like 'no of planes' but I could be wrong. it's plane-number. { struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); const struct drm_plane_state *pstate = _pstate->base; @@ -4434,6 +4434,12 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, if (!intel_wm_plane_visible(cstate, intel_pstate)) return 0; + /* only NV12 format has two planes */ + if (plane_num == 1 && fb->format->format != DRM_FORMAT_NV12) { + DRM_DEBUG_KMS("Non NV12 format have single plane\n"); + return -EINVAL; + } The comment says only NV12 format can have two planes, but if format != NV12 && plane_num == 1, why is this an error ? Also the debug message says "Non NV12 format have single plane". Shouldn't it ? Looks like you are expecting plane_number = 0, 1 for NV12 planes, and when plane_num is non-zero, you expect it to be NV12 only ? yes, non-planar formats will have single plane, that's why if format != NV12 & plane_num == 1 it's an error. + wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || fb->modifier == I915_FORMAT_MOD_Yf_TILED || fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || @@ -4441,6 +4447,7 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; + wp->is_nv12 = fb->format->format == DRM_FORMAT_NV12; if (plane->id == PLANE_CURSOR) { wp->width = intel_pstate->base.crtc_w; @@ -4453,7 +4460,10 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, wp->width = drm_rect_width(_pstate->base.src) >> 16; } - wp->cpp = fb->format->cpp[0]; + if (plane_num == 1 && wp->is_nv12) + wp->width /= 2; + + wp->cpp = fb->format->cpp[plane_num]; wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); @@ -4649,7 +4659,8 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, const struct skl_wm_params *wm_params, - struct skl_plane_wm *wm) + struct skl_plane_wm *wm, + int plane_num) Same question here { struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); struct drm_plane *plane = intel_pstate->base.plane; @@ -4657,15 +4668,20 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, uint16_t ddb_blocks; enum pipe pipe = intel_crtc->pipe; int level, max_level = ilk_wm_max_level(dev_priv); + enum plane_id plane_id = intel_plane->id; int ret; if (WARN_ON(!intel_pstate->base.fb)) return -EINVAL; - ddb_blocks = skl_ddb_entry_size(>plane[pipe][intel_plane->id]); + if (plane_num == 0) +
Re: [Intel-gfx] [PATCH 08/16] drm/i915/skl+: nv12 workaround disable WM level 1-7
Hi, On 2/8/2018 2:01 PM, Sharma, Shashank wrote: Regards Shashank On 2/6/2018 6:28 PM, Vidya Srinivas wrote: From: Mahesh KumarDisplay Workaround #0826 (SKL:ALL BXT:ALL) & #1059(CNL:A) Hardware sometimes fails to wake memory from pkg C states fetching the last few lines of planar YUV 420 (NV12) planes. This causes intermittent underflow and corruption. WA: Disable package C states or do not enable latency levels 1 through 7 (WM1 - WM7) on NV12 planes. v2: Addressed review comments by Maarten. Reviewed-by: Maarten Lankhorst Signed-off-by: Mahesh Kumar Signed-off-by: Vidya Srinivas --- drivers/gpu/drm/i915/intel_pm.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d9801bf..c37d014 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4654,6 +4654,17 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } } + /* + * Display WA #826 (SKL:ALL, BXT:ALL) & #1059 (CNL:A) + * disable wm level 1-7 on NV12 planes + */ + if (wp->is_nv12 && (level >= 1) && + (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || + IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0))) { Seeing that this WAR is applicable for all GEN9 and CNL some rev ids, Is this applicable for GLK too ? Not really for all GEN-9, it's valid for SKL/BXT-ALL & CNL some id, so it doesn't seems to be applicable for GLK. -Mahesh - Shashank + result->plane_en = false; + return 0; + } + result->plane_res_b = res_blocks; result->plane_res_l = res_lines; result->plane_en = true; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/icl: remove port A/E lane sharing limitation.
Hi, On 2/2/2018 6:26 PM, Jani Nikula wrote: On Fri, 02 Feb 2018, Mahesh Kumarwrote: Platforms before Gen11 were sharing lanes between port-A & port-E. This limitation is no more there. Changes since V1: - optimize the code (Shashank/Jani) - create helper function to get max lanes (ville) Changes since V2: - Include BIOS fail fix-up in same helper function (ville) Signed-off-by: Mahesh Kumar Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/i915/intel_ddi.c | 71 +++- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cfcd9cb37d5d..ee9ba78d19c8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2842,39 +2842,44 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dport) return false; } +static int +intel_ddi_max_lanes(struct drm_i915_private *dev_priv, + struct intel_digital_port *intel_dig_port) +{ Please ditch the dev_priv parameter and add: struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); ok, sure. + enum port port = intel_dig_port->base.port; + int max_lanes = 4; Unnecessary initialization. for ports other than PORT_A/E will have max_lanes=4 that's the reason initializing it here, will fix the usages. + + if (INTEL_GEN(dev_priv) >= 11) { + return 4; Please either set max_lanes = 4 here, or remove the else. On early returns, you don't need the else. Having both is confusing. yes, agree, will remove the else + } else if (port == PORT_A || port == PORT_E) { + if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) + max_lanes = port == PORT_A ? 4 : 0; + else + /* Both A and E share 2 lanes */ + max_lanes = 2; + } + + /* +* Some BIOS might fail to set this bit on port A if eDP +* wasn't lit up at boot. Force this bit set when needed +* so we use the proper lane count for our calculations. +*/ + if (intel_ddi_a_force_4_lanes(intel_dig_port)) { + DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); + intel_dig_port->saved_port_bits |= DDI_A_4_LANES; + max_lanes = 4; + } + + return max_lanes; +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; struct drm_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; - int max_lanes; - if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { - switch (port) { - case PORT_A: - max_lanes = 4; - break; - case PORT_E: - max_lanes = 0; - break; - default: - max_lanes = 4; - break; - } - } else { - switch (port) { - case PORT_A: - max_lanes = 2; - break; - case PORT_E: - max_lanes = 2; - break; - default: - max_lanes = 4; - break; - } - } init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || dev_priv->vbt.ddi_port_info[port].supports_hdmi); @@ -2954,19 +2959,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) MISSING_CASE(port); } - /* -* Some BIOS might fail to set this bit on port A if eDP -* wasn't lit up at boot. Force this bit set when needed -* so we use the proper lane count for our calculations. -*/ - if (intel_ddi_a_force_4_lanes(intel_dig_port)) { - DRM_DEBUG_KMS("Forcing DDI_A_4_LANES for port A\n"); - intel_dig_port->saved_port_bits |= DDI_A_4_LANES; - max_lanes = 4; - } - intel_dig_port->dp.output_reg = INVALID_MMIO_REG; - intel_dig_port->max_lanes = max_lanes; intel_encoder->type = INTEL_OUTPUT_DDI; intel_encoder->power_domain = intel_port_to_power_domain(port); @@ -2974,6 +2967,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; + intel_dig_port->max_lanes = intel_ddi_max_lanes(dev_priv, + intel_dig_port); Please keep this at the original location above. I moved this here because intel_encoder->port was not initialized in original
Re: [Intel-gfx] [PATCH 15/15] drm/i915: Add NV12 support to intel_framebuffer_init
Hi, On 1/30/2018 9:35 AM, Srinivas, Vidya wrote: -Original Message- From: Maarten Lankhorst [mailto:maarten.lankho...@linux.intel.com] Sent: Monday, January 29, 2018 10:47 PM To: Srinivas, Vidya; intel- g...@lists.freedesktop.org Subject: Re: [Intel-gfx] [PATCH 15/15] drm/i915: Add NV12 support to intel_framebuffer_init Op 20-01-18 om 22:45 schreef Vidya Srinivas: From: Chandra Konduru This patch adds NV12 as supported format to intel_framebuffer_init and performs various checks. v2: -Fix an issue in checks added (Chandra Konduru) v3: rebased (me) v4: Review comments by Ville addressed Added platform check for NV12 in intel_framebuffer_init Removed offset checks for NV12 case v5: Addressed review comments by Clinton A Taylor This NV12 support only correctly works on SKL. Plane color space conversion is different on GLK and later platforms causing the colors to display incorrectly. Ville's plane color space property patch series in review will fix this issue. - Restricted the NV12 case in intel_framebuffer_init to SKL and BXT only. v6: Rebased (me) v7: Addressed review comments by Ville Restricting the NV12 to BXT for now. v8: Rebased (me) Restricting the NV12 changes to BXT and KBL for now. v9: Rebased (me) Hey, Has NV12 been tested at all on skylake with rotation? y_min_scanlines = 16 for 90°/270° rotation with cpp=1 skl_needs_memory_bw_wa() doubles the scanlines required, which will trigger the following error quite easily when patching kms_rotation_crc to use NV12: [ 67.049190] [drm:skl_compute_wm_levels [i915]] Requested display configuration exceeds system watermark limitations [ 67.049212] [drm:skl_compute_wm_levels [i915]] [PLANE:28:plane 1A] blocks required = 161/572, lines required = 32/31 If we violate the spec for the workaround, by using 31 lines instead of 32 for 90/270 rotation, the tests work but this needs to be solved first before we can move forward. We are hitting this issue due to memory_bw_wa (this is applicable for GEN-9 only) & we are applying WA irrespective of it's required or not. I had plan to apply this WA based on our discussion, but it never materialized :( https://www.spinics.net/lists/intel-gfx/msg124872.html We came across many such scenarios during NV12 testing on BXT. During downscaling, the "Max supported pixel clock with scaling exceeded" is seen if the user layer tries to downscale much. And rotation, as you mentioned we have seen such messages. We discussed the same during the meeting long back and mentioned that if we remove the limitations, it works. But as per discussion, if limitations are removed, it may work, but there may be certain conditions where it may not work. Hence we concluded that some such cases are expected not to work. Either we can conclude that as a limitation (as expected behavior) OR we can enable WA only when it's required (as discussed, assuming all the planes are enabled with max supported scaling to avoid taking mutex in each flip). what you say? -Mahesh However, I will discuss once again with Mahesh Kumar (CC) who works on WM implementation to re-confirm on the same. ~Maarten ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 5/8] drm/i915/skl+: reset y_plane ddb structure also during calculation
From: Mahesh KumarCurrent code clears only plane ddb allocation if total ddb allocated to pipe in zero. y_plane ddb still contains old value, clear that as well. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5b8f715..a668204 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3381,6 +3381,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 7/8] drm/i915/skl+: change WM calc to fixed point 16.16
From: Mahesh KumarThis patch changes Watermak calculation to fixed point calculation. Problem with current calculation is during plane_blocks_per_line calculation we divide intermediate blocks with min_scanlines and takes floor of the result because of integer operation. hence we end-up assigning less blocks than required. Which leads to flickers. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0eaaadc..4263212 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3527,16 +3527,19 @@ static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) * for the read latency) and cpp should always be <= 8, so that * should allow pixel_rate up to ~2 GHz which seems sufficient since max * 2xcdclk is 1350 MHz and the pixel rate should never exceed that. + * Both Method1 & Method2 returns fixedpoint 16.16 output */ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency) { - uint32_t wm_intermediate_val, ret; + uint64_t wm_intermediate_val; + uint32_t ret; if (latency == 0) return UINT_MAX; - wm_intermediate_val = latency * pixel_rate * cpp / 512; - ret = DIV_ROUND_UP(wm_intermediate_val, 1000); + wm_intermediate_val = latency * pixel_rate * cpp; + wm_intermediate_val <<= 16; + ret = DIV_ROUND_UP_ULL(wm_intermediate_val, 1000 * 512); return ret; } @@ -3658,12 +3661,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (y_tiled) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); - plane_blocks_per_line /= y_min_scanlines; + plane_blocks_per_line = (plane_blocks_per_line << 16) / + y_min_scanlines; } else if (x_tiled) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + plane_blocks_per_line <<= 16; } else { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; + plane_blocks_per_line <<= 16; } method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); @@ -3690,7 +3696,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, selected_result = method1; } - res_blocks = selected_result + 1; + res_blocks = DIV_ROUND_UP(selected_result, 1 << 16) + 1; res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 6/8] drm/i915/skl: Add variables to check x_tile and y_tile
From: Mahesh KumarThis patch adds variable to check for X_tiled & y_tiled planes, instead of always checking against framebuffer-modifiers. Changes: - Created separate patch as per Paulo's comment - Added x_tiled variable as well Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a668204..0eaaadc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3602,6 +3602,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t plane_pixel_rate; uint32_t y_tile_minimum, y_min_scanlines; enum watermark_memory_wa mem_wa; + bool y_tiled = false, x_tiled = false; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; @@ -3621,6 +3622,12 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, cpp = drm_format_plane_cpp(fb->pixel_format, 0); plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); + if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) + y_tiled = true; + else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + x_tiled = true; + if (intel_rotation_90_or_270(pstate->rotation)) { int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : @@ -3648,16 +3655,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_min_scanlines *= 2; plane_bytes_per_line = width * cpp; - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); plane_blocks_per_line /= y_min_scanlines; - } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) { + } else if (x_tiled) { + plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + } else { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; - } else { - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); } method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); @@ -3668,8 +3674,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_tile_minimum = plane_blocks_per_line * y_min_scanlines; - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { selected_result = max(method2, y_tile_minimum); } else { uint32_t linetime_us = 0; @@ -3689,8 +3694,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { res_blocks += y_tile_minimum; res_lines += y_min_scanlines; } else { -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 1/8] drm/i915/skl+: use linetime latency instead of ddb size
This patch make changes to use linetime latency instead of allocated DDB size during plane watermark calculation in switch case, This is required to implement new DDB allocation algorithm. In New Algorithm DDB is allocated based on WM values, because of which number of DDB blocks will not be available during WM calculation, So this "linetime latency" is suggested by SV/HW team to use during switch-case for WM blocks selection. Changes since v1: - Rebase on top of Paulo's patch series Changes since v2: - Fix if-else condition (pointed by Maarten) Signed-off-by: "Kumar, Mahesh" <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7f1748a..098336d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3616,10 +3616,14 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { selected_result = max(method2, y_tile_minimum); } else { + uint32_t linetime_us = 0; + + linetime_us = DIV_ROUND_UP(width * 1000, + skl_pipe_pixel_rate(cstate)); if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && (plane_bytes_per_line / 512 < 1)) selected_result = method2; - else if ((ddb_allocation / plane_blocks_per_line) >= 1) + else if (latency >= linetime_us) selected_result = min(method1, method2); else selected_result = method1; -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 8/8] drm/i915/bxt: Enable IPC support
From: Mahesh KumarThis patch adds IPC support for platforms. This patch enables IPC only for BXT/KBL platform as for SKL recommendation is to keep is disabled. IPC (Isochronous Priority Control) is the hardware feature, which dynamically controles the memory read priority of Display. When IPC is enabled, plane read requests are sent at high priority until filling above the transition watermark, then the requests are sent at lower priority until dropping below the level 0 watermark. The lower priority requests allow other memory clients to have better memory access. When IPC is disabled, all plane read requests are sent at high priority. Changes since V1: - Remove commandline parameter to disable ipc - Address Paulo's comments Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 15 +++ 4 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b5f601c..58abbaa 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1415,6 +1415,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); + intel_enable_ipc(dev_priv); + /* Everything is in place, we can now relax! */ DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver.name, driver.major, driver.minor, driver.patchlevel, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a9c467c..c9ebf23 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6144,6 +6144,7 @@ enum { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST(1<<31) #define DBUF_POWER_STATE (1<<30) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2c1897b..45b0fa4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1766,6 +1766,7 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); +void intel_enable_ipc(struct drm_i915_private *dev_priv); static inline int intel_enable_rc6(void) { return i915.enable_rc6; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4263212..543aa5d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4833,6 +4833,21 @@ void intel_update_watermarks(struct drm_crtc *crtc) dev_priv->display.update_wm(crtc); } +void intel_enable_ipc(struct drm_i915_private *dev_priv) +{ + u32 val; + + /* enable IPC only for Broxton for now*/ + if (!IS_BROXTON(dev_priv) || !IS_KABYLAKE(dev_priv)) + return; + + val = I915_READ(DISP_ARB_CTL2); + + val |= DISP_IPC_ENABLE; + + I915_WRITE(DISP_ARB_CTL2, val); +} + /* * Lock protecting IPS related data structures */ -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 2/8] drm/i915/skl: New ddb allocation algorithm
From: Mahesh KumarThis patch implements new DDB allocation algorithm as per HW team recommendation. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane, for efficient power saving. Changes since v1: - Rebase on top of Paulo's patch series Changes since v2: - Fix the for loop condition to enable WM Changes since v3: - Fix crash in cursor i-g-t reported by Maarten - Rebase after addressing Paulo's comments - Few other ULT fixes Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 149 +--- 1 file changed, 79 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 098336d..84ec6b1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3344,6 +3344,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; @@ -3359,8 +3360,12 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; unsigned int total_data_rate; + uint16_t total_min_blocks = 0; + uint16_t total_level_ddb = 0; int num_active; - int id, i; + int max_level, level; + int id, i, ret = 0; + if (WARN_ON(!state)) return 0; @@ -3409,19 +3414,42 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, } for (i = 0; i < PLANE_CURSOR; i++) { - alloc_size -= minimum[i]; - alloc_size -= y_minimum[i]; + total_min_blocks += minimum[i]; + total_min_blocks += y_minimum[i]; } - /* -* 2. Distribute the remaining space in proportion to the amount of -* data each plane needs to fetch from memory. -* -* FIXME: we may not allocate every single block here. -*/ + for (level = ilk_wm_max_level(dev); level >= 0; level--) { + total_level_ddb = 0; + for (i = 0; i < PLANE_CURSOR; i++) { + /* +* TODO: We should calculate watermark values for Y/UV +* plane both in case of NV12 format and use both values +* for ddb calculation, As NV12 is disabled as of now. +* using only single plane value here. +*/ + uint16_t min = minimum[i] + y_minimum[i]; + uint16_t plane_level_ddb_wm = + max(pipe_wm->wm[level].plane_res_b[i], min); + total_level_ddb += plane_level_ddb_wm; + } + + if (total_level_ddb <= alloc_size) + break; + } + + if ((level < 0) || (total_min_blocks > alloc_size)) { + DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations"); + DRM_DEBUG_KMS("minimum required %d/%d\n", (level < 0) ? + total_level_ddb : total_min_blocks, alloc_size); + ret = -EINVAL; + goto exit; + } + max_level = level; + alloc_size -= total_level_ddb; + total_data_rate = skl_get_total_relative_data_rate(cstate); if (total_data_rate == 0) - return 0; + goto exit; start = alloc->start; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3436,7 +3464,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[id]; + plane_blocks = max(pipe_wm->wm[max_level].plane_res_b[id], + minimum[id]); plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); @@ -3444,12 +3473,13 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, if (data_rate) { ddb->plane[pipe][id].start = start; ddb->plane[pipe][id].end = start + plane_blocks; + start += plane_blocks; } - start += plane_blocks; - /* * allocation for y_plane part of planar format: +* TODO: Once we start calculating
[Intel-gfx] [PATCH v4 3/8] drm/i915: Decode system memory bandwidth
This patch adds support to decode system memory bandwidth which will be used for arbitrated display memory percentage calculation in GEN9 based system. Changes from v1: - Address comments from Paulo - implement decode function for SKL/KBL also Signed-off-by: "Kumar, Mahesh" <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.c | 170 drivers/gpu/drm/i915/i915_drv.h | 14 drivers/gpu/drm/i915/i915_reg.h | 38 + 3 files changed, 222 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 89d3222..b5f601c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -979,6 +979,170 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores)); } +static inline void skl_memdev_info_fill(struct memdev_info *info, uint32_t val) +{ + uint8_t channel_width, rank; + + info->rank_valid = true; + channel_width = (val >> SKL_DRAM_CHANNEL_WIDTH_SHIFT) & + SKL_DRAM_CHANNEL_WIDTH_MASK; + if (channel_width == SKL_DRAM_WIDTH_1) + info->channel_width_bytes = 1; + else if (channel_width == SKL_DRAM_WIDTH_2) + info->channel_width_bytes = 2; + else + info->channel_width_bytes = 4; + + rank = (val >> SKL_DRAM_RANK_SHIFT) & SKL_DRAM_RANK_MASK; + if (rank == SKL_DRAM_RANK_SINGLE) + info->rank = DRAM_RANK_SINGLE; + else + info->rank = DRAM_RANK_DUAL; +} + +static int +skl_get_memdev_info(struct drm_i915_private *dev_priv) +{ + uint32_t val = 0; + uint32_t mem_speed = 0; + struct memdev_info *memdev_info = _priv->memdev_info; + + val = I915_READ(SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); + mem_speed = div_u64((uint64_t) (val & SKL_REQ_DATA_MASK) * + SKL_MEMORY_FREQ_MULTIPLIER, 1000); + + if (mem_speed == 0) + return -EINVAL; + + memdev_info->valid = true; + memdev_info->mem_speed_khz = mem_speed; + memdev_info->num_channels = 0; + + memdev_info->rank_valid = false; + val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + + if (val != 0x) { + memdev_info->num_channels++; + skl_memdev_info_fill(memdev_info, val); + } + + val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + + if (val != 0x) { + memdev_info->num_channels++; + if (!memdev_info->rank_valid) + skl_memdev_info_fill(memdev_info, val); + } + + if (memdev_info->num_channels == 0) + memdev_info->valid = false; + return 0; +} + +static int +bxt_get_memdev_info(struct drm_i915_private *dev_priv) +{ + struct memdev_info *memdev_info = _priv->memdev_info; + uint32_t dram_channel; + uint32_t mem_speed, val; + uint8_t num_channel, dram_type; + int i; + + val = I915_READ(BXT_P_CR_MC_BIOS_REQ_0_0_0); + mem_speed = div_u64((uint64_t) (val & BXT_REQ_DATA_MASK) * + SKL_MEMORY_FREQ_MULTIPLIER, 1000); + + if (mem_speed == 0) + return -EINVAL; + + memdev_info->valid = true; + memdev_info->mem_speed_khz = mem_speed; + dram_type = (val >> BXT_DRAM_TYPE_SHIFT) & BXT_DRAM_TYPE_MASK; + dram_channel = (val >> BXT_DRAM_CHANNEL_SHIFT) & BXT_DRAM_CHANNEL_MASK; + num_channel = hweight32(dram_channel); + + /* +* The lpddr3 and lpddr4 technologies can have 1-4 channels and the +* channels are 32bits wide; while ddr3l technologies can have 1-2 +* channels and the channels are 64 bits wide. In case of single 64 bit +* wide DDR3L dimm sets two channel-active bits in +* P_CR_MC_BIOS_REQ_0_0_0 register and system with two DDR3L 64bit dimm +* will set all four channel-active bits in above register. +* In order to get actual number of channels in DDR3L DRAM we need to +* device total channel-active bits set by 2. +*/ + + switch (dram_type) { + case BXT_DRAM_TYPE_LPDDR3: + case BXT_DRAM_TYPE_LPDDR4: + memdev_info->channel_width_bytes = 4; + memdev_info->num_channels = num_channel; + break; + case BXT_DRAM_TYPE_DDR3L: + memdev_info->channel_width_bytes = 8; + memdev_info->num_channels = num_channel / 2; + break; + default: + DRM_DEBUG_KMS("Unknown DRAM type\n"); + memdev_info->valid = false; + return -EINVAL; + } + + /* +* Now read each DUNIT8/9/10/11 to check the rank of
[Intel-gfx] [PATCH v4 0/8] New DDB Algo and WM fixes
From: Mahesh Kumar <mahesh1.ku...@intel.com> This series implements new DDB allocation algorithm to solve the cases, where we have sufficient DDB available to enable multiple planes, But due to the current algorithm not dividing it properly among planes, we end-up failing the flip. It also takes care of enabling same watermark level for each plane, for efficient power saving. This series also implements Transition Watermarks and Gen-9 related arbitrated display bandwidth Workarounds. There are two steps in current WM programming. 1. Calculate minimum number of blocks required for a WM level to be enabled. For 1440x2560 panel we need 41 blocks as minimum number of blocks to enable WM0. This is the step which doesn't use vertical size. It only depends on Pipe drain rate and plane horizontal size as per the current Bspec algorithm. So all the plane below have minimum number of blocks required to enable WM0 as 41 Plane 1 - 1440x2560-Min blocks to enable WM0 = 41 Plane 2 - 1440x2560-Min blocks to enable WM0 = 41 Plane 3 - 1440x48 -Min blocks to enable WM0 = 41 Plane 4 - 1440x96 -Min blocks to enable WM0 = 41 2. Number of blocks allotted by the driver Driver allocates 12 for Plane 3 & 16 for plane 4 Total Dbuf Available = 508 Dbuf Available after 32 blocks for cursor = 508 - (32) = 476 allocate minimum blocks for each plane 8 * 4 = 32 remaining blocks = 476 - 32 = 444 Relative Data Rate for Planes Plane 1 = 1440 * 2560 * 3 = 11059200 Plane 2 = 1440 * 2560 * 3 = 11059200 Plane 3 = 1440 * 48 * 3 = 207360 Plane 4 = 1440 * 96 * 3 = 414720 Total Relative BW= 22740480 - Allocate Buffer buffer allocation = (Plane relative data rate / total data rate) * total remaming DDB + minimum plane DDB Plane 1 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 2 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 3 buffer allocation = (207360 / 22740480) * 444 + 8 = 12 Plane 4 buffer allocation = (414720 / 22740480) * 444 + 8 = 16 In this case it forced driver to disable Plane 3 & 4. Driver need to use more efficient way to allocate buffer that is optimum for power. New Algorithm suggested by HW team is: 1. Calculate minimum buffer allocations for each plane and for each watermark level 2. Add minimum buffer allocations required for enabling WM7 for all the planes Level 0 = 41 + 41 + 41 + 41 = 164 Level 1 = 42 + 42 + 42 + 42 = 168 Level 2 = 42 + 42 + 42 + 42 = 168 Level 3 = 94 + 94 + 94 + 94 = 376 Level 4 = 94 + 94 + 94 + 94 = 376 Level 5 = 94 + 94 + 94 + 94 = 376 Level 6 = 94 + 94 + 94 + 94 = 376 Level 7 = 94 + 94 + 94 + 94 = 376 3. Check to see how many buffer allocation are left and enable the best case. In this case since we have 476 blocks we can enable WM0-7 on all 4 planes. Let's say if we have only 200 block available then the best cases allocation is to enable Level2 which requires 168 blocks Changes since v1: - Rebased the series on top of Paulo's patches (under review) https://patchwork.freedesktop.org/series/12082/ - Add changes to calculate WM in fixed point 16.16 - Address review comments for Transition WM Changes since v2: - Added Paulo's WM fixes series URL in cover letter Changes since v3: - Address Review comments - Drop patch to set y-tile WA, as this is already there & as per HW team always setting the WA doesn't harm. - Drop Transition WM and patch to reduce function parameter patch - split patches Kumar, Mahesh (3): drm/i915/skl+: use linetime latency instead of ddb size drm/i915: Decode system memory bandwidth drm/i915/gen9: WM memory bandwidth related workaround Mahesh Kumar (5): drm/i915/skl: New ddb allocation algorithm drm/i915/skl+: reset y_plane ddb structure also during calculation drm/i915/skl: Add variables to check x_tile and y_tile drm/i915/skl+: change WM calc to fixed point 16.16 drm/i915/bxt: Enable IPC support drivers/gpu/drm/i915/i915_drv.c | 172 +++ drivers/gpu/drm/i915/i915_drv.h | 23 +++ drivers/gpu/drm/i915/i915_reg.h | 39 + drivers/gpu/drm/i915/intel_drv.h | 12 ++ drivers/gpu/drm/i915/intel_pm.c | 351 ++- 5 files changed, 514 insertions(+), 83 deletions(-) -- 2.10.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v4 4/8] drm/i915/gen9: WM memory bandwidth related workaround
This patch implemnets Workariunds related to display arbitrated memory bandwidth. These WA are applicabe for all gen-9 based platforms. Changes since v1: - Rebase on top of Paulo's patch series Changes since v2: - Rebase/rework after addressing Paulo's comments in previous patch Signed-off-by: "Kumar, Mahesh" <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 9 +++ drivers/gpu/drm/i915/intel_drv.h | 11 +++ drivers/gpu/drm/i915/intel_pm.c | 146 +++ 3 files changed, 166 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index adbd9aa..c169360 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1092,6 +1092,13 @@ enum intel_sbi_destination { SBI_MPHY, }; +/* SKL+ Watermark arbitrated display bandwidth Workarounds */ +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) @@ -1644,6 +1651,8 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; + /* any WaterMark memory workaround Required */ + enum watermark_memory_wa mem_wa; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f48e79a..2c1897b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1813,6 +1813,17 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } +static inline struct intel_crtc_state * +intel_atomic_get_existing_crtc_state(struct drm_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_existing_crtc_state(state, >base); + + return to_intel_crtc_state(crtc_state); +} + static inline struct intel_plane_state * intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, struct intel_plane *plane) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 84ec6b1..5b8f715 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3589,6 +3589,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(cstate->base.state); uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3598,10 +3600,17 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; uint32_t y_tile_minimum, y_min_scanlines; + enum watermark_memory_wa mem_wa; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; + mem_wa = intel_state ? intel_state->wm_results.mem_wa : WATERMARK_WA_NONE; + if (mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + width = drm_rect_width(_pstate->base.src) >> 16; height = drm_rect_height(_pstate->base.src) >> 16; @@ -3634,6 +3643,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_min_scanlines = 4; } + if (mem_wa == WATERMARK_WA_Y_TILED) + y_min_scanlines *= 2; + plane_bytes_per_line = width * cpp; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { @@ -4075,6 +4087,15 @@ skl_include_affected_pipes(struct drm_atomic_state *state) intel_state->wm_results.dirty_pipes = ~0; } + /* +* If Watermark workaround is changed we need to recalculate +* watermark values for all active pipes +*/ + if (intel_state->wm_results.mem_wa != dev_priv->wm.skl_hw.mem_wa) { + realloc_pipes = ~0; + intel_state->wm_results.dirty_pipes = ~0; + } + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { struct intel_crtc_state *cstate; @@ -4087,6 +4108,129 @@ skl_include_affected_pipes(struct drm_atomic_state *state) } static void +skl_set_memory_bandwidth_wm_wa(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->
[Intel-gfx] [PATCH v4] drm/i915/bxt: Implement Transition WM
From: Mahesh KumarThis patch enables Transition WM for SKL+ platforms. Transition WM are used if IPC is enabled, to decide, number of blocks to be fetched before reducing the priority of display to fetch from memory. Changes since v1: - Don't enable transition WM for GEN9 (Art/Paulo) - Rebase to use fixed point 16.16 calculation - Fix the use of selected result from latency level-0 Changes since v2: - Fix transition WM enable condition Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 60 ++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index de2e738..4814a1a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2862,6 +2862,8 @@ bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 +#define SKL_TRANS_WM_AMOUNT10 /* tunable value */ +#define SKL_TRANS_WM_MIN 14 #define SKL_SAGV_BLOCK_TIME30 /* µs */ /* @@ -3583,6 +3585,48 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst return pixel_rate; } +static void skl_compute_plane_trans_wm(const struct drm_i915_private *dev_priv, + struct skl_pipe_wm *pipe_wm, + struct intel_plane_state *intel_pstate, + uint32_t selected_result, + uint32_t y_tile_min, + bool y_tile) +{ + struct drm_plane_state *pstate = _pstate->base; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + uint16_t *out_blocks = _wm->trans_wm.plane_res_b[id]; + uint8_t *out_lines = _wm->trans_wm.plane_res_l[id]; + uint32_t trans_min = 0, trans_offset_blocks; + uint32_t trans_y_tile_min = 0, res_blocks = 0; + uint16_t trans_res_blocks = 0; + + /* Keep Trans WM disabled for GEN9 */ + if (IS_GEN9(dev_priv)) + goto exit; + + trans_min = SKL_TRANS_WM_MIN; + + trans_offset_blocks = (trans_min + SKL_TRANS_WM_AMOUNT) << 16; + + if (y_tile) { + trans_y_tile_min = 2 * y_tile_min; + res_blocks = max(trans_y_tile_min, selected_result) + + trans_offset_blocks; + } else { + res_blocks = selected_result + trans_offset_blocks; + } + + trans_res_blocks = DIV_ROUND_UP(res_blocks, 1 << 16) + 1; + + /* WA BUG:1938466 add one block for non y-tile planes */ + if (!y_tile) + trans_res_blocks += 1; +exit: + *out_blocks = trans_res_blocks; + *out_lines = 0; +} + + static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, struct intel_plane_state *intel_pstate, @@ -3709,6 +3753,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, *out_blocks = res_blocks; *out_lines = res_lines; + if (level == 0) + skl_compute_plane_trans_wm(dev_priv, pipe_wm, intel_pstate, + selected_result, y_tile_minimum, y_tiled); return 0; } @@ -3778,11 +3825,13 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, - struct skl_wm_level *trans_wm /* out */) + struct skl_wm_level *trans_wm, /* out */ + struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = cstate->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane; + enum pipe pipe = to_intel_crtc(crtc)->pipe; if (!cstate->base.active) return; @@ -3790,8 +3839,13 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, /* Until we know more, just disable transition WMs */ for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { int i = skl_wm_plane_id(intel_plane); + uint16_t plane_ddb = skl_ddb_entry_size(>plane[pipe][i]); + uint16_t trans_res_blocks = trans_wm->plane_res_b[i]; - trans_wm->plane_en[i] = false; + if ((trans_res_blocks > 0) && (trans_res_blocks <= plane_ddb)) + trans_wm->plane_en[i] = true; + else + trans_wm->plane_en[i] = false; } } @@ -3822,7 +3876,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, pipe_wm->linetime = skl_compute_linetime_wm(cstate); - skl_compute_transition_wm(cstate,
[Intel-gfx] [PATCH v4] drm/i915/skl: New ddb allocation algorithm
From: Mahesh KumarThis patch implements new DDB allocation algorithm as per HW team suggestion. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane, for efficient power saving. Changes since v1: - Rebase on top of Paulo's patch series Changes since v2: - Fix the for loop condition to enable WM Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 129 +--- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3370fc8..c52cc57 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3348,6 +3348,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; @@ -3363,8 +3364,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; unsigned int total_data_rate; + uint16_t total_min_blocks = 0; + uint16_t total_level_ddb = 0; int num_active; - int id, i; + int max_level, level; + int id, i, ret = 0; if (WARN_ON(!state)) return 0; @@ -3380,6 +3384,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } @@ -3413,19 +3418,42 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, } for (i = 0; i < PLANE_CURSOR; i++) { - alloc_size -= minimum[i]; - alloc_size -= y_minimum[i]; + total_min_blocks += minimum[i]; + total_min_blocks += y_minimum[i]; } - /* -* 2. Distribute the remaining space in proportion to the amount of -* data each plane needs to fetch from memory. -* -* FIXME: we may not allocate every single block here. -*/ + for (level = ilk_wm_max_level(dev); level >= 0; level--) { + total_level_ddb = 0; + for (i = 0; i < PLANE_CURSOR; i++) { + /* +* TODO: We should calculate watermark values for Y/UV +* plane both in case of NV12 format and use both values +* for ddb calculation, As NV12 is disabled as of now. +* using only single plane value here. +*/ + uint16_t min = minimum[i] + y_minimum[i]; + uint16_t plane_level_ddb_wm = + max(pipe_wm->wm[level].plane_res_b[i], min); + total_level_ddb += plane_level_ddb_wm; + } + + if (total_level_ddb <= alloc_size) + break; + } + + if ((level < 0) || (total_min_blocks > alloc_size)) { + DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations"); + DRM_DEBUG_KMS("minimum required %d/%d\n", (level < 0) ? + total_level_ddb : total_min_blocks, alloc_size); + ret = -EINVAL; + goto exit; + } + max_level = level; + alloc_size -= total_level_ddb; + total_data_rate = skl_get_total_relative_data_rate(cstate); if (total_data_rate == 0) - return 0; + goto exit; start = alloc->start; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3440,7 +3468,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[id]; + plane_blocks = max(pipe_wm->wm[max_level].plane_res_b[id], + minimum[id]); plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); @@ -3454,6 +3483,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* * allocation for y_plane part of planar format: +* TODO: Once we start calculating watermark values for Y/UV +* plane both consider it for
[Intel-gfx] [PATCH v3 4/9] drm/i915: Decode system memory bandwidth
From: Mahesh KumarThis patch adds support to decode system memory bandwidth which will be used for arbitrated display memory percentage calculation in GEN9 based system. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 96 + drivers/gpu/drm/i915/i915_drv.h | 18 drivers/gpu/drm/i915/i915_reg.h | 25 +++ 3 files changed, 139 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 02c34d6..0a4f18d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -973,6 +973,96 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores)); } +static void +intel_get_memdev_info(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + uint32_t val = 0; + uint32_t mem_speed = 0; + uint8_t dram_type; + uint32_t dram_channel; + uint8_t num_channel; + bool rank_valid = false; + + if (!IS_GEN9(dev_priv)) + goto exit; + + val = I915_READ(P_CR_MC_BIOS_REQ_0_0_0); + mem_speed = div_u64((uint64_t) (val & REQ_DATA_MASK) * + MEMORY_FREQ_MULTIPLIER, 1000); + + if (mem_speed == 0) + goto exit; + + dev_priv->memdev_info.valid = true; + dev_priv->memdev_info.mem_speed = mem_speed; + dram_type = (val >> DRAM_TYPE_SHIFT) & DRAM_TYPE_MASK; + dram_channel = (val >> DRAM_CHANNEL_SHIFT) & DRAM_CHANNEL_MASK; + num_channel = hweight32(dram_channel); + + /* +* The lpddr3 and lpddr4 technologies can have 1-4 channels and the +* channels are 32bits wide; while ddr3l technologies can have 1-2 +* channels and the channels are 64 bits wide. But SV team found that in +* case of single 64 bit wide DDR3L dimms two bits were set and system +* with two DDR3L 64bit dimm all four bits were set. +*/ + + switch (dram_type) { + case DRAM_TYPE_LPDDR3: + case DRAM_TYPE_LPDDR4: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + break; + case DRAM_TYPE_DDR3L: + dev_priv->memdev_info.data_width = 8; + dev_priv->memdev_info.num_channel = num_channel / 2; + break; + default: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + } + + /* +* Now read each DUNIT8/9/10/11 to check the rank of each dimms. +* all the dimms should have same rank as in first valid Dimm +*/ +#define D_CR_DRP0_DUNIT_INVALID0x + + dev_priv->memdev_info.rank_valid = true; + if (I915_READ(D_CR_DRP0_DUNIT8) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT8); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT9) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT9); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT10) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT10); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT11) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT11); + rank_valid = true; + } +#undef D_CR_DRP0_DUNIT_INVALID + + if (rank_valid) { + dev_priv->memdev_info.rank_valid = true; + dev_priv->memdev_info.rank = (val & DRAM_RANK_MASK); + } + + DRM_DEBUG_DRIVER("valid:%s speed-%d width-%d num_channel-%d\n", + dev_priv->memdev_info.valid ? "true" : "false", + dev_priv->memdev_info.mem_speed, + dev_priv->memdev_info.data_width, + dev_priv->memdev_info.num_channel); + DRM_DEBUG_DRIVER("rank_valid:%s rank-%d\n", + dev_priv->memdev_info.rank_valid ? "true" : "false", + dev_priv->memdev_info.rank); + return; +exit: + dev_priv->memdev_info.valid = false; +} + /** * i915_driver_init_hw - setup state requiring device access * @dev_priv: device private @@ -1076,6 +1166,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("can't enable MSI"); } + /* +* Fill the memdev structure to get the system raw bandwidth +* This will be used by WM algorithm, to implement GEN9 based WA +*/ + intel_get_memdev_info(dev); + return 0; out_ggtt: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4ec23e5..4313992 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@
[Intel-gfx] [PATCH v3 7/9] drm/i915/bxt: Enable IPC support
From: Mahesh KumarThis patch adds IPC support for platforms. This patch enables IPC only for BXT platform as for SKL recommendation is to keep is disabled This patch also adds kernel command-line option to enable/disable the IPC if required. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c| 5 + drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/i915_params.h | 1 + drivers/gpu/drm/i915/i915_reg.h| 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c| 21 + 6 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0a4f18d..22d84e6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1335,6 +1335,11 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); + /* +* Now enable the IPC for supported platforms +*/ + intel_enable_ipc(dev_priv); + /* Everything is in place, we can now relax! */ DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver.name, driver.major, driver.minor, driver.patchlevel, diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 768ad89..cc41b8d 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -62,6 +62,7 @@ struct i915_params i915 __read_mostly = { .inject_load_failure = 0, .enable_dpcd_backlight = false, .enable_gvt = false, + .enable_ipc = true, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -233,3 +234,7 @@ MODULE_PARM_DESC(enable_dpcd_backlight, module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); MODULE_PARM_DESC(enable_gvt, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); + +module_param_named(enable_ipc, i915.enable_ipc, bool, 0400); +MODULE_PARM_DESC(enable_ipc, + "Enable Isochronous Priority Control (default:true)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 3a0dd78..f99b9b9 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -65,6 +65,7 @@ struct i915_params { bool enable_dp_mst; bool enable_dpcd_backlight; bool enable_gvt; + bool enable_ipc; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b38445c..75b5b52 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6139,6 +6139,7 @@ enum { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST(1<<31) #define DBUF_POWER_STATE (1<<30) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 66cb46c..56c8ac8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1753,6 +1753,7 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); +void intel_enable_ipc(struct drm_i915_private *dev_priv); static inline int intel_enable_rc6(void) { return i915.enable_rc6; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d4390e4..8d0037c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4793,6 +4793,27 @@ void intel_update_watermarks(struct drm_crtc *crtc) } /* + * enable IPC for Supported Platforms + */ +void intel_enable_ipc(struct drm_i915_private *dev_priv) +{ + u32 val; + + /* enable IPC only for Broxton for now*/ + if (!IS_BROXTON(dev_priv)) + return; + + val = I915_READ(DISP_ARB_CTL2); + + if (i915.enable_ipc) + val |= DISP_IPC_ENABLE; + else + val &= ~DISP_IPC_ENABLE; + + I915_WRITE(DISP_ARB_CTL2, val); +} + +/* * Lock protecting IPS related data structures */ DEFINE_SPINLOCK(mchdev_lock); -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 6/9] drm/i915/skl+: change WM calc to fixed point 16.16
From: Mahesh KumarThis patch changes Watermak calculation to fixed point calculation. Problem with current calculation is during plane_blocks_per_line calculation we divide intermediate blocks with min_scanlines and takes floor of the result because of integer operation. hence we end-up assigning less blocks than required. Which leads to flickers. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0ec328b..d4390e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3530,13 +3530,15 @@ static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) */ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency) { - uint32_t wm_intermediate_val, ret; + uint64_t wm_intermediate_val; + uint32_t ret; if (latency == 0) return UINT_MAX; - wm_intermediate_val = latency * pixel_rate * cpp / 512; - ret = DIV_ROUND_UP(wm_intermediate_val, 1000); + wm_intermediate_val = latency * pixel_rate * cpp; + wm_intermediate_val <<= 16; + ret = DIV_ROUND_UP_ULL(wm_intermediate_val, 1000 * 512); return ret; } @@ -3605,6 +3607,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint16_t *out_blocks = >plane_res_b[id]; uint8_t *out_lines = >plane_res_l[id]; enum watermark_memory_wa mem_wa; + bool y_tiled = false; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; @@ -3652,14 +3655,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, plane_bytes_per_line = width * cpp; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + y_tiled = true; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); - plane_blocks_per_line /= y_min_scanlines; + plane_blocks_per_line = (plane_blocks_per_line << 16) / + y_min_scanlines; } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; + plane_blocks_per_line <<= 16; } else { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + plane_blocks_per_line <<= 16; } method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); @@ -3670,8 +3677,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_tile_minimum = plane_blocks_per_line * y_min_scanlines; - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { selected_result = max(method2, y_tile_minimum); } else { uint32_t linetime_us = 0; @@ -3688,12 +3694,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, selected_result = method1; } - res_blocks = selected_result + 1; + res_blocks = DIV_ROUND_UP(selected_result, 1 << 16) + 1; res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { res_blocks += y_tile_minimum; res_lines += y_min_scanlines; } else { -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 1/9] drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions
From: Mahesh KumarThis patch make use of plane_wm variable directly instead of passing skl_plane_wm struct. this way reduces number of argument requirement in watermark calculation functions. It also gives more freedom of decision making to implement Bspec WM workarounds. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 29 +++-- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 86c6d66..3fdec4d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3542,9 +3542,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_plane_state *intel_pstate, uint16_t ddb_allocation, int level, - uint16_t *out_blocks, /* out */ - uint8_t *out_lines, /* out */ - bool *enabled /* out */) + struct skl_pipe_wm *pipe_wm) { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; @@ -3557,6 +3555,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; uint32_t y_tile_minimum, y_min_scanlines; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + struct skl_wm_level *result = _wm->wm[level]; + uint16_t *out_blocks = >plane_res_b[id]; + uint8_t *out_lines = >plane_res_l[id]; + bool *enabled = >plane_en[id]; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3673,7 +3676,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, int level, -struct skl_wm_level *result) +struct skl_pipe_wm *pipe_wm) { struct drm_atomic_state *state = cstate->base.state; struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); @@ -3684,12 +3687,6 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, enum pipe pipe = intel_crtc->pipe; int ret; - /* -* We'll only calculate watermarks for planes that are actually -* enabled, so make sure all other planes are set as disabled. -*/ - memset(result, 0, sizeof(*result)); - for_each_intel_plane_mask(_priv->drm, intel_plane, cstate->base.plane_mask) { @@ -3727,9 +3724,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, intel_pstate, ddb_blocks, level, - >plane_res_b[i], - >plane_res_l[i], - >plane_en[i]); + pipe_wm); if (ret) return ret; } @@ -3777,9 +3772,15 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, int level, max_level = ilk_wm_max_level(dev); int ret; + /* +* We'll only calculate watermarks for planes that are actually +* enabled, so make sure all other planes are set as disabled. +*/ + memset(pipe_wm, 0, sizeof(*pipe_wm)); + for (level = 0; level <= max_level; level++) { ret = skl_compute_wm_level(dev_priv, ddb, cstate, - level, _wm->wm[level]); + level, pipe_wm); if (ret) return ret; } -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 9/9] drm/i915/bxt: Implement Transition WM
From: Mahesh KumarThis patch enables Transition WM for SKL+ platforms. Transition WM are used if IPC is enabled, to decide, number of blocks to be fetched before reducing the priority of display to fetch from memory. Changes since v1: - Don't enable transition WM for GEN9 (Art/Paulo) - Rebase to use fixed point 16.16 calculation - Fix the use of selected result from latency level-0 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 60 ++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8d0037c..f6a3fab 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2862,6 +2862,8 @@ bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 +#define SKL_TRANS_WM_AMOUNT10 /* tunable value */ +#define SKL_TRANS_WM_MIN 14 #define SKL_SAGV_BLOCK_TIME30 /* µs */ /* @@ -3583,6 +3585,48 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst return pixel_rate; } +static void skl_compute_plane_trans_wm(const struct drm_i915_private *dev_priv, + struct skl_pipe_wm *pipe_wm, + struct intel_plane_state *intel_pstate, + uint32_t selected_result, + uint32_t y_tile_min, + bool y_tile) +{ + struct drm_plane_state *pstate = _pstate->base; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + uint16_t *out_blocks = _wm->trans_wm.plane_res_b[id]; + uint8_t *out_lines = _wm->trans_wm.plane_res_l[id]; + uint32_t trans_min = 0, trans_offset_blocks; + uint32_t trans_y_tile_min = 0, res_blocks = 0; + uint16_t trans_res_blocks = 0; + + /* Keep Trans WM disabled for GEN9 */ + if (IS_GEN9(dev_priv)) + goto exit; + + trans_min = SKL_TRANS_WM_MIN; + + trans_offset_blocks = (trans_min + SKL_TRANS_WM_AMOUNT) << 16; + + if (y_tile) { + trans_y_tile_min = 2 * y_tile_min; + res_blocks = max(trans_y_tile_min, selected_result) + + trans_offset_blocks; + } else { + res_blocks = selected_result + trans_offset_blocks; + } + + trans_res_blocks = DIV_ROUND_UP(res_blocks, 1 << 16) + 1; + + /* WA BUG:1938466 add one block for non y-tile planes */ + if (!y_tile) + trans_res_blocks += 1; +exit: + *out_blocks = trans_res_blocks; + *out_lines = 0; +} + + static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, struct intel_plane_state *intel_pstate, @@ -3709,6 +3753,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, *out_blocks = res_blocks; *out_lines = res_lines; + if (level == 0) + skl_compute_plane_trans_wm(dev_priv, pipe_wm, intel_pstate, + selected_result, y_tile_minimum, y_tiled); return 0; } @@ -3778,11 +3825,13 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, - struct skl_wm_level *trans_wm /* out */) + struct skl_wm_level *trans_wm, /* out */ + struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = cstate->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane; + enum pipe pipe = to_intel_crtc(crtc)->pipe; if (!cstate->base.active) return; @@ -3790,8 +3839,13 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, /* Until we know more, just disable transition WMs */ for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { int i = skl_wm_plane_id(intel_plane); + uint16_t plane_ddb = skl_ddb_entry_size(>plane[pipe][i]); + uint16_t trans_res_blocks = trans_wm->plane_res_b[i]; - trans_wm->plane_en[i] = false; + if ((plane_ddb > 0) && (trans_res_blocks > plane_ddb)) + trans_wm->plane_en[i] = false; + else + trans_wm->plane_en[i] = true; } } @@ -3822,7 +3876,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, pipe_wm->linetime = skl_compute_linetime_wm(cstate); - skl_compute_transition_wm(cstate, _wm->trans_wm); + skl_compute_transition_wm(cstate,
[Intel-gfx] [PATCH v3 8/9] drm/i915/bxt: set chicken bit as IPC y-tile WA
From: Mahesh KumarIt implements the WA to enable IDLE_WAKEMEM bit of CHICKEN_DCPR_1 register for Broxton platform. When IPC is enabled & Y-tile is enabled in any of the enabled plane, above bit should be set. Without this WA system observes random hang. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 50 3 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4737a0e..79b9305 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1632,6 +1632,8 @@ struct skl_wm_values { unsigned dirty_pipes; /* any WaterMark memory workaround Required */ enum watermark_memory_wa mem_wa; + /* IPC Y-tiled WA related member */ + u32 y_plane_mask; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 75b5b52..210d9b0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5658,6 +5658,9 @@ enum { #define PLANE_NV12_BUF_CFG(pipe, plane)\ _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) +#define CHICKEN_DCPR_1 _MMIO(0x46430) +#define IDLE_WAKEMEM_MASK (1 << 13) + /* SKL new cursor registers */ #define _CUR_BUF_CFG_A 0x7017c #define _CUR_BUF_CFG_B 0x7117c diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5f50f53..ee7f88e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12415,6 +12415,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, bool is_crtc_enabled = crtc_state->active; bool turn_off, turn_on, visible, was_visible; struct drm_framebuffer *fb = plane_state->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(plane_state->state); int ret; if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { @@ -12501,6 +12503,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, !needs_scaling(old_plane_state)) pipe_config->disable_lp_wm = true; + if (fb && (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { + intel_state->wm_results.y_plane_mask |= + (1 << drm_plane_index(plane)); + } else { + intel_state->wm_results.y_plane_mask &= + ~(1 << drm_plane_index(plane)); + } + return 0; } @@ -13963,6 +13974,10 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; + /* Copy the Y-tile WA related states */ + intel_state->wm_results.y_plane_mask = + dev_priv->wm.skl_results.y_plane_mask; + for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); @@ -14204,6 +14219,32 @@ static void intel_update_crtcs(struct drm_atomic_state *state, } } +/* + * GEN9 IPC WA for Y-tiled + */ +void bxt_set_ipc_wa(struct drm_i915_private *dev_priv, bool enable) +{ + u32 val; + + if (!IS_BROXTON(dev_priv) || !i915.enable_ipc) + return; + + val = I915_READ(CHICKEN_DCPR_1); + /* +* If WA is already enabled or disabled +* no need to re-enable or disable it. +*/ + if ((enable && (val & IDLE_WAKEMEM_MASK)) || + (!enable && !(val & IDLE_WAKEMEM_MASK))) + return; + + if (enable) + val |= IDLE_WAKEMEM_MASK; + else + val &= ~IDLE_WAKEMEM_MASK; + I915_WRITE(CHICKEN_DCPR_1, val); +} + static void skl_update_crtcs(struct drm_atomic_state *state, unsigned int *crtc_vblank_mask) { @@ -14219,6 +14260,12 @@ static void skl_update_crtcs(struct drm_atomic_state *state, enum pipe pipe; /* +* If IPC WA need to be enabled, enable it now +*/ + if (intel_state->wm_results.y_plane_mask) + bxt_set_ipc_wa(dev_priv, true); + + /* * Whenever the number of active pipes changes, we need to make sure we * update the pipes in the right order so that their ddb allocations * never overlap with eachother inbetween CRTC updates. Otherwise we'll @@ -14261,6 +14308,9 @@ static void
[Intel-gfx] [PATCH v3 0/9] New DDB Algo and WM fixes
From: Mahesh KumarThis series implements new DDB allocation algorithm to solve the cases, where we have sufficient DDB available to enable multiple planes, But due to the current algorithm not dividing it properly among planes, we end-up failing the flip. It also takes care of enabling same watermark level for each plane, for efficient power saving. This series also implements Transition Watermarks and Gen-9 related arbitrated display bandwidth Workarounds. There are two steps in current WM programming. 1. Calculate minimum number of blocks required for a WM level to be enabled. For 1440x2560 panel we need 41 blocks as minimum number of blocks to enable WM0. This is the step which doesn't use vertical size. It only depends on Pipe drain rate and plane horizontal size as per the current Bspec algorithm. So all the plane below have minimum number of blocks required to enable WM0 as 41 Plane 1 - 1440x2560-Min blocks to enable WM0 = 41 Plane 2 - 1440x2560-Min blocks to enable WM0 = 41 Plane 3 - 1440x48 -Min blocks to enable WM0 = 41 Plane 4 - 1440x96 -Min blocks to enable WM0 = 41 2. Number of blocks allotted by the driver Driver allocates 12 for Plane 3 & 16 for plane 4 Total Dbuf Available = 508 Dbuf Available after 32 blocks for cursor = 508 - (32) = 476 allocate minimum blocks for each plane 8 * 4 = 32 remaining blocks = 476 - 32 = 444 Relative Data Rate for Planes Plane 1 = 1440 * 2560 * 3 = 11059200 Plane 2 = 1440 * 2560 * 3 = 11059200 Plane 3 = 1440 * 48 * 3 = 207360 Plane 4 = 1440 * 96 * 3 = 414720 Total Relative BW= 22740480 - Allocate Buffer buffer allocation = (Plane relative data rate / total data rate) * total remaming DDB + minimum plane DDB Plane 1 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 2 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 3 buffer allocation = (207360 / 22740480) * 444 + 8 = 12 Plane 4 buffer allocation = (414720 / 22740480) * 444 + 8 = 16 In this case it forced driver to disable Plane 3 & 4. Driver need to use more efficient way to allocate buffer that is optimum for power. New Algorithm suggested by HW team is: 1. Calculate minimum buffer allocations for each plane and for each watermark level 2. Add minimum buffer allocations required for enabling WM7 for all the planes Level 0 = 41 + 41 + 41 + 41 = 164 Level 1 = 42 + 42 + 42 + 42 = 168 Level 2 = 42 + 42 + 42 + 42 = 168 Level 3 = 94 + 94 + 94 + 94 = 376 Level 4 = 94 + 94 + 94 + 94 = 376 Level 5 = 94 + 94 + 94 + 94 = 376 Level 6 = 94 + 94 + 94 + 94 = 376 Level 7 = 94 + 94 + 94 + 94 = 376 3. Check to see how many buffer allocation are left and enable the best case. In this case since we have 476 blocks we can enable WM0-7 on all 4 planes. Let's say if we have only 200 block available then the best cases allocation is to enable Level2 which requires 168 blocks Changes since v1: - Rebased the series on top of Paulo's patches (under review) https://patchwork.freedesktop.org/series/12082/ - Add changes to calculate WM in fixed point 16.16 - Address review comments for Transition WM Changes since v2: - Added Paulo's WM fixes series URL in cover letter Mahesh Kumar (9): drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions drm/i915/skl+: use linetime latency instead of ddb size drm/i915/skl: New ddb allocation algorithm drm/i915: Decode system memory bandwidth drm/i915/gen9: WM memory bandwidth related workaround drm/i915/skl+: change WM calc to fixed point 16.16 drm/i915/bxt: Enable IPC support drm/i915/bxt: set chicken bit as IPC y-tile WA drm/i915/bxt: Implement Transition WM drivers/gpu/drm/i915/i915_drv.c | 101 + drivers/gpu/drm/i915/i915_drv.h | 29 +++ drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/i915_params.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 29 +++ drivers/gpu/drm/i915/intel_display.c | 50 + drivers/gpu/drm/i915/intel_drv.h | 12 + drivers/gpu/drm/i915/intel_pm.c | 412 +++ 8 files changed, 551 insertions(+), 88 deletions(-) -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v3 5/9] drm/i915/gen9: WM memory bandwidth related workaround
From: Mahesh KumarThis patch implemnets Workarounds related to display arbitrated memory bandwidth. These WA are applicabe for all gen-9 based platforms. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.h | 9 +++ drivers/gpu/drm/i915/intel_drv.h | 11 +++ drivers/gpu/drm/i915/intel_pm.c | 145 +++ 3 files changed, 165 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4313992..4737a0e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1074,6 +1074,13 @@ enum intel_sbi_destination { SBI_MPHY, }; +/* SKL+ Watermark arbitrated display bandwidth Workarounds */ +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) @@ -1623,6 +1630,8 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; + /* any WaterMark memory workaround Required */ + enum watermark_memory_wa mem_wa; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6cd7e8a..66cb46c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1800,6 +1800,17 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } +static inline struct intel_crtc_state * +intel_atomic_get_existing_crtc_state(struct drm_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_existing_crtc_state(state, >base); + + return to_intel_crtc_state(crtc_state); +} + static inline struct intel_plane_state * intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, struct intel_plane *plane) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7c70e07..0ec328b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3589,6 +3589,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(cstate->base.state); uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3602,10 +3604,17 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct skl_wm_level *result = _wm->wm[level]; uint16_t *out_blocks = >plane_res_b[id]; uint8_t *out_lines = >plane_res_l[id]; + enum watermark_memory_wa mem_wa; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; + mem_wa = intel_state ? intel_state->wm_results.mem_wa : WATERMARK_WA_NONE; + if (mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + width = drm_rect_width(_pstate->base.src) >> 16; height = drm_rect_height(_pstate->base.src) >> 16; @@ -3637,6 +3646,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_min_scanlines = 4; } + if (mem_wa == WATERMARK_WA_Y_TILED) + y_min_scanlines *= 2; + plane_bytes_per_line = width * cpp; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { @@ -4041,6 +4053,15 @@ skl_include_affected_pipes(struct drm_atomic_state *state) intel_state->wm_results.dirty_pipes = ~0; } + /* +* If Watermark workaround is changed we need to recalculate +* watermark values for all active pipes +*/ + if (intel_state->wm_results.mem_wa != dev_priv->wm.skl_hw.mem_wa) { + realloc_pipes = ~0; + intel_state->wm_results.dirty_pipes = ~0; + } + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { struct intel_crtc_state *cstate; @@ -4057,6 +4078,128 @@ skl_include_affected_pipes(struct drm_atomic_state *state) } static void +skl_set_memory_bandwidth_wm_wa(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *intel_crtc; + struct
[Intel-gfx] [PATCH v3 3/9] drm/i915/skl: New ddb allocation algorithm
From: Mahesh KumarThis patch implements new DDB allocation algorithm as per HW team suggestion. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane, for efficient power saving. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 129 +--- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cfd9b7d1..7c70e07 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3348,6 +3348,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; @@ -3363,8 +3364,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; unsigned int total_data_rate; + uint16_t total_min_blocks = 0; + uint16_t total_level_ddb = 0; int num_active; - int id, i; + int max_level, level; + int id, i, ret = 0; if (WARN_ON(!state)) return 0; @@ -3380,6 +3384,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } @@ -3413,19 +3418,42 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, } for (i = 0; i < PLANE_CURSOR; i++) { - alloc_size -= minimum[i]; - alloc_size -= y_minimum[i]; + total_min_blocks += minimum[i]; + total_min_blocks += y_minimum[i]; } - /* -* 2. Distribute the remaining space in proportion to the amount of -* data each plane needs to fetch from memory. -* -* FIXME: we may not allocate every single block here. -*/ + for (level = ilk_wm_max_level(dev); level >= 0; level--) { + total_level_ddb = 0; + for (i = 0; i < PLANE_CURSOR; i++) { + /* +* TODO: We should calculate watermark values for Y/UV +* plane both in case of NV12 format and use both values +* for ddb calculation, As NV12 is disabled as of now. +* using only single plane value here. +*/ + uint16_t min = minimum[i] + y_minimum[i]; + uint16_t plane_level_ddb_wm = + max(pipe_wm->wm[level].plane_res_b[i], min); + total_level_ddb += plane_level_ddb_wm; + } + + if (total_level_ddb <= alloc_size) + break; + } + + if ((level < 0) || (total_min_blocks > alloc_size)) { + DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations"); + DRM_DEBUG_KMS("minimum required %d/%d\n", (level < 0) ? + total_level_ddb : total_min_blocks, alloc_size); + ret = -EINVAL; + goto exit; + } + max_level = level; + alloc_size -= total_level_ddb; + total_data_rate = skl_get_total_relative_data_rate(cstate); if (total_data_rate == 0) - return 0; + goto exit; start = alloc->start; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3440,7 +3468,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[id]; + plane_blocks = max(pipe_wm->wm[max_level].plane_res_b[id], + minimum[id]); plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); @@ -3454,6 +3483,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* * allocation for y_plane part of planar format: +* TODO: Once we start calculating watermark values for Y/UV +* plane both consider it for initial allowed wm blocks. */
[Intel-gfx] [PATCH v3 2/9] drm/i915/skl+: use linetime latency instead of ddb size
From: Mahesh KumarThis patch make changes to use linetime latency instead of allocated DDB size during plane watermark calculation in switch case, This is required to implement new DDB allocation algorithm. In New Algorithm DDB is allocated based on WM values, because of which number of DDB blocks will not be available during WM calculation, So this "linetime latency" is suggested by SV/HW team to use during switch-case for WM blocks selection. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3fdec4d..cfd9b7d1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3622,10 +3622,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { selected_result = max(method2, y_tile_minimum); } else { + uint32_t linetime_us = 0; + + linetime_us = DIV_ROUND_UP(width * 1000, + skl_pipe_pixel_rate(cstate)); + if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && (plane_bytes_per_line / 512 < 1)) selected_result = method2; - else if ((ddb_allocation / plane_blocks_per_line) >= 1) + if (latency >= linetime_us) selected_result = min(method1, method2); else selected_result = method1; -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 3/9] drm/i915/skl: New ddb allocation algorithm
From: Mahesh KumarThis patch implements new DDB allocation algorithm as per HW team suggestion. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane, for efficient power saving. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 129 +--- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cfd9b7d1..7c70e07 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3348,6 +3348,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; @@ -3363,8 +3364,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; unsigned int total_data_rate; + uint16_t total_min_blocks = 0; + uint16_t total_level_ddb = 0; int num_active; - int id, i; + int max_level, level; + int id, i, ret = 0; if (WARN_ON(!state)) return 0; @@ -3380,6 +3384,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } @@ -3413,19 +3418,42 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, } for (i = 0; i < PLANE_CURSOR; i++) { - alloc_size -= minimum[i]; - alloc_size -= y_minimum[i]; + total_min_blocks += minimum[i]; + total_min_blocks += y_minimum[i]; } - /* -* 2. Distribute the remaining space in proportion to the amount of -* data each plane needs to fetch from memory. -* -* FIXME: we may not allocate every single block here. -*/ + for (level = ilk_wm_max_level(dev); level >= 0; level--) { + total_level_ddb = 0; + for (i = 0; i < PLANE_CURSOR; i++) { + /* +* TODO: We should calculate watermark values for Y/UV +* plane both in case of NV12 format and use both values +* for ddb calculation, As NV12 is disabled as of now. +* using only single plane value here. +*/ + uint16_t min = minimum[i] + y_minimum[i]; + uint16_t plane_level_ddb_wm = + max(pipe_wm->wm[level].plane_res_b[i], min); + total_level_ddb += plane_level_ddb_wm; + } + + if (total_level_ddb <= alloc_size) + break; + } + + if ((level < 0) || (total_min_blocks > alloc_size)) { + DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations"); + DRM_DEBUG_KMS("minimum required %d/%d\n", (level < 0) ? + total_level_ddb : total_min_blocks, alloc_size); + ret = -EINVAL; + goto exit; + } + max_level = level; + alloc_size -= total_level_ddb; + total_data_rate = skl_get_total_relative_data_rate(cstate); if (total_data_rate == 0) - return 0; + goto exit; start = alloc->start; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3440,7 +3468,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[id]; + plane_blocks = max(pipe_wm->wm[max_level].plane_res_b[id], + minimum[id]); plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); @@ -3454,6 +3483,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* * allocation for y_plane part of planar format: +* TODO: Once we start calculating watermark values for Y/UV +* plane both consider it for initial allowed wm blocks. */
[Intel-gfx] [PATCH v2 7/9] drm/i915/bxt: Enable IPC support
From: Mahesh KumarThis patch adds IPC support for platforms. This patch enables IPC only for BXT platform as for SKL recommendation is to keep is disabled This patch also adds kernel command-line option to enable/disable the IPC if required. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c| 5 + drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/i915_params.h | 1 + drivers/gpu/drm/i915/i915_reg.h| 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c| 21 + 6 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0a4f18d..22d84e6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1335,6 +1335,11 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); + /* +* Now enable the IPC for supported platforms +*/ + intel_enable_ipc(dev_priv); + /* Everything is in place, we can now relax! */ DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver.name, driver.major, driver.minor, driver.patchlevel, diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 768ad89..cc41b8d 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -62,6 +62,7 @@ struct i915_params i915 __read_mostly = { .inject_load_failure = 0, .enable_dpcd_backlight = false, .enable_gvt = false, + .enable_ipc = true, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -233,3 +234,7 @@ MODULE_PARM_DESC(enable_dpcd_backlight, module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); MODULE_PARM_DESC(enable_gvt, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); + +module_param_named(enable_ipc, i915.enable_ipc, bool, 0400); +MODULE_PARM_DESC(enable_ipc, + "Enable Isochronous Priority Control (default:true)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 3a0dd78..f99b9b9 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -65,6 +65,7 @@ struct i915_params { bool enable_dp_mst; bool enable_dpcd_backlight; bool enable_gvt; + bool enable_ipc; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b38445c..75b5b52 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6139,6 +6139,7 @@ enum { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST(1<<31) #define DBUF_POWER_STATE (1<<30) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bd45a2c..4645d6e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1760,6 +1760,7 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); +void intel_enable_ipc(struct drm_i915_private *dev_priv); static inline int intel_enable_rc6(void) { return i915.enable_rc6; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d4390e4..8d0037c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4793,6 +4793,27 @@ void intel_update_watermarks(struct drm_crtc *crtc) } /* + * enable IPC for Supported Platforms + */ +void intel_enable_ipc(struct drm_i915_private *dev_priv) +{ + u32 val; + + /* enable IPC only for Broxton for now*/ + if (!IS_BROXTON(dev_priv)) + return; + + val = I915_READ(DISP_ARB_CTL2); + + if (i915.enable_ipc) + val |= DISP_IPC_ENABLE; + else + val &= ~DISP_IPC_ENABLE; + + I915_WRITE(DISP_ARB_CTL2, val); +} + +/* * Lock protecting IPS related data structures */ DEFINE_SPINLOCK(mchdev_lock); -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 5/9] drm/i915/gen9: WM memory bandwidth related workaround
From: Mahesh KumarThis patch implemnets Workariunds related to display arbitrated memory bandwidth. These WA are applicabe for all gen-9 based platforms. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.h | 9 +++ drivers/gpu/drm/i915/intel_drv.h | 11 +++ drivers/gpu/drm/i915/intel_pm.c | 145 +++ 3 files changed, 165 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8236927..7964c0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1061,6 +1061,13 @@ enum intel_sbi_destination { SBI_MPHY, }; +/* SKL+ Watermark arbitrated display bandwidth Workarounds */ +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) @@ -1610,6 +1617,8 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; + /* any WaterMark memory workaround Required */ + enum watermark_memory_wa mem_wa; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ed6b53f..bd45a2c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1807,6 +1807,17 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } +static inline struct intel_crtc_state * +intel_atomic_get_existing_crtc_state(struct drm_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_existing_crtc_state(state, >base); + + return to_intel_crtc_state(crtc_state); +} + static inline struct intel_plane_state * intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, struct intel_plane *plane) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7c70e07..0ec328b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3589,6 +3589,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(cstate->base.state); uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3602,10 +3604,17 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct skl_wm_level *result = _wm->wm[level]; uint16_t *out_blocks = >plane_res_b[id]; uint8_t *out_lines = >plane_res_l[id]; + enum watermark_memory_wa mem_wa; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; + mem_wa = intel_state ? intel_state->wm_results.mem_wa : WATERMARK_WA_NONE; + if (mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + width = drm_rect_width(_pstate->base.src) >> 16; height = drm_rect_height(_pstate->base.src) >> 16; @@ -3637,6 +3646,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_min_scanlines = 4; } + if (mem_wa == WATERMARK_WA_Y_TILED) + y_min_scanlines *= 2; + plane_bytes_per_line = width * cpp; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { @@ -4041,6 +4053,15 @@ skl_include_affected_pipes(struct drm_atomic_state *state) intel_state->wm_results.dirty_pipes = ~0; } + /* +* If Watermark workaround is changed we need to recalculate +* watermark values for all active pipes +*/ + if (intel_state->wm_results.mem_wa != dev_priv->wm.skl_hw.mem_wa) { + realloc_pipes = ~0; + intel_state->wm_results.dirty_pipes = ~0; + } + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { struct intel_crtc_state *cstate; @@ -4057,6 +4078,128 @@ skl_include_affected_pipes(struct drm_atomic_state *state) } static void +skl_set_memory_bandwidth_wm_wa(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *intel_crtc; + struct
[Intel-gfx] [PATCH v2 6/9] drm/i915/skl+: change WM calc to fixed point 16.16
From: Mahesh KumarThis patch changes Watermak calculation to fixed point calculation. Problem with current calculation is during plane_blocks_per_line calculation we divide intermediate blocks with min_scanlines and takes floor of the result because of integer operation. hence we end-up assigning less blocks than required. Which leads to flickers. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0ec328b..d4390e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3530,13 +3530,15 @@ static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) */ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency) { - uint32_t wm_intermediate_val, ret; + uint64_t wm_intermediate_val; + uint32_t ret; if (latency == 0) return UINT_MAX; - wm_intermediate_val = latency * pixel_rate * cpp / 512; - ret = DIV_ROUND_UP(wm_intermediate_val, 1000); + wm_intermediate_val = latency * pixel_rate * cpp; + wm_intermediate_val <<= 16; + ret = DIV_ROUND_UP_ULL(wm_intermediate_val, 1000 * 512); return ret; } @@ -3605,6 +3607,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint16_t *out_blocks = >plane_res_b[id]; uint8_t *out_lines = >plane_res_l[id]; enum watermark_memory_wa mem_wa; + bool y_tiled = false; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; @@ -3652,14 +3655,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, plane_bytes_per_line = width * cpp; if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + y_tiled = true; plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); - plane_blocks_per_line /= y_min_scanlines; + plane_blocks_per_line = (plane_blocks_per_line << 16) / + y_min_scanlines; } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; + plane_blocks_per_line <<= 16; } else { plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + plane_blocks_per_line <<= 16; } method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); @@ -3670,8 +3677,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_tile_minimum = plane_blocks_per_line * y_min_scanlines; - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { selected_result = max(method2, y_tile_minimum); } else { uint32_t linetime_us = 0; @@ -3688,12 +3694,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, selected_result = method1; } - res_blocks = selected_result + 1; + res_blocks = DIV_ROUND_UP(selected_result, 1 << 16) + 1; res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); if (level >= 1 && level <= 7) { - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { + if (y_tiled) { res_blocks += y_tile_minimum; res_lines += y_min_scanlines; } else { -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 0/9] New DDB Algo and WM fixes
From: Mahesh KumarThis series implements new DDB allocation algorithm to solve the cases, where we have sufficient DDB available to enable multiple planes, But due to the current algorithm not dividing it properly among planes, we end-up failing the flip. It also takes care of enabling same watermark level for each plane, for efficient power saving. This series also implements Transition Watermarks and Gen-9 related arbitrated display bandwidth Workarounds. There are two steps in current WM programming. 1. Calculate minimum number of blocks required for a WM level to be enabled. For 1440x2560 panel we need 41 blocks as minimum number of blocks to enable WM0. This is the step which doesn't use vertical size. It only depends on Pipe drain rate and plane horizontal size as per the current Bspec algorithm. So all the plane below have minimum number of blocks required to enable WM0 as 41 Plane 1 - 1440x2560-Min blocks to enable WM0 = 41 Plane 2 - 1440x2560-Min blocks to enable WM0 = 41 Plane 3 - 1440x48 -Min blocks to enable WM0 = 41 Plane 4 - 1440x96 -Min blocks to enable WM0 = 41 2. Number of blocks allotted by the driver Driver allocates 12 for Plane 3 & 16 for plane 4 Total Dbuf Available = 508 Dbuf Available after 32 blocks for cursor = 508 - (32) = 476 allocate minimum blocks for each plane 8 * 4 = 32 remaining blocks = 476 - 32 = 444 Relative Data Rate for Planes Plane 1 = 1440 * 2560 * 3 = 11059200 Plane 2 = 1440 * 2560 * 3 = 11059200 Plane 3 = 1440 * 48 * 3 = 207360 Plane 4 = 1440 * 96 * 3 = 414720 Total Relative BW= 22740480 - Allocate Buffer buffer allocation = (Plane relative data rate / total data rate) * total remaming DDB + minimum plane DDB Plane 1 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 2 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 3 buffer allocation = (207360 / 22740480) * 444 + 8 = 12 Plane 4 buffer allocation = (414720 / 22740480) * 444 + 8 = 16 In this case it forced driver to disable Plane 3 & 4. Driver need to use more efficient way to allocate buffer that is optimum for power. New Algorithm suggested by HW team is: 1. Calculate minimum buffer allocations for each plane and for each watermark level 2. Add minimum buffer allocations required for enabling WM7 for all the planes Level 0 = 41 + 41 + 41 + 41 = 164 Level 1 = 42 + 42 + 42 + 42 = 168 Level 2 = 42 + 42 + 42 + 42 = 168 Level 3 = 94 + 94 + 94 + 94 = 376 Level 4 = 94 + 94 + 94 + 94 = 376 Level 5 = 94 + 94 + 94 + 94 = 376 Level 6 = 94 + 94 + 94 + 94 = 376 Level 7 = 94 + 94 + 94 + 94 = 376 3. Check to see how many buffer allocation are left and enable the best case. In this case since we have 476 blocks we can enable WM0-7 on all 4 planes. Let's say if we have only 200 block available then the best cases allocation is to enable Level2 which requires 168 blocks Changes since v1: - Rebased the series on top of Paulo's patches - Add changes to calculate WM in fixed point 16.16 - Address review comments for Transition WM Mahesh Kumar (9): drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions drm/i915/skl+: use linetime latency instead of ddb size drm/i915/skl: New ddb allocation algorithm drm/i915: Decode system memory bandwidth drm/i915/gen9: WM memory bandwidth related workaround drm/i915/skl+: change WM calc to fixed point 16.16 drm/i915/bxt: Enable IPC support drm/i915/bxt: set chicken bit as IPC y-tile WA drm/i915/bxt: Implement Transition WM drivers/gpu/drm/i915/i915_drv.c | 101 + drivers/gpu/drm/i915/i915_drv.h | 29 +++ drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/i915_params.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 29 +++ drivers/gpu/drm/i915/intel_display.c | 50 + drivers/gpu/drm/i915/intel_drv.h | 12 + drivers/gpu/drm/i915/intel_pm.c | 412 +++ 8 files changed, 551 insertions(+), 88 deletions(-) -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 4/9] drm/i915: Decode system memory bandwidth
From: Mahesh KumarThis patch adds support to decode system memory bandwidth which will be used for arbitrated display memory percentage calculation in GEN9 based system. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.c | 96 + drivers/gpu/drm/i915/i915_drv.h | 18 drivers/gpu/drm/i915/i915_reg.h | 25 +++ 3 files changed, 139 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 02c34d6..0a4f18d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -973,6 +973,96 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores)); } +static void +intel_get_memdev_info(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + uint32_t val = 0; + uint32_t mem_speed = 0; + uint8_t dram_type; + uint32_t dram_channel; + uint8_t num_channel; + bool rank_valid = false; + + if (!IS_GEN9(dev_priv)) + goto exit; + + val = I915_READ(P_CR_MC_BIOS_REQ_0_0_0); + mem_speed = div_u64((uint64_t) (val & REQ_DATA_MASK) * + MEMORY_FREQ_MULTIPLIER, 1000); + + if (mem_speed == 0) + goto exit; + + dev_priv->memdev_info.valid = true; + dev_priv->memdev_info.mem_speed = mem_speed; + dram_type = (val >> DRAM_TYPE_SHIFT) & DRAM_TYPE_MASK; + dram_channel = (val >> DRAM_CHANNEL_SHIFT) & DRAM_CHANNEL_MASK; + num_channel = hweight32(dram_channel); + + /* +* The lpddr3 and lpddr4 technologies can have 1-4 channels and the +* channels are 32bits wide; while ddr3l technologies can have 1-2 +* channels and the channels are 64 bits wide. But SV team found that in +* case of single 64 bit wide DDR3L dimms two bits were set and system +* with two DDR3L 64bit dimm all four bits were set. +*/ + + switch (dram_type) { + case DRAM_TYPE_LPDDR3: + case DRAM_TYPE_LPDDR4: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + break; + case DRAM_TYPE_DDR3L: + dev_priv->memdev_info.data_width = 8; + dev_priv->memdev_info.num_channel = num_channel / 2; + break; + default: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + } + + /* +* Now read each DUNIT8/9/10/11 to check the rank of each dimms. +* all the dimms should have same rank as in first valid Dimm +*/ +#define D_CR_DRP0_DUNIT_INVALID0x + + dev_priv->memdev_info.rank_valid = true; + if (I915_READ(D_CR_DRP0_DUNIT8) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT8); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT9) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT9); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT10) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT10); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT11) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT11); + rank_valid = true; + } +#undef D_CR_DRP0_DUNIT_INVALID + + if (rank_valid) { + dev_priv->memdev_info.rank_valid = true; + dev_priv->memdev_info.rank = (val & DRAM_RANK_MASK); + } + + DRM_DEBUG_DRIVER("valid:%s speed-%d width-%d num_channel-%d\n", + dev_priv->memdev_info.valid ? "true" : "false", + dev_priv->memdev_info.mem_speed, + dev_priv->memdev_info.data_width, + dev_priv->memdev_info.num_channel); + DRM_DEBUG_DRIVER("rank_valid:%s rank-%d\n", + dev_priv->memdev_info.rank_valid ? "true" : "false", + dev_priv->memdev_info.rank); + return; +exit: + dev_priv->memdev_info.valid = false; +} + /** * i915_driver_init_hw - setup state requiring device access * @dev_priv: device private @@ -1076,6 +1166,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("can't enable MSI"); } + /* +* Fill the memdev structure to get the system raw bandwidth +* This will be used by WM algorithm, to implement GEN9 based WA +*/ + intel_get_memdev_info(dev); + return 0; out_ggtt: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f05869b..8236927 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@
[Intel-gfx] [PATCH v2 1/9] drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions
From: Mahesh KumarThis patch make use of plane_wm variable directly instead of passing skl_plane_wm struct. this way reduces number of argument requirement in watermark calculation functions. It also gives more freedom of decision making to implement Bspec WM workarounds. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 29 +++-- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 86c6d66..3fdec4d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3542,9 +3542,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_plane_state *intel_pstate, uint16_t ddb_allocation, int level, - uint16_t *out_blocks, /* out */ - uint8_t *out_lines, /* out */ - bool *enabled /* out */) + struct skl_pipe_wm *pipe_wm) { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; @@ -3557,6 +3555,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; uint32_t y_tile_minimum, y_min_scanlines; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + struct skl_wm_level *result = _wm->wm[level]; + uint16_t *out_blocks = >plane_res_b[id]; + uint8_t *out_lines = >plane_res_l[id]; + bool *enabled = >plane_en[id]; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3673,7 +3676,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, int level, -struct skl_wm_level *result) +struct skl_pipe_wm *pipe_wm) { struct drm_atomic_state *state = cstate->base.state; struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); @@ -3684,12 +3687,6 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, enum pipe pipe = intel_crtc->pipe; int ret; - /* -* We'll only calculate watermarks for planes that are actually -* enabled, so make sure all other planes are set as disabled. -*/ - memset(result, 0, sizeof(*result)); - for_each_intel_plane_mask(_priv->drm, intel_plane, cstate->base.plane_mask) { @@ -3727,9 +3724,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, intel_pstate, ddb_blocks, level, - >plane_res_b[i], - >plane_res_l[i], - >plane_en[i]); + pipe_wm); if (ret) return ret; } @@ -3777,9 +3772,15 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, int level, max_level = ilk_wm_max_level(dev); int ret; + /* +* We'll only calculate watermarks for planes that are actually +* enabled, so make sure all other planes are set as disabled. +*/ + memset(pipe_wm, 0, sizeof(*pipe_wm)); + for (level = 0; level <= max_level; level++) { ret = skl_compute_wm_level(dev_priv, ddb, cstate, - level, _wm->wm[level]); + level, pipe_wm); if (ret) return ret; } -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2 9/9] drm/i915/bxt: Implement Transition WM
From: Mahesh KumarThis patch enables Transition WM for SKL+ platforms. Transition WM are used if IPC is enabled, to decide, number of blocks to be fetched before reducing the priority of display to fetch from memory. Changes since v1: - Don't enable transition WM for GEN9 (Art/Paulo) - Rebase to use fixed point 16.16 calculation - Fix the use of selected result from latency level-0 Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 60 ++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8d0037c..f6a3fab 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2862,6 +2862,8 @@ bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 +#define SKL_TRANS_WM_AMOUNT10 /* tunable value */ +#define SKL_TRANS_WM_MIN 14 #define SKL_SAGV_BLOCK_TIME30 /* µs */ /* @@ -3583,6 +3585,48 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst return pixel_rate; } +static void skl_compute_plane_trans_wm(const struct drm_i915_private *dev_priv, + struct skl_pipe_wm *pipe_wm, + struct intel_plane_state *intel_pstate, + uint32_t selected_result, + uint32_t y_tile_min, + bool y_tile) +{ + struct drm_plane_state *pstate = _pstate->base; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + uint16_t *out_blocks = _wm->trans_wm.plane_res_b[id]; + uint8_t *out_lines = _wm->trans_wm.plane_res_l[id]; + uint32_t trans_min = 0, trans_offset_blocks; + uint32_t trans_y_tile_min = 0, res_blocks = 0; + uint16_t trans_res_blocks = 0; + + /* Keep Trans WM disabled for GEN9 */ + if (IS_GEN9(dev_priv)) + goto exit; + + trans_min = SKL_TRANS_WM_MIN; + + trans_offset_blocks = (trans_min + SKL_TRANS_WM_AMOUNT) << 16; + + if (y_tile) { + trans_y_tile_min = 2 * y_tile_min; + res_blocks = max(trans_y_tile_min, selected_result) + + trans_offset_blocks; + } else { + res_blocks = selected_result + trans_offset_blocks; + } + + trans_res_blocks = DIV_ROUND_UP(res_blocks, 1 << 16) + 1; + + /* WA BUG:1938466 add one block for non y-tile planes */ + if (!y_tile) + trans_res_blocks += 1; +exit: + *out_blocks = trans_res_blocks; + *out_lines = 0; +} + + static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, struct intel_plane_state *intel_pstate, @@ -3709,6 +3753,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, *out_blocks = res_blocks; *out_lines = res_lines; + if (level == 0) + skl_compute_plane_trans_wm(dev_priv, pipe_wm, intel_pstate, + selected_result, y_tile_minimum, y_tiled); return 0; } @@ -3778,11 +3825,13 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, - struct skl_wm_level *trans_wm /* out */) + struct skl_wm_level *trans_wm, /* out */ + struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = cstate->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane; + enum pipe pipe = to_intel_crtc(crtc)->pipe; if (!cstate->base.active) return; @@ -3790,8 +3839,13 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, /* Until we know more, just disable transition WMs */ for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { int i = skl_wm_plane_id(intel_plane); + uint16_t plane_ddb = skl_ddb_entry_size(>plane[pipe][i]); + uint16_t trans_res_blocks = trans_wm->plane_res_b[i]; - trans_wm->plane_en[i] = false; + if ((plane_ddb > 0) && (trans_res_blocks > plane_ddb)) + trans_wm->plane_en[i] = false; + else + trans_wm->plane_en[i] = true; } } @@ -3822,7 +3876,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, pipe_wm->linetime = skl_compute_linetime_wm(cstate); - skl_compute_transition_wm(cstate, _wm->trans_wm); + skl_compute_transition_wm(cstate,
[Intel-gfx] [PATCH v2 8/9] drm/i915/bxt: set chicken bit as IPC y-tile WA
From: Mahesh KumarIt implements the WA to enable IDLE_WAKEMEM bit of CHICKEN_DCPR_1 register for Broxton platform. When IPC is enabled & Y-tile is enabled in any of the enabled plane, above bit should be set. Without this WA system observes random hang. Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 50 3 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7964c0f..c94eedb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1619,6 +1619,8 @@ struct skl_wm_values { unsigned dirty_pipes; /* any WaterMark memory workaround Required */ enum watermark_memory_wa mem_wa; + /* IPC Y-tiled WA related member */ + u32 y_plane_mask; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 75b5b52..210d9b0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5658,6 +5658,9 @@ enum { #define PLANE_NV12_BUF_CFG(pipe, plane)\ _MMIO_PLANE(plane, _PLANE_NV12_BUF_CFG_1(pipe), _PLANE_NV12_BUF_CFG_2(pipe)) +#define CHICKEN_DCPR_1 _MMIO(0x46430) +#define IDLE_WAKEMEM_MASK (1 << 13) + /* SKL new cursor registers */ #define _CUR_BUF_CFG_A 0x7017c #define _CUR_BUF_CFG_B 0x7117c diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a6c3caa..c75685d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12429,6 +12429,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, bool is_crtc_enabled = crtc_state->active; bool turn_off, turn_on, visible, was_visible; struct drm_framebuffer *fb = plane_state->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(plane_state->state); int ret; if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { @@ -12515,6 +12517,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, !needs_scaling(old_plane_state)) pipe_config->disable_lp_wm = true; + if (fb && (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || + fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { + intel_state->wm_results.y_plane_mask |= + (1 << drm_plane_index(plane)); + } else { + intel_state->wm_results.y_plane_mask &= + ~(1 << drm_plane_index(plane)); + } + return 0; } @@ -13985,6 +13996,10 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; + /* Copy the Y-tile WA related states */ + intel_state->wm_results.y_plane_mask = + dev_priv->wm.skl_results.y_plane_mask; + for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); @@ -14226,6 +14241,32 @@ static void intel_update_crtcs(struct drm_atomic_state *state, } } +/* + * GEN9 IPC WA for Y-tiled + */ +void bxt_set_ipc_wa(struct drm_i915_private *dev_priv, bool enable) +{ + u32 val; + + if (!IS_BROXTON(dev_priv) || !i915.enable_ipc) + return; + + val = I915_READ(CHICKEN_DCPR_1); + /* +* If WA is already enabled or disabled +* no need to re-enable or disable it. +*/ + if ((enable && (val & IDLE_WAKEMEM_MASK)) || + (!enable && !(val & IDLE_WAKEMEM_MASK))) + return; + + if (enable) + val |= IDLE_WAKEMEM_MASK; + else + val &= ~IDLE_WAKEMEM_MASK; + I915_WRITE(CHICKEN_DCPR_1, val); +} + static void skl_update_crtcs(struct drm_atomic_state *state, unsigned int *crtc_vblank_mask) { @@ -14241,6 +14282,12 @@ static void skl_update_crtcs(struct drm_atomic_state *state, enum pipe pipe; /* +* If IPC WA need to be enabled, enable it now +*/ + if (intel_state->wm_results.y_plane_mask) + bxt_set_ipc_wa(dev_priv, true); + + /* * Whenever the number of active pipes changes, we need to make sure we * update the pipes in the right order so that their ddb allocations * never overlap with eachother inbetween CRTC updates. Otherwise we'll @@ -14283,6 +14330,9 @@ static void
[Intel-gfx] [PATCH v2 2/9] drm/i915/skl+: use linetime latency instead of ddb size
From: Mahesh KumarThis patch make changes to use linetime latency instead of allocated DDB size during plane watermark calculation in switch case, This is required to implement new DDB allocation algorithm. In New Algorithm DDB is allocated based on WM values, because of which number of DDB blocks will not be available during WM calculation, So this "linetime latency" is suggested by SV/HW team to use during switch-case for WM blocks selection. Changes since v1: - Rebase on top of Paulo's patch series Signed-off-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3fdec4d..cfd9b7d1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3622,10 +3622,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { selected_result = max(method2, y_tile_minimum); } else { + uint32_t linetime_us = 0; + + linetime_us = DIV_ROUND_UP(width * 1000, + skl_pipe_pixel_rate(cstate)); + if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && (plane_bytes_per_line / 512 < 1)) selected_result = method2; - else if ((ddb_allocation / plane_blocks_per_line) >= 1) + if (latency >= linetime_us) selected_result = min(method1, method2); else selected_result = method1; -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] FOR_UPSTREAM [VPG]: drm/i915/skl+: Implement Transition WM
This patch enables Transition WM for SKL+ platforms. Transition WM are used if IPC is enabled, to decide, number of blocks to be fetched before reducing the priority of display to fetch from memory. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 57 ++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9f69050..f4f387f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2861,6 +2861,8 @@ bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 #define SKL_SAGV_BLOCK_TIME30 /* µs */ +#define SKL_TRANS_WM_AMOUNT10 +#define SKL_TRANS_WM_MIN 14 /* * Return the index of a plane in the SKL DDB and wm result arrays. Primary @@ -3579,6 +3581,41 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst return pixel_rate; } +static void skl_compute_plane_trans_wm(const struct drm_i915_private *dev_priv, + struct skl_pipe_wm *pipe_wm, + struct intel_plane_state *intel_pstate, + uint32_t y_tile_min, + bool y_tile) +{ + struct drm_plane_state *pstate = _pstate->base; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + uint16_t *out_blocks = _wm->trans_wm.plane_res_b[id]; + uint8_t *out_lines = _wm->trans_wm.plane_res_l[id]; + uint16_t res_blocks = pipe_wm->wm[0].plane_res_b[id]; + uint32_t trans_min = 0, trans_offset_blocks; + uint16_t trans_y_tile_min = 0; + uint16_t trans_res_blocks; + + + if (IS_GEN9(dev_priv)) + trans_min = SKL_TRANS_WM_MIN; + + trans_offset_blocks = trans_min + SKL_TRANS_WM_AMOUNT; + + if (y_tile) { + trans_y_tile_min = 2 * y_tile_min; + trans_res_blocks = max(trans_y_tile_min, res_blocks) + + trans_offset_blocks; + } else { + trans_res_blocks = res_blocks + trans_offset_blocks; + /* WA BUG:1938466 add one block for non y-tile planes */ + trans_res_blocks += 1; + } + + *out_blocks = trans_res_blocks; + *out_lines = 0; +} + static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_crtc_state *cstate, struct intel_plane_state *intel_pstate, @@ -3600,6 +3637,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct skl_wm_level *result = _wm->wm[level]; uint16_t *out_blocks = >plane_res_b[id]; uint8_t *out_lines = >plane_res_l[id]; + uint32_t y_tile_minimum = 0; + bool y_tile = false; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; @@ -3627,7 +3666,6 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { uint32_t min_scanlines = 4; - uint32_t y_tile_minimum; if (intel_rotation_90_or_270(pstate->rotation)) { int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? drm_format_plane_cpp(fb->pixel_format, 1) : @@ -3646,6 +3684,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } y_tile_minimum = plane_blocks_per_line * min_scanlines; selected_result = max(method2, y_tile_minimum); + y_tile = true; } else { linetime_us = DIV_ROUND_UP(width * 1000, skl_pipe_pixel_rate(cstate)); @@ -3669,6 +3708,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, *out_blocks = res_blocks; *out_lines = res_lines; + if (level == 0) + skl_compute_plane_trans_wm(dev_priv, pipe_wm, intel_pstate, + y_tile_minimum, y_tile); return 0; } @@ -3738,11 +3780,13 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, - struct skl_wm_level *trans_wm /* out */) + struct skl_wm_level *trans_wm, + struct skl_ddb_allocation *ddb) { struct drm_crtc *crtc = cstate->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane; + enum pipe p
[Intel-gfx] [PATCH 2/7] drm/i915/skl+: use linetime latency instead of ddb size
This patch make changes to use linetime latency instead of allocated DDB size during plane watermark calculation in switch case, This is required to implement new DDB allocation algorithm. In New Algorithm DDB is allocated based on WM values, because of which number of DDB blocks will not be available during WM calculation, So this "linetime latency" is suggested by SV/HW team to use during switch-case for WM blocks selection. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aba6fd0..b2f17eb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3554,6 +3554,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint8_t cpp; uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; + uint32_t linetime_us = 0; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3603,7 +3604,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, y_tile_minimum = plane_blocks_per_line * min_scanlines; selected_result = max(method2, y_tile_minimum); } else { - if ((ddb_allocation / plane_blocks_per_line) >= 1) + linetime_us = DIV_ROUND_UP(width * 1000, + skl_pipe_pixel_rate(cstate)); + if (latency >= linetime_us) selected_result = min(method1, method2); else selected_result = method1; -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 4/7] drm/i915/skl: New ddb allocation algorithm
This patch implements new DDB allocation algorithm as per HW team suggestion. This algo takecare of scenario where we allocate less DDB for the planes with lower relative pixel rate, but they require more DDB to work. It also takes care of enabling same watermark level for each plane, for efficient power saving. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 129 +--- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5fa02cb..9f69050 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3331,6 +3331,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, static int skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, + struct skl_pipe_wm *pipe_wm, struct skl_ddb_allocation *ddb /* out */) { struct drm_atomic_state *state = cstate->base.state; @@ -3346,8 +3347,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t *minimum = cstate->wm.skl.minimum_blocks; uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; unsigned int total_data_rate; + uint16_t total_min_blocks = 0; + uint16_t total_level_ddb = 0; int num_active; - int id, i; + int max_level, level; + int id, i, ret = 0; if (WARN_ON(!state)) return 0; @@ -3363,6 +3367,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) { memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); + memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); return 0; } @@ -3396,19 +3401,42 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, } for (i = 0; i < PLANE_CURSOR; i++) { - alloc_size -= minimum[i]; - alloc_size -= y_minimum[i]; + total_min_blocks += minimum[i]; + total_min_blocks += y_minimum[i]; } - /* -* 2. Distribute the remaining space in proportion to the amount of -* data each plane needs to fetch from memory. -* -* FIXME: we may not allocate every single block here. -*/ + for (level = ilk_wm_max_level(dev); level >= 0; level--) { + total_level_ddb = 0; + for (i = 0; i < PLANE_CURSOR; i++) { + /* +* TODO: We should calculate watermark values for Y/UV +* plane both in case of NV12 format and use both values +* for ddb calculation, As NV12 is disabled as of now. +* using only single plane value here. +*/ + uint16_t min = minimum[i] + y_minimum[i]; + uint16_t plane_level_ddb_wm = + max(pipe_wm->wm[level].plane_res_b[i], min); + total_level_ddb += plane_level_ddb_wm; + } + + if (total_level_ddb <= alloc_size) + break; + } + + if ((level < 0) || (total_min_blocks > alloc_size)) { + DRM_DEBUG_KMS("Requested display configuration exceeds system DDB limitations"); + DRM_DEBUG_KMS("minimum required %d/%d\n", (level < 0) ? + total_level_ddb : total_min_blocks, alloc_size); + ret = -EINVAL; + goto exit; + } + max_level = level; + alloc_size -= total_level_ddb; + total_data_rate = skl_get_total_relative_data_rate(cstate); if (total_data_rate == 0) - return 0; + goto exit; start = alloc->start; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3423,7 +3451,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * promote the expression to 64 bits to avoid overflowing, the * result is < available as data_rate / total_data_rate < 1 */ - plane_blocks = minimum[id]; + plane_blocks = max(pipe_wm->wm[max_level].plane_res_b[id], + minimum[id]); plane_blocks += div_u64((uint64_t)alloc_size * data_rate, total_data_rate); @@ -3437,6 +3466,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, /* * allocation for y_plane part of planar format: +* TODO: Once we start calculating watermark values for Y/UV +* plane both consider it for initial allowed wm blocks. */ y_data_rate = cstate-&
[Intel-gfx] [PATCH 5/7] drm/i915: Decode system memory bandwidth
This patch adds support to decode system memory bandwidth which will be used for arbitrated display memory percentage calculation in GEN9 based system. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.c | 96 + drivers/gpu/drm/i915/i915_drv.h | 18 drivers/gpu/drm/i915/i915_reg.h | 25 +++ 3 files changed, 139 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 47fe072..5ece036 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -996,6 +996,96 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores)); } +static void +intel_get_memdev_info(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + uint32_t val = 0; + uint32_t mem_speed = 0; + uint8_t dram_type; + uint32_t dram_channel; + uint8_t num_channel; + bool rank_valid = false; + + if (!IS_GEN9(dev_priv)) + goto exit; + + val = I915_READ(P_CR_MC_BIOS_REQ_0_0_0); + mem_speed = div_u64((uint64_t) (val & REQ_DATA_MASK) * + MEMORY_FREQ_MULTIPLIER, 1000); + + if (mem_speed == 0) + goto exit; + + dev_priv->memdev_info.valid = true; + dev_priv->memdev_info.mem_speed = mem_speed; + dram_type = (val >> DRAM_TYPE_SHIFT) & DRAM_TYPE_MASK; + dram_channel = (val >> DRAM_CHANNEL_SHIFT) & DRAM_CHANNEL_MASK; + num_channel = hweight32(dram_channel); + + /* +* The lpddr3 and lpddr4 technologies can have 1-4 channels and the +* channels are 32bits wide; while ddr3l technologies can have 1-2 +* channels and the channels are 64 bits wide. But SV team found that in +* case of single 64 bit wide DDR3L dimms two bits were set and system +* with two DDR3L 64bit dimm all four bits were set. +*/ + + switch (dram_type) { + case DRAM_TYPE_LPDDR3: + case DRAM_TYPE_LPDDR4: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + break; + case DRAM_TYPE_DDR3L: + dev_priv->memdev_info.data_width = 8; + dev_priv->memdev_info.num_channel = num_channel / 2; + break; + default: + dev_priv->memdev_info.data_width = 4; + dev_priv->memdev_info.num_channel = num_channel; + } + + /* +* Now read each DUNIT8/9/10/11 to check the rank of each dimms. +* all the dimms should have same rank as in first valid Dimm +*/ +#define D_CR_DRP0_DUNIT_INVALID0x + + dev_priv->memdev_info.rank_valid = true; + if (I915_READ(D_CR_DRP0_DUNIT8) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT8); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT9) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT9); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT10) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT10); + rank_valid = true; + } else if (I915_READ(D_CR_DRP0_DUNIT11) != D_CR_DRP0_DUNIT_INVALID) { + val = I915_READ(D_CR_DRP0_DUNIT11); + rank_valid = true; + } +#undef D_CR_DRP0_DUNIT_INVALID + + if (rank_valid) { + dev_priv->memdev_info.rank_valid = true; + dev_priv->memdev_info.rank = (val & DRAM_RANK_MASK); + } + + DRM_DEBUG_DRIVER("valid:%s speed-%d width-%d num_channel-%d\n", + dev_priv->memdev_info.valid ? "true" : "false", + dev_priv->memdev_info.mem_speed, + dev_priv->memdev_info.data_width, + dev_priv->memdev_info.num_channel); + DRM_DEBUG_DRIVER("rank_valid:%s rank-%d\n", + dev_priv->memdev_info.rank_valid ? "true" : "false", + dev_priv->memdev_info.rank); + return; +exit: + dev_priv->memdev_info.valid = false; +} + /** * i915_driver_init_hw - setup state requiring device access * @dev_priv: device private @@ -1099,6 +1189,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) DRM_DEBUG_DRIVER("can't enable MSI"); } + /* +* Fill the memdev structure to get the system raw bandwidth +* This will be used by WM algorithm, to implement GEN9 based WA +*/ + intel_get_memdev_info(dev); + return 0; out_ggtt: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/
[Intel-gfx] [PATCH 0/7] Implement New DDB allocation algorithm
This series implements new DDB allocation algorithm to solve the cases, where we have sufficient DDB available to enable multiple planes, But due to the current algorithm not dividing it properly among planes, we end-up failing the flip. It also takes care of enabling same watermark level for each plane, for efficient power saving. This series also implements Transition Watermarks and Gen-9 related arbitrated display bandwidth Workarounds. There are two steps in current WM programming. 1. Calculate minimum number of blocks required for a WM level to be enabled. For 1440x2560 panel we need 41 blocks as minimum number of blocks to enable WM0. This is the step which doesn't use vertical size. It only depends on Pipe drain rate and plane horizontal size as per the current Bspec algorithm. So all the plane below have minimum number of blocks required to enable WM0 as 41 Plane 1 - 1440x2560-Min blocks to enable WM0 = 41 Plane 2 - 1440x2560-Min blocks to enable WM0 = 41 Plane 3 - 1440x48 -Min blocks to enable WM0 = 41 Plane 4 - 1440x96 -Min blocks to enable WM0 = 41 2. Number of blocks allotted by the driver Driver allocates 12 for Plane 3 & 16 for plane 4 Total Dbuf Available = 508 Dbuf Available after 32 blocks for cursor = 508 - (32) = 476 allocate minimum blocks for each plane 8 * 4 = 32 remaining blocks = 476 - 32 = 444 Relative Data Rate for Planes Plane 1 = 1440 * 2560 * 3 = 11059200 Plane 2 = 1440 * 2560 * 3 = 11059200 Plane 3 = 1440 * 48 * 3 = 207360 Plane 4 = 1440 * 96 * 3 = 414720 Total Relative BW= 22740480 - Allocate Buffer buffer allocation = (Plane relative data rate / total data rate) * total remaming DDB + minimum plane DDB Plane 1 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 2 buffer allocation = (11059200 / 22740480) * 444 + 8 = 223 Plane 3 buffer allocation = (207360 / 22740480) * 444 + 8 = 12 Plane 4 buffer allocation = (414720 / 22740480) * 444 + 8 = 16 In this case it forced driver to disable Plane 3 & 4. Driver need to use more efficient way to allocate buffer that is optimum for power. New Algorithm suggested by HW team is: 1. Calculate minimum buffer allocations for each plane and for each watermark level 2. Add minimum buffer allocations required for enabling WM7 for all the planes Level 0 = 41 + 41 + 41 + 41 = 164 Level 1 = 42 + 42 + 42 + 42 = 168 Level 2 = 42 + 42 + 42 + 42 = 168 Level 3 = 94 + 94 + 94 + 94 = 376 Level 4 = 94 + 94 + 94 + 94 = 376 Level 5 = 94 + 94 + 94 + 94 = 376 Level 6 = 94 + 94 + 94 + 94 = 376 Level 7 = 94 + 94 + 94 + 94 = 376 3. Check to see how many buffer allocation are left and enable the best case. In this case since we have 476 blocks we can enable WM0-7 on all 4 planes. Let's say if we have only 200 block available then the best cases allocation is to enable Level2 which requires 168 blocks Kumar, Mahesh (7): drm/i915/hsw+: set intel_crtc active once pipe is active drm/i915/skl+: use linetime latency instead of ddb size drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions drm/i915/skl: New ddb allocation algorithm drm/i915: Decode system memory bandwidth FOR_UPSTREAM [VPG]: drm/i915/skl+: Implement Transition WM drm/i915/gen9: WM memory bandwidth related workaround drivers/gpu/drm/i915/i915_drv.c | 96 + drivers/gpu/drm/i915/i915_drv.h | 27 +++ drivers/gpu/drm/i915/i915_reg.h | 25 +++ drivers/gpu/drm/i915/intel_display.c | 4 +- drivers/gpu/drm/i915/intel_drv.h | 11 ++ drivers/gpu/drm/i915/intel_pm.c | 366 +++ 6 files changed, 447 insertions(+), 82 deletions(-) -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/gen9: WM memory bandwidth related workaround
This patch implemnets Workariunds related to display arbitrated memory bandwidth. These WA are applicabe for all gen-9 based platforms. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 9 +++ drivers/gpu/drm/i915/intel_drv.h | 11 +++ drivers/gpu/drm/i915/intel_pm.c | 145 +++ 3 files changed, 165 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d0123f8..095af6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1055,6 +1055,13 @@ enum intel_sbi_destination { SBI_MPHY, }; +/* SKL+ Watermark arbitrated display bandwidth Workarounds */ +enum watermark_memory_wa { + WATERMARK_WA_NONE, + WATERMARK_WA_X_TILED, + WATERMARK_WA_Y_TILED, +}; + #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) @@ -1604,6 +1611,8 @@ struct skl_ddb_allocation { struct skl_wm_values { unsigned dirty_pipes; + /* any WaterMark memory workaround Required */ + enum watermark_memory_wa mem_wa; struct skl_ddb_allocation ddb; uint32_t wm_linetime[I915_MAX_PIPES]; uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 570a7ca..f2c38cc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1807,6 +1807,17 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } +static inline struct intel_crtc_state * +intel_atomic_get_existing_crtc_state(struct drm_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_existing_crtc_state(state, >base); + + return to_intel_crtc_state(crtc_state); +} + static inline struct intel_plane_state * intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, struct intel_plane *plane) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ac0d0ca..e9cd6ac 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3624,6 +3624,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(cstate->base.state); uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t method1, method2; uint32_t plane_bytes_per_line, plane_blocks_per_line; @@ -3639,10 +3641,17 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint8_t *out_lines = >plane_res_l[id]; uint32_t y_tile_minimum = 0; bool y_tile = false; + enum watermark_memory_wa mem_wa; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) return 0; + mem_wa = intel_state ? intel_state->wm_results.mem_wa : WATERMARK_WA_NONE; + if (mem_wa != WATERMARK_WA_NONE) { + if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) + latency += 15; + } + width = drm_rect_width(_pstate->base.src) >> 16; height = drm_rect_height(_pstate->base.src) >> 16; @@ -3682,6 +3691,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, WARN(1, "Unsupported pixel depth for rotation"); } } + if (mem_wa == WATERMARK_WA_Y_TILED) + min_scanlines *= 2; + y_tile_minimum = plane_blocks_per_line * min_scanlines; selected_result = max(method2, y_tile_minimum); y_tile = true; @@ -4065,6 +4077,15 @@ skl_include_affected_pipes(struct drm_atomic_state *state) intel_state->wm_results.dirty_pipes = ~0; } + /* +* If Watermark workaround is changed we need to recalculate +* watermark values for all active pipes +*/ + if (intel_state->wm_results.mem_wa != dev_priv->wm.skl_hw.mem_wa) { + realloc_pipes = ~0; + intel_state->wm_results.dirty_pipes = ~0; + } + for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { struct intel_crtc_state *cstate; @@ -4081,6 +4102,128 @@ skl_include_affected_pipes(struct drm_atomic_state *state) } static void +skl_set_memory_bandwidth_wm_wa(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); +
[Intel-gfx] [PATCH 3/7] drm/i915/skl: pass pipe_wm in skl_compute_(wm_level/plane_wm) functions
This patch make use of plane_wm variable directly instead of passing skl_plane_wm struct. this way reduces number of argument requirement in watermark calculation functions. It also gives more freedom of decision making to implement Bspec WM workarounds. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 29 +++-- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b2f17eb..5fa02cb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3540,9 +3540,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct intel_plane_state *intel_pstate, uint16_t ddb_allocation, int level, - uint16_t *out_blocks, /* out */ - uint8_t *out_lines, /* out */ - bool *enabled /* out */) + struct skl_pipe_wm *pipe_wm) { struct drm_plane_state *pstate = _pstate->base; struct drm_framebuffer *fb = pstate->fb; @@ -3555,6 +3553,11 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, uint32_t width = 0, height = 0; uint32_t plane_pixel_rate; uint32_t linetime_us = 0; + int id = skl_wm_plane_id(to_intel_plane(pstate->plane)); + struct skl_wm_level *result = _wm->wm[level]; + uint16_t *out_blocks = >plane_res_b[id]; + uint8_t *out_lines = >plane_res_l[id]; + bool *enabled = >plane_en[id]; if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { *enabled = false; @@ -3655,7 +3658,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, int level, -struct skl_wm_level *result) +struct skl_pipe_wm *pipe_wm) { struct drm_atomic_state *state = cstate->base.state; struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); @@ -3666,12 +3669,6 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, enum pipe pipe = intel_crtc->pipe; int ret; - /* -* We'll only calculate watermarks for planes that are actually -* enabled, so make sure all other planes are set as disabled. -*/ - memset(result, 0, sizeof(*result)); - for_each_intel_plane_mask(_priv->drm, intel_plane, cstate->base.plane_mask) { @@ -3709,9 +3706,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, intel_pstate, ddb_blocks, level, - >plane_res_b[i], - >plane_res_l[i], - >plane_en[i]); + pipe_wm); if (ret) return ret; } @@ -3759,9 +3754,15 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, int level, max_level = ilk_wm_max_level(dev); int ret; + /* +* We'll only calculate watermarks for planes that are actually +* enabled, so make sure all other planes are set as disabled. +*/ + memset(pipe_wm, 0, sizeof(*pipe_wm)); + for (level = 0; level <= max_level; level++) { ret = skl_compute_wm_level(dev_priv, ddb, cstate, - level, _wm->wm[level]); + level, pipe_wm); if (ret) return ret; } -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/7] drm/i915/hsw+: set intel_crtc active once pipe is active
Set the intel_crtc->active flag after pipe/crtc is actually active in haswell_crtc_enable function. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e4e6141..7258883 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5427,8 +5427,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_color_set_csc(_config->base); - intel_crtc->active = true; - if (intel_crtc->config->has_pch_encoder) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); else @@ -5475,6 +5473,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); + intel_crtc->active = true; + intel_encoders_enable(crtc, pipe_config, old_state); if (intel_crtc->config->has_pch_encoder) { -- 2.8.3 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/skl: Correct other-pipe watermark update condition check (v2)
Yes, it doesn't solve all warnings. Other than fbdev restore, there is one warning which I faced during DPMS/Hot-plug, which is due to calculation of watermarks twice. Once for first CRTC "Pipe-A" (during which it consider/calculates watermark for other pipe "Pipe-B" as well & stores in structure "intel_crtc->wm.active.skl") & Now in same atomic_commit, when it calculate watermark for second CRTC "Pipe-B" , that time watermark for other-pipe (in this case pipe-A) already have calculated values so it gives !wm_changed warning. Hoping 2-stage watermark programming will take care of this, as in that case, If I'm not misunderstood final results should be stored after calculation for all pipes. Regards, -Mahesh On 10/23/2015 10:11 PM, Matt Roper wrote: From: "Kumar, Mahesh" <mahesh1.ku...@intel.com> If ddb allocation for planes in current CRTC is changed, that doesn't lead to ddb allocation change for other CRTCs, because our DDB allocation is not dynamic according to plane parameters, ddb is allocated according to number of CRTC enabled, & divided equally among CTRC's. In current condition check during Watermark calculation, if number of plane/ddb allocation changes for current CRTC, Watermark for other pipes are recalculated. But there is no change in DDB allocation of other pipe so watermark is also not changed, This leads to warning messages. WARN_ON(!wm_changed) This patch corrects this and check if DDB allocation for pipes is changed, then only recalculate watermarks. v2 (by Matt): Rebased to latest -nightly and fixed a typo Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> Reviewed-by(v1): Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Matt Roper <matthew.d.ro...@intel.com> --- I don't think this solves all the !wm_changed warnings (I still see one during fbdev restore following various igt tests), but it seems like a move in the right direction so I figured I'd go ahead and rebase Mahesh' patch so it can get merged. drivers/gpu/drm/i915/intel_pm.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0fb0459..0467e34 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3064,14 +3064,12 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; const struct skl_ddb_allocation *cur_ddb = _priv->wm.skl_hw.ddb; - enum pipe pipe = intel_crtc->pipe; - - if (memcmp(new_ddb->plane[pipe], cur_ddb->plane[pipe], - sizeof(new_ddb->plane[pipe]))) - return true; - if (memcmp(_ddb->plane[pipe][PLANE_CURSOR], _ddb->plane[pipe][PLANE_CURSOR], - sizeof(new_ddb->plane[pipe][PLANE_CURSOR]))) + /* +* If ddb allocation of pipes changed, it may require recalculation of +* watermarks +*/ + if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe))) return true; return false; ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/skl: Correct other-pipe watermark update condition check
If ddb allocation for planes in current CRTC is changed, that doesn't lead to ddb allocation change for other CRTCs, because our DDB allocation is not dynamic according to plane parameters, ddb is allocated according to number of CRTC enabled, & divided equally among CTRC's. In current condition check during Watermark calculation, if number of plane/ddb allocation changes for current CRTC, Watermark for other pipes are recalculated. But there is no change in DDB allocation of other pipe so watermark is also not changed, This leads to warning messages. WARN_ON(!wm_changed) This patch corrects this and check if DDB allocation for pipes is changed, then only recalculate watermarks. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 62de97e..a1ed920 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3127,14 +3127,12 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb, struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; const struct skl_ddb_allocation *cur_ddb = _priv->wm.skl_hw.ddb; - enum pipe pipe = intel_crtc->pipe; - - if (memcmp(new_ddb->plane[pipe], cur_ddb->plane[pipe], - sizeof(new_ddb->plane[pipe]))) - return true; - if (memcmp(_ddb->cursor[pipe], _ddb->cursor[pipe], - sizeof(new_ddb->cursor[pipe]))) + /* +* If ddb allocation of pipes chenged, it may require recalculation of +* watermarks +*/ + if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe))) return true; return false; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/skl+: Fix Watermark calculation for Broxton
In case of Y-Tiling, "plane_blocks_per_line" calculation is different than X/None-Tiling case. This patch corrects this calculation according to Bspec. plane blocks per line = Plane memory format is Y tile ? ceiling[4 * plane bytes per line / 512]/4 : ceiling[plane bytes per line / 512] As per BSpec Don't increment selected "result_blocks" & "result_lines" in case of BROXTON. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a1ed920..5cfb5d9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3247,7 +3247,13 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, latency); plane_bytes_per_line = p_params->horiz_pixels * bytes_per_pixel; - plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); + + if (p_params->tiling == I915_FORMAT_MOD_Y_TILED || + p_params->tiling == I915_FORMAT_MOD_Yf_TILED) { + plane_blocks_per_line = DIV_ROUND_UP(4 * plane_bytes_per_line, 512); + plane_blocks_per_line /= 4; + } else + plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); if (p_params->tiling == I915_FORMAT_MOD_Y_TILED || p_params->tiling == I915_FORMAT_MOD_Yf_TILED) { @@ -3277,7 +3283,7 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, res_blocks = selected_result + 1; res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line); - if (level >= 1 && level <= 7) { + if (level >= 1 && level <= 7 && !IS_BROXTON(dev_priv->dev)) { if (p_params->tiling == I915_FORMAT_MOD_Y_TILED || p_params->tiling == I915_FORMAT_MOD_Yf_TILED) res_lines += 4; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 1/2] drm/i915/skl: Avoid using un-initialized bits_per_pixel
Don't rely on fb->bits_per_pixel as intel_framebuffer_init is not filling bits_per_pixel field of fb-struct for YUV pixel format. This leads to divide by zero error during watermark calculation. Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> Cc: Konduru, Chandra <chandra.kond...@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ea49661..1b90f03 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3170,7 +3170,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, if (fb) { p->plane[0].enabled = true; p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb->pixel_format, 1) : fb->bits_per_pixel / 8; + drm_format_plane_cpp(fb->pixel_format, 1) : + drm_format_plane_cpp(fb->pixel_format, 0); p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ? drm_format_plane_cpp(fb->pixel_format, 0) : 0; p->plane[0].tiling = fb->modifier[0]; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH 2/2] drm/i915/skl+: Add YUV pixel format in Capability list
GEN >= 9 supports YUV format for all planes, but it's not exported in Capability list of primary plane. Add YUV formats in skl_primary_formats list. Testcase: igt/kms_universal_plane.c Signed-off-by: Kumar, Mahesh <mahesh1.ku...@intel.com> Cc: Konduru, Chandra <chandra.kond...@intel.com> --- drivers/gpu/drm/i915/intel_display.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0377520..5ab8a1a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = { DRM_FORMAT_ABGR, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, }; /* Cursor formats */ -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH V2] drm/i915/skl+: Add YUV pixel format in Capability list
Ok..., Will resubmit the patch with suggested changes. Regards, -Mahesh On 8/24/2015 3:53 PM, Jindal, Sonika wrote: Can you please add the test case name to the commit message? Also, this should be split into two patches one addressing the divide by zero error and another one to add plane formats. Regards, Sonika -Original Message- From: Intel-gfx [mailto:intel-gfx-boun...@lists.freedesktop.org] On Behalf Of Kumar, Mahesh Sent: Friday, July 17, 2015 7:21 PM To: intel-gfx@lists.freedesktop.org Subject: [Intel-gfx] [PATCH V2] drm/i915/skl+: Add YUV pixel format in Capability list GEN = 9 supports YUV format for all planes, but it's not exported in Capability list of primary plane. Add YUV formats in skl_primary_formats list. Don't rely on fb-bits_per_pixel as intel_framebuffer_init is not filling bits_per_pixel field of fb-struct for YUV pixel format. This leads to divide by zero error during watermark calculation. V2: Don't break NV12 case. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com Cc: Konduru, Chandra chandra.kond...@intel.com --- IGT changes made for testcase will be sent in separate patch. drivers/gpu/drm/i915/intel_display.c | 4 drivers/gpu/drm/i915/intel_pm.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af0bcfe..d31704a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = { DRM_FORMAT_ABGR, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, }; /* Cursor formats */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5eeddc9..5768f8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3164,7 +3164,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, if (fb) { p-plane[0].enabled = true; p-plane[0].bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb-pixel_format, 1) : fb-bits_per_pixel / 8; + drm_format_plane_cpp(fb-pixel_format, 1) : + drm_format_plane_cpp(fb-pixel_format, 0); p-plane[0].y_bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? drm_format_plane_cpp(fb-pixel_format, 0) : 0; p-plane[0].tiling = fb-modifier[0]; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH v2] kms_universal_plane: subtest for yuv pixel format in primary plane
This test commit YUV framebuffer in primay plane. I'm using empty FB, because this fulfills the purpose of testing YUV. V2: Revert chnages for MAX_PLANE count as per nabendu's comment. These changes are already floating for review. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com --- lib/igt_fb.c| 4 +++ tests/kms_universal_plane.c | 82 + 2 files changed, 86 insertions(+) diff --git a/lib/igt_fb.c b/lib/igt_fb.c index 134dbd2..e570bfa 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -66,6 +66,10 @@ static struct format_desc_struct { DF(XRGB,RGB24, 32, 24), DF(XRGB2101010, RGB30, 32, 30), DF(ARGB,ARGB32, 32, 32), + DF(YUYV,INVALID,16, 16), + DF(YVYU,INVALID,16, 16), + DF(UYVY,INVALID,16, 16), + DF(VYUY,INVALID,16, 16), }; #undef DF diff --git a/tests/kms_universal_plane.c b/tests/kms_universal_plane.c index 635cc79..ed4b134 100644 --- a/tests/kms_universal_plane.c +++ b/tests/kms_universal_plane.c @@ -57,6 +57,12 @@ typedef struct { struct igt_fb red_fb, blue_fb; } pageflip_test_t; +typedef struct { + data_t *data; + struct igt_fb fullsize_fb, undersize_fb; +} primary_yuv_test_t; + + static void functional_test_init(functional_test_t *test, igt_output_t *output, enum pipe pipe) { @@ -430,6 +436,77 @@ sanity_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) } static void +primary_yuv_test_init(primary_yuv_test_t *test, igt_output_t *output, enum pipe pipe) +{ + data_t *data = test-data; + drmModeModeInfo *mode; + + igt_output_set_pipe(output, pipe); + + mode = igt_output_get_mode(output); + igt_create_fb(data-drm_fd, mode-hdisplay, mode-vdisplay, + DRM_FORMAT_YUYV, + LOCAL_DRM_FORMAT_MOD_NONE, + test-fullsize_fb); + igt_create_fb(data-drm_fd, 300, 300, + DRM_FORMAT_YVYU, + LOCAL_DRM_FORMAT_MOD_NONE, + test-undersize_fb); +} + +static void +primary_yuv_test_fini(primary_yuv_test_t *test, igt_output_t *output) +{ + igt_remove_fb(test-data-drm_fd, test-fullsize_fb); + igt_remove_fb(test-data-drm_fd, test-undersize_fb); + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit2(test-data-display, COMMIT_LEGACY); +} + +/* + * YUV pixel format test for primary plane + * Display Full frame in primay then 300x300 frame + */ + +static void +primary_yuv_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) +{ + primary_yuv_test_t test = { .data = data }; + igt_plane_t *primary; + + igt_skip_on(pipe = data-display.n_pipes); + + igt_output_set_pipe(output, pipe); + + primary_yuv_test_init(test, output, pipe); + + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + + /* Use legacy API to set a mode with a Fullsize FB */ + igt_plane_set_fb(primary, test.fullsize_fb); + igt_display_commit2(data-display, COMMIT_LEGACY); + + /* Disable the primary plane */ + igt_plane_set_fb(primary, NULL); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Use Universal API to set a mode with a Fullsize FB */ + igt_plane_set_fb(primary, test.fullsize_fb); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Use Universal API to set a mode with a Undersize FB */ + igt_plane_set_fb(primary, test.undersize_fb); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Disable the primary plane */ + igt_plane_set_fb(primary, NULL); + + primary_yuv_test_fini(test, output); + +} + +static void pageflip_test_init(pageflip_test_t *test, igt_output_t *output, enum pipe pipe) { data_t *data = test-data; @@ -663,6 +740,11 @@ run_tests_for_pipe(data_t *data, enum pipe pipe) kmstest_pipe_name(pipe)) for_each_connected_output(data-display, output) cursor_leak_test_pipe(data, pipe, output); + + igt_subtest_f(primary-plane-pipe-%s-yuv, + kmstest_pipe_name(pipe)) + for_each_connected_output(data-display, output) + primary_yuv_test_pipe(data, pipe, output); } static data_t data; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] kms_universal_plane: subtest for yuv pixel format in primary plane
This test commit YUV framebuffer in primay plane. I'm using empty FB, because this fulfills the purpose of testing YUV. Increase IGT_MAX_PLANES to 5 and add enum for IGT_PLANE_4, as in Broxton we have 4Plane+1cursor plane. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com --- lib/igt_fb.c| 4 +++ lib/igt_kms.c | 1 + lib/igt_kms.h | 3 +- tests/kms_universal_plane.c | 82 + 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/lib/igt_fb.c b/lib/igt_fb.c index 134dbd2..e570bfa 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -66,6 +66,10 @@ static struct format_desc_struct { DF(XRGB,RGB24, 32, 24), DF(XRGB2101010, RGB30, 32, 30), DF(ARGB,ARGB32, 32, 32), + DF(YUYV,INVALID,16, 16), + DF(YVYU,INVALID,16, 16), + DF(UYVY,INVALID,16, 16), + DF(VYUY,INVALID,16, 16), }; #undef DF diff --git a/lib/igt_kms.c b/lib/igt_kms.c index 0bb16b4..781ffa5 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -213,6 +213,7 @@ const char *kmstest_plane_name(enum igt_plane plane) [IGT_PLANE_1] = plane1, [IGT_PLANE_2] = plane2, [IGT_PLANE_3] = plane3, + [IGT_PLANE_4] = plane4, [IGT_PLANE_CURSOR] = cursor, }; diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 09c08aa..14c8b28 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -53,6 +53,7 @@ enum igt_plane { IGT_PLANE_PRIMARY = IGT_PLANE_1, IGT_PLANE_2, IGT_PLANE_3, +IGT_PLANE_4, IGT_PLANE_CURSOR, }; @@ -205,7 +206,7 @@ struct igt_pipe { igt_display_t *display; enum pipe pipe; bool enabled; -#define IGT_MAX_PLANES 4 +#define IGT_MAX_PLANES 5 int n_planes; igt_plane_t planes[IGT_MAX_PLANES]; uint64_t background; /* Background color MSB BGR 16bpc LSB */ diff --git a/tests/kms_universal_plane.c b/tests/kms_universal_plane.c index 635cc79..ed4b134 100644 --- a/tests/kms_universal_plane.c +++ b/tests/kms_universal_plane.c @@ -57,6 +57,12 @@ typedef struct { struct igt_fb red_fb, blue_fb; } pageflip_test_t; +typedef struct { + data_t *data; + struct igt_fb fullsize_fb, undersize_fb; +} primary_yuv_test_t; + + static void functional_test_init(functional_test_t *test, igt_output_t *output, enum pipe pipe) { @@ -430,6 +436,77 @@ sanity_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) } static void +primary_yuv_test_init(primary_yuv_test_t *test, igt_output_t *output, enum pipe pipe) +{ + data_t *data = test-data; + drmModeModeInfo *mode; + + igt_output_set_pipe(output, pipe); + + mode = igt_output_get_mode(output); + igt_create_fb(data-drm_fd, mode-hdisplay, mode-vdisplay, + DRM_FORMAT_YUYV, + LOCAL_DRM_FORMAT_MOD_NONE, + test-fullsize_fb); + igt_create_fb(data-drm_fd, 300, 300, + DRM_FORMAT_YVYU, + LOCAL_DRM_FORMAT_MOD_NONE, + test-undersize_fb); +} + +static void +primary_yuv_test_fini(primary_yuv_test_t *test, igt_output_t *output) +{ + igt_remove_fb(test-data-drm_fd, test-fullsize_fb); + igt_remove_fb(test-data-drm_fd, test-undersize_fb); + + igt_output_set_pipe(output, PIPE_ANY); + igt_display_commit2(test-data-display, COMMIT_LEGACY); +} + +/* + * YUV pixel format test for primary plane + * Display Full frame in primay then 300x300 frame + */ + +static void +primary_yuv_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) +{ + primary_yuv_test_t test = { .data = data }; + igt_plane_t *primary; + + igt_skip_on(pipe = data-display.n_pipes); + + igt_output_set_pipe(output, pipe); + + primary_yuv_test_init(test, output, pipe); + + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + + /* Use legacy API to set a mode with a Fullsize FB */ + igt_plane_set_fb(primary, test.fullsize_fb); + igt_display_commit2(data-display, COMMIT_LEGACY); + + /* Disable the primary plane */ + igt_plane_set_fb(primary, NULL); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Use Universal API to set a mode with a Fullsize FB */ + igt_plane_set_fb(primary, test.fullsize_fb); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Use Universal API to set a mode with a Undersize FB */ + igt_plane_set_fb(primary, test.undersize_fb); + igt_display_commit2(data-display, COMMIT_UNIVERSAL); + + /* Disable the primary plane */ + igt_plane_set_fb(primary, NULL); + + primary_yuv_test_fini(test, output); + +} + +static void pageflip_test_init(pageflip_test_t *test
[Intel-gfx] [PATCH V2] drm/i915/skl+: Add YUV pixel format in Capability list
GEN = 9 supports YUV format for all planes, but it's not exported in Capability list of primary plane. Add YUV formats in skl_primary_formats list. Don't rely on fb-bits_per_pixel as intel_framebuffer_init is not filling bits_per_pixel field of fb-struct for YUV pixel format. This leads to divide by zero error during watermark calculation. V2: Don't break NV12 case. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com Cc: Konduru, Chandra chandra.kond...@intel.com --- IGT changes made for testcase will be sent in separate patch. drivers/gpu/drm/i915/intel_display.c | 4 drivers/gpu/drm/i915/intel_pm.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af0bcfe..d31704a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = { DRM_FORMAT_ABGR, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, }; /* Cursor formats */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5eeddc9..5768f8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3164,7 +3164,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, if (fb) { p-plane[0].enabled = true; p-plane[0].bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb-pixel_format, 1) : fb-bits_per_pixel / 8; + drm_format_plane_cpp(fb-pixel_format, 1) : + drm_format_plane_cpp(fb-pixel_format, 0); p-plane[0].y_bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? drm_format_plane_cpp(fb-pixel_format, 0) : 0; p-plane[0].tiling = fb-modifier[0]; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/skl+: Add YUV pixel format in Capability list
GEN = 9 supports YUV format for all planes, but it's not exported in Capability list of primary plane. Add YUV formats in skl_primary_formats list. Don't rely on fb-bits_per_pixel as intel_framebuffer_init is not filling bits_per_pixel field of fb-struct for YUV pixel format. This leads to divide by zero error during watermark calculation. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com Cc: Konduru, Chandra chandra.kond...@intel.com --- drivers/gpu/drm/i915/intel_display.c | 4 drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bb58cb6..f4b27af 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -72,6 +72,10 @@ static const uint32_t skl_primary_formats[] = { DRM_FORMAT_ABGR, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, }; /* Cursor formats */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f2be1ce..1d13b7e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3156,8 +3156,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, /* For planar: Bpp is for uv plane, y_Bpp is for y plane */ if (fb) { p-plane[0].enabled = true; - p-plane[0].bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? - drm_format_plane_cpp(fb-pixel_format, 1) : fb-bits_per_pixel / 8; + p-plane[0].bytes_per_pixel = + drm_format_plane_cpp(fb-pixel_format, 1); p-plane[0].y_bytes_per_pixel = fb-pixel_format == DRM_FORMAT_NV12 ? drm_format_plane_cpp(fb-pixel_format, 0) : 0; p-plane[0].tiling = fb-modifier[0]; -- 1.9.1 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx
[Intel-gfx] [PATCH] drm/i915/skl: Add check for minimum allocable Display Data Blocks
Fifo Underrun is observed when allocating minimum allocable blocks for any plane, This patch calculate checks for upper lower DDB bound for each plane according to total allocated DDB for that Pipe. Signed-off-by: Kumar, Mahesh mahesh1.ku...@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 48 + 2 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 26ffe8b..fe51a5a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1536,6 +1536,8 @@ struct skl_ddb_allocation { struct skl_ddb_entry pipe[I915_MAX_PIPES]; struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; struct skl_ddb_entry cursor[I915_MAX_PIPES]; + uint16_t min_alloc[I915_MAX_PIPES][I915_MAX_PLANES]; + uint16_t max_alloc[I915_MAX_PIPES][I915_MAX_PLANES]; }; struct skl_wm_values { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3c64810..d4d8994 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2482,6 +2482,43 @@ skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc, } static void +skl_calculate_allocable_blocks(struct intel_crtc *intel_crtc, + const struct skl_pipe_wm_parameters *params, + uint16_t alloc_size, struct skl_ddb_allocation *ddb) +{ + uint16_t min; + uint16_t total_min_alloc = 0; + enum pipe pipe = intel_crtc-pipe; + int plane; + + for (plane = 0; plane intel_num_planes(intel_crtc); plane++) { + const struct intel_plane_wm_parameters *p; + + p = params-plane[plane]; + ddb-min_alloc[pipe][plane] = 0; + + if (!p-enabled) + continue; + + /* +* TODO: Calculate PlaneMinAlloc according to X/Y-Tiling +* calculation, for now use X-Tiling PlaneMinAlloc +*/ + + min = 8; + + ddb-min_alloc[pipe][plane] = min; + total_min_alloc += min; + + } + + for (plane = 0; plane intel_num_planes(intel_crtc); plane++) { + ddb-max_alloc[pipe][plane] = alloc_size - total_min_alloc + + ddb-min_alloc[pipe][plane]; + } +} + +static void skl_allocate_pipe_ddb(struct drm_crtc *crtc, const struct intel_wm_config *config, const struct skl_pipe_wm_parameters *params, @@ -2519,6 +2556,8 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params); start = alloc-start; + + skl_calculate_allocable_blocks(intel_crtc, params, alloc_size, ddb); for (plane = 0; plane intel_num_planes(intel_crtc); plane++) { const struct intel_plane_wm_parameters *p; unsigned int data_rate; @@ -2537,6 +2576,15 @@ skl_allocate_pipe_ddb(struct drm_crtc *crtc, plane_blocks = div_u64((uint64_t)alloc_size * data_rate, total_data_rate); + /* +* Limit plane_blocks if out of limit +*/ + + if (plane_blocks ddb-max_alloc[pipe][plane]) + plane_blocks = ddb-max_alloc[pipe][plane]; + if (plane_blocks ddb-min_alloc[pipe][plane]) + plane_blocks = ddb-min_alloc[pipe][plane]; + ddb-plane[pipe][plane].start = start; ddb-plane[pipe][plane].end = start + plane_blocks; -- 2.3.0 ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx