drm/amd/display: Parse scanline registers
authorSylvia Tsai <sylvia.tsai@amd.com>
Tue, 11 Apr 2017 19:15:28 +0000 (15:15 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:23:47 +0000 (17:23 -0400)
They could differ between ASIC generations

Signed-off-by: Sylvia Tsai <sylvia.tsai@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h

index 93f10bc772c4b5a8b3b40555bd1af2fbe9cf4b50..84995a48ec6110f722bcebe5917a624ec39e1b6c 100644 (file)
@@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
                                        u32 *vbl, u32 *position)
 {
+       uint32_t v_blank_start, v_blank_end, h_position, v_position;
+
        if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
                return -EINVAL;
        else {
@@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
                        return 0;
                }
 
-               return dc_stream_get_scanoutpos(acrtc->stream, vbl, position);
+               /*
+                * TODO rework base driver to use values directly.
+                * for now parse it back into reg-format
+                */
+               dc_stream_get_scanoutpos(acrtc->stream,
+                                        &v_blank_start,
+                                        &v_blank_end,
+                                        &h_position,
+                                        &v_position);
+
+               *position = (v_position) || (h_position << 16);
+               *vbl = (v_blank_start) || (v_blank_end << 16);
        }
 
        return 0;
index bf209f7bbf9861cd1db648c89585a3c95440869c..3dbd6c0885d8ac043db8d51fc50bcdd053ae911f 100644 (file)
@@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream)
        return 0;
 }
 
-uint32_t dc_stream_get_scanoutpos(
-               const struct dc_stream *dc_stream,
-               uint32_t *vbl,
-               uint32_t *position)
+bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream,
+                                 uint32_t *v_blank_start,
+                                 uint32_t *v_blank_end,
+                                 uint32_t *h_position,
+                                 uint32_t *v_position)
 {
        uint8_t i;
+       bool ret = false;
        struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
        struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
        struct resource_context *res_ctx =
@@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos(
                if (res_ctx->pipe_ctx[i].stream != stream)
                        continue;
 
-               return tg->funcs->get_scanoutpos(tg, vbl, position);
+               tg->funcs->get_scanoutpos(tg,
+                                         v_blank_start,
+                                         v_blank_end,
+                                         h_position,
+                                         v_position);
+
+               ret = true;
+               break;
        }
 
-       return 0;
+       return ret;
 }
 
 
index 97af8f63eec337452b992304d8020b41da1964c4..7d548b4d02994281365839952ccfa2bff5155793 100644 (file)
@@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream);
  * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
  * being refactored properly to be dce-specific
  */
-uint32_t dc_stream_get_scanoutpos(
-               const struct dc_stream *stream, uint32_t *vbl, uint32_t *position);
+bool dc_stream_get_scanoutpos(const struct dc_stream *stream,
+                                 uint32_t *v_blank_start,
+                                 uint32_t *v_blank_end,
+                                 uint32_t *h_position,
+                                 uint32_t *v_position);
 
 /*
  * Structure to store surface/stream associations for validation
index 006412be7a02251ce7ea23735e2eb4f411169914..7070aaf9e433f8f4ec8589776fa96131667fdb4f 100644 (file)
@@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions(
  *  @param [out] vpos, hpos
  *****************************************************************************
  */
-uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+void dce110_timing_generator_get_crtc_scanoutpos(
        struct timing_generator *tg,
-       uint32_t *vbl,
-       uint32_t *position)
+       uint32_t *v_blank_start,
+       uint32_t *v_blank_end,
+       uint32_t *h_position,
+       uint32_t *v_position)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-       /* TODO 1: Update the implementation once caller is updated
-        * WARNING!! This function is returning the whole register value
-        * because the caller is expecting it instead of proper vertical and
-        * horizontal position. This should be a temporary implementation
-        * until the caller is updated. */
 
-       /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */
-
-       *vbl = dm_read_reg(tg->ctx,
+       uint32_t v_blank_start_end  = dm_read_reg(tg->ctx,
                        CRTC_REG(mmCRTC_V_BLANK_START_END));
 
-       *position = dm_read_reg(tg->ctx,
-                       CRTC_REG(mmCRTC_STATUS_POSITION));
+       *v_blank_start = get_reg_field_value(v_blank_start_end,
+                                            CRTC_V_BLANK_START_END,
+                                            CRTC_V_BLANK_START);
+       *v_blank_end = get_reg_field_value(v_blank_start_end,
+                                          CRTC_V_BLANK_START_END,
+                                          CRTC_V_BLANK_END);
 
-       /* @TODO: return value should indicate if current
-        * crtc is inside vblank*/
-       return 0;
+       dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
 }
 
 /* TODO: is it safe to assume that mask/shift of Primary and Underlay
@@ -1875,34 +1872,31 @@ void dce110_tg_set_colors(struct timing_generator *tg,
 bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-       uint32_t vbl = 0;
+       uint32_t v_blank_start = 0;
+       uint32_t v_blank_end = 0;
        uint32_t val = 0;
-       uint32_t position, vbl_start;
+       uint32_t h_position, v_position;
 
        tg->funcs->get_scanoutpos(
                        tg,
-                       &vbl,
-                       &position);
+                       &v_blank_start,
+                       &v_blank_end,
+                       &h_position,
+                       &v_position);
 
-       if (vbl == 0)
+       if (v_blank_start == 0 || v_blank_end == 0)
                return false;
 
-       vbl_start =
-               get_reg_field_value(
-               vbl,
-               CRTC_V_BLANK_START_END,
-               CRTC_V_BLANK_START);
-
        set_reg_field_value(
                val,
-               vbl_start,
+               v_blank_start,
                CRTC_VERTICAL_INTERRUPT0_POSITION,
                CRTC_VERTICAL_INTERRUPT0_LINE_START);
 
-       /* Set interaval width for interrupt to fire to 1 scanline */
+       /* Set interval width for interrupt to fire to 1 scanline */
        set_reg_field_value(
                val,
-               vbl_start + width,
+               v_blank_start + width,
                CRTC_VERTICAL_INTERRUPT0_POSITION,
                CRTC_VERTICAL_INTERRUPT0_LINE_END);
 
