]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c
drm/amd/dc: Add dc display driver (v2)
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce / dce_hwseq.c
1 /*
2 * Copyright 2016 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "dce_hwseq.h"
27 #include "reg_helper.h"
28 #include "hw_sequencer.h"
29
30 #define CTX \
31 hws->ctx
32 #define REG(reg)\
33 hws->regs->reg
34
35 #undef FN
36 #define FN(reg_name, field_name) \
37 hws->shifts->field_name, hws->masks->field_name
38
39 void dce_enable_fe_clock(struct dce_hwseq *hws,
40 unsigned int fe_inst, bool enable)
41 {
42 REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst],
43 DCFE_CLOCK_ENABLE, enable);
44 }
45
46 void dce_pipe_control_lock(struct dce_hwseq *hws,
47 unsigned int blnd_inst,
48 enum pipe_lock_control control_mask,
49 bool lock)
50 {
51 uint32_t lock_val = lock ? 1 : 0;
52 uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode;
53
54 uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst],
55 BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
56 BLND_SCL_V_UPDATE_LOCK, &scl,
57 BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf,
58 BLND_BLND_V_UPDATE_LOCK, &blnd,
59 BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);
60
61 if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
62 dcp_grph = lock_val;
63
64 if (control_mask & PIPE_LOCK_CONTROL_SCL)
65 scl = lock_val;
66
67 if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
68 dcp_grph_surf = lock_val;
69
70 if (control_mask & PIPE_LOCK_CONTROL_BLENDER)
71 blnd = lock_val;
72
73 if (control_mask & PIPE_LOCK_CONTROL_MODE)
74 update_lock_mode = lock_val;
75
76 REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val,
77 BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
78 BLND_SCL_V_UPDATE_LOCK, scl,
79 BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf,
80 BLND_BLND_V_UPDATE_LOCK, blnd,
81 BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
82
83 if (hws->wa.blnd_crtc_trigger)
84 if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) {
85 uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]);
86 REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value);
87 }
88 }
89
90 void dce_set_blender_mode(struct dce_hwseq *hws,
91 unsigned int blnd_inst,
92 enum blnd_mode mode)
93 {
94 uint32_t feedthrough = 1;
95 uint32_t blnd_mode = 0;
96 uint32_t multiplied_mode = 0;
97 uint32_t alpha_mode = 2;
98
99 switch (mode) {
100 case BLND_MODE_OTHER_PIPE:
101 feedthrough = 0;
102 blnd_mode = 1;
103 alpha_mode = 0;
104 break;
105 case BLND_MODE_BLENDING:
106 feedthrough = 0;
107 blnd_mode = 2;
108 alpha_mode = 0;
109 multiplied_mode = 1;
110 break;
111 case BLND_MODE_CURRENT_PIPE:
112 default:
113 if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
114 blnd_inst == 0)
115 feedthrough = 0;
116 break;
117 }
118
119 REG_UPDATE_4(BLND_CONTROL[blnd_inst],
120 BLND_FEEDTHROUGH_EN, feedthrough,
121 BLND_ALPHA_MODE, alpha_mode,
122 BLND_MODE, blnd_mode,
123 BLND_MULTIPLIED_MODE, multiplied_mode);
124 }
125
126
127 static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
128 {
129 if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
130 REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
131 DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
132 }
133
134 static void dce_underlay_clock_enable(struct dce_hwseq *hws)
135 {
136 /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
137 if (REG(DCFEV_CLOCK_CONTROL))
138 REG_UPDATE(DCFEV_CLOCK_CONTROL,
139 DCFEV_CLOCK_ENABLE, 1);
140 }
141
142 static void enable_hw_base_light_sleep(void)
143 {
144 /* TODO: implement */
145 }
146
147 static void disable_sw_manual_control_light_sleep(void)
148 {
149 /* TODO: implement */
150 }
151
152 void dce_clock_gating_power_up(struct dce_hwseq *hws,
153 bool enable)
154 {
155 if (enable) {
156 enable_hw_base_light_sleep();
157 disable_sw_manual_control_light_sleep();
158 } else {
159 dce_disable_sram_shut_down(hws);
160 dce_underlay_clock_enable(hws);
161 }
162 }
163
164 void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
165 struct clock_source *clk_src,
166 unsigned int tg_inst)
167 {
168 if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) {
169 REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
170 DP_DTO0_ENABLE, 1);
171
172 } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
173 uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
174
175 REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
176 PHYPLL_PIXEL_RATE_SOURCE, rate_source,
177 PIXEL_RATE_PLL_SOURCE, 0);
178
179 REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
180 DP_DTO0_ENABLE, 0);
181
182 } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
183 uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
184
185 REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
186 PIXEL_RATE_SOURCE, rate_source,
187 DP_DTO0_ENABLE, 0);
188
189 if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
190 REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
191 PIXEL_RATE_PLL_SOURCE, 1);
192 } else {
193 DC_ERR("unknown clock source");
194 }
195 }