aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch')
-rw-r--r--common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch278
1 files changed, 278 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch b/common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch
new file mode 100644
index 00000000..605db313
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0580-drm-amd-dal-Fix-issue-where-unused-HW-is-not-powered.patch
@@ -0,0 +1,278 @@
+From a174d4b05bfe7554d77c1c3be0ad56fbbb8b2fd9 Mon Sep 17 00:00:00 2001
+From: Anthony Koo <Anthony.Koo@amd.com>
+Date: Sat, 5 Dec 2015 01:57:27 -0500
+Subject: [PATCH 0580/1110] drm/amd/dal: Fix issue where unused HW is not
+ powered down after boot
+
+[Description]
+init_hw is called on dc create and on set power state call,
+but what appears incorrect is that it is setting accelerated
+mode bit in scratch register.
+
+We actually expect accelerated mode bit to be set on first commit,
+when we actually enter accelerated mode. Entering accelerated
+mode actually involves a handoff between VBIOS controlled
+programming of display pipe to Driver control. During this process,
+we want to init and power down all existing HW.
+
+Power down of HW in enter accelerated mode was also not very
+correct, since it currently takes the first commit context. But what
+we really wanted to do is power everything off.
+
+Finally, we need to do power gate of pipe when unused, but also
+ungate when enabling the pipe.
+
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/dal/dc/core/dc.c | 6 +-
+ .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 97 +++++++++++-----------
+ drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h | 4 +-
+ 3 files changed, 53 insertions(+), 54 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+index 50505f4..7fc9f17 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
+@@ -167,8 +167,6 @@ static void init_hw(struct dc *dc)
+ dc->hwss.encoder_power_up(link->link_enc);
+ }
+
+- dal_bios_parser_set_scratch_acc_mode_change(bp);
+-
+ for(i = 0; i < dc->res_pool.controller_count; i++) {
+ struct timing_generator *tg = dc->res_pool.timing_generators[i];
+
+@@ -653,7 +651,7 @@ bool dc_commit_targets(
+
+ if (!dal_adapter_service_is_in_accelerated_mode(
+ dc->res_pool.adapter_srv)) {
+- dc->hwss.enable_accelerated_mode(context);
++ dc->hwss.enable_accelerated_mode(dc);
+ }
+
+ for (i = 0; i < dc->current_context.target_count; i++) {
+@@ -859,7 +857,7 @@ void dc_set_power_state(
+ /* NULL means "reset/release all DC targets" */
+ dc_commit_targets(dc, NULL, 0);
+
+- dc->hwss.power_down(&dc->current_context);
++ dc->hwss.power_down(dc);
+ break;
+ }
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
+index 81935e5..edbf3ce 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
+@@ -785,8 +785,21 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+ bool timing_changed = context->res_ctx.controller_ctx[controller_idx]
+ .flags.timing_changed;
+ enum color_space color_space;
++ struct bios_parser *bp;
++
++ bp = dal_adapter_service_get_bios_parser(
++ context->res_ctx.pool.adapter_srv);
+
+ if (timing_changed) {
++ dce110_enable_display_power_gating(
++ stream->ctx, controller_idx, bp,
++ PIPE_GATING_CONTROL_DISABLE);
++
++ /* Must blank CRTC after disabling power gating and before any
++ * programming, otherwise CRTC will be hung in bad state
++ */
++ dce110_timing_generator_blank_crtc(stream->tg);
++
+ core_link_disable_stream(
+ stream->sink->link, stream);
+
+@@ -898,47 +911,34 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+
+ /******************************************************************************/
+
+-static void power_down_encoders(struct validate_context *context)
++static void power_down_encoders(struct dc *dc)
+ {
+ int i;
+- struct core_target *target;
+- struct core_stream *stream;
+
+- for (i = 0; i < context->target_count; i++) {
+- target = context->targets[i];
+- stream = DC_STREAM_TO_CORE(target->public.streams[0]);
+-
+- core_link_disable_stream(stream->sink->link, stream);
++ for (i = 0; i < dc->link_count; i++) {
++ dce110_link_encoder_disable_output(
++ dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
+ }
+ }
+
+-static void power_down_controllers(struct validate_context *context)
++static void power_down_controllers(struct dc *dc)
+ {
+ int i;
+- struct core_target *target;
+- struct core_stream *stream;
+-
+- for (i = 0; i < context->target_count; i++) {
+- target = context->targets[i];
+- stream = DC_STREAM_TO_CORE(target->public.streams[0]);
+
+- dce110_timing_generator_disable_crtc(stream->tg);
++ for (i = 0; i < dc->res_pool.controller_count; i++) {
++ dce110_timing_generator_disable_crtc(
++ dc->res_pool.timing_generators[i]);
+ }
+ }
+
+-static void power_down_clock_sources(struct validate_context *context)
++static void power_down_clock_sources(struct dc *dc)
+ {
+ int i;
+- struct core_target *target;
+- struct core_stream *stream;
+-
+- for (i = 0; i < context->target_count; i++) {
+- target = context->targets[i];
+- stream = DC_STREAM_TO_CORE(target->public.streams[0]);
+
++ for (i = 0; i < dc->res_pool.clk_src_count; i++) {
+ if (false == dal_clock_source_power_down_pll(
+- stream->clock_source,
+- stream->controller_idx + 1)) {
++ dc->res_pool.clock_sources[i],
++ i+1)) {
+ dal_error(
+ "Failed to power down pll! (clk src index=%d)\n",
+ i);
+@@ -946,35 +946,29 @@ static void power_down_clock_sources(struct validate_context *context)
+ }
+ }
+
+-static void power_down_all_hw_blocks(struct validate_context *context)
++static void power_down_all_hw_blocks(struct dc *dc)
+ {
+- power_down_encoders(context);
++ power_down_encoders(dc);
+
+- power_down_controllers(context);
++ power_down_controllers(dc);
+
+- power_down_clock_sources(context);
++ power_down_clock_sources(dc);
+ }
+
+ static void disable_vga_and_power_gate_all_controllers(
+- struct validate_context *context)
++ struct dc *dc)
+ {
+ int i;
+- struct core_target *target;
+- struct core_stream *stream;
+ struct timing_generator *tg;
+ struct bios_parser *bp;
+ struct dc_context *ctx;
+- uint8_t controller_id;
+
+ bp = dal_adapter_service_get_bios_parser(
+- context->res_ctx.pool.adapter_srv);
++ dc->res_pool.adapter_srv);
+
+- for (i = 0; i < context->target_count; i++) {
+- target = context->targets[i];
+- stream = DC_STREAM_TO_CORE(target->public.streams[0]);
+- tg = stream->tg;
+- ctx = stream->ctx;
+- controller_id = stream->controller_idx;
++ for (i = 0; i < dc->res_pool.controller_count; i++) {
++ tg = dc->res_pool.timing_generators[i];
++ ctx = dc->ctx;
+
+ dce110_timing_generator_disable_vga(tg);
+
+@@ -982,7 +976,7 @@ static void disable_vga_and_power_gate_all_controllers(
+ * powergating. */
+ dce110_enable_display_pipe_clock_gating(ctx,
+ true);
+- dce110_enable_display_power_gating(ctx, controller_id, bp,
++ dce110_enable_display_power_gating(ctx, i+1, bp,
+ PIPE_GATING_CONTROL_ENABLE);
+ }
+ }
+@@ -994,16 +988,16 @@ static void disable_vga_and_power_gate_all_controllers(
+ * 3. Enable power gating for controller
+ * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
+ */
+-static void enable_accelerated_mode(struct validate_context *context)
++static void enable_accelerated_mode(struct dc *dc)
+ {
+ struct bios_parser *bp;
+
+ bp = dal_adapter_service_get_bios_parser(
+- context->res_ctx.pool.adapter_srv);
++ dc->res_pool.adapter_srv);
+
+- power_down_all_hw_blocks(context);
++ power_down_all_hw_blocks(dc);
+
+- disable_vga_and_power_gate_all_controllers(context);
++ disable_vga_and_power_gate_all_controllers(dc);
+
+ dal_bios_parser_set_scratch_acc_mode_change(bp);
+ }
+@@ -1565,6 +1559,10 @@ static bool update_plane_address(
+ static void reset_single_stream_hw_ctx(struct core_stream *stream,
+ struct validate_context *context)
+ {
++ struct bios_parser *bp;
++
++ bp = dal_adapter_service_get_bios_parser(
++ context->res_ctx.pool.adapter_srv);
+ if (stream->audio) {
+ dal_audio_disable_output(stream->audio,
+ stream->stream_enc->id,
+@@ -1580,6 +1578,9 @@ static void reset_single_stream_hw_ctx(struct core_stream *stream,
+ dce110_transform_set_scaler_bypass(stream->xfm);
+ disable_stereo_mixer(stream->ctx);
+ unreference_clock_source(&context->res_ctx, stream->clock_source);
++ dce110_enable_display_power_gating(
++ stream->ctx, stream->controller_idx, bp,
++ PIPE_GATING_CONTROL_ENABLE);
+ }
+
+ static void reset_hw_ctx(struct dc *dc,
+@@ -1604,10 +1605,10 @@ static void reset_hw_ctx(struct dc *dc,
+ }
+ }
+
+-static void power_down(struct validate_context *context)
++static void power_down(struct dc *dc)
+ {
+- power_down_all_hw_blocks(context);
+- disable_vga_and_power_gate_all_controllers(context);
++ power_down_all_hw_blocks(dc);
++ disable_vga_and_power_gate_all_controllers(dc);
+
+ }
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+index 67cc020..b9f21bb 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
+@@ -65,9 +65,9 @@ struct hw_sequencer_funcs {
+ const struct gamma_ramp *ramp,
+ const struct gamma_parameters *params);
+
+- void (*power_down)(struct validate_context *context);
++ void (*power_down)(struct dc *dc);
+
+- void (*enable_accelerated_mode)(struct validate_context *context);
++ void (*enable_accelerated_mode)(struct dc *dc);
+
+ void (*get_crtc_positions)(
+ struct timing_generator *tg,
+--
+2.7.4
+