index ca387b40fc67acc52f364d81ce1b46f85a6f331f..f14a4d91cd8e7560ef802a89da7db83be694ccae 100644 (file)
@@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control(
        struct timing_generator *tg,
        uint32_t value);
 
-uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+void dce110_timing_generator_get_crtc_scanoutpos(
        struct timing_generator *tg,
-       uint32_t *vbl,
-       uint32_t *position);
+       uint32_t *v_blank_start,
+       uint32_t *v_blank_end,
+       uint32_t *h_position,
+       uint32_t *v_position);
 
 void dce110_timing_generator_enable_advanced_request(
        struct timing_generator *tg,
index 95cb1768aeb54516d5d7e475162bed3bc281342d..1318df7ed47e9e8190723b0b7363c90d5214f343 100644 (file)
@@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr(
        }
 }
 
-uint32_t dce120_timing_generator_get_crtc_scanoutpos(
+void dce120_timing_generator_get_crtc_scanoutpos(
        struct timing_generator *tg,
-       uint32_t *vbl,
-       uint32_t *position)
+       uint32_t *v_blank_start,
+       uint32_t *v_blank_end,
+       uint32_t *h_position,
+       uint32_t *v_position)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 
-       *vbl = dm_read_reg_soc15(
+       uint32_t v_blank_start_end = dm_read_reg_soc15(
                        tg->ctx,
                        mmCRTC0_CRTC_V_BLANK_START_END,
                        tg110->offsets.crtc);
 
-       *position = dm_read_reg_soc15(
-                               tg->ctx,
-                               mmCRTC0_CRTC_STATUS_POSITION,
-                               tg110->offsets.crtc);
+       *v_blank_start = get_reg_field_value(v_blank_start_end,
+                                            CRTC0_CRTC_V_BLANK_START_END,
+                                            CRTC_V_BLANK_START);
+       *v_blank_end = get_reg_field_value(v_blank_start_end,
+                                          CRTC0_CRTC_V_BLANK_START_END,
+                                          CRTC_V_BLANK_END);
 
-       return 0;
+       dce120_timing_generator_get_crtc_positions(tg, h_position, v_position);
 }
 
 void dce120_timing_generator_enable_advanced_request(
@@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr(
                uint8_t width)
 {
        struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
-       uint32_t vbl, position, vbl_start;
+       uint32_t v_blank_start, v_blank_end, h_position, v_position;
 
        tg->funcs->get_scanoutpos(
                                tg,
-                               &vbl,
-                               &position);
+                               &v_blank_start,
+                               &v_blank_end,
+                               &h_position,
+                               &v_position);
 
-       if (vbl == 0)
+       if (v_blank_start == 0 || v_blank_end == 0)
                return false;
 
-       vbl_start =
-               get_reg_field_value(
-               vbl,
-               CRTC0_CRTC_V_BLANK_START_END,
-               CRTC_V_BLANK_START);
-
        CRTC_REG_SET_2(
                        CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
-                       CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start,
-                       CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width);
+                       CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
+                       CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
 
        return true;
 }
index 51902a4f8798a4350a9ef6e5f9ef92441333b4d8..b3deaf2d81739d4303a3ca36facc91aeed4d42b9 100644 (file)
@@ -120,10 +120,12 @@ struct timing_generator_funcs {
                                                                int32_t *h_position,
                                                                int32_t *v_position);
        uint32_t (*get_frame_count)(struct timing_generator *tg);
-       uint32_t (*get_scanoutpos)(
+       void (*get_scanoutpos)(
                struct timing_generator *tg,
-               uint32_t *vbl,
-               uint32_t *position);
+               uint32_t *v_blank_start,
+               uint32_t *v_blank_end,
+               uint32_t *h_position,
+               uint32_t *v_position);
        void (*set_early_control)(struct timing_generator *tg,
                                                           uint32_t early_cntl);
        void (*wait_for_state)(struct timing_generator *tg,