Linux-libre 5.3.12-gnu
[librecmc/linux-libre.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 #include "core_types.h"
30
31 #define CTX \
32         hws->ctx
33 #define REG(reg)\
34         hws->regs->reg
35
36 #undef FN
37 #define FN(reg_name, field_name) \
38         hws->shifts->field_name, hws->masks->field_name
39
40 void dce_enable_fe_clock(struct dce_hwseq *hws,
41                 unsigned int fe_inst, bool enable)
42 {
43         REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst],
44                         DCFE_CLOCK_ENABLE, enable);
45 }
46
47 void dce_pipe_control_lock(struct dc *dc,
48                 struct pipe_ctx *pipe,
49                 bool lock)
50 {
51         uint32_t lock_val = lock ? 1 : 0;
52         uint32_t dcp_grph, scl, blnd, update_lock_mode, val;
53         struct dce_hwseq *hws = dc->hwseq;
54
55         /* Not lock pipe when blank */
56         if (lock && pipe->stream_res.tg->funcs->is_blanked &&
57             pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg))
58                 return;
59
60         val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst],
61                         BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
62                         BLND_SCL_V_UPDATE_LOCK, &scl,
63                         BLND_BLND_V_UPDATE_LOCK, &blnd,
64                         BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);
65
66         dcp_grph = lock_val;
67         scl = lock_val;
68         blnd = lock_val;
69         update_lock_mode = lock_val;
70
71         REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
72                         BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
73                         BLND_SCL_V_UPDATE_LOCK, scl);
74
75         if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0)
76                 REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
77                                 BLND_BLND_V_UPDATE_LOCK, blnd,
78                                 BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
79
80         if (hws->wa.blnd_crtc_trigger) {
81                 if (!lock) {
82                         uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst]);
83                         REG_WRITE(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst], value);
84                 }
85         }
86 }
87
88 void dce_set_blender_mode(struct dce_hwseq *hws,
89         unsigned int blnd_inst,
90         enum blnd_mode mode)
91 {
92         uint32_t feedthrough = 1;
93         uint32_t blnd_mode = 0;
94         uint32_t multiplied_mode = 0;
95         uint32_t alpha_mode = 2;
96
97         switch (mode) {
98         case BLND_MODE_OTHER_PIPE:
99                 feedthrough = 0;
100                 blnd_mode = 1;
101                 alpha_mode = 0;
102                 break;
103         case BLND_MODE_BLENDING:
104                 feedthrough = 0;
105                 blnd_mode = 2;
106                 alpha_mode = 0;
107                 multiplied_mode = 1;
108                 break;
109         case BLND_MODE_CURRENT_PIPE:
110         default:
111                 if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
112                                 blnd_inst == 0)
113                         feedthrough = 0;
114                 break;
115         }
116
117         REG_UPDATE(BLND_CONTROL[blnd_inst],
118                 BLND_MODE, blnd_mode);
119
120         if (hws->masks->BLND_ALPHA_MODE != 0) {
121                 REG_UPDATE_3(BLND_CONTROL[blnd_inst],
122                         BLND_FEEDTHROUGH_EN, feedthrough,
123                         BLND_ALPHA_MODE, alpha_mode,
124                         BLND_MULTIPLIED_MODE, multiplied_mode);
125         }
126 }
127
128
129 static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
130 {
131         if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
132                 REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
133                                 DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
134 }
135
136 static void dce_underlay_clock_enable(struct dce_hwseq *hws)
137 {
138         /* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
139         if (REG(DCFEV_CLOCK_CONTROL))
140                 REG_UPDATE(DCFEV_CLOCK_CONTROL,
141                                 DCFEV_CLOCK_ENABLE, 1);
142 }
143
144 static void enable_hw_base_light_sleep(void)
145 {
146         /* TODO: implement */
147 }
148
149 static void disable_sw_manual_control_light_sleep(void)
150 {
151         /* TODO: implement */
152 }
153
154 void dce_clock_gating_power_up(struct dce_hwseq *hws,
155                 bool enable)
156 {
157         if (enable) {
158                 enable_hw_base_light_sleep();
159                 disable_sw_manual_control_light_sleep();
160         } else {
161                 dce_disable_sram_shut_down(hws);
162                 dce_underlay_clock_enable(hws);
163         }
164 }
165
166 void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
167                 struct clock_source *clk_src,
168                 unsigned int tg_inst)
169 {
170         if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO || clk_src->dp_clk_src) {
171                 REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
172                                 DP_DTO0_ENABLE, 1);
173
174         } else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
175                 uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
176
177                 REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
178                                 PHYPLL_PIXEL_RATE_SOURCE, rate_source,
179                                 PIXEL_RATE_PLL_SOURCE, 0);
180
181                 REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
182                                 DP_DTO0_ENABLE, 0);
183
184         } else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
185                 uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
186
187                 REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
188                                 PIXEL_RATE_SOURCE, rate_source,
189                                 DP_DTO0_ENABLE, 0);
190
191                 if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
192                         REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
193                                         PIXEL_RATE_PLL_SOURCE, 1);
194         } else {
195                 DC_ERR("Unknown clock source. clk_src id: %d, TG_inst: %d",
196                        clk_src->id, tg_inst);
197         }
198 }
199
200 /* Only use LUT for 8 bit formats */
201 bool dce_use_lut(enum surface_pixel_format format)
202 {
203         switch (format) {
204         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
205         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
206                 return true;
207         default:
208                 return false;
209         }
210 }