aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvia Tsai <sylvia.tsai@amd.com>2017-04-11 15:15:28 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-09-26 17:23:47 -0400
commit81c509633aa93442d58b895f773892b3e8d936cf (patch)
treee3a42a842efa15b5863092ddb15d00889bfc2082
parent1ce71fcd5dddf4a3198a96e422122edc210847e9 (diff)
drm/amd/display: Parse scanline registers
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>
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h8
7 files changed, 89 insertions, 66 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 93f10bc772c4..84995a48ec61 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -103,6 +103,8 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
103static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, 103static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
104 u32 *vbl, u32 *position) 104 u32 *vbl, u32 *position)
105{ 105{
106 uint32_t v_blank_start, v_blank_end, h_position, v_position;
107
106 if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) 108 if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
107 return -EINVAL; 109 return -EINVAL;
108 else { 110 else {
@@ -113,7 +115,18 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
113 return 0; 115 return 0;
114 } 116 }
115 117
116 return dc_stream_get_scanoutpos(acrtc->stream, vbl, position); 118 /*
119 * TODO rework base driver to use values directly.
120 * for now parse it back into reg-format
121 */
122 dc_stream_get_scanoutpos(acrtc->stream,
123 &v_blank_start,
124 &v_blank_end,
125 &h_position,
126 &v_position);
127
128 *position = (v_position) || (h_position << 16);
129 *vbl = (v_blank_start) || (v_blank_end << 16);
117 } 130 }
118 131
119 return 0; 132 return 0;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index bf209f7bbf98..3dbd6c0885d8 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -282,12 +282,14 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *dc_stream)
282 return 0; 282 return 0;
283} 283}
284 284
285uint32_t dc_stream_get_scanoutpos( 285bool dc_stream_get_scanoutpos(const struct dc_stream *dc_stream,
286 const struct dc_stream *dc_stream, 286 uint32_t *v_blank_start,
287 uint32_t *vbl, 287 uint32_t *v_blank_end,
288 uint32_t *position) 288 uint32_t *h_position,
289 uint32_t *v_position)
289{ 290{
290 uint8_t i; 291 uint8_t i;
292 bool ret = false;
291 struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream); 293 struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
292 struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc); 294 struct core_dc *core_dc = DC_TO_CORE(stream->ctx->dc);
293 struct resource_context *res_ctx = 295 struct resource_context *res_ctx =
@@ -299,10 +301,17 @@ uint32_t dc_stream_get_scanoutpos(
299 if (res_ctx->pipe_ctx[i].stream != stream) 301 if (res_ctx->pipe_ctx[i].stream != stream)
300 continue; 302 continue;
301 303
302 return tg->funcs->get_scanoutpos(tg, vbl, position); 304 tg->funcs->get_scanoutpos(tg,
305 v_blank_start,
306 v_blank_end,
307 h_position,
308 v_position);
309
310 ret = true;
311 break;
303 } 312 }
304 313
305 return 0; 314 return ret;
306} 315}
307 316
308 317
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 97af8f63eec3..7d548b4d0299 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -484,8 +484,11 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream *stream);
484 * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos) 484 * This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
485 * being refactored properly to be dce-specific 485 * being refactored properly to be dce-specific
486 */ 486 */
487uint32_t dc_stream_get_scanoutpos( 487bool dc_stream_get_scanoutpos(const struct dc_stream *stream,
488 const struct dc_stream *stream, uint32_t *vbl, uint32_t *position); 488 uint32_t *v_blank_start,
489 uint32_t *v_blank_end,
490 uint32_t *h_position,
491 uint32_t *v_position);
489 492
490/* 493/*
491 * Structure to store surface/stream associations for validation 494 * Structure to store surface/stream associations for validation
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
index 006412be7a02..7070aaf9e433 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
@@ -574,29 +574,26 @@ void dce110_timing_generator_get_crtc_positions(
574 * @param [out] vpos, hpos 574 * @param [out] vpos, hpos
575 ***************************************************************************** 575 *****************************************************************************
576 */ 576 */
577uint32_t dce110_timing_generator_get_crtc_scanoutpos( 577void dce110_timing_generator_get_crtc_scanoutpos(
578 struct timing_generator *tg, 578 struct timing_generator *tg,
579 uint32_t *vbl, 579 uint32_t *v_blank_start,
580 uint32_t *position) 580 uint32_t *v_blank_end,
581 uint32_t *h_position,
582 uint32_t *v_position)
581{ 583{
582 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 584 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
583 /* TODO 1: Update the implementation once caller is updated
584 * WARNING!! This function is returning the whole register value
585 * because the caller is expecting it instead of proper vertical and
586 * horizontal position. This should be a temporary implementation
587 * until the caller is updated. */
588 585
589 /* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */ 586 uint32_t v_blank_start_end = dm_read_reg(tg->ctx,
590
591 *vbl = dm_read_reg(tg->ctx,
592 CRTC_REG(mmCRTC_V_BLANK_START_END)); 587 CRTC_REG(mmCRTC_V_BLANK_START_END));
593 588
594 *position = dm_read_reg(tg->ctx, 589 *v_blank_start = get_reg_field_value(v_blank_start_end,
595 CRTC_REG(mmCRTC_STATUS_POSITION)); 590 CRTC_V_BLANK_START_END,
591 CRTC_V_BLANK_START);
592 *v_blank_end = get_reg_field_value(v_blank_start_end,
593 CRTC_V_BLANK_START_END,
594 CRTC_V_BLANK_END);
596 595
597 /* @TODO: return value should indicate if current 596 dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
598 * crtc is inside vblank*/
599 return 0;
600} 597}
601 598
602/* TODO: is it safe to assume that mask/shift of Primary and Underlay 599/* 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,
1875bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width) 1872bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
1876{ 1873{
1877 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1874 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1878 uint32_t vbl = 0; 1875 uint32_t v_blank_start = 0;
1876 uint32_t v_blank_end = 0;
1879 uint32_t val = 0; 1877 uint32_t val = 0;
1880 uint32_t position, vbl_start; 1878 uint32_t h_position, v_position;
1881 1879
1882 tg->funcs->get_scanoutpos( 1880 tg->funcs->get_scanoutpos(
1883 tg, 1881 tg,
1884 &vbl, 1882 &v_blank_start,
1885 &position); 1883 &v_blank_end,
1884 &h_position,
1885 &v_position);
1886 1886
1887 if (vbl == 0) 1887 if (v_blank_start == 0 || v_blank_end == 0)
1888 return false; 1888 return false;
1889 1889
1890 vbl_start =
1891 get_reg_field_value(
1892 vbl,
1893 CRTC_V_BLANK_START_END,
1894 CRTC_V_BLANK_START);
1895
1896 set_reg_field_value( 1890 set_reg_field_value(
1897 val, 1891 val,
1898 vbl_start, 1892 v_blank_start,
1899 CRTC_VERTICAL_INTERRUPT0_POSITION, 1893 CRTC_VERTICAL_INTERRUPT0_POSITION,
1900 CRTC_VERTICAL_INTERRUPT0_LINE_START); 1894 CRTC_VERTICAL_INTERRUPT0_LINE_START);
1901 1895
1902 /* Set interaval width for interrupt to fire to 1 scanline */ 1896 /* Set interval width for interrupt to fire to 1 scanline */
1903 set_reg_field_value( 1897 set_reg_field_value(
1904 val, 1898 val,
1905 vbl_start + width, 1899 v_blank_start + width,
1906 CRTC_VERTICAL_INTERRUPT0_POSITION, 1900 CRTC_VERTICAL_INTERRUPT0_POSITION,
1907 CRTC_VERTICAL_INTERRUPT0_LINE_END); 1901 CRTC_VERTICAL_INTERRUPT0_LINE_END);
1908 1902
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
index ca387b40fc67..f14a4d91cd8e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.h
@@ -230,10 +230,12 @@ void dce110_timing_generator_set_static_screen_control(
230 struct timing_generator *tg, 230 struct timing_generator *tg,
231 uint32_t value); 231 uint32_t value);
232 232
233uint32_t dce110_timing_generator_get_crtc_scanoutpos( 233void dce110_timing_generator_get_crtc_scanoutpos(
234 struct timing_generator *tg, 234 struct timing_generator *tg,
235 uint32_t *vbl, 235 uint32_t *v_blank_start,
236 uint32_t *position); 236 uint32_t *v_blank_end,
237 uint32_t *h_position,
238 uint32_t *v_position);
237 239
238void dce110_timing_generator_enable_advanced_request( 240void dce110_timing_generator_enable_advanced_request(
239 struct timing_generator *tg, 241 struct timing_generator *tg,
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
index 95cb1768aeb5..1318df7ed47e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
@@ -576,24 +576,28 @@ void dce120_timing_generator_set_drr(
576 } 576 }
577} 577}
578 578
579uint32_t dce120_timing_generator_get_crtc_scanoutpos( 579void dce120_timing_generator_get_crtc_scanoutpos(
580 struct timing_generator *tg, 580 struct timing_generator *tg,
581 uint32_t *vbl, 581 uint32_t *v_blank_start,
582 uint32_t *position) 582 uint32_t *v_blank_end,
583 uint32_t *h_position,
584 uint32_t *v_position)
583{ 585{
584 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 586 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
585 587
586 *vbl = dm_read_reg_soc15( 588 uint32_t v_blank_start_end = dm_read_reg_soc15(
587 tg->ctx, 589 tg->ctx,
588 mmCRTC0_CRTC_V_BLANK_START_END, 590 mmCRTC0_CRTC_V_BLANK_START_END,
589 tg110->offsets.crtc); 591 tg110->offsets.crtc);
590 592
591 *position = dm_read_reg_soc15( 593 *v_blank_start = get_reg_field_value(v_blank_start_end,
592 tg->ctx, 594 CRTC0_CRTC_V_BLANK_START_END,
593 mmCRTC0_CRTC_STATUS_POSITION, 595 CRTC_V_BLANK_START);
594 tg110->offsets.crtc); 596 *v_blank_end = get_reg_field_value(v_blank_start_end,
597 CRTC0_CRTC_V_BLANK_START_END,
598 CRTC_V_BLANK_END);
595 599
596 return 0; 600 dce120_timing_generator_get_crtc_positions(tg, h_position, v_position);
597} 601}
598 602
599void dce120_timing_generator_enable_advanced_request( 603void dce120_timing_generator_enable_advanced_request(
@@ -1044,26 +1048,22 @@ static bool dce120_arm_vert_intr(
1044 uint8_t width) 1048 uint8_t width)
1045{ 1049{
1046 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); 1050 struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1047 uint32_t vbl, position, vbl_start; 1051 uint32_t v_blank_start, v_blank_end, h_position, v_position;
1048 1052
1049 tg->funcs->get_scanoutpos( 1053 tg->funcs->get_scanoutpos(
1050 tg, 1054 tg,
1051 &vbl, 1055 &v_blank_start,
1052 &position); 1056 &v_blank_end,
1057 &h_position,
1058 &v_position);
1053 1059
1054 if (vbl == 0) 1060 if (v_blank_start == 0 || v_blank_end == 0)
1055 return false; 1061 return false;
1056 1062
1057 vbl_start =
1058 get_reg_field_value(
1059 vbl,
1060 CRTC0_CRTC_V_BLANK_START_END,
1061 CRTC_V_BLANK_START);
1062
1063 CRTC_REG_SET_2( 1063 CRTC_REG_SET_2(
1064 CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION, 1064 CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1065 CRTC_VERTICAL_INTERRUPT0_LINE_START, vbl_start, 1065 CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1066 CRTC_VERTICAL_INTERRUPT0_LINE_END, vbl_start + width); 1066 CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1067 1067
1068 return true; 1068 return true;
1069} 1069}
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 51902a4f8798..b3deaf2d8173 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -120,10 +120,12 @@ struct timing_generator_funcs {
120 int32_t *h_position, 120 int32_t *h_position,
121 int32_t *v_position); 121 int32_t *v_position);
122 uint32_t (*get_frame_count)(struct timing_generator *tg); 122 uint32_t (*get_frame_count)(struct timing_generator *tg);
123 uint32_t (*get_scanoutpos)( 123 void (*get_scanoutpos)(
124 struct timing_generator *tg, 124 struct timing_generator *tg,
125 uint32_t *vbl, 125 uint32_t *v_blank_start,
126 uint32_t *position); 126 uint32_t *v_blank_end,
127 uint32_t *h_position,
128 uint32_t *v_position);
127 void (*set_early_control)(struct timing_generator *tg, 129 void (*set_early_control)(struct timing_generator *tg,
128 uint32_t early_cntl); 130 uint32_t early_cntl);
129 void (*wait_for_state)(struct timing_generator *tg, 131 void (*wait_for_state)(struct timing_generator *tg,