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_private.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  
dce_enable_fe_clock(struct dce_hwseq * hws,unsigned int fe_inst,bool enable)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  
dce_pipe_control_lock(struct dc * dc,struct pipe_ctx * pipe,bool lock)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  #if defined(CONFIG_DRM_AMD_DC_SI)
dce60_pipe_control_lock(struct dc * dc,struct pipe_ctx * pipe,bool lock)89  void dce60_pipe_control_lock(struct dc *dc,
90  		struct pipe_ctx *pipe,
91  		bool lock)
92  {
93  	/* DCE6 has no BLND_V_UPDATE_LOCK register */
94  }
95  #endif
96  
dce_set_blender_mode(struct dce_hwseq * hws,unsigned int blnd_inst,enum blnd_mode mode)97  void dce_set_blender_mode(struct dce_hwseq *hws,
98  	unsigned int blnd_inst,
99  	enum blnd_mode mode)
100  {
101  	uint32_t feedthrough = 1;
102  	uint32_t blnd_mode = 0;
103  	uint32_t multiplied_mode = 0;
104  	uint32_t alpha_mode = 2;
105  
106  	switch (mode) {
107  	case BLND_MODE_OTHER_PIPE:
108  		feedthrough = 0;
109  		blnd_mode = 1;
110  		alpha_mode = 0;
111  		break;
112  	case BLND_MODE_BLENDING:
113  		feedthrough = 0;
114  		blnd_mode = 2;
115  		alpha_mode = 0;
116  		multiplied_mode = 1;
117  		break;
118  	case BLND_MODE_CURRENT_PIPE:
119  	default:
120  		if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
121  				blnd_inst == 0)
122  			feedthrough = 0;
123  		break;
124  	}
125  
126  	REG_UPDATE(BLND_CONTROL[blnd_inst],
127  		BLND_MODE, blnd_mode);
128  
129  	if (hws->masks->BLND_ALPHA_MODE != 0) {
130  		REG_UPDATE_3(BLND_CONTROL[blnd_inst],
131  			BLND_FEEDTHROUGH_EN, feedthrough,
132  			BLND_ALPHA_MODE, alpha_mode,
133  			BLND_MULTIPLIED_MODE, multiplied_mode);
134  	}
135  }
136  
137  
dce_disable_sram_shut_down(struct dce_hwseq * hws)138  static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
139  {
140  	if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
141  		REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
142  				DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
143  }
144  
dce_underlay_clock_enable(struct dce_hwseq * hws)145  static void dce_underlay_clock_enable(struct dce_hwseq *hws)
146  {
147  	/* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
148  	if (REG(DCFEV_CLOCK_CONTROL))
149  		REG_UPDATE(DCFEV_CLOCK_CONTROL,
150  				DCFEV_CLOCK_ENABLE, 1);
151  }
152  
enable_hw_base_light_sleep(void)153  static void enable_hw_base_light_sleep(void)
154  {
155  	/* TODO: implement */
156  }
157  
disable_sw_manual_control_light_sleep(void)158  static void disable_sw_manual_control_light_sleep(void)
159  {
160  	/* TODO: implement */
161  }
162  
dce_clock_gating_power_up(struct dce_hwseq * hws,bool enable)163  void dce_clock_gating_power_up(struct dce_hwseq *hws,
164  		bool enable)
165  {
166  	if (enable) {
167  		enable_hw_base_light_sleep();
168  		disable_sw_manual_control_light_sleep();
169  	} else {
170  		dce_disable_sram_shut_down(hws);
171  		dce_underlay_clock_enable(hws);
172  	}
173  }
174  
dce_crtc_switch_to_clk_src(struct dce_hwseq * hws,struct clock_source * clk_src,unsigned int tg_inst)175  void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
176  		struct clock_source *clk_src,
177  		unsigned int tg_inst)
178  {
179  	if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO || clk_src->dp_clk_src) {
180  		REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
181  				DP_DTO0_ENABLE, 1);
182  
183  	} else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
184  		uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
185  
186  		REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
187  				PHYPLL_PIXEL_RATE_SOURCE, rate_source,
188  				PIXEL_RATE_PLL_SOURCE, 0);
189  
190  		REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
191  				DP_DTO0_ENABLE, 0);
192  
193  	} else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
194  		uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
195  
196  		REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
197  				PIXEL_RATE_SOURCE, rate_source,
198  				DP_DTO0_ENABLE, 0);
199  
200  		if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
201  			REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
202  					PIXEL_RATE_PLL_SOURCE, 1);
203  	} else {
204  		DC_ERR("Unknown clock source. clk_src id: %d, TG_inst: %d",
205  		       clk_src->id, tg_inst);
206  	}
207  }
208  
209  /* Only use LUT for 8 bit formats */
dce_use_lut(enum surface_pixel_format format)210  bool dce_use_lut(enum surface_pixel_format format)
211  {
212  	switch (format) {
213  	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
214  	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
215  		return true;
216  	default:
217  		return false;
218  	}
219  }
220