1b843c749SSergey Zigachev /*
2b843c749SSergey Zigachev * Copyright 2015 Advanced Micro Devices, Inc.
3b843c749SSergey Zigachev *
4b843c749SSergey Zigachev * Permission is hereby granted, free of charge, to any person obtaining a
5b843c749SSergey Zigachev * copy of this software and associated documentation files (the "Software"),
6b843c749SSergey Zigachev * to deal in the Software without restriction, including without limitation
7b843c749SSergey Zigachev * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b843c749SSergey Zigachev * and/or sell copies of the Software, and to permit persons to whom the
9b843c749SSergey Zigachev * Software is furnished to do so, subject to the following conditions:
10b843c749SSergey Zigachev *
11b843c749SSergey Zigachev * The above copyright notice and this permission notice shall be included in
12b843c749SSergey Zigachev * all copies or substantial portions of the Software.
13b843c749SSergey Zigachev *
14b843c749SSergey Zigachev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b843c749SSergey Zigachev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b843c749SSergey Zigachev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17b843c749SSergey Zigachev * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b843c749SSergey Zigachev * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b843c749SSergey Zigachev * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b843c749SSergey Zigachev * OTHER DEALINGS IN THE SOFTWARE.
21b843c749SSergey Zigachev *
22b843c749SSergey Zigachev * Authors: AMD
23b843c749SSergey Zigachev *
24b843c749SSergey Zigachev */
25b843c749SSergey Zigachev #include "dm_services.h"
26b843c749SSergey Zigachev #include "dc.h"
27b843c749SSergey Zigachev #include "dc_bios_types.h"
28b843c749SSergey Zigachev #include "core_types.h"
29b843c749SSergey Zigachev #include "core_status.h"
30b843c749SSergey Zigachev #include "resource.h"
31b843c749SSergey Zigachev #include "dm_helpers.h"
32b843c749SSergey Zigachev #include "dce110_hw_sequencer.h"
33b843c749SSergey Zigachev #include "dce110_timing_generator.h"
34b843c749SSergey Zigachev #include "dce/dce_hwseq.h"
35b843c749SSergey Zigachev #include "gpio_service_interface.h"
36b843c749SSergey Zigachev
37b843c749SSergey Zigachev #include "dce110_compressor.h"
38b843c749SSergey Zigachev
39b843c749SSergey Zigachev #include "bios/bios_parser_helper.h"
40b843c749SSergey Zigachev #include "timing_generator.h"
41b843c749SSergey Zigachev #include "mem_input.h"
42b843c749SSergey Zigachev #include "opp.h"
43b843c749SSergey Zigachev #include "ipp.h"
44b843c749SSergey Zigachev #include "transform.h"
45b843c749SSergey Zigachev #include "stream_encoder.h"
46b843c749SSergey Zigachev #include "link_encoder.h"
47b843c749SSergey Zigachev #include "link_hwss.h"
48b843c749SSergey Zigachev #include "clock_source.h"
49b843c749SSergey Zigachev #include "abm.h"
50b843c749SSergey Zigachev #include "audio.h"
51b843c749SSergey Zigachev #include "reg_helper.h"
52b843c749SSergey Zigachev
53b843c749SSergey Zigachev /* include DCE11 register header files */
54b843c749SSergey Zigachev #include "dce/dce_11_0_d.h"
55b843c749SSergey Zigachev #include "dce/dce_11_0_sh_mask.h"
56b843c749SSergey Zigachev #include "custom_float.h"
57b843c749SSergey Zigachev
58b843c749SSergey Zigachev #include "atomfirmware.h"
59b843c749SSergey Zigachev
60b843c749SSergey Zigachev /*
61b843c749SSergey Zigachev * All values are in milliseconds;
62b843c749SSergey Zigachev * For eDP, after power-up/power/down,
63b843c749SSergey Zigachev * 300/500 msec max. delay from LCDVCC to black video generation
64b843c749SSergey Zigachev */
65b843c749SSergey Zigachev #define PANEL_POWER_UP_TIMEOUT 300
66b843c749SSergey Zigachev #define PANEL_POWER_DOWN_TIMEOUT 500
67b843c749SSergey Zigachev #define HPD_CHECK_INTERVAL 10
68b843c749SSergey Zigachev
69b843c749SSergey Zigachev #define CTX \
70b843c749SSergey Zigachev hws->ctx
71b843c749SSergey Zigachev
72b843c749SSergey Zigachev #define DC_LOGGER_INIT()
73b843c749SSergey Zigachev
74b843c749SSergey Zigachev #define REG(reg)\
75b843c749SSergey Zigachev hws->regs->reg
76b843c749SSergey Zigachev
77b843c749SSergey Zigachev #undef FN
78b843c749SSergey Zigachev #define FN(reg_name, field_name) \
79b843c749SSergey Zigachev hws->shifts->field_name, hws->masks->field_name
80b843c749SSergey Zigachev
81b843c749SSergey Zigachev struct dce110_hw_seq_reg_offsets {
82b843c749SSergey Zigachev uint32_t crtc;
83b843c749SSergey Zigachev };
84b843c749SSergey Zigachev
85b843c749SSergey Zigachev static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
86b843c749SSergey Zigachev {
87b843c749SSergey Zigachev .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
88b843c749SSergey Zigachev },
89b843c749SSergey Zigachev {
90b843c749SSergey Zigachev .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
91b843c749SSergey Zigachev },
92b843c749SSergey Zigachev {
93b843c749SSergey Zigachev .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
94b843c749SSergey Zigachev },
95b843c749SSergey Zigachev {
96b843c749SSergey Zigachev .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
97b843c749SSergey Zigachev }
98b843c749SSergey Zigachev };
99b843c749SSergey Zigachev
100b843c749SSergey Zigachev #define HW_REG_BLND(reg, id)\
101b843c749SSergey Zigachev (reg + reg_offsets[id].blnd)
102b843c749SSergey Zigachev
103b843c749SSergey Zigachev #define HW_REG_CRTC(reg, id)\
104b843c749SSergey Zigachev (reg + reg_offsets[id].crtc)
105b843c749SSergey Zigachev
106b843c749SSergey Zigachev #define MAX_WATERMARK 0xFFFF
107b843c749SSergey Zigachev #define SAFE_NBP_MARK 0x7FFF
108b843c749SSergey Zigachev
109b843c749SSergey Zigachev /*******************************************************************************
110b843c749SSergey Zigachev * Private definitions
111b843c749SSergey Zigachev ******************************************************************************/
112b843c749SSergey Zigachev /***************************PIPE_CONTROL***********************************/
dce110_init_pte(struct dc_context * ctx)113b843c749SSergey Zigachev static void dce110_init_pte(struct dc_context *ctx)
114b843c749SSergey Zigachev {
115b843c749SSergey Zigachev uint32_t addr;
116b843c749SSergey Zigachev uint32_t value = 0;
117b843c749SSergey Zigachev uint32_t chunk_int = 0;
118b843c749SSergey Zigachev uint32_t chunk_mul = 0;
119b843c749SSergey Zigachev
120b843c749SSergey Zigachev addr = mmUNP_DVMM_PTE_CONTROL;
121b843c749SSergey Zigachev value = dm_read_reg(ctx, addr);
122b843c749SSergey Zigachev
123b843c749SSergey Zigachev set_reg_field_value(
124b843c749SSergey Zigachev value,
125b843c749SSergey Zigachev 0,
126b843c749SSergey Zigachev DVMM_PTE_CONTROL,
127b843c749SSergey Zigachev DVMM_USE_SINGLE_PTE);
128b843c749SSergey Zigachev
129b843c749SSergey Zigachev set_reg_field_value(
130b843c749SSergey Zigachev value,
131b843c749SSergey Zigachev 1,
132b843c749SSergey Zigachev DVMM_PTE_CONTROL,
133b843c749SSergey Zigachev DVMM_PTE_BUFFER_MODE0);
134b843c749SSergey Zigachev
135b843c749SSergey Zigachev set_reg_field_value(
136b843c749SSergey Zigachev value,
137b843c749SSergey Zigachev 1,
138b843c749SSergey Zigachev DVMM_PTE_CONTROL,
139b843c749SSergey Zigachev DVMM_PTE_BUFFER_MODE1);
140b843c749SSergey Zigachev
141b843c749SSergey Zigachev dm_write_reg(ctx, addr, value);
142b843c749SSergey Zigachev
143b843c749SSergey Zigachev addr = mmDVMM_PTE_REQ;
144b843c749SSergey Zigachev value = dm_read_reg(ctx, addr);
145b843c749SSergey Zigachev
146b843c749SSergey Zigachev chunk_int = get_reg_field_value(
147b843c749SSergey Zigachev value,
148b843c749SSergey Zigachev DVMM_PTE_REQ,
149b843c749SSergey Zigachev HFLIP_PTEREQ_PER_CHUNK_INT);
150b843c749SSergey Zigachev
151b843c749SSergey Zigachev chunk_mul = get_reg_field_value(
152b843c749SSergey Zigachev value,
153b843c749SSergey Zigachev DVMM_PTE_REQ,
154b843c749SSergey Zigachev HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
155b843c749SSergey Zigachev
156b843c749SSergey Zigachev if (chunk_int != 0x4 || chunk_mul != 0x4) {
157b843c749SSergey Zigachev
158b843c749SSergey Zigachev set_reg_field_value(
159b843c749SSergey Zigachev value,
160b843c749SSergey Zigachev 255,
161b843c749SSergey Zigachev DVMM_PTE_REQ,
162b843c749SSergey Zigachev MAX_PTEREQ_TO_ISSUE);
163b843c749SSergey Zigachev
164b843c749SSergey Zigachev set_reg_field_value(
165b843c749SSergey Zigachev value,
166b843c749SSergey Zigachev 4,
167b843c749SSergey Zigachev DVMM_PTE_REQ,
168b843c749SSergey Zigachev HFLIP_PTEREQ_PER_CHUNK_INT);
169b843c749SSergey Zigachev
170b843c749SSergey Zigachev set_reg_field_value(
171b843c749SSergey Zigachev value,
172b843c749SSergey Zigachev 4,
173b843c749SSergey Zigachev DVMM_PTE_REQ,
174b843c749SSergey Zigachev HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
175b843c749SSergey Zigachev
176b843c749SSergey Zigachev dm_write_reg(ctx, addr, value);
177b843c749SSergey Zigachev }
178b843c749SSergey Zigachev }
179b843c749SSergey Zigachev /**************************************************************************/
180b843c749SSergey Zigachev
enable_display_pipe_clock_gating(struct dc_context * ctx,bool clock_gating)181b843c749SSergey Zigachev static void enable_display_pipe_clock_gating(
182b843c749SSergey Zigachev struct dc_context *ctx,
183b843c749SSergey Zigachev bool clock_gating)
184b843c749SSergey Zigachev {
185b843c749SSergey Zigachev /*TODO*/
186b843c749SSergey Zigachev }
187b843c749SSergey Zigachev
dce110_enable_display_power_gating(struct dc * dc,uint8_t controller_id,struct dc_bios * dcb,enum pipe_gating_control power_gating)188b843c749SSergey Zigachev static bool dce110_enable_display_power_gating(
189b843c749SSergey Zigachev struct dc *dc,
190b843c749SSergey Zigachev uint8_t controller_id,
191b843c749SSergey Zigachev struct dc_bios *dcb,
192b843c749SSergey Zigachev enum pipe_gating_control power_gating)
193b843c749SSergey Zigachev {
194b843c749SSergey Zigachev enum bp_result bp_result = BP_RESULT_OK;
195b843c749SSergey Zigachev enum bp_pipe_control_action cntl;
196b843c749SSergey Zigachev struct dc_context *ctx = dc->ctx;
197b843c749SSergey Zigachev unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
198b843c749SSergey Zigachev
199b843c749SSergey Zigachev if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
200b843c749SSergey Zigachev return true;
201b843c749SSergey Zigachev
202b843c749SSergey Zigachev if (power_gating == PIPE_GATING_CONTROL_INIT)
203b843c749SSergey Zigachev cntl = ASIC_PIPE_INIT;
204b843c749SSergey Zigachev else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
205b843c749SSergey Zigachev cntl = ASIC_PIPE_ENABLE;
206b843c749SSergey Zigachev else
207b843c749SSergey Zigachev cntl = ASIC_PIPE_DISABLE;
208b843c749SSergey Zigachev
209b843c749SSergey Zigachev if (controller_id == underlay_idx)
210b843c749SSergey Zigachev controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
211b843c749SSergey Zigachev
212b843c749SSergey Zigachev if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
213b843c749SSergey Zigachev
214b843c749SSergey Zigachev bp_result = dcb->funcs->enable_disp_power_gating(
215b843c749SSergey Zigachev dcb, controller_id + 1, cntl);
216b843c749SSergey Zigachev
217b843c749SSergey Zigachev /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
218b843c749SSergey Zigachev * by default when command table is called
219b843c749SSergey Zigachev *
220b843c749SSergey Zigachev * Bios parser accepts controller_id = 6 as indicative of
221b843c749SSergey Zigachev * underlay pipe in dce110. But we do not support more
222b843c749SSergey Zigachev * than 3.
223b843c749SSergey Zigachev */
224b843c749SSergey Zigachev if (controller_id < CONTROLLER_ID_MAX - 1)
225b843c749SSergey Zigachev dm_write_reg(ctx,
226b843c749SSergey Zigachev HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
227b843c749SSergey Zigachev 0);
228b843c749SSergey Zigachev }
229b843c749SSergey Zigachev
230b843c749SSergey Zigachev if (power_gating != PIPE_GATING_CONTROL_ENABLE)
231b843c749SSergey Zigachev dce110_init_pte(ctx);
232b843c749SSergey Zigachev
233b843c749SSergey Zigachev if (bp_result == BP_RESULT_OK)
234b843c749SSergey Zigachev return true;
235b843c749SSergey Zigachev else
236b843c749SSergey Zigachev return false;
237b843c749SSergey Zigachev }
238b843c749SSergey Zigachev
build_prescale_params(struct ipp_prescale_params * prescale_params,const struct dc_plane_state * plane_state)239b843c749SSergey Zigachev static void build_prescale_params(struct ipp_prescale_params *prescale_params,
240b843c749SSergey Zigachev const struct dc_plane_state *plane_state)
241b843c749SSergey Zigachev {
242b843c749SSergey Zigachev prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
243b843c749SSergey Zigachev
244b843c749SSergey Zigachev switch (plane_state->format) {
245b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
246b843c749SSergey Zigachev prescale_params->scale = 0x2082;
247b843c749SSergey Zigachev break;
248b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
249b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
250b843c749SSergey Zigachev prescale_params->scale = 0x2020;
251b843c749SSergey Zigachev break;
252b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
253b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
254b843c749SSergey Zigachev prescale_params->scale = 0x2008;
255b843c749SSergey Zigachev break;
256b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
257b843c749SSergey Zigachev case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
258b843c749SSergey Zigachev prescale_params->scale = 0x2000;
259b843c749SSergey Zigachev break;
260b843c749SSergey Zigachev default:
261b843c749SSergey Zigachev ASSERT(false);
262b843c749SSergey Zigachev break;
263b843c749SSergey Zigachev }
264b843c749SSergey Zigachev }
265b843c749SSergey Zigachev
266b843c749SSergey Zigachev static bool
dce110_set_input_transfer_func(struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)267b843c749SSergey Zigachev dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
268b843c749SSergey Zigachev const struct dc_plane_state *plane_state)
269b843c749SSergey Zigachev {
270b843c749SSergey Zigachev struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
271b843c749SSergey Zigachev const struct dc_transfer_func *tf = NULL;
272b843c749SSergey Zigachev struct ipp_prescale_params prescale_params = { 0 };
273b843c749SSergey Zigachev bool result = true;
274b843c749SSergey Zigachev
275b843c749SSergey Zigachev if (ipp == NULL)
276b843c749SSergey Zigachev return false;
277b843c749SSergey Zigachev
278b843c749SSergey Zigachev if (plane_state->in_transfer_func)
279b843c749SSergey Zigachev tf = plane_state->in_transfer_func;
280b843c749SSergey Zigachev
281b843c749SSergey Zigachev build_prescale_params(&prescale_params, plane_state);
282b843c749SSergey Zigachev ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
283b843c749SSergey Zigachev
284b843c749SSergey Zigachev if (plane_state->gamma_correction &&
285b843c749SSergey Zigachev !plane_state->gamma_correction->is_identity &&
286b843c749SSergey Zigachev dce_use_lut(plane_state->format))
287b843c749SSergey Zigachev ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
288b843c749SSergey Zigachev
289b843c749SSergey Zigachev if (tf == NULL) {
290b843c749SSergey Zigachev /* Default case if no input transfer function specified */
291b843c749SSergey Zigachev ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
292b843c749SSergey Zigachev } else if (tf->type == TF_TYPE_PREDEFINED) {
293b843c749SSergey Zigachev switch (tf->tf) {
294b843c749SSergey Zigachev case TRANSFER_FUNCTION_SRGB:
295b843c749SSergey Zigachev ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
296b843c749SSergey Zigachev break;
297b843c749SSergey Zigachev case TRANSFER_FUNCTION_BT709:
298b843c749SSergey Zigachev ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
299b843c749SSergey Zigachev break;
300b843c749SSergey Zigachev case TRANSFER_FUNCTION_LINEAR:
301b843c749SSergey Zigachev ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
302b843c749SSergey Zigachev break;
303b843c749SSergey Zigachev case TRANSFER_FUNCTION_PQ:
304b843c749SSergey Zigachev default:
305b843c749SSergey Zigachev result = false;
306b843c749SSergey Zigachev break;
307b843c749SSergey Zigachev }
308b843c749SSergey Zigachev } else if (tf->type == TF_TYPE_BYPASS) {
309b843c749SSergey Zigachev ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
310b843c749SSergey Zigachev } else {
311b843c749SSergey Zigachev /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
312b843c749SSergey Zigachev result = false;
313b843c749SSergey Zigachev }
314b843c749SSergey Zigachev
315b843c749SSergey Zigachev return result;
316b843c749SSergey Zigachev }
317b843c749SSergey Zigachev
convert_to_custom_float(struct pwl_result_data * rgb_resulted,struct curve_points * arr_points,uint32_t hw_points_num)318b843c749SSergey Zigachev static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
319b843c749SSergey Zigachev struct curve_points *arr_points,
320b843c749SSergey Zigachev uint32_t hw_points_num)
321b843c749SSergey Zigachev {
322b843c749SSergey Zigachev struct custom_float_format fmt;
323b843c749SSergey Zigachev
324b843c749SSergey Zigachev struct pwl_result_data *rgb = rgb_resulted;
325b843c749SSergey Zigachev
326b843c749SSergey Zigachev uint32_t i = 0;
327b843c749SSergey Zigachev
328b843c749SSergey Zigachev fmt.exponenta_bits = 6;
329b843c749SSergey Zigachev fmt.mantissa_bits = 12;
330b843c749SSergey Zigachev fmt.sign = true;
331b843c749SSergey Zigachev
332b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
333b843c749SSergey Zigachev &arr_points[0].custom_float_x)) {
334b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
335b843c749SSergey Zigachev return false;
336b843c749SSergey Zigachev }
337b843c749SSergey Zigachev
338b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
339b843c749SSergey Zigachev &arr_points[0].custom_float_offset)) {
340b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
341b843c749SSergey Zigachev return false;
342b843c749SSergey Zigachev }
343b843c749SSergey Zigachev
344b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
345b843c749SSergey Zigachev &arr_points[0].custom_float_slope)) {
346b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
347b843c749SSergey Zigachev return false;
348b843c749SSergey Zigachev }
349b843c749SSergey Zigachev
350b843c749SSergey Zigachev fmt.mantissa_bits = 10;
351b843c749SSergey Zigachev fmt.sign = false;
352b843c749SSergey Zigachev
353b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
354b843c749SSergey Zigachev &arr_points[1].custom_float_x)) {
355b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
356b843c749SSergey Zigachev return false;
357b843c749SSergey Zigachev }
358b843c749SSergey Zigachev
359b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
360b843c749SSergey Zigachev &arr_points[1].custom_float_y)) {
361b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
362b843c749SSergey Zigachev return false;
363b843c749SSergey Zigachev }
364b843c749SSergey Zigachev
365b843c749SSergey Zigachev if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
366b843c749SSergey Zigachev &arr_points[1].custom_float_slope)) {
367b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
368b843c749SSergey Zigachev return false;
369b843c749SSergey Zigachev }
370b843c749SSergey Zigachev
371b843c749SSergey Zigachev fmt.mantissa_bits = 12;
372b843c749SSergey Zigachev fmt.sign = true;
373b843c749SSergey Zigachev
374b843c749SSergey Zigachev while (i != hw_points_num) {
375b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->red, &fmt,
376b843c749SSergey Zigachev &rgb->red_reg)) {
377b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
378b843c749SSergey Zigachev return false;
379b843c749SSergey Zigachev }
380b843c749SSergey Zigachev
381b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->green, &fmt,
382b843c749SSergey Zigachev &rgb->green_reg)) {
383b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
384b843c749SSergey Zigachev return false;
385b843c749SSergey Zigachev }
386b843c749SSergey Zigachev
387b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->blue, &fmt,
388b843c749SSergey Zigachev &rgb->blue_reg)) {
389b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
390b843c749SSergey Zigachev return false;
391b843c749SSergey Zigachev }
392b843c749SSergey Zigachev
393b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
394b843c749SSergey Zigachev &rgb->delta_red_reg)) {
395b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
396b843c749SSergey Zigachev return false;
397b843c749SSergey Zigachev }
398b843c749SSergey Zigachev
399b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
400b843c749SSergey Zigachev &rgb->delta_green_reg)) {
401b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
402b843c749SSergey Zigachev return false;
403b843c749SSergey Zigachev }
404b843c749SSergey Zigachev
405b843c749SSergey Zigachev if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
406b843c749SSergey Zigachev &rgb->delta_blue_reg)) {
407b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
408b843c749SSergey Zigachev return false;
409b843c749SSergey Zigachev }
410b843c749SSergey Zigachev
411b843c749SSergey Zigachev ++rgb;
412b843c749SSergey Zigachev ++i;
413b843c749SSergey Zigachev }
414b843c749SSergey Zigachev
415b843c749SSergey Zigachev return true;
416b843c749SSergey Zigachev }
417b843c749SSergey Zigachev
418b843c749SSergey Zigachev #define MAX_LOW_POINT 25
419b843c749SSergey Zigachev #define NUMBER_REGIONS 16
420b843c749SSergey Zigachev #define NUMBER_SW_SEGMENTS 16
421b843c749SSergey Zigachev
422b843c749SSergey Zigachev static bool
dce110_translate_regamma_to_hw_format(const struct dc_transfer_func * output_tf,struct pwl_params * regamma_params)423b843c749SSergey Zigachev dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
424b843c749SSergey Zigachev struct pwl_params *regamma_params)
425b843c749SSergey Zigachev {
426b843c749SSergey Zigachev struct curve_points *arr_points;
427b843c749SSergey Zigachev struct pwl_result_data *rgb_resulted;
428b843c749SSergey Zigachev struct pwl_result_data *rgb;
429b843c749SSergey Zigachev struct pwl_result_data *rgb_plus_1;
430b843c749SSergey Zigachev struct fixed31_32 y_r;
431b843c749SSergey Zigachev struct fixed31_32 y_g;
432b843c749SSergey Zigachev struct fixed31_32 y_b;
433b843c749SSergey Zigachev struct fixed31_32 y1_min;
434b843c749SSergey Zigachev struct fixed31_32 y3_max;
435b843c749SSergey Zigachev
436b843c749SSergey Zigachev int32_t region_start, region_end;
437b843c749SSergey Zigachev uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points;
438b843c749SSergey Zigachev
439b843c749SSergey Zigachev if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
440b843c749SSergey Zigachev return false;
441b843c749SSergey Zigachev
442b843c749SSergey Zigachev arr_points = regamma_params->arr_points;
443b843c749SSergey Zigachev rgb_resulted = regamma_params->rgb_resulted;
444b843c749SSergey Zigachev hw_points = 0;
445b843c749SSergey Zigachev
446b843c749SSergey Zigachev memset(regamma_params, 0, sizeof(struct pwl_params));
447b843c749SSergey Zigachev
448b843c749SSergey Zigachev if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
449b843c749SSergey Zigachev /* 16 segments
450b843c749SSergey Zigachev * segments are from 2^-11 to 2^5
451b843c749SSergey Zigachev */
452b843c749SSergey Zigachev region_start = -11;
453b843c749SSergey Zigachev region_end = region_start + NUMBER_REGIONS;
454b843c749SSergey Zigachev
455b843c749SSergey Zigachev for (i = 0; i < NUMBER_REGIONS; i++)
456b843c749SSergey Zigachev seg_distr[i] = 4;
457b843c749SSergey Zigachev
458b843c749SSergey Zigachev } else {
459b843c749SSergey Zigachev /* 10 segments
460b843c749SSergey Zigachev * segment is from 2^-10 to 2^1
461b843c749SSergey Zigachev * We include an extra segment for range [2^0, 2^1). This is to
462b843c749SSergey Zigachev * ensure that colors with normalized values of 1 don't miss the
463b843c749SSergey Zigachev * LUT.
464b843c749SSergey Zigachev */
465b843c749SSergey Zigachev region_start = -10;
466b843c749SSergey Zigachev region_end = 1;
467b843c749SSergey Zigachev
468b843c749SSergey Zigachev seg_distr[0] = 4;
469b843c749SSergey Zigachev seg_distr[1] = 4;
470b843c749SSergey Zigachev seg_distr[2] = 4;
471b843c749SSergey Zigachev seg_distr[3] = 4;
472b843c749SSergey Zigachev seg_distr[4] = 4;
473b843c749SSergey Zigachev seg_distr[5] = 4;
474b843c749SSergey Zigachev seg_distr[6] = 4;
475b843c749SSergey Zigachev seg_distr[7] = 4;
476b843c749SSergey Zigachev seg_distr[8] = 4;
477b843c749SSergey Zigachev seg_distr[9] = 4;
478b843c749SSergey Zigachev seg_distr[10] = 0;
479b843c749SSergey Zigachev seg_distr[11] = -1;
480b843c749SSergey Zigachev seg_distr[12] = -1;
481b843c749SSergey Zigachev seg_distr[13] = -1;
482b843c749SSergey Zigachev seg_distr[14] = -1;
483b843c749SSergey Zigachev seg_distr[15] = -1;
484b843c749SSergey Zigachev }
485b843c749SSergey Zigachev
486b843c749SSergey Zigachev for (k = 0; k < 16; k++) {
487b843c749SSergey Zigachev if (seg_distr[k] != -1)
488b843c749SSergey Zigachev hw_points += (1 << seg_distr[k]);
489b843c749SSergey Zigachev }
490b843c749SSergey Zigachev
491b843c749SSergey Zigachev j = 0;
492b843c749SSergey Zigachev for (k = 0; k < (region_end - region_start); k++) {
493b843c749SSergey Zigachev increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
494b843c749SSergey Zigachev start_index = (region_start + k + MAX_LOW_POINT) *
495b843c749SSergey Zigachev NUMBER_SW_SEGMENTS;
496b843c749SSergey Zigachev for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
497b843c749SSergey Zigachev i += increment) {
498b843c749SSergey Zigachev if (j == hw_points - 1)
499b843c749SSergey Zigachev break;
500b843c749SSergey Zigachev rgb_resulted[j].red = output_tf->tf_pts.red[i];
501b843c749SSergey Zigachev rgb_resulted[j].green = output_tf->tf_pts.green[i];
502b843c749SSergey Zigachev rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
503b843c749SSergey Zigachev j++;
504b843c749SSergey Zigachev }
505b843c749SSergey Zigachev }
506b843c749SSergey Zigachev
507b843c749SSergey Zigachev /* last point */
508b843c749SSergey Zigachev start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
509b843c749SSergey Zigachev rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
510b843c749SSergey Zigachev rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
511b843c749SSergey Zigachev rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
512b843c749SSergey Zigachev
513b843c749SSergey Zigachev arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2),
514b843c749SSergey Zigachev dc_fixpt_from_int(region_start));
515b843c749SSergey Zigachev arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2),
516b843c749SSergey Zigachev dc_fixpt_from_int(region_end));
517b843c749SSergey Zigachev
518b843c749SSergey Zigachev y_r = rgb_resulted[0].red;
519b843c749SSergey Zigachev y_g = rgb_resulted[0].green;
520b843c749SSergey Zigachev y_b = rgb_resulted[0].blue;
521b843c749SSergey Zigachev
522b843c749SSergey Zigachev y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b));
523b843c749SSergey Zigachev
524b843c749SSergey Zigachev arr_points[0].y = y1_min;
525b843c749SSergey Zigachev arr_points[0].slope = dc_fixpt_div(arr_points[0].y,
526b843c749SSergey Zigachev arr_points[0].x);
527b843c749SSergey Zigachev
528b843c749SSergey Zigachev y_r = rgb_resulted[hw_points - 1].red;
529b843c749SSergey Zigachev y_g = rgb_resulted[hw_points - 1].green;
530b843c749SSergey Zigachev y_b = rgb_resulted[hw_points - 1].blue;
531b843c749SSergey Zigachev
532b843c749SSergey Zigachev /* see comment above, m_arrPoints[1].y should be the Y value for the
533b843c749SSergey Zigachev * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
534b843c749SSergey Zigachev */
535b843c749SSergey Zigachev y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b));
536b843c749SSergey Zigachev
537b843c749SSergey Zigachev arr_points[1].y = y3_max;
538b843c749SSergey Zigachev
539b843c749SSergey Zigachev arr_points[1].slope = dc_fixpt_zero;
540b843c749SSergey Zigachev
541b843c749SSergey Zigachev if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
542b843c749SSergey Zigachev /* for PQ, we want to have a straight line from last HW X point,
543b843c749SSergey Zigachev * and the slope to be such that we hit 1.0 at 10000 nits.
544b843c749SSergey Zigachev */
545b843c749SSergey Zigachev const struct fixed31_32 end_value = dc_fixpt_from_int(125);
546b843c749SSergey Zigachev
547b843c749SSergey Zigachev arr_points[1].slope = dc_fixpt_div(
548b843c749SSergey Zigachev dc_fixpt_sub(dc_fixpt_one, arr_points[1].y),
549b843c749SSergey Zigachev dc_fixpt_sub(end_value, arr_points[1].x));
550b843c749SSergey Zigachev }
551b843c749SSergey Zigachev
552b843c749SSergey Zigachev regamma_params->hw_points_num = hw_points;
553b843c749SSergey Zigachev
554b843c749SSergey Zigachev i = 1;
555b843c749SSergey Zigachev for (k = 0; k < 16 && i < 16; k++) {
556b843c749SSergey Zigachev if (seg_distr[k] != -1) {
557b843c749SSergey Zigachev regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
558b843c749SSergey Zigachev regamma_params->arr_curve_points[i].offset =
559b843c749SSergey Zigachev regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
560b843c749SSergey Zigachev }
561b843c749SSergey Zigachev i++;
562b843c749SSergey Zigachev }
563b843c749SSergey Zigachev
564b843c749SSergey Zigachev if (seg_distr[k] != -1)
565b843c749SSergey Zigachev regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
566b843c749SSergey Zigachev
567b843c749SSergey Zigachev rgb = rgb_resulted;
568b843c749SSergey Zigachev rgb_plus_1 = rgb_resulted + 1;
569b843c749SSergey Zigachev
570b843c749SSergey Zigachev i = 1;
571b843c749SSergey Zigachev
572b843c749SSergey Zigachev while (i != hw_points + 1) {
573b843c749SSergey Zigachev if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
574b843c749SSergey Zigachev rgb_plus_1->red = rgb->red;
575b843c749SSergey Zigachev if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
576b843c749SSergey Zigachev rgb_plus_1->green = rgb->green;
577b843c749SSergey Zigachev if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
578b843c749SSergey Zigachev rgb_plus_1->blue = rgb->blue;
579b843c749SSergey Zigachev
580b843c749SSergey Zigachev rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
581b843c749SSergey Zigachev rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
582b843c749SSergey Zigachev rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
583b843c749SSergey Zigachev
584b843c749SSergey Zigachev ++rgb_plus_1;
585b843c749SSergey Zigachev ++rgb;
586b843c749SSergey Zigachev ++i;
587b843c749SSergey Zigachev }
588b843c749SSergey Zigachev
589b843c749SSergey Zigachev convert_to_custom_float(rgb_resulted, arr_points, hw_points);
590b843c749SSergey Zigachev
591b843c749SSergey Zigachev return true;
592b843c749SSergey Zigachev }
593b843c749SSergey Zigachev
594b843c749SSergey Zigachev static bool
dce110_set_output_transfer_func(struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)595b843c749SSergey Zigachev dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
596b843c749SSergey Zigachev const struct dc_stream_state *stream)
597b843c749SSergey Zigachev {
598b843c749SSergey Zigachev struct transform *xfm = pipe_ctx->plane_res.xfm;
599b843c749SSergey Zigachev
600b843c749SSergey Zigachev xfm->funcs->opp_power_on_regamma_lut(xfm, true);
601b843c749SSergey Zigachev xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
602b843c749SSergey Zigachev
603b843c749SSergey Zigachev if (stream->out_transfer_func &&
604b843c749SSergey Zigachev stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
605b843c749SSergey Zigachev stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
606b843c749SSergey Zigachev xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
607b843c749SSergey Zigachev } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
608b843c749SSergey Zigachev &xfm->regamma_params)) {
609b843c749SSergey Zigachev xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
610b843c749SSergey Zigachev xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
611b843c749SSergey Zigachev } else {
612b843c749SSergey Zigachev xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
613b843c749SSergey Zigachev }
614b843c749SSergey Zigachev
615b843c749SSergey Zigachev xfm->funcs->opp_power_on_regamma_lut(xfm, false);
616b843c749SSergey Zigachev
617b843c749SSergey Zigachev return true;
618b843c749SSergey Zigachev }
619b843c749SSergey Zigachev
bios_parser_crtc_source_select(struct pipe_ctx * pipe_ctx)620b843c749SSergey Zigachev static enum dc_status bios_parser_crtc_source_select(
621b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx)
622b843c749SSergey Zigachev {
623b843c749SSergey Zigachev struct dc_bios *dcb;
624b843c749SSergey Zigachev /* call VBIOS table to set CRTC source for the HW
625b843c749SSergey Zigachev * encoder block
626b843c749SSergey Zigachev * note: video bios clears all FMT setting here. */
627b843c749SSergey Zigachev struct bp_crtc_source_select crtc_source_select = {0};
628b843c749SSergey Zigachev const struct dc_sink *sink = pipe_ctx->stream->sink;
629b843c749SSergey Zigachev
630b843c749SSergey Zigachev crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id;
631b843c749SSergey Zigachev crtc_source_select.controller_id = pipe_ctx->stream_res.tg->inst + 1;
632b843c749SSergey Zigachev /*TODO: Need to un-hardcode color depth, dp_audio and account for
633b843c749SSergey Zigachev * the case where signal and sink signal is different (translator
634b843c749SSergey Zigachev * encoder)*/
635b843c749SSergey Zigachev crtc_source_select.signal = pipe_ctx->stream->signal;
636b843c749SSergey Zigachev crtc_source_select.enable_dp_audio = false;
637b843c749SSergey Zigachev crtc_source_select.sink_signal = pipe_ctx->stream->signal;
638b843c749SSergey Zigachev
639b843c749SSergey Zigachev switch (pipe_ctx->stream->timing.display_color_depth) {
640b843c749SSergey Zigachev case COLOR_DEPTH_666:
641b843c749SSergey Zigachev crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR;
642b843c749SSergey Zigachev break;
643b843c749SSergey Zigachev case COLOR_DEPTH_888:
644b843c749SSergey Zigachev crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
645b843c749SSergey Zigachev break;
646b843c749SSergey Zigachev case COLOR_DEPTH_101010:
647b843c749SSergey Zigachev crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR;
648b843c749SSergey Zigachev break;
649b843c749SSergey Zigachev case COLOR_DEPTH_121212:
650b843c749SSergey Zigachev crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR;
651b843c749SSergey Zigachev break;
652b843c749SSergey Zigachev default:
653b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
654b843c749SSergey Zigachev crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
655b843c749SSergey Zigachev break;
656b843c749SSergey Zigachev }
657b843c749SSergey Zigachev
658b843c749SSergey Zigachev dcb = sink->ctx->dc_bios;
659b843c749SSergey Zigachev
660b843c749SSergey Zigachev if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
661b843c749SSergey Zigachev dcb,
662b843c749SSergey Zigachev &crtc_source_select)) {
663b843c749SSergey Zigachev return DC_ERROR_UNEXPECTED;
664b843c749SSergey Zigachev }
665b843c749SSergey Zigachev
666b843c749SSergey Zigachev return DC_OK;
667b843c749SSergey Zigachev }
668b843c749SSergey Zigachev
dce110_update_info_frame(struct pipe_ctx * pipe_ctx)669b843c749SSergey Zigachev void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
670b843c749SSergey Zigachev {
671b843c749SSergey Zigachev bool is_hdmi;
672b843c749SSergey Zigachev bool is_dp;
673b843c749SSergey Zigachev
674b843c749SSergey Zigachev ASSERT(pipe_ctx->stream);
675b843c749SSergey Zigachev
676b843c749SSergey Zigachev if (pipe_ctx->stream_res.stream_enc == NULL)
677b843c749SSergey Zigachev return; /* this is not root pipe */
678b843c749SSergey Zigachev
679b843c749SSergey Zigachev is_hdmi = dc_is_hdmi_signal(pipe_ctx->stream->signal);
680b843c749SSergey Zigachev is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
681b843c749SSergey Zigachev
682b843c749SSergey Zigachev if (!is_hdmi && !is_dp)
683b843c749SSergey Zigachev return;
684b843c749SSergey Zigachev
685b843c749SSergey Zigachev if (is_hdmi)
686b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
687b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
688b843c749SSergey Zigachev &pipe_ctx->stream_res.encoder_info_frame);
689b843c749SSergey Zigachev else
690b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
691b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
692b843c749SSergey Zigachev &pipe_ctx->stream_res.encoder_info_frame);
693b843c749SSergey Zigachev }
694b843c749SSergey Zigachev
dce110_enable_stream(struct pipe_ctx * pipe_ctx)695b843c749SSergey Zigachev void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
696b843c749SSergey Zigachev {
697b843c749SSergey Zigachev enum dc_lane_count lane_count =
698b843c749SSergey Zigachev pipe_ctx->stream->sink->link->cur_link_settings.lane_count;
699b843c749SSergey Zigachev
700b843c749SSergey Zigachev struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
701b843c749SSergey Zigachev struct dc_link *link = pipe_ctx->stream->sink->link;
702b843c749SSergey Zigachev
703b843c749SSergey Zigachev
704b843c749SSergey Zigachev uint32_t active_total_with_borders;
705b843c749SSergey Zigachev uint32_t early_control = 0;
706b843c749SSergey Zigachev struct timing_generator *tg = pipe_ctx->stream_res.tg;
707b843c749SSergey Zigachev
708b843c749SSergey Zigachev /* For MST, there are multiply stream go to only one link.
709b843c749SSergey Zigachev * connect DIG back_end to front_end while enable_stream and
710b843c749SSergey Zigachev * disconnect them during disable_stream
711b843c749SSergey Zigachev * BY this, it is logic clean to separate stream and link */
712b843c749SSergey Zigachev link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
713b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->id, true);
714b843c749SSergey Zigachev
715b843c749SSergey Zigachev /* update AVI info frame (HDMI, DP)*/
716b843c749SSergey Zigachev /* TODO: FPGA may change to hwss.update_info_frame */
717b843c749SSergey Zigachev dce110_update_info_frame(pipe_ctx);
718b843c749SSergey Zigachev
719b843c749SSergey Zigachev /* enable early control to avoid corruption on DP monitor*/
720b843c749SSergey Zigachev active_total_with_borders =
721b843c749SSergey Zigachev timing->h_addressable
722b843c749SSergey Zigachev + timing->h_border_left
723b843c749SSergey Zigachev + timing->h_border_right;
724b843c749SSergey Zigachev
725b843c749SSergey Zigachev if (lane_count != 0)
726b843c749SSergey Zigachev early_control = active_total_with_borders % lane_count;
727b843c749SSergey Zigachev
728b843c749SSergey Zigachev if (early_control == 0)
729b843c749SSergey Zigachev early_control = lane_count;
730b843c749SSergey Zigachev
731b843c749SSergey Zigachev tg->funcs->set_early_control(tg, early_control);
732b843c749SSergey Zigachev
733b843c749SSergey Zigachev /* enable audio only within mode set */
734b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio != NULL) {
735b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
736b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
737b843c749SSergey Zigachev }
738b843c749SSergey Zigachev
739b843c749SSergey Zigachev
740b843c749SSergey Zigachev
741b843c749SSergey Zigachev
742b843c749SSergey Zigachev }
743b843c749SSergey Zigachev
744b843c749SSergey Zigachev /*todo: cloned in stream enc, fix*/
is_panel_backlight_on(struct dce_hwseq * hws)745b843c749SSergey Zigachev static bool is_panel_backlight_on(struct dce_hwseq *hws)
746b843c749SSergey Zigachev {
747b843c749SSergey Zigachev uint32_t value;
748b843c749SSergey Zigachev
749b843c749SSergey Zigachev REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
750b843c749SSergey Zigachev
751b843c749SSergey Zigachev return value;
752b843c749SSergey Zigachev }
753b843c749SSergey Zigachev
is_panel_powered_on(struct dce_hwseq * hws)754b843c749SSergey Zigachev static bool is_panel_powered_on(struct dce_hwseq *hws)
755b843c749SSergey Zigachev {
756b843c749SSergey Zigachev uint32_t pwr_seq_state, dig_on, dig_on_ovrd;
757b843c749SSergey Zigachev
758b843c749SSergey Zigachev
759b843c749SSergey Zigachev REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state);
760b843c749SSergey Zigachev
761b843c749SSergey Zigachev REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd);
762b843c749SSergey Zigachev
763b843c749SSergey Zigachev return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1);
764b843c749SSergey Zigachev }
765b843c749SSergey Zigachev
link_transmitter_control(struct dc_bios * bios,struct bp_transmitter_control * cntl)766b843c749SSergey Zigachev static enum bp_result link_transmitter_control(
767b843c749SSergey Zigachev struct dc_bios *bios,
768b843c749SSergey Zigachev struct bp_transmitter_control *cntl)
769b843c749SSergey Zigachev {
770b843c749SSergey Zigachev enum bp_result result;
771b843c749SSergey Zigachev
772b843c749SSergey Zigachev result = bios->funcs->transmitter_control(bios, cntl);
773b843c749SSergey Zigachev
774b843c749SSergey Zigachev return result;
775b843c749SSergey Zigachev }
776b843c749SSergey Zigachev
777b843c749SSergey Zigachev /*
778b843c749SSergey Zigachev * @brief
779b843c749SSergey Zigachev * eDP only.
780b843c749SSergey Zigachev */
hwss_edp_wait_for_hpd_ready(struct dc_link * link,bool power_up)781b843c749SSergey Zigachev void hwss_edp_wait_for_hpd_ready(
782b843c749SSergey Zigachev struct dc_link *link,
783b843c749SSergey Zigachev bool power_up)
784b843c749SSergey Zigachev {
785b843c749SSergey Zigachev struct dc_context *ctx = link->ctx;
786b843c749SSergey Zigachev struct graphics_object_id connector = link->link_enc->connector;
787b843c749SSergey Zigachev struct gpio *hpd;
788b843c749SSergey Zigachev bool edp_hpd_high = false;
789b843c749SSergey Zigachev uint32_t time_elapsed = 0;
790b843c749SSergey Zigachev uint32_t timeout = power_up ?
791b843c749SSergey Zigachev PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
792b843c749SSergey Zigachev
793b843c749SSergey Zigachev if (dal_graphics_object_id_get_connector_id(connector)
794b843c749SSergey Zigachev != CONNECTOR_ID_EDP) {
795b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
796b843c749SSergey Zigachev return;
797b843c749SSergey Zigachev }
798b843c749SSergey Zigachev
799b843c749SSergey Zigachev if (!power_up)
800b843c749SSergey Zigachev /*
801b843c749SSergey Zigachev * From KV, we will not HPD low after turning off VCC -
802b843c749SSergey Zigachev * instead, we will check the SW timer in power_up().
803b843c749SSergey Zigachev */
804b843c749SSergey Zigachev return;
805b843c749SSergey Zigachev
806b843c749SSergey Zigachev /*
807b843c749SSergey Zigachev * When we power on/off the eDP panel,
808b843c749SSergey Zigachev * we need to wait until SENSE bit is high/low.
809b843c749SSergey Zigachev */
810b843c749SSergey Zigachev
811b843c749SSergey Zigachev /* obtain HPD */
812b843c749SSergey Zigachev /* TODO what to do with this? */
813b843c749SSergey Zigachev hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
814b843c749SSergey Zigachev
815b843c749SSergey Zigachev if (!hpd) {
816b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
817b843c749SSergey Zigachev return;
818b843c749SSergey Zigachev }
819b843c749SSergey Zigachev
820b843c749SSergey Zigachev dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
821b843c749SSergey Zigachev
822b843c749SSergey Zigachev /* wait until timeout or panel detected */
823b843c749SSergey Zigachev
824b843c749SSergey Zigachev do {
825b843c749SSergey Zigachev uint32_t detected = 0;
826b843c749SSergey Zigachev
827b843c749SSergey Zigachev dal_gpio_get_value(hpd, &detected);
828b843c749SSergey Zigachev
829b843c749SSergey Zigachev if (!(detected ^ power_up)) {
830b843c749SSergey Zigachev edp_hpd_high = true;
831b843c749SSergey Zigachev break;
832b843c749SSergey Zigachev }
833b843c749SSergey Zigachev
834b843c749SSergey Zigachev msleep(HPD_CHECK_INTERVAL);
835b843c749SSergey Zigachev
836b843c749SSergey Zigachev time_elapsed += HPD_CHECK_INTERVAL;
837b843c749SSergey Zigachev } while (time_elapsed < timeout);
838b843c749SSergey Zigachev
839b843c749SSergey Zigachev dal_gpio_close(hpd);
840b843c749SSergey Zigachev
841b843c749SSergey Zigachev dal_gpio_destroy_irq(&hpd);
842b843c749SSergey Zigachev
843b843c749SSergey Zigachev if (false == edp_hpd_high) {
844b843c749SSergey Zigachev DC_LOG_ERROR(
845b843c749SSergey Zigachev "%s: wait timed out!\n", __func__);
846b843c749SSergey Zigachev }
847b843c749SSergey Zigachev }
848b843c749SSergey Zigachev
hwss_edp_power_control(struct dc_link * link,bool power_up)849b843c749SSergey Zigachev void hwss_edp_power_control(
850b843c749SSergey Zigachev struct dc_link *link,
851b843c749SSergey Zigachev bool power_up)
852b843c749SSergey Zigachev {
853b843c749SSergey Zigachev struct dc_context *ctx = link->ctx;
854b843c749SSergey Zigachev struct dce_hwseq *hwseq = ctx->dc->hwseq;
855b843c749SSergey Zigachev struct bp_transmitter_control cntl = { 0 };
856b843c749SSergey Zigachev enum bp_result bp_result;
857b843c749SSergey Zigachev
858b843c749SSergey Zigachev
859b843c749SSergey Zigachev if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
860b843c749SSergey Zigachev != CONNECTOR_ID_EDP) {
861b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
862b843c749SSergey Zigachev return;
863b843c749SSergey Zigachev }
864b843c749SSergey Zigachev
865b843c749SSergey Zigachev if (power_up != is_panel_powered_on(hwseq)) {
866b843c749SSergey Zigachev /* Send VBIOS command to prompt eDP panel power */
867b843c749SSergey Zigachev if (power_up) {
868b843c749SSergey Zigachev unsigned long long current_ts = dm_get_timestamp(ctx);
869b843c749SSergey Zigachev unsigned long long duration_in_ms =
870b843c749SSergey Zigachev div64_u64(dm_get_elapse_time_in_ns(
871b843c749SSergey Zigachev ctx,
872b843c749SSergey Zigachev current_ts,
873b843c749SSergey Zigachev link->link_trace.time_stamp.edp_poweroff), 1000000);
874b843c749SSergey Zigachev unsigned long long wait_time_ms = 0;
875b843c749SSergey Zigachev
876b843c749SSergey Zigachev /* max 500ms from LCDVDD off to on */
877b843c749SSergey Zigachev unsigned long long edp_poweroff_time_ms = 500;
878b843c749SSergey Zigachev
879b843c749SSergey Zigachev if (link->local_sink != NULL)
880b843c749SSergey Zigachev edp_poweroff_time_ms =
881b843c749SSergey Zigachev 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms;
882b843c749SSergey Zigachev if (link->link_trace.time_stamp.edp_poweroff == 0)
883b843c749SSergey Zigachev wait_time_ms = edp_poweroff_time_ms;
884b843c749SSergey Zigachev else if (duration_in_ms < edp_poweroff_time_ms)
885b843c749SSergey Zigachev wait_time_ms = edp_poweroff_time_ms - duration_in_ms;
886b843c749SSergey Zigachev
887b843c749SSergey Zigachev if (wait_time_ms) {
888b843c749SSergey Zigachev msleep(wait_time_ms);
889b843c749SSergey Zigachev dm_output_to_console("%s: wait %lld ms to power on eDP.\n",
890b843c749SSergey Zigachev __func__, wait_time_ms);
891b843c749SSergey Zigachev }
892b843c749SSergey Zigachev
893b843c749SSergey Zigachev }
894b843c749SSergey Zigachev
895b843c749SSergey Zigachev DC_LOG_HW_RESUME_S3(
896b843c749SSergey Zigachev "%s: Panel Power action: %s\n",
897b843c749SSergey Zigachev __func__, (power_up ? "On":"Off"));
898b843c749SSergey Zigachev
899b843c749SSergey Zigachev cntl.action = power_up ?
900b843c749SSergey Zigachev TRANSMITTER_CONTROL_POWER_ON :
901b843c749SSergey Zigachev TRANSMITTER_CONTROL_POWER_OFF;
902b843c749SSergey Zigachev cntl.transmitter = link->link_enc->transmitter;
903b843c749SSergey Zigachev cntl.connector_obj_id = link->link_enc->connector;
904b843c749SSergey Zigachev cntl.coherent = false;
905b843c749SSergey Zigachev cntl.lanes_number = LANE_COUNT_FOUR;
906b843c749SSergey Zigachev cntl.hpd_sel = link->link_enc->hpd_source;
907b843c749SSergey Zigachev bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
908b843c749SSergey Zigachev
909b843c749SSergey Zigachev if (!power_up)
910b843c749SSergey Zigachev /*save driver power off time stamp*/
911b843c749SSergey Zigachev link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx);
912b843c749SSergey Zigachev else
913b843c749SSergey Zigachev link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx);
914b843c749SSergey Zigachev
915b843c749SSergey Zigachev if (bp_result != BP_RESULT_OK)
916b843c749SSergey Zigachev DC_LOG_ERROR(
917b843c749SSergey Zigachev "%s: Panel Power bp_result: %d\n",
918b843c749SSergey Zigachev __func__, bp_result);
919b843c749SSergey Zigachev } else {
920b843c749SSergey Zigachev DC_LOG_HW_RESUME_S3(
921b843c749SSergey Zigachev "%s: Skipping Panel Power action: %s\n",
922b843c749SSergey Zigachev __func__, (power_up ? "On":"Off"));
923b843c749SSergey Zigachev }
924b843c749SSergey Zigachev }
925b843c749SSergey Zigachev
926b843c749SSergey Zigachev /*todo: cloned in stream enc, fix*/
927b843c749SSergey Zigachev /*
928b843c749SSergey Zigachev * @brief
929b843c749SSergey Zigachev * eDP only. Control the backlight of the eDP panel
930b843c749SSergey Zigachev */
hwss_edp_backlight_control(struct dc_link * link,bool enable)931b843c749SSergey Zigachev void hwss_edp_backlight_control(
932b843c749SSergey Zigachev struct dc_link *link,
933b843c749SSergey Zigachev bool enable)
934b843c749SSergey Zigachev {
935b843c749SSergey Zigachev struct dc_context *ctx = link->ctx;
936b843c749SSergey Zigachev struct dce_hwseq *hws = ctx->dc->hwseq;
937b843c749SSergey Zigachev struct bp_transmitter_control cntl = { 0 };
938b843c749SSergey Zigachev
939b843c749SSergey Zigachev if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
940b843c749SSergey Zigachev != CONNECTOR_ID_EDP) {
941b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
942b843c749SSergey Zigachev return;
943b843c749SSergey Zigachev }
944b843c749SSergey Zigachev
945b843c749SSergey Zigachev if (enable && is_panel_backlight_on(hws)) {
946b843c749SSergey Zigachev DC_LOG_HW_RESUME_S3(
947b843c749SSergey Zigachev "%s: panel already powered up. Do nothing.\n",
948b843c749SSergey Zigachev __func__);
949b843c749SSergey Zigachev return;
950b843c749SSergey Zigachev }
951b843c749SSergey Zigachev
952b843c749SSergey Zigachev /* Send VBIOS command to control eDP panel backlight */
953b843c749SSergey Zigachev
954b843c749SSergey Zigachev DC_LOG_HW_RESUME_S3(
955b843c749SSergey Zigachev "%s: backlight action: %s\n",
956b843c749SSergey Zigachev __func__, (enable ? "On":"Off"));
957b843c749SSergey Zigachev
958b843c749SSergey Zigachev cntl.action = enable ?
959b843c749SSergey Zigachev TRANSMITTER_CONTROL_BACKLIGHT_ON :
960b843c749SSergey Zigachev TRANSMITTER_CONTROL_BACKLIGHT_OFF;
961b843c749SSergey Zigachev
962b843c749SSergey Zigachev /*cntl.engine_id = ctx->engine;*/
963b843c749SSergey Zigachev cntl.transmitter = link->link_enc->transmitter;
964b843c749SSergey Zigachev cntl.connector_obj_id = link->link_enc->connector;
965b843c749SSergey Zigachev /*todo: unhardcode*/
966b843c749SSergey Zigachev cntl.lanes_number = LANE_COUNT_FOUR;
967b843c749SSergey Zigachev cntl.hpd_sel = link->link_enc->hpd_source;
968b843c749SSergey Zigachev cntl.signal = SIGNAL_TYPE_EDP;
969b843c749SSergey Zigachev
970b843c749SSergey Zigachev /* For eDP, the following delays might need to be considered
971b843c749SSergey Zigachev * after link training completed:
972b843c749SSergey Zigachev * idle period - min. accounts for required BS-Idle pattern,
973b843c749SSergey Zigachev * max. allows for source frame synchronization);
974b843c749SSergey Zigachev * 50 msec max. delay from valid video data from source
975b843c749SSergey Zigachev * to video on dislpay or backlight enable.
976b843c749SSergey Zigachev *
977b843c749SSergey Zigachev * Disable the delay for now.
978b843c749SSergey Zigachev * Enable it in the future if necessary.
979b843c749SSergey Zigachev */
980b843c749SSergey Zigachev /* dc_service_sleep_in_milliseconds(50); */
981b843c749SSergey Zigachev /*edp 1.2*/
982b843c749SSergey Zigachev if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
983b843c749SSergey Zigachev edp_receiver_ready_T7(link);
984b843c749SSergey Zigachev link_transmitter_control(ctx->dc_bios, &cntl);
985b843c749SSergey Zigachev /*edp 1.2*/
986b843c749SSergey Zigachev if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
987b843c749SSergey Zigachev edp_receiver_ready_T9(link);
988b843c749SSergey Zigachev }
989b843c749SSergey Zigachev
dce110_enable_audio_stream(struct pipe_ctx * pipe_ctx)990b843c749SSergey Zigachev void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
991b843c749SSergey Zigachev {
992b843c749SSergey Zigachev struct dc *core_dc = pipe_ctx->stream->ctx->dc;
993b843c749SSergey Zigachev /* notify audio driver for audio modes of monitor */
994b843c749SSergey Zigachev struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu;
995b843c749SSergey Zigachev unsigned int i, num_audio = 1;
996b843c749SSergey Zigachev
997b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio) {
998b843c749SSergey Zigachev for (i = 0; i < MAX_PIPES; i++) {
999b843c749SSergey Zigachev /*current_state not updated yet*/
1000b843c749SSergey Zigachev if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
1001b843c749SSergey Zigachev num_audio++;
1002b843c749SSergey Zigachev }
1003b843c749SSergey Zigachev
1004b843c749SSergey Zigachev pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
1005b843c749SSergey Zigachev
1006b843c749SSergey Zigachev if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
1007b843c749SSergey Zigachev /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
1008b843c749SSergey Zigachev pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
1009b843c749SSergey Zigachev /* un-mute audio */
1010b843c749SSergey Zigachev /* TODO: audio should be per stream rather than per link */
1011b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
1012b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc, false);
1013b843c749SSergey Zigachev }
1014b843c749SSergey Zigachev }
1015b843c749SSergey Zigachev
dce110_disable_audio_stream(struct pipe_ctx * pipe_ctx,int option)1016b843c749SSergey Zigachev void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
1017b843c749SSergey Zigachev {
1018b843c749SSergey Zigachev struct dc *dc = pipe_ctx->stream->ctx->dc;
1019b843c749SSergey Zigachev
1020b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
1021b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc, true);
1022b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio) {
1023b843c749SSergey Zigachev struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
1024b843c749SSergey Zigachev
1025b843c749SSergey Zigachev if (option != KEEP_ACQUIRED_RESOURCE ||
1026b843c749SSergey Zigachev !dc->debug.az_endpoint_mute_only) {
1027b843c749SSergey Zigachev /*only disalbe az_endpoint if power down or free*/
1028b843c749SSergey Zigachev pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
1029b843c749SSergey Zigachev }
1030b843c749SSergey Zigachev
1031b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1032b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
1033b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc);
1034b843c749SSergey Zigachev else
1035b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
1036b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc);
1037b843c749SSergey Zigachev /*don't free audio if it is from retrain or internal disable stream*/
1038b843c749SSergey Zigachev if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
1039b843c749SSergey Zigachev /*we have to dynamic arbitrate the audio endpoints*/
1040b843c749SSergey Zigachev /*we free the resource, need reset is_audio_acquired*/
1041b843c749SSergey Zigachev update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
1042b843c749SSergey Zigachev pipe_ctx->stream_res.audio = NULL;
1043b843c749SSergey Zigachev }
1044b843c749SSergey Zigachev if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
1045b843c749SSergey Zigachev /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
1046b843c749SSergey Zigachev pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
1047b843c749SSergey Zigachev
1048b843c749SSergey Zigachev /* TODO: notify audio driver for if audio modes list changed
1049b843c749SSergey Zigachev * add audio mode list change flag */
1050b843c749SSergey Zigachev /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
1051b843c749SSergey Zigachev * stream->stream_engine_id);
1052b843c749SSergey Zigachev */
1053b843c749SSergey Zigachev }
1054b843c749SSergey Zigachev }
1055b843c749SSergey Zigachev
dce110_disable_stream(struct pipe_ctx * pipe_ctx,int option)1056b843c749SSergey Zigachev void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
1057b843c749SSergey Zigachev {
1058b843c749SSergey Zigachev struct dc_stream_state *stream = pipe_ctx->stream;
1059b843c749SSergey Zigachev struct dc_link *link = stream->sink->link;
1060b843c749SSergey Zigachev struct dc *dc = pipe_ctx->stream->ctx->dc;
1061b843c749SSergey Zigachev
1062b843c749SSergey Zigachev if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1063b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
1064b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc);
1065b843c749SSergey Zigachev
1066b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1067b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
1068b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc);
1069b843c749SSergey Zigachev
1070b843c749SSergey Zigachev dc->hwss.disable_audio_stream(pipe_ctx, option);
1071b843c749SSergey Zigachev
1072b843c749SSergey Zigachev link->link_enc->funcs->connect_dig_be_to_fe(
1073b843c749SSergey Zigachev link->link_enc,
1074b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->id,
1075b843c749SSergey Zigachev false);
1076b843c749SSergey Zigachev
1077b843c749SSergey Zigachev }
1078b843c749SSergey Zigachev
dce110_unblank_stream(struct pipe_ctx * pipe_ctx,struct dc_link_settings * link_settings)1079b843c749SSergey Zigachev void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
1080b843c749SSergey Zigachev struct dc_link_settings *link_settings)
1081b843c749SSergey Zigachev {
1082b843c749SSergey Zigachev struct encoder_unblank_param params = { { 0 } };
1083b843c749SSergey Zigachev struct dc_stream_state *stream = pipe_ctx->stream;
1084b843c749SSergey Zigachev struct dc_link *link = stream->sink->link;
1085b843c749SSergey Zigachev
1086b843c749SSergey Zigachev /* only 3 items below are used by unblank */
1087b843c749SSergey Zigachev params.pixel_clk_khz =
1088b843c749SSergey Zigachev pipe_ctx->stream->timing.pix_clk_khz;
1089b843c749SSergey Zigachev params.link_settings.link_rate = link_settings->link_rate;
1090b843c749SSergey Zigachev
1091b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1092b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
1093b843c749SSergey Zigachev
1094b843c749SSergey Zigachev if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1095b843c749SSergey Zigachev link->dc->hwss.edp_backlight_control(link, true);
1096b843c749SSergey Zigachev stream->bl_pwm_level = EDP_BACKLIGHT_RAMP_DISABLE_LEVEL;
1097b843c749SSergey Zigachev }
1098b843c749SSergey Zigachev }
dce110_blank_stream(struct pipe_ctx * pipe_ctx)1099b843c749SSergey Zigachev void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
1100b843c749SSergey Zigachev {
1101b843c749SSergey Zigachev struct dc_stream_state *stream = pipe_ctx->stream;
1102b843c749SSergey Zigachev struct dc_link *link = stream->sink->link;
1103b843c749SSergey Zigachev
1104b843c749SSergey Zigachev if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1105b843c749SSergey Zigachev link->dc->hwss.edp_backlight_control(link, false);
1106b843c749SSergey Zigachev dc_link_set_abm_disable(link);
1107b843c749SSergey Zigachev }
1108b843c749SSergey Zigachev
1109b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1110b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
1111b843c749SSergey Zigachev }
1112b843c749SSergey Zigachev
1113b843c749SSergey Zigachev
dce110_set_avmute(struct pipe_ctx * pipe_ctx,bool enable)1114b843c749SSergey Zigachev void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
1115b843c749SSergey Zigachev {
1116b843c749SSergey Zigachev if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
1117b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
1118b843c749SSergey Zigachev }
1119b843c749SSergey Zigachev
translate_to_dto_source(enum controller_id crtc_id)1120b843c749SSergey Zigachev static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
1121b843c749SSergey Zigachev {
1122b843c749SSergey Zigachev switch (crtc_id) {
1123b843c749SSergey Zigachev case CONTROLLER_ID_D0:
1124b843c749SSergey Zigachev return DTO_SOURCE_ID0;
1125b843c749SSergey Zigachev case CONTROLLER_ID_D1:
1126b843c749SSergey Zigachev return DTO_SOURCE_ID1;
1127b843c749SSergey Zigachev case CONTROLLER_ID_D2:
1128b843c749SSergey Zigachev return DTO_SOURCE_ID2;
1129b843c749SSergey Zigachev case CONTROLLER_ID_D3:
1130b843c749SSergey Zigachev return DTO_SOURCE_ID3;
1131b843c749SSergey Zigachev case CONTROLLER_ID_D4:
1132b843c749SSergey Zigachev return DTO_SOURCE_ID4;
1133b843c749SSergey Zigachev case CONTROLLER_ID_D5:
1134b843c749SSergey Zigachev return DTO_SOURCE_ID5;
1135b843c749SSergey Zigachev default:
1136b843c749SSergey Zigachev return DTO_SOURCE_UNKNOWN;
1137b843c749SSergey Zigachev }
1138b843c749SSergey Zigachev }
1139b843c749SSergey Zigachev
build_audio_output(struct dc_state * state,const struct pipe_ctx * pipe_ctx,struct audio_output * audio_output)1140b843c749SSergey Zigachev static void build_audio_output(
1141b843c749SSergey Zigachev struct dc_state *state,
1142b843c749SSergey Zigachev const struct pipe_ctx *pipe_ctx,
1143b843c749SSergey Zigachev struct audio_output *audio_output)
1144b843c749SSergey Zigachev {
1145b843c749SSergey Zigachev const struct dc_stream_state *stream = pipe_ctx->stream;
1146b843c749SSergey Zigachev audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
1147b843c749SSergey Zigachev
1148b843c749SSergey Zigachev audio_output->signal = pipe_ctx->stream->signal;
1149b843c749SSergey Zigachev
1150b843c749SSergey Zigachev /* audio_crtc_info */
1151b843c749SSergey Zigachev
1152b843c749SSergey Zigachev audio_output->crtc_info.h_total =
1153b843c749SSergey Zigachev stream->timing.h_total;
1154b843c749SSergey Zigachev
1155b843c749SSergey Zigachev /*
1156b843c749SSergey Zigachev * Audio packets are sent during actual CRTC blank physical signal, we
1157b843c749SSergey Zigachev * need to specify actual active signal portion
1158b843c749SSergey Zigachev */
1159b843c749SSergey Zigachev audio_output->crtc_info.h_active =
1160b843c749SSergey Zigachev stream->timing.h_addressable
1161b843c749SSergey Zigachev + stream->timing.h_border_left
1162b843c749SSergey Zigachev + stream->timing.h_border_right;
1163b843c749SSergey Zigachev
1164b843c749SSergey Zigachev audio_output->crtc_info.v_active =
1165b843c749SSergey Zigachev stream->timing.v_addressable
1166b843c749SSergey Zigachev + stream->timing.v_border_top
1167b843c749SSergey Zigachev + stream->timing.v_border_bottom;
1168b843c749SSergey Zigachev
1169b843c749SSergey Zigachev audio_output->crtc_info.pixel_repetition = 1;
1170b843c749SSergey Zigachev
1171b843c749SSergey Zigachev audio_output->crtc_info.interlaced =
1172b843c749SSergey Zigachev stream->timing.flags.INTERLACE;
1173b843c749SSergey Zigachev
1174b843c749SSergey Zigachev audio_output->crtc_info.refresh_rate =
1175b843c749SSergey Zigachev (stream->timing.pix_clk_khz*1000)/
1176b843c749SSergey Zigachev (stream->timing.h_total*stream->timing.v_total);
1177b843c749SSergey Zigachev
1178b843c749SSergey Zigachev audio_output->crtc_info.color_depth =
1179b843c749SSergey Zigachev stream->timing.display_color_depth;
1180b843c749SSergey Zigachev
1181b843c749SSergey Zigachev audio_output->crtc_info.requested_pixel_clock =
1182b843c749SSergey Zigachev pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1183b843c749SSergey Zigachev
1184b843c749SSergey Zigachev audio_output->crtc_info.calculated_pixel_clock =
1185b843c749SSergey Zigachev pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1186b843c749SSergey Zigachev
1187b843c749SSergey Zigachev /*for HDMI, audio ACR is with deep color ratio factor*/
1188b843c749SSergey Zigachev if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
1189b843c749SSergey Zigachev audio_output->crtc_info.requested_pixel_clock ==
1190b843c749SSergey Zigachev stream->timing.pix_clk_khz) {
1191b843c749SSergey Zigachev if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
1192b843c749SSergey Zigachev audio_output->crtc_info.requested_pixel_clock =
1193b843c749SSergey Zigachev audio_output->crtc_info.requested_pixel_clock/2;
1194b843c749SSergey Zigachev audio_output->crtc_info.calculated_pixel_clock =
1195b843c749SSergey Zigachev pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2;
1196b843c749SSergey Zigachev
1197b843c749SSergey Zigachev }
1198b843c749SSergey Zigachev }
1199b843c749SSergey Zigachev
1200b843c749SSergey Zigachev if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
1201b843c749SSergey Zigachev pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1202b843c749SSergey Zigachev audio_output->pll_info.dp_dto_source_clock_in_khz =
1203b843c749SSergey Zigachev state->dis_clk->funcs->get_dp_ref_clk_frequency(
1204b843c749SSergey Zigachev state->dis_clk);
1205b843c749SSergey Zigachev }
1206b843c749SSergey Zigachev
1207b843c749SSergey Zigachev audio_output->pll_info.feed_back_divider =
1208b843c749SSergey Zigachev pipe_ctx->pll_settings.feedback_divider;
1209b843c749SSergey Zigachev
1210b843c749SSergey Zigachev audio_output->pll_info.dto_source =
1211b843c749SSergey Zigachev translate_to_dto_source(
1212b843c749SSergey Zigachev pipe_ctx->stream_res.tg->inst + 1);
1213b843c749SSergey Zigachev
1214b843c749SSergey Zigachev /* TODO hard code to enable for now. Need get from stream */
1215b843c749SSergey Zigachev audio_output->pll_info.ss_enabled = true;
1216b843c749SSergey Zigachev
1217b843c749SSergey Zigachev audio_output->pll_info.ss_percentage =
1218b843c749SSergey Zigachev pipe_ctx->pll_settings.ss_percentage;
1219b843c749SSergey Zigachev }
1220b843c749SSergey Zigachev
get_surface_visual_confirm_color(const struct pipe_ctx * pipe_ctx,struct tg_color * color)1221b843c749SSergey Zigachev static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
1222b843c749SSergey Zigachev struct tg_color *color)
1223b843c749SSergey Zigachev {
1224b843c749SSergey Zigachev uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
1225b843c749SSergey Zigachev
1226b843c749SSergey Zigachev switch (pipe_ctx->plane_res.scl_data.format) {
1227b843c749SSergey Zigachev case PIXEL_FORMAT_ARGB8888:
1228b843c749SSergey Zigachev /* set boarder color to red */
1229b843c749SSergey Zigachev color->color_r_cr = color_value;
1230b843c749SSergey Zigachev break;
1231b843c749SSergey Zigachev
1232b843c749SSergey Zigachev case PIXEL_FORMAT_ARGB2101010:
1233b843c749SSergey Zigachev /* set boarder color to blue */
1234b843c749SSergey Zigachev color->color_b_cb = color_value;
1235b843c749SSergey Zigachev break;
1236b843c749SSergey Zigachev case PIXEL_FORMAT_420BPP8:
1237b843c749SSergey Zigachev /* set boarder color to green */
1238b843c749SSergey Zigachev color->color_g_y = color_value;
1239b843c749SSergey Zigachev break;
1240b843c749SSergey Zigachev case PIXEL_FORMAT_420BPP10:
1241b843c749SSergey Zigachev /* set boarder color to yellow */
1242b843c749SSergey Zigachev color->color_g_y = color_value;
1243b843c749SSergey Zigachev color->color_r_cr = color_value;
1244b843c749SSergey Zigachev break;
1245b843c749SSergey Zigachev case PIXEL_FORMAT_FP16:
1246b843c749SSergey Zigachev /* set boarder color to white */
1247b843c749SSergey Zigachev color->color_r_cr = color_value;
1248b843c749SSergey Zigachev color->color_b_cb = color_value;
1249b843c749SSergey Zigachev color->color_g_y = color_value;
1250b843c749SSergey Zigachev break;
1251b843c749SSergey Zigachev default:
1252b843c749SSergey Zigachev break;
1253b843c749SSergey Zigachev }
1254b843c749SSergey Zigachev }
1255b843c749SSergey Zigachev
program_scaler(const struct dc * dc,const struct pipe_ctx * pipe_ctx)1256b843c749SSergey Zigachev static void program_scaler(const struct dc *dc,
1257b843c749SSergey Zigachev const struct pipe_ctx *pipe_ctx)
1258b843c749SSergey Zigachev {
1259b843c749SSergey Zigachev struct tg_color color = {0};
1260b843c749SSergey Zigachev
1261b843c749SSergey Zigachev #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1262b843c749SSergey Zigachev /* TOFPGA */
1263b843c749SSergey Zigachev if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
1264b843c749SSergey Zigachev return;
1265b843c749SSergey Zigachev #endif
1266b843c749SSergey Zigachev
1267b843c749SSergey Zigachev if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
1268b843c749SSergey Zigachev get_surface_visual_confirm_color(pipe_ctx, &color);
1269b843c749SSergey Zigachev else
1270b843c749SSergey Zigachev color_space_to_black_color(dc,
1271b843c749SSergey Zigachev pipe_ctx->stream->output_color_space,
1272b843c749SSergey Zigachev &color);
1273b843c749SSergey Zigachev
1274b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
1275b843c749SSergey Zigachev pipe_ctx->plane_res.xfm,
1276b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.lb_params.depth,
1277b843c749SSergey Zigachev &pipe_ctx->stream->bit_depth_params);
1278b843c749SSergey Zigachev
1279b843c749SSergey Zigachev if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
1280b843c749SSergey Zigachev /*
1281b843c749SSergey Zigachev * The way 420 is packed, 2 channels carry Y component, 1 channel
1282b843c749SSergey Zigachev * alternate between Cb and Cr, so both channels need the pixel
1283b843c749SSergey Zigachev * value for Y
1284b843c749SSergey Zigachev */
1285b843c749SSergey Zigachev if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
1286b843c749SSergey Zigachev color.color_r_cr = color.color_g_y;
1287b843c749SSergey Zigachev
1288b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
1289b843c749SSergey Zigachev pipe_ctx->stream_res.tg,
1290b843c749SSergey Zigachev &color);
1291b843c749SSergey Zigachev }
1292b843c749SSergey Zigachev
1293b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
1294b843c749SSergey Zigachev &pipe_ctx->plane_res.scl_data);
1295b843c749SSergey Zigachev }
1296b843c749SSergey Zigachev
dce110_enable_stream_timing(struct pipe_ctx * pipe_ctx,struct dc_state * context,struct dc * dc)1297b843c749SSergey Zigachev static enum dc_status dce110_enable_stream_timing(
1298b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx,
1299b843c749SSergey Zigachev struct dc_state *context,
1300b843c749SSergey Zigachev struct dc *dc)
1301b843c749SSergey Zigachev {
1302b843c749SSergey Zigachev struct dc_stream_state *stream = pipe_ctx->stream;
1303b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1304b843c749SSergey Zigachev pipe_ctx[pipe_ctx->pipe_idx];
1305b843c749SSergey Zigachev struct tg_color black_color = {0};
1306b843c749SSergey Zigachev
1307b843c749SSergey Zigachev if (!pipe_ctx_old->stream) {
1308b843c749SSergey Zigachev
1309b843c749SSergey Zigachev /* program blank color */
1310b843c749SSergey Zigachev color_space_to_black_color(dc,
1311b843c749SSergey Zigachev stream->output_color_space, &black_color);
1312b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->set_blank_color(
1313b843c749SSergey Zigachev pipe_ctx->stream_res.tg,
1314b843c749SSergey Zigachev &black_color);
1315b843c749SSergey Zigachev
1316b843c749SSergey Zigachev /*
1317b843c749SSergey Zigachev * Must blank CRTC after disabling power gating and before any
1318b843c749SSergey Zigachev * programming, otherwise CRTC will be hung in bad state
1319b843c749SSergey Zigachev */
1320b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
1321b843c749SSergey Zigachev
1322b843c749SSergey Zigachev if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
1323b843c749SSergey Zigachev pipe_ctx->clock_source,
1324b843c749SSergey Zigachev &pipe_ctx->stream_res.pix_clk_params,
1325b843c749SSergey Zigachev &pipe_ctx->pll_settings)) {
1326b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
1327b843c749SSergey Zigachev return DC_ERROR_UNEXPECTED;
1328b843c749SSergey Zigachev }
1329b843c749SSergey Zigachev
1330b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->program_timing(
1331b843c749SSergey Zigachev pipe_ctx->stream_res.tg,
1332b843c749SSergey Zigachev &stream->timing,
1333b843c749SSergey Zigachev true);
1334b843c749SSergey Zigachev
1335b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
1336b843c749SSergey Zigachev pipe_ctx->stream_res.tg,
1337b843c749SSergey Zigachev 0x182);
1338b843c749SSergey Zigachev }
1339b843c749SSergey Zigachev
1340b843c749SSergey Zigachev if (!pipe_ctx_old->stream) {
1341b843c749SSergey Zigachev if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
1342b843c749SSergey Zigachev pipe_ctx->stream_res.tg)) {
1343b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
1344b843c749SSergey Zigachev return DC_ERROR_UNEXPECTED;
1345b843c749SSergey Zigachev }
1346b843c749SSergey Zigachev }
1347b843c749SSergey Zigachev
1348b843c749SSergey Zigachev
1349b843c749SSergey Zigachev
1350b843c749SSergey Zigachev return DC_OK;
1351b843c749SSergey Zigachev }
1352b843c749SSergey Zigachev
apply_single_controller_ctx_to_hw(struct pipe_ctx * pipe_ctx,struct dc_state * context,struct dc * dc)1353b843c749SSergey Zigachev static enum dc_status apply_single_controller_ctx_to_hw(
1354b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx,
1355b843c749SSergey Zigachev struct dc_state *context,
1356b843c749SSergey Zigachev struct dc *dc)
1357b843c749SSergey Zigachev {
1358b843c749SSergey Zigachev struct dc_stream_state *stream = pipe_ctx->stream;
1359b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1360b843c749SSergey Zigachev pipe_ctx[pipe_ctx->pipe_idx];
1361b843c749SSergey Zigachev
1362b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio != NULL) {
1363b843c749SSergey Zigachev struct audio_output audio_output;
1364b843c749SSergey Zigachev
1365b843c749SSergey Zigachev build_audio_output(context, pipe_ctx, &audio_output);
1366b843c749SSergey Zigachev
1367b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1368b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
1369b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1370b843c749SSergey Zigachev pipe_ctx->stream_res.audio->inst,
1371b843c749SSergey Zigachev &pipe_ctx->stream->audio_info);
1372b843c749SSergey Zigachev else
1373b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
1374b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1375b843c749SSergey Zigachev pipe_ctx->stream_res.audio->inst,
1376b843c749SSergey Zigachev &pipe_ctx->stream->audio_info,
1377b843c749SSergey Zigachev &audio_output.crtc_info);
1378b843c749SSergey Zigachev
1379b843c749SSergey Zigachev pipe_ctx->stream_res.audio->funcs->az_configure(
1380b843c749SSergey Zigachev pipe_ctx->stream_res.audio,
1381b843c749SSergey Zigachev pipe_ctx->stream->signal,
1382b843c749SSergey Zigachev &audio_output.crtc_info,
1383b843c749SSergey Zigachev &pipe_ctx->stream->audio_info);
1384b843c749SSergey Zigachev }
1385b843c749SSergey Zigachev
1386b843c749SSergey Zigachev /* */
1387b843c749SSergey Zigachev dc->hwss.enable_stream_timing(pipe_ctx, context, dc);
1388b843c749SSergey Zigachev
1389b843c749SSergey Zigachev /* FPGA does not program backend */
1390b843c749SSergey Zigachev if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1391b843c749SSergey Zigachev pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1392b843c749SSergey Zigachev pipe_ctx->stream_res.opp,
1393b843c749SSergey Zigachev COLOR_SPACE_YCBCR601,
1394b843c749SSergey Zigachev stream->timing.display_color_depth,
1395b843c749SSergey Zigachev pipe_ctx->stream->signal);
1396b843c749SSergey Zigachev
1397b843c749SSergey Zigachev pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1398b843c749SSergey Zigachev pipe_ctx->stream_res.opp,
1399b843c749SSergey Zigachev &stream->bit_depth_params,
1400b843c749SSergey Zigachev &stream->clamping);
1401b843c749SSergey Zigachev return DC_OK;
1402b843c749SSergey Zigachev }
1403b843c749SSergey Zigachev /* TODO: move to stream encoder */
1404b843c749SSergey Zigachev if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1405b843c749SSergey Zigachev if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
1406b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
1407b843c749SSergey Zigachev return DC_ERROR_UNEXPECTED;
1408b843c749SSergey Zigachev }
1409b843c749SSergey Zigachev pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1410b843c749SSergey Zigachev pipe_ctx->stream_res.opp,
1411b843c749SSergey Zigachev COLOR_SPACE_YCBCR601,
1412b843c749SSergey Zigachev stream->timing.display_color_depth,
1413b843c749SSergey Zigachev pipe_ctx->stream->signal);
1414b843c749SSergey Zigachev
1415b843c749SSergey Zigachev if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1416b843c749SSergey Zigachev stream->sink->link->link_enc->funcs->setup(
1417b843c749SSergey Zigachev stream->sink->link->link_enc,
1418b843c749SSergey Zigachev pipe_ctx->stream->signal);
1419b843c749SSergey Zigachev
1420b843c749SSergey Zigachev if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1421b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
1422b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1423b843c749SSergey Zigachev pipe_ctx->stream_res.tg->inst,
1424b843c749SSergey Zigachev stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
1425b843c749SSergey Zigachev
1426b843c749SSergey Zigachev
1427b843c749SSergey Zigachev pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1428b843c749SSergey Zigachev pipe_ctx->stream_res.opp,
1429b843c749SSergey Zigachev &stream->bit_depth_params,
1430b843c749SSergey Zigachev &stream->clamping);
1431b843c749SSergey Zigachev
1432b843c749SSergey Zigachev if (dc_is_dp_signal(pipe_ctx->stream->signal))
1433b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
1434b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1435b843c749SSergey Zigachev &stream->timing,
1436b843c749SSergey Zigachev stream->output_color_space);
1437b843c749SSergey Zigachev
1438b843c749SSergey Zigachev if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1439b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
1440b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1441b843c749SSergey Zigachev &stream->timing,
1442b843c749SSergey Zigachev stream->phy_pix_clk,
1443b843c749SSergey Zigachev pipe_ctx->stream_res.audio != NULL);
1444b843c749SSergey Zigachev
1445b843c749SSergey Zigachev if (dc_is_dvi_signal(pipe_ctx->stream->signal))
1446b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute(
1447b843c749SSergey Zigachev pipe_ctx->stream_res.stream_enc,
1448b843c749SSergey Zigachev &stream->timing,
1449b843c749SSergey Zigachev (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
1450b843c749SSergey Zigachev true : false);
1451b843c749SSergey Zigachev
1452b843c749SSergey Zigachev resource_build_info_frame(pipe_ctx);
1453b843c749SSergey Zigachev dce110_update_info_frame(pipe_ctx);
1454b843c749SSergey Zigachev if (!pipe_ctx_old->stream)
1455b843c749SSergey Zigachev core_link_enable_stream(context, pipe_ctx);
1456b843c749SSergey Zigachev
1457b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1458b843c749SSergey Zigachev
1459b843c749SSergey Zigachev pipe_ctx->stream->sink->link->psr_enabled = false;
1460b843c749SSergey Zigachev
1461b843c749SSergey Zigachev return DC_OK;
1462b843c749SSergey Zigachev }
1463b843c749SSergey Zigachev
1464b843c749SSergey Zigachev /******************************************************************************/
1465b843c749SSergey Zigachev
power_down_encoders(struct dc * dc)1466b843c749SSergey Zigachev static void power_down_encoders(struct dc *dc)
1467b843c749SSergey Zigachev {
1468b843c749SSergey Zigachev int i;
1469b843c749SSergey Zigachev enum connector_id connector_id;
1470b843c749SSergey Zigachev enum signal_type signal = SIGNAL_TYPE_NONE;
1471b843c749SSergey Zigachev
1472b843c749SSergey Zigachev /* do not know BIOS back-front mapping, simply blank all. It will not
1473b843c749SSergey Zigachev * hurt for non-DP
1474b843c749SSergey Zigachev */
1475b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1476b843c749SSergey Zigachev dc->res_pool->stream_enc[i]->funcs->dp_blank(
1477b843c749SSergey Zigachev dc->res_pool->stream_enc[i]);
1478b843c749SSergey Zigachev }
1479b843c749SSergey Zigachev
1480b843c749SSergey Zigachev for (i = 0; i < dc->link_count; i++) {
1481b843c749SSergey Zigachev connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id);
1482b843c749SSergey Zigachev if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
1483b843c749SSergey Zigachev (connector_id == CONNECTOR_ID_EDP)) {
1484b843c749SSergey Zigachev
1485b843c749SSergey Zigachev if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
1486b843c749SSergey Zigachev dp_receiver_power_ctrl(dc->links[i], false);
1487b843c749SSergey Zigachev if (connector_id == CONNECTOR_ID_EDP)
1488b843c749SSergey Zigachev signal = SIGNAL_TYPE_EDP;
1489b843c749SSergey Zigachev }
1490b843c749SSergey Zigachev
1491b843c749SSergey Zigachev dc->links[i]->link_enc->funcs->disable_output(
1492b843c749SSergey Zigachev dc->links[i]->link_enc, signal);
1493b843c749SSergey Zigachev }
1494b843c749SSergey Zigachev }
1495b843c749SSergey Zigachev
power_down_controllers(struct dc * dc)1496b843c749SSergey Zigachev static void power_down_controllers(struct dc *dc)
1497b843c749SSergey Zigachev {
1498b843c749SSergey Zigachev int i;
1499b843c749SSergey Zigachev
1500b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1501b843c749SSergey Zigachev dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1502b843c749SSergey Zigachev dc->res_pool->timing_generators[i]);
1503b843c749SSergey Zigachev }
1504b843c749SSergey Zigachev }
1505b843c749SSergey Zigachev
power_down_clock_sources(struct dc * dc)1506b843c749SSergey Zigachev static void power_down_clock_sources(struct dc *dc)
1507b843c749SSergey Zigachev {
1508b843c749SSergey Zigachev int i;
1509b843c749SSergey Zigachev
1510b843c749SSergey Zigachev if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1511b843c749SSergey Zigachev dc->res_pool->dp_clock_source) == false)
1512b843c749SSergey Zigachev dm_error("Failed to power down pll! (dp clk src)\n");
1513b843c749SSergey Zigachev
1514b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1515b843c749SSergey Zigachev if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1516b843c749SSergey Zigachev dc->res_pool->clock_sources[i]) == false)
1517b843c749SSergey Zigachev dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1518b843c749SSergey Zigachev }
1519b843c749SSergey Zigachev }
1520b843c749SSergey Zigachev
power_down_all_hw_blocks(struct dc * dc)1521b843c749SSergey Zigachev static void power_down_all_hw_blocks(struct dc *dc)
1522b843c749SSergey Zigachev {
1523b843c749SSergey Zigachev power_down_encoders(dc);
1524b843c749SSergey Zigachev
1525b843c749SSergey Zigachev power_down_controllers(dc);
1526b843c749SSergey Zigachev
1527b843c749SSergey Zigachev power_down_clock_sources(dc);
1528b843c749SSergey Zigachev
1529b843c749SSergey Zigachev if (dc->fbc_compressor)
1530b843c749SSergey Zigachev dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1531b843c749SSergey Zigachev }
1532b843c749SSergey Zigachev
disable_vga_and_power_gate_all_controllers(struct dc * dc)1533b843c749SSergey Zigachev static void disable_vga_and_power_gate_all_controllers(
1534b843c749SSergey Zigachev struct dc *dc)
1535b843c749SSergey Zigachev {
1536b843c749SSergey Zigachev int i;
1537b843c749SSergey Zigachev struct timing_generator *tg;
1538b843c749SSergey Zigachev struct dc_context *ctx = dc->ctx;
1539b843c749SSergey Zigachev
1540b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1541b843c749SSergey Zigachev tg = dc->res_pool->timing_generators[i];
1542b843c749SSergey Zigachev
1543b843c749SSergey Zigachev if (tg->funcs->disable_vga)
1544b843c749SSergey Zigachev tg->funcs->disable_vga(tg);
1545b843c749SSergey Zigachev }
1546b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
1547b843c749SSergey Zigachev /* Enable CLOCK gating for each pipe BEFORE controller
1548b843c749SSergey Zigachev * powergating. */
1549b843c749SSergey Zigachev enable_display_pipe_clock_gating(ctx,
1550b843c749SSergey Zigachev true);
1551b843c749SSergey Zigachev
1552b843c749SSergey Zigachev dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
1553b843c749SSergey Zigachev dc->hwss.disable_plane(dc,
1554b843c749SSergey Zigachev &dc->current_state->res_ctx.pipe_ctx[i]);
1555b843c749SSergey Zigachev }
1556b843c749SSergey Zigachev }
1557b843c749SSergey Zigachev
get_link_for_edp(struct dc * dc)1558b843c749SSergey Zigachev static struct dc_link *get_link_for_edp(struct dc *dc)
1559b843c749SSergey Zigachev {
1560b843c749SSergey Zigachev int i;
1561b843c749SSergey Zigachev
1562b843c749SSergey Zigachev for (i = 0; i < dc->link_count; i++) {
1563b843c749SSergey Zigachev if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP)
1564b843c749SSergey Zigachev return dc->links[i];
1565b843c749SSergey Zigachev }
1566b843c749SSergey Zigachev return NULL;
1567b843c749SSergey Zigachev }
1568b843c749SSergey Zigachev
get_link_for_edp_not_in_use(struct dc * dc,struct dc_state * context)1569b843c749SSergey Zigachev static struct dc_link *get_link_for_edp_not_in_use(
1570b843c749SSergey Zigachev struct dc *dc,
1571b843c749SSergey Zigachev struct dc_state *context)
1572b843c749SSergey Zigachev {
1573b843c749SSergey Zigachev int i;
1574b843c749SSergey Zigachev struct dc_link *link = NULL;
1575b843c749SSergey Zigachev
1576b843c749SSergey Zigachev /* check if eDP panel is suppose to be set mode, if yes, no need to disable */
1577b843c749SSergey Zigachev for (i = 0; i < context->stream_count; i++) {
1578b843c749SSergey Zigachev if (context->streams[i]->signal == SIGNAL_TYPE_EDP)
1579b843c749SSergey Zigachev return NULL;
1580b843c749SSergey Zigachev }
1581b843c749SSergey Zigachev
1582b843c749SSergey Zigachev /* check if there is an eDP panel not in use */
1583b843c749SSergey Zigachev for (i = 0; i < dc->link_count; i++) {
1584b843c749SSergey Zigachev if (dc->links[i]->local_sink &&
1585b843c749SSergey Zigachev dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1586b843c749SSergey Zigachev link = dc->links[i];
1587b843c749SSergey Zigachev break;
1588b843c749SSergey Zigachev }
1589b843c749SSergey Zigachev }
1590b843c749SSergey Zigachev
1591b843c749SSergey Zigachev return link;
1592b843c749SSergey Zigachev }
1593b843c749SSergey Zigachev
1594b843c749SSergey Zigachev /**
1595b843c749SSergey Zigachev * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
1596b843c749SSergey Zigachev * 1. Power down all DC HW blocks
1597b843c749SSergey Zigachev * 2. Disable VGA engine on all controllers
1598b843c749SSergey Zigachev * 3. Enable power gating for controller
1599b843c749SSergey Zigachev * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
1600b843c749SSergey Zigachev */
dce110_enable_accelerated_mode(struct dc * dc,struct dc_state * context)1601b843c749SSergey Zigachev void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
1602b843c749SSergey Zigachev {
1603b843c749SSergey Zigachev struct dc_link *edp_link_to_turnoff = NULL;
1604b843c749SSergey Zigachev struct dc_link *edp_link = get_link_for_edp(dc);
1605b843c749SSergey Zigachev bool can_eDP_fast_boot_optimize = false;
1606b843c749SSergey Zigachev
1607b843c749SSergey Zigachev if (edp_link) {
1608b843c749SSergey Zigachev /* this seems to cause blank screens on DCE8 */
1609b843c749SSergey Zigachev if ((dc->ctx->dce_version == DCE_VERSION_8_0) ||
1610b843c749SSergey Zigachev (dc->ctx->dce_version == DCE_VERSION_8_1) ||
1611b843c749SSergey Zigachev (dc->ctx->dce_version == DCE_VERSION_8_3))
1612b843c749SSergey Zigachev can_eDP_fast_boot_optimize = false;
1613b843c749SSergey Zigachev else
1614b843c749SSergey Zigachev can_eDP_fast_boot_optimize =
1615b843c749SSergey Zigachev edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc);
1616b843c749SSergey Zigachev }
1617b843c749SSergey Zigachev
1618b843c749SSergey Zigachev if (can_eDP_fast_boot_optimize) {
1619b843c749SSergey Zigachev edp_link_to_turnoff = get_link_for_edp_not_in_use(dc, context);
1620b843c749SSergey Zigachev
1621b843c749SSergey Zigachev /* if OS doesn't light up eDP and eDP link is available, we want to disable
1622b843c749SSergey Zigachev * If resume from S4/S5, should optimization.
1623b843c749SSergey Zigachev */
1624b843c749SSergey Zigachev if (!edp_link_to_turnoff)
1625b843c749SSergey Zigachev dc->apply_edp_fast_boot_optimization = true;
1626b843c749SSergey Zigachev }
1627b843c749SSergey Zigachev
1628b843c749SSergey Zigachev if (!dc->apply_edp_fast_boot_optimization) {
1629b843c749SSergey Zigachev if (edp_link_to_turnoff) {
1630b843c749SSergey Zigachev /*turn off backlight before DP_blank and encoder powered down*/
1631b843c749SSergey Zigachev dc->hwss.edp_backlight_control(edp_link_to_turnoff, false);
1632b843c749SSergey Zigachev }
1633b843c749SSergey Zigachev /*resume from S3, no vbios posting, no need to power down again*/
1634b843c749SSergey Zigachev power_down_all_hw_blocks(dc);
1635b843c749SSergey Zigachev disable_vga_and_power_gate_all_controllers(dc);
1636b843c749SSergey Zigachev if (edp_link_to_turnoff)
1637b843c749SSergey Zigachev dc->hwss.edp_power_control(edp_link_to_turnoff, false);
1638b843c749SSergey Zigachev }
1639b843c749SSergey Zigachev bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1640b843c749SSergey Zigachev }
1641b843c749SSergey Zigachev
compute_pstate_blackout_duration(struct bw_fixed blackout_duration,const struct dc_stream_state * stream)1642b843c749SSergey Zigachev static uint32_t compute_pstate_blackout_duration(
1643b843c749SSergey Zigachev struct bw_fixed blackout_duration,
1644b843c749SSergey Zigachev const struct dc_stream_state *stream)
1645b843c749SSergey Zigachev {
1646b843c749SSergey Zigachev uint32_t total_dest_line_time_ns;
1647b843c749SSergey Zigachev uint32_t pstate_blackout_duration_ns;
1648b843c749SSergey Zigachev
1649b843c749SSergey Zigachev pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1650b843c749SSergey Zigachev
1651b843c749SSergey Zigachev total_dest_line_time_ns = 1000000UL *
1652b843c749SSergey Zigachev stream->timing.h_total /
1653b843c749SSergey Zigachev stream->timing.pix_clk_khz +
1654b843c749SSergey Zigachev pstate_blackout_duration_ns;
1655b843c749SSergey Zigachev
1656b843c749SSergey Zigachev return total_dest_line_time_ns;
1657b843c749SSergey Zigachev }
1658b843c749SSergey Zigachev
dce110_set_displaymarks(const struct dc * dc,struct dc_state * context)1659b843c749SSergey Zigachev static void dce110_set_displaymarks(
1660b843c749SSergey Zigachev const struct dc *dc,
1661b843c749SSergey Zigachev struct dc_state *context)
1662b843c749SSergey Zigachev {
1663b843c749SSergey Zigachev uint8_t i, num_pipes;
1664b843c749SSergey Zigachev unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1665b843c749SSergey Zigachev
1666b843c749SSergey Zigachev for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1667b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1668b843c749SSergey Zigachev uint32_t total_dest_line_time_ns;
1669b843c749SSergey Zigachev
1670b843c749SSergey Zigachev if (pipe_ctx->stream == NULL)
1671b843c749SSergey Zigachev continue;
1672b843c749SSergey Zigachev
1673b843c749SSergey Zigachev total_dest_line_time_ns = compute_pstate_blackout_duration(
1674b843c749SSergey Zigachev dc->bw_vbios->blackout_duration, pipe_ctx->stream);
1675b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
1676b843c749SSergey Zigachev pipe_ctx->plane_res.mi,
1677b843c749SSergey Zigachev context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1678b843c749SSergey Zigachev context->bw.dce.stutter_exit_wm_ns[num_pipes],
1679b843c749SSergey Zigachev context->bw.dce.stutter_entry_wm_ns[num_pipes],
1680b843c749SSergey Zigachev context->bw.dce.urgent_wm_ns[num_pipes],
1681b843c749SSergey Zigachev total_dest_line_time_ns);
1682b843c749SSergey Zigachev if (i == underlay_idx) {
1683b843c749SSergey Zigachev num_pipes++;
1684b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1685b843c749SSergey Zigachev pipe_ctx->plane_res.mi,
1686b843c749SSergey Zigachev context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1687b843c749SSergey Zigachev context->bw.dce.stutter_exit_wm_ns[num_pipes],
1688b843c749SSergey Zigachev context->bw.dce.urgent_wm_ns[num_pipes],
1689b843c749SSergey Zigachev total_dest_line_time_ns);
1690b843c749SSergey Zigachev }
1691b843c749SSergey Zigachev num_pipes++;
1692b843c749SSergey Zigachev }
1693b843c749SSergey Zigachev }
1694b843c749SSergey Zigachev
dce110_set_safe_displaymarks(struct resource_context * res_ctx,const struct resource_pool * pool)1695b843c749SSergey Zigachev void dce110_set_safe_displaymarks(
1696b843c749SSergey Zigachev struct resource_context *res_ctx,
1697b843c749SSergey Zigachev const struct resource_pool *pool)
1698b843c749SSergey Zigachev {
1699b843c749SSergey Zigachev int i;
1700b843c749SSergey Zigachev int underlay_idx = pool->underlay_pipe_index;
1701b843c749SSergey Zigachev struct dce_watermarks max_marks = {
1702b843c749SSergey Zigachev MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1703b843c749SSergey Zigachev struct dce_watermarks nbp_marks = {
1704b843c749SSergey Zigachev SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1705b843c749SSergey Zigachev struct dce_watermarks min_marks = { 0, 0, 0, 0};
1706b843c749SSergey Zigachev
1707b843c749SSergey Zigachev for (i = 0; i < MAX_PIPES; i++) {
1708b843c749SSergey Zigachev if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
1709b843c749SSergey Zigachev continue;
1710b843c749SSergey Zigachev
1711b843c749SSergey Zigachev res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
1712b843c749SSergey Zigachev res_ctx->pipe_ctx[i].plane_res.mi,
1713b843c749SSergey Zigachev nbp_marks,
1714b843c749SSergey Zigachev max_marks,
1715b843c749SSergey Zigachev min_marks,
1716b843c749SSergey Zigachev max_marks,
1717b843c749SSergey Zigachev MAX_WATERMARK);
1718b843c749SSergey Zigachev
1719b843c749SSergey Zigachev if (i == underlay_idx)
1720b843c749SSergey Zigachev res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1721b843c749SSergey Zigachev res_ctx->pipe_ctx[i].plane_res.mi,
1722b843c749SSergey Zigachev nbp_marks,
1723b843c749SSergey Zigachev max_marks,
1724b843c749SSergey Zigachev max_marks,
1725b843c749SSergey Zigachev MAX_WATERMARK);
1726b843c749SSergey Zigachev
1727b843c749SSergey Zigachev }
1728b843c749SSergey Zigachev }
1729b843c749SSergey Zigachev
1730b843c749SSergey Zigachev /*******************************************************************************
1731b843c749SSergey Zigachev * Public functions
1732b843c749SSergey Zigachev ******************************************************************************/
1733b843c749SSergey Zigachev
set_drr(struct pipe_ctx ** pipe_ctx,int num_pipes,int vmin,int vmax)1734b843c749SSergey Zigachev static void set_drr(struct pipe_ctx **pipe_ctx,
1735b843c749SSergey Zigachev int num_pipes, int vmin, int vmax)
1736b843c749SSergey Zigachev {
1737b843c749SSergey Zigachev int i = 0;
1738b843c749SSergey Zigachev struct drr_params params = {0};
1739b843c749SSergey Zigachev
1740b843c749SSergey Zigachev params.vertical_total_max = vmax;
1741b843c749SSergey Zigachev params.vertical_total_min = vmin;
1742b843c749SSergey Zigachev
1743b843c749SSergey Zigachev /* TODO: If multiple pipes are to be supported, you need
1744b843c749SSergey Zigachev * some GSL stuff
1745b843c749SSergey Zigachev */
1746b843c749SSergey Zigachev
1747b843c749SSergey Zigachev for (i = 0; i < num_pipes; i++) {
1748b843c749SSergey Zigachev pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms);
1749b843c749SSergey Zigachev }
1750b843c749SSergey Zigachev }
1751b843c749SSergey Zigachev
get_position(struct pipe_ctx ** pipe_ctx,int num_pipes,struct crtc_position * position)1752b843c749SSergey Zigachev static void get_position(struct pipe_ctx **pipe_ctx,
1753b843c749SSergey Zigachev int num_pipes,
1754b843c749SSergey Zigachev struct crtc_position *position)
1755b843c749SSergey Zigachev {
1756b843c749SSergey Zigachev int i = 0;
1757b843c749SSergey Zigachev
1758b843c749SSergey Zigachev /* TODO: handle pipes > 1
1759b843c749SSergey Zigachev */
1760b843c749SSergey Zigachev for (i = 0; i < num_pipes; i++)
1761b843c749SSergey Zigachev pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
1762b843c749SSergey Zigachev }
1763b843c749SSergey Zigachev
set_static_screen_control(struct pipe_ctx ** pipe_ctx,int num_pipes,const struct dc_static_screen_events * events)1764b843c749SSergey Zigachev static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1765b843c749SSergey Zigachev int num_pipes, const struct dc_static_screen_events *events)
1766b843c749SSergey Zigachev {
1767b843c749SSergey Zigachev unsigned int i;
1768b843c749SSergey Zigachev unsigned int value = 0;
1769b843c749SSergey Zigachev
1770b843c749SSergey Zigachev if (events->overlay_update)
1771b843c749SSergey Zigachev value |= 0x100;
1772b843c749SSergey Zigachev if (events->surface_update)
1773b843c749SSergey Zigachev value |= 0x80;
1774b843c749SSergey Zigachev if (events->cursor_update)
1775b843c749SSergey Zigachev value |= 0x2;
1776b843c749SSergey Zigachev if (events->force_trigger)
1777b843c749SSergey Zigachev value |= 0x1;
1778b843c749SSergey Zigachev
1779b843c749SSergey Zigachev value |= 0x84;
1780b843c749SSergey Zigachev
1781b843c749SSergey Zigachev for (i = 0; i < num_pipes; i++)
1782b843c749SSergey Zigachev pipe_ctx[i]->stream_res.tg->funcs->
1783b843c749SSergey Zigachev set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
1784b843c749SSergey Zigachev }
1785b843c749SSergey Zigachev
1786b843c749SSergey Zigachev /* unit: in_khz before mode set, get pixel clock from context. ASIC register
1787b843c749SSergey Zigachev * may not be programmed yet
1788b843c749SSergey Zigachev */
get_max_pixel_clock_for_all_paths(struct dc * dc,struct dc_state * context)1789b843c749SSergey Zigachev static uint32_t get_max_pixel_clock_for_all_paths(
1790b843c749SSergey Zigachev struct dc *dc,
1791b843c749SSergey Zigachev struct dc_state *context)
1792b843c749SSergey Zigachev {
1793b843c749SSergey Zigachev uint32_t max_pix_clk = 0;
1794b843c749SSergey Zigachev int i;
1795b843c749SSergey Zigachev
1796b843c749SSergey Zigachev for (i = 0; i < MAX_PIPES; i++) {
1797b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1798b843c749SSergey Zigachev
1799b843c749SSergey Zigachev if (pipe_ctx->stream == NULL)
1800b843c749SSergey Zigachev continue;
1801b843c749SSergey Zigachev
1802b843c749SSergey Zigachev /* do not check under lay */
1803b843c749SSergey Zigachev if (pipe_ctx->top_pipe)
1804b843c749SSergey Zigachev continue;
1805b843c749SSergey Zigachev
1806b843c749SSergey Zigachev if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk)
1807b843c749SSergey Zigachev max_pix_clk =
1808b843c749SSergey Zigachev pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1809b843c749SSergey Zigachev }
1810b843c749SSergey Zigachev
1811b843c749SSergey Zigachev return max_pix_clk;
1812b843c749SSergey Zigachev }
1813b843c749SSergey Zigachev
1814b843c749SSergey Zigachev /*
1815b843c749SSergey Zigachev * Check if FBC can be enabled
1816b843c749SSergey Zigachev */
should_enable_fbc(struct dc * dc,struct dc_state * context,uint32_t * pipe_idx)1817b843c749SSergey Zigachev static bool should_enable_fbc(struct dc *dc,
1818b843c749SSergey Zigachev struct dc_state *context,
1819b843c749SSergey Zigachev uint32_t *pipe_idx)
1820b843c749SSergey Zigachev {
1821b843c749SSergey Zigachev uint32_t i;
1822b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = NULL;
1823b843c749SSergey Zigachev struct resource_context *res_ctx = &context->res_ctx;
1824b843c749SSergey Zigachev
1825b843c749SSergey Zigachev
1826b843c749SSergey Zigachev ASSERT(dc->fbc_compressor);
1827b843c749SSergey Zigachev
1828b843c749SSergey Zigachev /* FBC memory should be allocated */
1829b843c749SSergey Zigachev if (!dc->ctx->fbc_gpu_addr)
1830b843c749SSergey Zigachev return false;
1831b843c749SSergey Zigachev
1832b843c749SSergey Zigachev /* Only supports single display */
1833b843c749SSergey Zigachev if (context->stream_count != 1)
1834b843c749SSergey Zigachev return false;
1835b843c749SSergey Zigachev
1836b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
1837b843c749SSergey Zigachev if (res_ctx->pipe_ctx[i].stream) {
1838b843c749SSergey Zigachev pipe_ctx = &res_ctx->pipe_ctx[i];
1839b843c749SSergey Zigachev *pipe_idx = i;
1840b843c749SSergey Zigachev break;
1841b843c749SSergey Zigachev }
1842b843c749SSergey Zigachev }
1843b843c749SSergey Zigachev
1844b843c749SSergey Zigachev /* Pipe context should be found */
1845b843c749SSergey Zigachev ASSERT(pipe_ctx);
1846b843c749SSergey Zigachev
1847b843c749SSergey Zigachev /* Only supports eDP */
1848b843c749SSergey Zigachev if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP)
1849b843c749SSergey Zigachev return false;
1850b843c749SSergey Zigachev
1851b843c749SSergey Zigachev /* PSR should not be enabled */
1852b843c749SSergey Zigachev if (pipe_ctx->stream->sink->link->psr_enabled)
1853b843c749SSergey Zigachev return false;
1854b843c749SSergey Zigachev
1855b843c749SSergey Zigachev /* Nothing to compress */
1856b843c749SSergey Zigachev if (!pipe_ctx->plane_state)
1857b843c749SSergey Zigachev return false;
1858b843c749SSergey Zigachev
1859b843c749SSergey Zigachev /* Only for non-linear tiling */
1860b843c749SSergey Zigachev if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
1861b843c749SSergey Zigachev return false;
1862b843c749SSergey Zigachev
1863b843c749SSergey Zigachev return true;
1864b843c749SSergey Zigachev }
1865b843c749SSergey Zigachev
1866b843c749SSergey Zigachev /*
1867b843c749SSergey Zigachev * Enable FBC
1868b843c749SSergey Zigachev */
enable_fbc(struct dc * dc,struct dc_state * context)1869b843c749SSergey Zigachev static void enable_fbc(struct dc *dc,
1870b843c749SSergey Zigachev struct dc_state *context)
1871b843c749SSergey Zigachev {
1872b843c749SSergey Zigachev uint32_t pipe_idx = 0;
1873b843c749SSergey Zigachev
1874b843c749SSergey Zigachev if (should_enable_fbc(dc, context, &pipe_idx)) {
1875b843c749SSergey Zigachev /* Program GRPH COMPRESSED ADDRESS and PITCH */
1876b843c749SSergey Zigachev struct compr_addr_and_pitch_params params = {0, 0, 0};
1877b843c749SSergey Zigachev struct compressor *compr = dc->fbc_compressor;
1878b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1879b843c749SSergey Zigachev
1880b843c749SSergey Zigachev
1881b843c749SSergey Zigachev params.source_view_width = pipe_ctx->stream->timing.h_addressable;
1882b843c749SSergey Zigachev params.source_view_height = pipe_ctx->stream->timing.v_addressable;
1883b843c749SSergey Zigachev
1884b843c749SSergey Zigachev compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
1885b843c749SSergey Zigachev
1886b843c749SSergey Zigachev compr->funcs->surface_address_and_pitch(compr, ¶ms);
1887b843c749SSergey Zigachev compr->funcs->set_fbc_invalidation_triggers(compr, 1);
1888b843c749SSergey Zigachev
1889b843c749SSergey Zigachev compr->funcs->enable_fbc(compr, ¶ms);
1890b843c749SSergey Zigachev }
1891b843c749SSergey Zigachev }
1892b843c749SSergey Zigachev
dce110_reset_hw_ctx_wrap(struct dc * dc,struct dc_state * context)1893b843c749SSergey Zigachev static void dce110_reset_hw_ctx_wrap(
1894b843c749SSergey Zigachev struct dc *dc,
1895b843c749SSergey Zigachev struct dc_state *context)
1896b843c749SSergey Zigachev {
1897b843c749SSergey Zigachev int i;
1898b843c749SSergey Zigachev
1899b843c749SSergey Zigachev /* Reset old context */
1900b843c749SSergey Zigachev /* look up the targets that have been removed since last commit */
1901b843c749SSergey Zigachev for (i = 0; i < MAX_PIPES; i++) {
1902b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx_old =
1903b843c749SSergey Zigachev &dc->current_state->res_ctx.pipe_ctx[i];
1904b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1905b843c749SSergey Zigachev
1906b843c749SSergey Zigachev /* Note: We need to disable output if clock sources change,
1907b843c749SSergey Zigachev * since bios does optimization and doesn't apply if changing
1908b843c749SSergey Zigachev * PHY when not already disabled.
1909b843c749SSergey Zigachev */
1910b843c749SSergey Zigachev
1911b843c749SSergey Zigachev /* Skip underlay pipe since it will be handled in commit surface*/
1912b843c749SSergey Zigachev if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1913b843c749SSergey Zigachev continue;
1914b843c749SSergey Zigachev
1915b843c749SSergey Zigachev if (!pipe_ctx->stream ||
1916b843c749SSergey Zigachev pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1917b843c749SSergey Zigachev struct clock_source *old_clk = pipe_ctx_old->clock_source;
1918b843c749SSergey Zigachev
1919b843c749SSergey Zigachev /* Disable if new stream is null. O/w, if stream is
1920b843c749SSergey Zigachev * disabled already, no need to disable again.
1921b843c749SSergey Zigachev */
1922b843c749SSergey Zigachev if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off)
1923b843c749SSergey Zigachev core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE);
1924b843c749SSergey Zigachev
1925b843c749SSergey Zigachev pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
1926b843c749SSergey Zigachev if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
1927b843c749SSergey Zigachev dm_error("DC: failed to blank crtc!\n");
1928b843c749SSergey Zigachev BREAK_TO_DEBUGGER();
1929b843c749SSergey Zigachev }
1930b843c749SSergey Zigachev pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
1931b843c749SSergey Zigachev pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
1932b843c749SSergey Zigachev pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
1933b843c749SSergey Zigachev
1934b843c749SSergey Zigachev if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx,
1935b843c749SSergey Zigachev dc->res_pool,
1936b843c749SSergey Zigachev old_clk))
1937b843c749SSergey Zigachev old_clk->funcs->cs_power_down(old_clk);
1938b843c749SSergey Zigachev
1939b843c749SSergey Zigachev dc->hwss.disable_plane(dc, pipe_ctx_old);
1940b843c749SSergey Zigachev
1941b843c749SSergey Zigachev pipe_ctx_old->stream = NULL;
1942b843c749SSergey Zigachev }
1943b843c749SSergey Zigachev }
1944b843c749SSergey Zigachev }
1945b843c749SSergey Zigachev
dce110_setup_audio_dto(struct dc * dc,struct dc_state * context)1946b843c749SSergey Zigachev static void dce110_setup_audio_dto(
1947b843c749SSergey Zigachev struct dc *dc,
1948b843c749SSergey Zigachev struct dc_state *context)
1949b843c749SSergey Zigachev {
1950b843c749SSergey Zigachev int i;
1951b843c749SSergey Zigachev
1952b843c749SSergey Zigachev /* program audio wall clock. use HDMI as clock source if HDMI
1953b843c749SSergey Zigachev * audio active. Otherwise, use DP as clock source
1954b843c749SSergey Zigachev * first, loop to find any HDMI audio, if not, loop find DP audio
1955b843c749SSergey Zigachev */
1956b843c749SSergey Zigachev /* Setup audio rate clock source */
1957b843c749SSergey Zigachev /* Issue:
1958b843c749SSergey Zigachev * Audio lag happened on DP monitor when unplug a HDMI monitor
1959b843c749SSergey Zigachev *
1960b843c749SSergey Zigachev * Cause:
1961b843c749SSergey Zigachev * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
1962b843c749SSergey Zigachev * is set to either dto0 or dto1, audio should work fine.
1963b843c749SSergey Zigachev * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
1964b843c749SSergey Zigachev * set to dto0 will cause audio lag.
1965b843c749SSergey Zigachev *
1966b843c749SSergey Zigachev * Solution:
1967b843c749SSergey Zigachev * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
1968b843c749SSergey Zigachev * find first available pipe with audio, setup audio wall DTO per topology
1969b843c749SSergey Zigachev * instead of per pipe.
1970b843c749SSergey Zigachev */
1971b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
1972b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1973b843c749SSergey Zigachev
1974b843c749SSergey Zigachev if (pipe_ctx->stream == NULL)
1975b843c749SSergey Zigachev continue;
1976b843c749SSergey Zigachev
1977b843c749SSergey Zigachev if (pipe_ctx->top_pipe)
1978b843c749SSergey Zigachev continue;
1979b843c749SSergey Zigachev
1980b843c749SSergey Zigachev if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
1981b843c749SSergey Zigachev continue;
1982b843c749SSergey Zigachev
1983b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio != NULL) {
1984b843c749SSergey Zigachev struct audio_output audio_output;
1985b843c749SSergey Zigachev
1986b843c749SSergey Zigachev build_audio_output(context, pipe_ctx, &audio_output);
1987b843c749SSergey Zigachev
1988b843c749SSergey Zigachev pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
1989b843c749SSergey Zigachev pipe_ctx->stream_res.audio,
1990b843c749SSergey Zigachev pipe_ctx->stream->signal,
1991b843c749SSergey Zigachev &audio_output.crtc_info,
1992b843c749SSergey Zigachev &audio_output.pll_info);
1993b843c749SSergey Zigachev break;
1994b843c749SSergey Zigachev }
1995b843c749SSergey Zigachev }
1996b843c749SSergey Zigachev
1997b843c749SSergey Zigachev /* no HDMI audio is found, try DP audio */
1998b843c749SSergey Zigachev if (i == dc->res_pool->pipe_count) {
1999b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2000b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2001b843c749SSergey Zigachev
2002b843c749SSergey Zigachev if (pipe_ctx->stream == NULL)
2003b843c749SSergey Zigachev continue;
2004b843c749SSergey Zigachev
2005b843c749SSergey Zigachev if (pipe_ctx->top_pipe)
2006b843c749SSergey Zigachev continue;
2007b843c749SSergey Zigachev
2008b843c749SSergey Zigachev if (!dc_is_dp_signal(pipe_ctx->stream->signal))
2009b843c749SSergey Zigachev continue;
2010b843c749SSergey Zigachev
2011b843c749SSergey Zigachev if (pipe_ctx->stream_res.audio != NULL) {
2012b843c749SSergey Zigachev struct audio_output audio_output;
2013b843c749SSergey Zigachev
2014b843c749SSergey Zigachev build_audio_output(context, pipe_ctx, &audio_output);
2015b843c749SSergey Zigachev
2016b843c749SSergey Zigachev pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2017b843c749SSergey Zigachev pipe_ctx->stream_res.audio,
2018b843c749SSergey Zigachev pipe_ctx->stream->signal,
2019b843c749SSergey Zigachev &audio_output.crtc_info,
2020b843c749SSergey Zigachev &audio_output.pll_info);
2021b843c749SSergey Zigachev break;
2022b843c749SSergey Zigachev }
2023b843c749SSergey Zigachev }
2024b843c749SSergey Zigachev }
2025b843c749SSergey Zigachev }
2026b843c749SSergey Zigachev
dce110_apply_ctx_to_hw(struct dc * dc,struct dc_state * context)2027b843c749SSergey Zigachev enum dc_status dce110_apply_ctx_to_hw(
2028b843c749SSergey Zigachev struct dc *dc,
2029b843c749SSergey Zigachev struct dc_state *context)
2030b843c749SSergey Zigachev {
2031b843c749SSergey Zigachev struct dc_bios *dcb = dc->ctx->dc_bios;
2032b843c749SSergey Zigachev enum dc_status status;
2033b843c749SSergey Zigachev int i;
2034b843c749SSergey Zigachev
2035b843c749SSergey Zigachev /* Reset old context */
2036b843c749SSergey Zigachev /* look up the targets that have been removed since last commit */
2037b843c749SSergey Zigachev dc->hwss.reset_hw_ctx_wrap(dc, context);
2038b843c749SSergey Zigachev
2039b843c749SSergey Zigachev /* Skip applying if no targets */
2040b843c749SSergey Zigachev if (context->stream_count <= 0)
2041b843c749SSergey Zigachev return DC_OK;
2042b843c749SSergey Zigachev
2043b843c749SSergey Zigachev /* Apply new context */
2044b843c749SSergey Zigachev dcb->funcs->set_scratch_critical_state(dcb, true);
2045b843c749SSergey Zigachev
2046b843c749SSergey Zigachev /* below is for real asic only */
2047b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2048b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx_old =
2049b843c749SSergey Zigachev &dc->current_state->res_ctx.pipe_ctx[i];
2050b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2051b843c749SSergey Zigachev
2052b843c749SSergey Zigachev if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
2053b843c749SSergey Zigachev continue;
2054b843c749SSergey Zigachev
2055b843c749SSergey Zigachev if (pipe_ctx->stream == pipe_ctx_old->stream) {
2056b843c749SSergey Zigachev if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
2057b843c749SSergey Zigachev dce_crtc_switch_to_clk_src(dc->hwseq,
2058b843c749SSergey Zigachev pipe_ctx->clock_source, i);
2059b843c749SSergey Zigachev continue;
2060b843c749SSergey Zigachev }
2061b843c749SSergey Zigachev
2062b843c749SSergey Zigachev dc->hwss.enable_display_power_gating(
2063b843c749SSergey Zigachev dc, i, dc->ctx->dc_bios,
2064b843c749SSergey Zigachev PIPE_GATING_CONTROL_DISABLE);
2065b843c749SSergey Zigachev }
2066b843c749SSergey Zigachev
2067b843c749SSergey Zigachev if (dc->fbc_compressor)
2068b843c749SSergey Zigachev dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2069b843c749SSergey Zigachev
2070b843c749SSergey Zigachev dce110_setup_audio_dto(dc, context);
2071b843c749SSergey Zigachev
2072b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2073b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx_old =
2074b843c749SSergey Zigachev &dc->current_state->res_ctx.pipe_ctx[i];
2075b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2076b843c749SSergey Zigachev
2077b843c749SSergey Zigachev if (pipe_ctx->stream == NULL)
2078b843c749SSergey Zigachev continue;
2079b843c749SSergey Zigachev
2080b843c749SSergey Zigachev if (pipe_ctx->stream == pipe_ctx_old->stream)
2081b843c749SSergey Zigachev continue;
2082b843c749SSergey Zigachev
2083b843c749SSergey Zigachev if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
2084b843c749SSergey Zigachev continue;
2085b843c749SSergey Zigachev
2086b843c749SSergey Zigachev if (pipe_ctx->top_pipe)
2087b843c749SSergey Zigachev continue;
2088b843c749SSergey Zigachev
2089b843c749SSergey Zigachev status = apply_single_controller_ctx_to_hw(
2090b843c749SSergey Zigachev pipe_ctx,
2091b843c749SSergey Zigachev context,
2092b843c749SSergey Zigachev dc);
2093b843c749SSergey Zigachev
2094b843c749SSergey Zigachev if (DC_OK != status)
2095b843c749SSergey Zigachev return status;
2096b843c749SSergey Zigachev }
2097b843c749SSergey Zigachev
2098b843c749SSergey Zigachev dcb->funcs->set_scratch_critical_state(dcb, false);
2099b843c749SSergey Zigachev
2100b843c749SSergey Zigachev if (dc->fbc_compressor)
2101b843c749SSergey Zigachev enable_fbc(dc, context);
2102b843c749SSergey Zigachev
2103b843c749SSergey Zigachev return DC_OK;
2104b843c749SSergey Zigachev }
2105b843c749SSergey Zigachev
2106b843c749SSergey Zigachev /*******************************************************************************
2107b843c749SSergey Zigachev * Front End programming
2108b843c749SSergey Zigachev ******************************************************************************/
set_default_colors(struct pipe_ctx * pipe_ctx)2109b843c749SSergey Zigachev static void set_default_colors(struct pipe_ctx *pipe_ctx)
2110b843c749SSergey Zigachev {
2111b843c749SSergey Zigachev struct default_adjustment default_adjust = { 0 };
2112b843c749SSergey Zigachev
2113b843c749SSergey Zigachev default_adjust.force_hw_default = false;
2114b843c749SSergey Zigachev default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
2115b843c749SSergey Zigachev default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
2116b843c749SSergey Zigachev default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
2117b843c749SSergey Zigachev default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
2118b843c749SSergey Zigachev
2119b843c749SSergey Zigachev /* display color depth */
2120b843c749SSergey Zigachev default_adjust.color_depth =
2121b843c749SSergey Zigachev pipe_ctx->stream->timing.display_color_depth;
2122b843c749SSergey Zigachev
2123b843c749SSergey Zigachev /* Lb color depth */
2124b843c749SSergey Zigachev default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
2125b843c749SSergey Zigachev
2126b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
2127b843c749SSergey Zigachev pipe_ctx->plane_res.xfm, &default_adjust);
2128b843c749SSergey Zigachev }
2129b843c749SSergey Zigachev
2130b843c749SSergey Zigachev
2131b843c749SSergey Zigachev /*******************************************************************************
2132b843c749SSergey Zigachev * In order to turn on/off specific surface we will program
2133b843c749SSergey Zigachev * Blender + CRTC
2134b843c749SSergey Zigachev *
2135b843c749SSergey Zigachev * In case that we have two surfaces and they have a different visibility
2136b843c749SSergey Zigachev * we can't turn off the CRTC since it will turn off the entire display
2137b843c749SSergey Zigachev *
2138b843c749SSergey Zigachev * |----------------------------------------------- |
2139b843c749SSergey Zigachev * |bottom pipe|curr pipe | | |
2140b843c749SSergey Zigachev * |Surface |Surface | Blender | CRCT |
2141b843c749SSergey Zigachev * |visibility |visibility | Configuration| |
2142b843c749SSergey Zigachev * |------------------------------------------------|
2143b843c749SSergey Zigachev * | off | off | CURRENT_PIPE | blank |
2144b843c749SSergey Zigachev * | off | on | CURRENT_PIPE | unblank |
2145b843c749SSergey Zigachev * | on | off | OTHER_PIPE | unblank |
2146b843c749SSergey Zigachev * | on | on | BLENDING | unblank |
2147b843c749SSergey Zigachev * -------------------------------------------------|
2148b843c749SSergey Zigachev *
2149b843c749SSergey Zigachev ******************************************************************************/
program_surface_visibility(const struct dc * dc,struct pipe_ctx * pipe_ctx)2150b843c749SSergey Zigachev static void program_surface_visibility(const struct dc *dc,
2151b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx)
2152b843c749SSergey Zigachev {
2153b843c749SSergey Zigachev enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
2154b843c749SSergey Zigachev bool blank_target = false;
2155b843c749SSergey Zigachev
2156b843c749SSergey Zigachev if (pipe_ctx->bottom_pipe) {
2157b843c749SSergey Zigachev
2158b843c749SSergey Zigachev /* For now we are supporting only two pipes */
2159b843c749SSergey Zigachev ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
2160b843c749SSergey Zigachev
2161b843c749SSergey Zigachev if (pipe_ctx->bottom_pipe->plane_state->visible) {
2162b843c749SSergey Zigachev if (pipe_ctx->plane_state->visible)
2163b843c749SSergey Zigachev blender_mode = BLND_MODE_BLENDING;
2164b843c749SSergey Zigachev else
2165b843c749SSergey Zigachev blender_mode = BLND_MODE_OTHER_PIPE;
2166b843c749SSergey Zigachev
2167b843c749SSergey Zigachev } else if (!pipe_ctx->plane_state->visible)
2168b843c749SSergey Zigachev blank_target = true;
2169b843c749SSergey Zigachev
2170b843c749SSergey Zigachev } else if (!pipe_ctx->plane_state->visible)
2171b843c749SSergey Zigachev blank_target = true;
2172b843c749SSergey Zigachev
2173b843c749SSergey Zigachev dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode);
2174b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
2175b843c749SSergey Zigachev
2176b843c749SSergey Zigachev }
2177b843c749SSergey Zigachev
program_gamut_remap(struct pipe_ctx * pipe_ctx)2178b843c749SSergey Zigachev static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2179b843c749SSergey Zigachev {
2180b843c749SSergey Zigachev int i = 0;
2181b843c749SSergey Zigachev struct xfm_grph_csc_adjustment adjust;
2182b843c749SSergey Zigachev memset(&adjust, 0, sizeof(adjust));
2183b843c749SSergey Zigachev adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2184b843c749SSergey Zigachev
2185b843c749SSergey Zigachev
2186b843c749SSergey Zigachev if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2187b843c749SSergey Zigachev adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2188b843c749SSergey Zigachev
2189b843c749SSergey Zigachev for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2190b843c749SSergey Zigachev adjust.temperature_matrix[i] =
2191b843c749SSergey Zigachev pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2192b843c749SSergey Zigachev }
2193b843c749SSergey Zigachev
2194b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2195b843c749SSergey Zigachev }
update_plane_addr(const struct dc * dc,struct pipe_ctx * pipe_ctx)2196b843c749SSergey Zigachev static void update_plane_addr(const struct dc *dc,
2197b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx)
2198b843c749SSergey Zigachev {
2199b843c749SSergey Zigachev struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2200b843c749SSergey Zigachev
2201b843c749SSergey Zigachev if (plane_state == NULL)
2202b843c749SSergey Zigachev return;
2203b843c749SSergey Zigachev
2204b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
2205b843c749SSergey Zigachev pipe_ctx->plane_res.mi,
2206b843c749SSergey Zigachev &plane_state->address,
2207b843c749SSergey Zigachev plane_state->flip_immediate);
2208b843c749SSergey Zigachev
2209b843c749SSergey Zigachev plane_state->status.requested_address = plane_state->address;
2210b843c749SSergey Zigachev }
2211b843c749SSergey Zigachev
dce110_update_pending_status(struct pipe_ctx * pipe_ctx)2212b843c749SSergey Zigachev static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2213b843c749SSergey Zigachev {
2214b843c749SSergey Zigachev struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2215b843c749SSergey Zigachev
2216b843c749SSergey Zigachev if (plane_state == NULL)
2217b843c749SSergey Zigachev return;
2218b843c749SSergey Zigachev
2219b843c749SSergey Zigachev plane_state->status.is_flip_pending =
2220b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
2221b843c749SSergey Zigachev pipe_ctx->plane_res.mi);
2222b843c749SSergey Zigachev
2223b843c749SSergey Zigachev if (plane_state->status.is_flip_pending && !plane_state->visible)
2224b843c749SSergey Zigachev pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
2225b843c749SSergey Zigachev
2226b843c749SSergey Zigachev plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
2227b843c749SSergey Zigachev if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2228b843c749SSergey Zigachev pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
2229b843c749SSergey Zigachev plane_state->status.is_right_eye =\
2230b843c749SSergey Zigachev !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2231b843c749SSergey Zigachev }
2232b843c749SSergey Zigachev }
2233b843c749SSergey Zigachev
dce110_power_down(struct dc * dc)2234b843c749SSergey Zigachev void dce110_power_down(struct dc *dc)
2235b843c749SSergey Zigachev {
2236b843c749SSergey Zigachev power_down_all_hw_blocks(dc);
2237b843c749SSergey Zigachev disable_vga_and_power_gate_all_controllers(dc);
2238b843c749SSergey Zigachev }
2239b843c749SSergey Zigachev
wait_for_reset_trigger_to_occur(struct dc_context * dc_ctx,struct timing_generator * tg)2240b843c749SSergey Zigachev static bool wait_for_reset_trigger_to_occur(
2241b843c749SSergey Zigachev struct dc_context *dc_ctx,
2242b843c749SSergey Zigachev struct timing_generator *tg)
2243b843c749SSergey Zigachev {
2244b843c749SSergey Zigachev bool rc = false;
2245b843c749SSergey Zigachev
2246b843c749SSergey Zigachev /* To avoid endless loop we wait at most
2247b843c749SSergey Zigachev * frames_to_wait_on_triggered_reset frames for the reset to occur. */
2248b843c749SSergey Zigachev const uint32_t frames_to_wait_on_triggered_reset = 10;
2249b843c749SSergey Zigachev uint32_t i;
2250b843c749SSergey Zigachev
2251b843c749SSergey Zigachev for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2252b843c749SSergey Zigachev
2253b843c749SSergey Zigachev if (!tg->funcs->is_counter_moving(tg)) {
2254b843c749SSergey Zigachev DC_ERROR("TG counter is not moving!\n");
2255b843c749SSergey Zigachev break;
2256b843c749SSergey Zigachev }
2257b843c749SSergey Zigachev
2258b843c749SSergey Zigachev if (tg->funcs->did_triggered_reset_occur(tg)) {
2259b843c749SSergey Zigachev rc = true;
2260b843c749SSergey Zigachev /* usually occurs at i=1 */
2261b843c749SSergey Zigachev DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2262b843c749SSergey Zigachev i);
2263b843c749SSergey Zigachev break;
2264b843c749SSergey Zigachev }
2265b843c749SSergey Zigachev
2266b843c749SSergey Zigachev /* Wait for one frame. */
2267b843c749SSergey Zigachev tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2268b843c749SSergey Zigachev tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2269b843c749SSergey Zigachev }
2270b843c749SSergey Zigachev
2271b843c749SSergey Zigachev if (false == rc)
2272b843c749SSergey Zigachev DC_ERROR("GSL: Timeout on reset trigger!\n");
2273b843c749SSergey Zigachev
2274b843c749SSergey Zigachev return rc;
2275b843c749SSergey Zigachev }
2276b843c749SSergey Zigachev
2277b843c749SSergey Zigachev /* Enable timing synchronization for a group of Timing Generators. */
dce110_enable_timing_synchronization(struct dc * dc,int group_index,int group_size,struct pipe_ctx * grouped_pipes[])2278b843c749SSergey Zigachev static void dce110_enable_timing_synchronization(
2279b843c749SSergey Zigachev struct dc *dc,
2280b843c749SSergey Zigachev int group_index,
2281b843c749SSergey Zigachev int group_size,
2282b843c749SSergey Zigachev struct pipe_ctx *grouped_pipes[])
2283b843c749SSergey Zigachev {
2284b843c749SSergey Zigachev struct dc_context *dc_ctx = dc->ctx;
2285b843c749SSergey Zigachev struct dcp_gsl_params gsl_params = { 0 };
2286b843c749SSergey Zigachev int i;
2287b843c749SSergey Zigachev
2288b843c749SSergey Zigachev DC_SYNC_INFO("GSL: Setting-up...\n");
2289b843c749SSergey Zigachev
2290b843c749SSergey Zigachev /* Designate a single TG in the group as a master.
2291b843c749SSergey Zigachev * Since HW doesn't care which one, we always assign
2292b843c749SSergey Zigachev * the 1st one in the group. */
2293b843c749SSergey Zigachev gsl_params.gsl_group = 0;
2294b843c749SSergey Zigachev gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
2295b843c749SSergey Zigachev
2296b843c749SSergey Zigachev for (i = 0; i < group_size; i++)
2297b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2298b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg, &gsl_params);
2299b843c749SSergey Zigachev
2300b843c749SSergey Zigachev /* Reset slave controllers on master VSync */
2301b843c749SSergey Zigachev DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2302b843c749SSergey Zigachev
2303b843c749SSergey Zigachev for (i = 1 /* skip the master */; i < group_size; i++)
2304b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2305b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg,
2306b843c749SSergey Zigachev gsl_params.gsl_group);
2307b843c749SSergey Zigachev
2308b843c749SSergey Zigachev for (i = 1 /* skip the master */; i < group_size; i++) {
2309b843c749SSergey Zigachev DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2310b843c749SSergey Zigachev wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2311b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2312b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg);
2313b843c749SSergey Zigachev }
2314b843c749SSergey Zigachev
2315b843c749SSergey Zigachev /* GSL Vblank synchronization is a one time sync mechanism, assumption
2316b843c749SSergey Zigachev * is that the sync'ed displays will not drift out of sync over time*/
2317b843c749SSergey Zigachev DC_SYNC_INFO("GSL: Restoring register states.\n");
2318b843c749SSergey Zigachev for (i = 0; i < group_size; i++)
2319b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2320b843c749SSergey Zigachev
2321b843c749SSergey Zigachev DC_SYNC_INFO("GSL: Set-up complete.\n");
2322b843c749SSergey Zigachev }
2323b843c749SSergey Zigachev
dce110_enable_per_frame_crtc_position_reset(struct dc * dc,int group_size,struct pipe_ctx * grouped_pipes[])2324b843c749SSergey Zigachev static void dce110_enable_per_frame_crtc_position_reset(
2325b843c749SSergey Zigachev struct dc *dc,
2326b843c749SSergey Zigachev int group_size,
2327b843c749SSergey Zigachev struct pipe_ctx *grouped_pipes[])
2328b843c749SSergey Zigachev {
2329b843c749SSergey Zigachev struct dc_context *dc_ctx = dc->ctx;
2330b843c749SSergey Zigachev struct dcp_gsl_params gsl_params = { 0 };
2331b843c749SSergey Zigachev int i;
2332b843c749SSergey Zigachev
2333b843c749SSergey Zigachev gsl_params.gsl_group = 0;
2334b843c749SSergey Zigachev gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst;
2335b843c749SSergey Zigachev
2336b843c749SSergey Zigachev for (i = 0; i < group_size; i++)
2337b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2338b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg, &gsl_params);
2339b843c749SSergey Zigachev
2340b843c749SSergey Zigachev DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2341b843c749SSergey Zigachev
2342b843c749SSergey Zigachev for (i = 1; i < group_size; i++)
2343b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2344b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg,
2345b843c749SSergey Zigachev gsl_params.gsl_master,
2346b843c749SSergey Zigachev &grouped_pipes[i]->stream->triggered_crtc_reset);
2347b843c749SSergey Zigachev
2348b843c749SSergey Zigachev DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2349b843c749SSergey Zigachev for (i = 1; i < group_size; i++)
2350b843c749SSergey Zigachev wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2351b843c749SSergey Zigachev
2352b843c749SSergey Zigachev for (i = 0; i < group_size; i++)
2353b843c749SSergey Zigachev grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2354b843c749SSergey Zigachev
2355b843c749SSergey Zigachev }
2356b843c749SSergey Zigachev
init_hw(struct dc * dc)2357b843c749SSergey Zigachev static void init_hw(struct dc *dc)
2358b843c749SSergey Zigachev {
2359b843c749SSergey Zigachev int i;
2360b843c749SSergey Zigachev struct dc_bios *bp;
2361b843c749SSergey Zigachev struct transform *xfm;
2362b843c749SSergey Zigachev struct abm *abm;
2363b843c749SSergey Zigachev
2364b843c749SSergey Zigachev bp = dc->ctx->dc_bios;
2365b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2366b843c749SSergey Zigachev xfm = dc->res_pool->transforms[i];
2367b843c749SSergey Zigachev xfm->funcs->transform_reset(xfm);
2368b843c749SSergey Zigachev
2369b843c749SSergey Zigachev dc->hwss.enable_display_power_gating(
2370b843c749SSergey Zigachev dc, i, bp,
2371b843c749SSergey Zigachev PIPE_GATING_CONTROL_INIT);
2372b843c749SSergey Zigachev dc->hwss.enable_display_power_gating(
2373b843c749SSergey Zigachev dc, i, bp,
2374b843c749SSergey Zigachev PIPE_GATING_CONTROL_DISABLE);
2375b843c749SSergey Zigachev dc->hwss.enable_display_pipe_clock_gating(
2376b843c749SSergey Zigachev dc->ctx,
2377b843c749SSergey Zigachev true);
2378b843c749SSergey Zigachev }
2379b843c749SSergey Zigachev
2380b843c749SSergey Zigachev dce_clock_gating_power_up(dc->hwseq, false);
2381b843c749SSergey Zigachev /***************************************/
2382b843c749SSergey Zigachev
2383b843c749SSergey Zigachev for (i = 0; i < dc->link_count; i++) {
2384b843c749SSergey Zigachev /****************************************/
2385b843c749SSergey Zigachev /* Power up AND update implementation according to the
2386b843c749SSergey Zigachev * required signal (which may be different from the
2387b843c749SSergey Zigachev * default signal on connector). */
2388b843c749SSergey Zigachev struct dc_link *link = dc->links[i];
2389b843c749SSergey Zigachev
2390b843c749SSergey Zigachev if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
2391b843c749SSergey Zigachev dc->hwss.edp_power_control(link, true);
2392b843c749SSergey Zigachev
2393b843c749SSergey Zigachev link->link_enc->funcs->hw_init(link->link_enc);
2394b843c749SSergey Zigachev }
2395b843c749SSergey Zigachev
2396b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2397b843c749SSergey Zigachev struct timing_generator *tg = dc->res_pool->timing_generators[i];
2398b843c749SSergey Zigachev
2399b843c749SSergey Zigachev tg->funcs->disable_vga(tg);
2400b843c749SSergey Zigachev
2401b843c749SSergey Zigachev /* Blank controller using driver code instead of
2402b843c749SSergey Zigachev * command table. */
2403b843c749SSergey Zigachev tg->funcs->set_blank(tg, true);
2404b843c749SSergey Zigachev hwss_wait_for_blank_complete(tg);
2405b843c749SSergey Zigachev }
2406b843c749SSergey Zigachev
2407b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->audio_count; i++) {
2408b843c749SSergey Zigachev struct audio *audio = dc->res_pool->audios[i];
2409b843c749SSergey Zigachev audio->funcs->hw_init(audio);
2410b843c749SSergey Zigachev }
2411b843c749SSergey Zigachev
2412b843c749SSergey Zigachev abm = dc->res_pool->abm;
2413b843c749SSergey Zigachev if (abm != NULL) {
2414b843c749SSergey Zigachev abm->funcs->init_backlight(abm);
2415b843c749SSergey Zigachev abm->funcs->abm_init(abm);
2416b843c749SSergey Zigachev }
2417b843c749SSergey Zigachev
2418b843c749SSergey Zigachev if (dc->fbc_compressor)
2419b843c749SSergey Zigachev dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
2420b843c749SSergey Zigachev
2421b843c749SSergey Zigachev }
2422b843c749SSergey Zigachev
dce110_fill_display_configs(const struct dc_state * context,struct dm_pp_display_configuration * pp_display_cfg)2423b843c749SSergey Zigachev void dce110_fill_display_configs(
2424b843c749SSergey Zigachev const struct dc_state *context,
2425b843c749SSergey Zigachev struct dm_pp_display_configuration *pp_display_cfg)
2426b843c749SSergey Zigachev {
2427b843c749SSergey Zigachev int j;
2428b843c749SSergey Zigachev int num_cfgs = 0;
2429b843c749SSergey Zigachev
2430b843c749SSergey Zigachev for (j = 0; j < context->stream_count; j++) {
2431b843c749SSergey Zigachev int k;
2432b843c749SSergey Zigachev
2433b843c749SSergey Zigachev const struct dc_stream_state *stream = context->streams[j];
2434b843c749SSergey Zigachev struct dm_pp_single_disp_config *cfg =
2435b843c749SSergey Zigachev &pp_display_cfg->disp_configs[num_cfgs];
2436b843c749SSergey Zigachev const struct pipe_ctx *pipe_ctx = NULL;
2437b843c749SSergey Zigachev
2438b843c749SSergey Zigachev for (k = 0; k < MAX_PIPES; k++)
2439b843c749SSergey Zigachev if (stream == context->res_ctx.pipe_ctx[k].stream) {
2440b843c749SSergey Zigachev pipe_ctx = &context->res_ctx.pipe_ctx[k];
2441b843c749SSergey Zigachev break;
2442b843c749SSergey Zigachev }
2443b843c749SSergey Zigachev
2444b843c749SSergey Zigachev ASSERT(pipe_ctx != NULL);
2445b843c749SSergey Zigachev
2446b843c749SSergey Zigachev /* only notify active stream */
2447b843c749SSergey Zigachev if (stream->dpms_off)
2448b843c749SSergey Zigachev continue;
2449b843c749SSergey Zigachev
2450b843c749SSergey Zigachev num_cfgs++;
2451b843c749SSergey Zigachev cfg->signal = pipe_ctx->stream->signal;
2452b843c749SSergey Zigachev cfg->pipe_idx = pipe_ctx->stream_res.tg->inst;
2453b843c749SSergey Zigachev cfg->src_height = stream->src.height;
2454b843c749SSergey Zigachev cfg->src_width = stream->src.width;
2455b843c749SSergey Zigachev cfg->ddi_channel_mapping =
2456b843c749SSergey Zigachev stream->sink->link->ddi_channel_mapping.raw;
2457b843c749SSergey Zigachev cfg->transmitter =
2458b843c749SSergey Zigachev stream->sink->link->link_enc->transmitter;
2459b843c749SSergey Zigachev cfg->link_settings.lane_count =
2460b843c749SSergey Zigachev stream->sink->link->cur_link_settings.lane_count;
2461b843c749SSergey Zigachev cfg->link_settings.link_rate =
2462b843c749SSergey Zigachev stream->sink->link->cur_link_settings.link_rate;
2463b843c749SSergey Zigachev cfg->link_settings.link_spread =
2464b843c749SSergey Zigachev stream->sink->link->cur_link_settings.link_spread;
2465b843c749SSergey Zigachev cfg->sym_clock = stream->phy_pix_clk;
2466b843c749SSergey Zigachev /* Round v_refresh*/
2467b843c749SSergey Zigachev cfg->v_refresh = stream->timing.pix_clk_khz * 1000;
2468b843c749SSergey Zigachev cfg->v_refresh /= stream->timing.h_total;
2469b843c749SSergey Zigachev cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
2470b843c749SSergey Zigachev / stream->timing.v_total;
2471b843c749SSergey Zigachev }
2472b843c749SSergey Zigachev
2473b843c749SSergey Zigachev pp_display_cfg->display_count = num_cfgs;
2474b843c749SSergey Zigachev }
2475b843c749SSergey Zigachev
dce110_get_min_vblank_time_us(const struct dc_state * context)2476b843c749SSergey Zigachev uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
2477b843c749SSergey Zigachev {
2478b843c749SSergey Zigachev uint8_t j;
2479b843c749SSergey Zigachev uint32_t min_vertical_blank_time = -1;
2480b843c749SSergey Zigachev
2481b843c749SSergey Zigachev for (j = 0; j < context->stream_count; j++) {
2482b843c749SSergey Zigachev struct dc_stream_state *stream = context->streams[j];
2483b843c749SSergey Zigachev uint32_t vertical_blank_in_pixels = 0;
2484b843c749SSergey Zigachev uint32_t vertical_blank_time = 0;
2485b843c749SSergey Zigachev
2486b843c749SSergey Zigachev vertical_blank_in_pixels = stream->timing.h_total *
2487b843c749SSergey Zigachev (stream->timing.v_total
2488b843c749SSergey Zigachev - stream->timing.v_addressable);
2489b843c749SSergey Zigachev
2490b843c749SSergey Zigachev vertical_blank_time = vertical_blank_in_pixels
2491b843c749SSergey Zigachev * 1000 / stream->timing.pix_clk_khz;
2492b843c749SSergey Zigachev
2493b843c749SSergey Zigachev if (min_vertical_blank_time > vertical_blank_time)
2494b843c749SSergey Zigachev min_vertical_blank_time = vertical_blank_time;
2495b843c749SSergey Zigachev }
2496b843c749SSergey Zigachev
2497b843c749SSergey Zigachev return min_vertical_blank_time;
2498b843c749SSergey Zigachev }
2499b843c749SSergey Zigachev
determine_sclk_from_bounding_box(const struct dc * dc,int required_sclk)2500b843c749SSergey Zigachev static int determine_sclk_from_bounding_box(
2501b843c749SSergey Zigachev const struct dc *dc,
2502b843c749SSergey Zigachev int required_sclk)
2503b843c749SSergey Zigachev {
2504b843c749SSergey Zigachev int i;
2505b843c749SSergey Zigachev
2506b843c749SSergey Zigachev /*
2507b843c749SSergey Zigachev * Some asics do not give us sclk levels, so we just report the actual
2508b843c749SSergey Zigachev * required sclk
2509b843c749SSergey Zigachev */
2510b843c749SSergey Zigachev if (dc->sclk_lvls.num_levels == 0)
2511b843c749SSergey Zigachev return required_sclk;
2512b843c749SSergey Zigachev
2513b843c749SSergey Zigachev for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
2514b843c749SSergey Zigachev if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
2515b843c749SSergey Zigachev return dc->sclk_lvls.clocks_in_khz[i];
2516b843c749SSergey Zigachev }
2517b843c749SSergey Zigachev /*
2518b843c749SSergey Zigachev * even maximum level could not satisfy requirement, this
2519b843c749SSergey Zigachev * is unexpected at this stage, should have been caught at
2520b843c749SSergey Zigachev * validation time
2521b843c749SSergey Zigachev */
2522b843c749SSergey Zigachev ASSERT(0);
2523b843c749SSergey Zigachev return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
2524b843c749SSergey Zigachev }
2525b843c749SSergey Zigachev
pplib_apply_display_requirements(struct dc * dc,struct dc_state * context)2526b843c749SSergey Zigachev static void pplib_apply_display_requirements(
2527b843c749SSergey Zigachev struct dc *dc,
2528b843c749SSergey Zigachev struct dc_state *context)
2529b843c749SSergey Zigachev {
2530b843c749SSergey Zigachev struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2531b843c749SSergey Zigachev
2532b843c749SSergey Zigachev pp_display_cfg->all_displays_in_sync =
2533b843c749SSergey Zigachev context->bw.dce.all_displays_in_sync;
2534b843c749SSergey Zigachev pp_display_cfg->nb_pstate_switch_disable =
2535b843c749SSergey Zigachev context->bw.dce.nbp_state_change_enable == false;
2536b843c749SSergey Zigachev pp_display_cfg->cpu_cc6_disable =
2537b843c749SSergey Zigachev context->bw.dce.cpuc_state_change_enable == false;
2538b843c749SSergey Zigachev pp_display_cfg->cpu_pstate_disable =
2539b843c749SSergey Zigachev context->bw.dce.cpup_state_change_enable == false;
2540b843c749SSergey Zigachev pp_display_cfg->cpu_pstate_separation_time =
2541b843c749SSergey Zigachev context->bw.dce.blackout_recovery_time_us;
2542b843c749SSergey Zigachev
2543b843c749SSergey Zigachev pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz
2544b843c749SSergey Zigachev / MEMORY_TYPE_MULTIPLIER;
2545b843c749SSergey Zigachev
2546b843c749SSergey Zigachev pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
2547b843c749SSergey Zigachev dc,
2548b843c749SSergey Zigachev context->bw.dce.sclk_khz);
2549b843c749SSergey Zigachev
2550b843c749SSergey Zigachev pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
2551b843c749SSergey Zigachev
2552b843c749SSergey Zigachev pp_display_cfg->min_engine_clock_deep_sleep_khz
2553b843c749SSergey Zigachev = context->bw.dce.sclk_deep_sleep_khz;
2554b843c749SSergey Zigachev
2555b843c749SSergey Zigachev pp_display_cfg->avail_mclk_switch_time_us =
2556b843c749SSergey Zigachev dce110_get_min_vblank_time_us(context);
2557b843c749SSergey Zigachev /* TODO: dce11.2*/
2558b843c749SSergey Zigachev pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
2559b843c749SSergey Zigachev
2560b843c749SSergey Zigachev pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz;
2561b843c749SSergey Zigachev
2562b843c749SSergey Zigachev dce110_fill_display_configs(context, pp_display_cfg);
2563b843c749SSergey Zigachev
2564b843c749SSergey Zigachev /* TODO: is this still applicable?*/
2565b843c749SSergey Zigachev if (pp_display_cfg->display_count == 1) {
2566b843c749SSergey Zigachev const struct dc_crtc_timing *timing =
2567b843c749SSergey Zigachev &context->streams[0]->timing;
2568b843c749SSergey Zigachev
2569b843c749SSergey Zigachev pp_display_cfg->crtc_index =
2570b843c749SSergey Zigachev pp_display_cfg->disp_configs[0].pipe_idx;
2571b843c749SSergey Zigachev pp_display_cfg->line_time_in_us = timing->h_total * 1000
2572b843c749SSergey Zigachev / timing->pix_clk_khz;
2573b843c749SSergey Zigachev }
2574b843c749SSergey Zigachev
2575b843c749SSergey Zigachev if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2576b843c749SSergey Zigachev struct dm_pp_display_configuration)) != 0)
2577b843c749SSergey Zigachev dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2578b843c749SSergey Zigachev
2579b843c749SSergey Zigachev dc->prev_display_config = *pp_display_cfg;
2580b843c749SSergey Zigachev }
2581b843c749SSergey Zigachev
dce110_set_bandwidth(struct dc * dc,struct dc_state * context,bool decrease_allowed)2582b843c749SSergey Zigachev static void dce110_set_bandwidth(
2583b843c749SSergey Zigachev struct dc *dc,
2584b843c749SSergey Zigachev struct dc_state *context,
2585b843c749SSergey Zigachev bool decrease_allowed)
2586b843c749SSergey Zigachev {
2587b843c749SSergey Zigachev struct dc_clocks req_clks;
2588b843c749SSergey Zigachev
2589b843c749SSergey Zigachev req_clks.dispclk_khz = context->bw.dce.dispclk_khz;
2590b843c749SSergey Zigachev req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context);
2591b843c749SSergey Zigachev
2592b843c749SSergey Zigachev if (decrease_allowed)
2593b843c749SSergey Zigachev dce110_set_displaymarks(dc, context);
2594b843c749SSergey Zigachev else
2595b843c749SSergey Zigachev dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
2596b843c749SSergey Zigachev
2597b843c749SSergey Zigachev dc->res_pool->dccg->funcs->update_clocks(
2598b843c749SSergey Zigachev dc->res_pool->dccg,
2599b843c749SSergey Zigachev &req_clks,
2600b843c749SSergey Zigachev decrease_allowed);
2601b843c749SSergey Zigachev pplib_apply_display_requirements(dc, context);
2602b843c749SSergey Zigachev }
2603b843c749SSergey Zigachev
dce110_program_front_end_for_pipe(struct dc * dc,struct pipe_ctx * pipe_ctx)2604b843c749SSergey Zigachev static void dce110_program_front_end_for_pipe(
2605b843c749SSergey Zigachev struct dc *dc, struct pipe_ctx *pipe_ctx)
2606b843c749SSergey Zigachev {
2607b843c749SSergey Zigachev struct mem_input *mi = pipe_ctx->plane_res.mi;
2608b843c749SSergey Zigachev struct pipe_ctx *old_pipe = NULL;
2609b843c749SSergey Zigachev struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2610b843c749SSergey Zigachev struct xfm_grph_csc_adjustment adjust;
2611b843c749SSergey Zigachev struct out_csc_color_matrix tbl_entry;
2612b843c749SSergey Zigachev unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
2613b843c749SSergey Zigachev unsigned int i;
2614b843c749SSergey Zigachev DC_LOGGER_INIT();
2615b843c749SSergey Zigachev memset(&tbl_entry, 0, sizeof(tbl_entry));
2616b843c749SSergey Zigachev
2617b843c749SSergey Zigachev if (dc->current_state)
2618b843c749SSergey Zigachev old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2619b843c749SSergey Zigachev
2620b843c749SSergey Zigachev memset(&adjust, 0, sizeof(adjust));
2621b843c749SSergey Zigachev adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2622b843c749SSergey Zigachev
2623b843c749SSergey Zigachev dce_enable_fe_clock(dc->hwseq, mi->inst, true);
2624b843c749SSergey Zigachev
2625b843c749SSergey Zigachev set_default_colors(pipe_ctx);
2626b843c749SSergey Zigachev if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2627b843c749SSergey Zigachev == true) {
2628b843c749SSergey Zigachev tbl_entry.color_space =
2629b843c749SSergey Zigachev pipe_ctx->stream->output_color_space;
2630b843c749SSergey Zigachev
2631b843c749SSergey Zigachev for (i = 0; i < 12; i++)
2632b843c749SSergey Zigachev tbl_entry.regval[i] =
2633b843c749SSergey Zigachev pipe_ctx->stream->csc_color_matrix.matrix[i];
2634b843c749SSergey Zigachev
2635b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2636b843c749SSergey Zigachev (pipe_ctx->plane_res.xfm, &tbl_entry);
2637b843c749SSergey Zigachev }
2638b843c749SSergey Zigachev
2639b843c749SSergey Zigachev if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2640b843c749SSergey Zigachev adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2641b843c749SSergey Zigachev
2642b843c749SSergey Zigachev for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2643b843c749SSergey Zigachev adjust.temperature_matrix[i] =
2644b843c749SSergey Zigachev pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2645b843c749SSergey Zigachev }
2646b843c749SSergey Zigachev
2647b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2648b843c749SSergey Zigachev
2649b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2650b843c749SSergey Zigachev
2651b843c749SSergey Zigachev program_scaler(dc, pipe_ctx);
2652b843c749SSergey Zigachev
2653b843c749SSergey Zigachev /* fbc not applicable on Underlay pipe */
2654b843c749SSergey Zigachev if (dc->fbc_compressor && old_pipe->stream &&
2655b843c749SSergey Zigachev pipe_ctx->pipe_idx != underlay_idx) {
2656b843c749SSergey Zigachev if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
2657b843c749SSergey Zigachev dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2658b843c749SSergey Zigachev else
2659b843c749SSergey Zigachev enable_fbc(dc, dc->current_state);
2660b843c749SSergey Zigachev }
2661b843c749SSergey Zigachev
2662b843c749SSergey Zigachev mi->funcs->mem_input_program_surface_config(
2663b843c749SSergey Zigachev mi,
2664b843c749SSergey Zigachev plane_state->format,
2665b843c749SSergey Zigachev &plane_state->tiling_info,
2666b843c749SSergey Zigachev &plane_state->plane_size,
2667b843c749SSergey Zigachev plane_state->rotation,
2668b843c749SSergey Zigachev NULL,
2669b843c749SSergey Zigachev false);
2670b843c749SSergey Zigachev if (mi->funcs->set_blank)
2671b843c749SSergey Zigachev mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
2672b843c749SSergey Zigachev
2673b843c749SSergey Zigachev if (dc->config.gpu_vm_support)
2674b843c749SSergey Zigachev mi->funcs->mem_input_program_pte_vm(
2675b843c749SSergey Zigachev pipe_ctx->plane_res.mi,
2676b843c749SSergey Zigachev plane_state->format,
2677b843c749SSergey Zigachev &plane_state->tiling_info,
2678b843c749SSergey Zigachev plane_state->rotation);
2679b843c749SSergey Zigachev
2680b843c749SSergey Zigachev /* Moved programming gamma from dc to hwss */
2681b843c749SSergey Zigachev if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2682b843c749SSergey Zigachev pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2683b843c749SSergey Zigachev pipe_ctx->plane_state->update_flags.bits.gamma_change)
2684b843c749SSergey Zigachev dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2685b843c749SSergey Zigachev
2686b843c749SSergey Zigachev if (pipe_ctx->plane_state->update_flags.bits.full_update)
2687b843c749SSergey Zigachev dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2688b843c749SSergey Zigachev
2689b843c749SSergey Zigachev DC_LOG_SURFACE(
2690b843c749SSergey Zigachev "Pipe:%d %p: addr hi:0x%x, "
2691b843c749SSergey Zigachev "addr low:0x%x, "
2692b843c749SSergey Zigachev "src: %d, %d, %d,"
2693b843c749SSergey Zigachev " %d; dst: %d, %d, %d, %d;"
2694b843c749SSergey Zigachev "clip: %d, %d, %d, %d\n",
2695b843c749SSergey Zigachev pipe_ctx->pipe_idx,
2696b843c749SSergey Zigachev (void *) pipe_ctx->plane_state,
2697b843c749SSergey Zigachev pipe_ctx->plane_state->address.grph.addr.high_part,
2698b843c749SSergey Zigachev pipe_ctx->plane_state->address.grph.addr.low_part,
2699b843c749SSergey Zigachev pipe_ctx->plane_state->src_rect.x,
2700b843c749SSergey Zigachev pipe_ctx->plane_state->src_rect.y,
2701b843c749SSergey Zigachev pipe_ctx->plane_state->src_rect.width,
2702b843c749SSergey Zigachev pipe_ctx->plane_state->src_rect.height,
2703b843c749SSergey Zigachev pipe_ctx->plane_state->dst_rect.x,
2704b843c749SSergey Zigachev pipe_ctx->plane_state->dst_rect.y,
2705b843c749SSergey Zigachev pipe_ctx->plane_state->dst_rect.width,
2706b843c749SSergey Zigachev pipe_ctx->plane_state->dst_rect.height,
2707b843c749SSergey Zigachev pipe_ctx->plane_state->clip_rect.x,
2708b843c749SSergey Zigachev pipe_ctx->plane_state->clip_rect.y,
2709b843c749SSergey Zigachev pipe_ctx->plane_state->clip_rect.width,
2710b843c749SSergey Zigachev pipe_ctx->plane_state->clip_rect.height);
2711b843c749SSergey Zigachev
2712b843c749SSergey Zigachev DC_LOG_SURFACE(
2713b843c749SSergey Zigachev "Pipe %d: width, height, x, y\n"
2714b843c749SSergey Zigachev "viewport:%d, %d, %d, %d\n"
2715b843c749SSergey Zigachev "recout: %d, %d, %d, %d\n",
2716b843c749SSergey Zigachev pipe_ctx->pipe_idx,
2717b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.viewport.width,
2718b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.viewport.height,
2719b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.viewport.x,
2720b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.viewport.y,
2721b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.recout.width,
2722b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.recout.height,
2723b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.recout.x,
2724b843c749SSergey Zigachev pipe_ctx->plane_res.scl_data.recout.y);
2725b843c749SSergey Zigachev }
2726b843c749SSergey Zigachev
dce110_apply_ctx_for_surface(struct dc * dc,const struct dc_stream_state * stream,int num_planes,struct dc_state * context)2727b843c749SSergey Zigachev static void dce110_apply_ctx_for_surface(
2728b843c749SSergey Zigachev struct dc *dc,
2729b843c749SSergey Zigachev const struct dc_stream_state *stream,
2730b843c749SSergey Zigachev int num_planes,
2731b843c749SSergey Zigachev struct dc_state *context)
2732b843c749SSergey Zigachev {
2733b843c749SSergey Zigachev int i;
2734b843c749SSergey Zigachev
2735b843c749SSergey Zigachev if (num_planes == 0)
2736b843c749SSergey Zigachev return;
2737b843c749SSergey Zigachev
2738b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2739b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2740b843c749SSergey Zigachev struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2741b843c749SSergey Zigachev
2742b843c749SSergey Zigachev if (stream == pipe_ctx->stream) {
2743b843c749SSergey Zigachev if (!pipe_ctx->top_pipe &&
2744b843c749SSergey Zigachev (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2745b843c749SSergey Zigachev dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
2746b843c749SSergey Zigachev }
2747b843c749SSergey Zigachev }
2748b843c749SSergey Zigachev
2749b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2750b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2751b843c749SSergey Zigachev
2752b843c749SSergey Zigachev if (pipe_ctx->stream != stream)
2753b843c749SSergey Zigachev continue;
2754b843c749SSergey Zigachev
2755b843c749SSergey Zigachev /* Need to allocate mem before program front end for Fiji */
2756b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
2757b843c749SSergey Zigachev pipe_ctx->plane_res.mi,
2758b843c749SSergey Zigachev pipe_ctx->stream->timing.h_total,
2759b843c749SSergey Zigachev pipe_ctx->stream->timing.v_total,
2760b843c749SSergey Zigachev pipe_ctx->stream->timing.pix_clk_khz,
2761b843c749SSergey Zigachev context->stream_count);
2762b843c749SSergey Zigachev
2763b843c749SSergey Zigachev dce110_program_front_end_for_pipe(dc, pipe_ctx);
2764b843c749SSergey Zigachev
2765b843c749SSergey Zigachev dc->hwss.update_plane_addr(dc, pipe_ctx);
2766b843c749SSergey Zigachev
2767b843c749SSergey Zigachev program_surface_visibility(dc, pipe_ctx);
2768b843c749SSergey Zigachev
2769b843c749SSergey Zigachev }
2770b843c749SSergey Zigachev
2771b843c749SSergey Zigachev for (i = 0; i < dc->res_pool->pipe_count; i++) {
2772b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2773b843c749SSergey Zigachev struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2774b843c749SSergey Zigachev
2775b843c749SSergey Zigachev if ((stream == pipe_ctx->stream) &&
2776b843c749SSergey Zigachev (!pipe_ctx->top_pipe) &&
2777b843c749SSergey Zigachev (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2778b843c749SSergey Zigachev dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
2779b843c749SSergey Zigachev }
2780b843c749SSergey Zigachev }
2781b843c749SSergey Zigachev
dce110_power_down_fe(struct dc * dc,struct pipe_ctx * pipe_ctx)2782b843c749SSergey Zigachev static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
2783b843c749SSergey Zigachev {
2784b843c749SSergey Zigachev int fe_idx = pipe_ctx->plane_res.mi ?
2785b843c749SSergey Zigachev pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
2786b843c749SSergey Zigachev
2787b843c749SSergey Zigachev /* Do not power down fe when stream is active on dce*/
2788b843c749SSergey Zigachev if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
2789b843c749SSergey Zigachev return;
2790b843c749SSergey Zigachev
2791b843c749SSergey Zigachev dc->hwss.enable_display_power_gating(
2792b843c749SSergey Zigachev dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2793b843c749SSergey Zigachev
2794b843c749SSergey Zigachev dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2795b843c749SSergey Zigachev dc->res_pool->transforms[fe_idx]);
2796b843c749SSergey Zigachev }
2797b843c749SSergey Zigachev
dce110_wait_for_mpcc_disconnect(struct dc * dc,struct resource_pool * res_pool,struct pipe_ctx * pipe_ctx)2798b843c749SSergey Zigachev static void dce110_wait_for_mpcc_disconnect(
2799b843c749SSergey Zigachev struct dc *dc,
2800b843c749SSergey Zigachev struct resource_pool *res_pool,
2801b843c749SSergey Zigachev struct pipe_ctx *pipe_ctx)
2802b843c749SSergey Zigachev {
2803b843c749SSergey Zigachev /* do nothing*/
2804b843c749SSergey Zigachev }
2805b843c749SSergey Zigachev
program_csc_matrix(struct pipe_ctx * pipe_ctx,enum dc_color_space colorspace,uint16_t * matrix)2806b843c749SSergey Zigachev static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
2807b843c749SSergey Zigachev enum dc_color_space colorspace,
2808b843c749SSergey Zigachev uint16_t *matrix)
2809b843c749SSergey Zigachev {
2810b843c749SSergey Zigachev int i;
2811b843c749SSergey Zigachev struct out_csc_color_matrix tbl_entry;
2812b843c749SSergey Zigachev
2813b843c749SSergey Zigachev if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2814b843c749SSergey Zigachev == true) {
2815b843c749SSergey Zigachev enum dc_color_space color_space =
2816b843c749SSergey Zigachev pipe_ctx->stream->output_color_space;
2817b843c749SSergey Zigachev
2818b843c749SSergey Zigachev //uint16_t matrix[12];
2819b843c749SSergey Zigachev for (i = 0; i < 12; i++)
2820b843c749SSergey Zigachev tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
2821b843c749SSergey Zigachev
2822b843c749SSergey Zigachev tbl_entry.color_space = color_space;
2823b843c749SSergey Zigachev //tbl_entry.regval = matrix;
2824b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry);
2825b843c749SSergey Zigachev }
2826b843c749SSergey Zigachev }
2827b843c749SSergey Zigachev
2828*78973132SSergey Zigachev static
dce110_set_cursor_position(struct pipe_ctx * pipe_ctx)2829b843c749SSergey Zigachev void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
2830b843c749SSergey Zigachev {
2831b843c749SSergey Zigachev struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2832b843c749SSergey Zigachev struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
2833b843c749SSergey Zigachev struct mem_input *mi = pipe_ctx->plane_res.mi;
2834b843c749SSergey Zigachev struct dc_cursor_mi_param param = {
2835b843c749SSergey Zigachev .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
2836b843c749SSergey Zigachev .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
2837b843c749SSergey Zigachev .viewport = pipe_ctx->plane_res.scl_data.viewport,
2838b843c749SSergey Zigachev .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2839b843c749SSergey Zigachev .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2840b843c749SSergey Zigachev .rotation = pipe_ctx->plane_state->rotation,
2841b843c749SSergey Zigachev .mirror = pipe_ctx->plane_state->horizontal_mirror
2842b843c749SSergey Zigachev };
2843b843c749SSergey Zigachev
2844b843c749SSergey Zigachev if (pipe_ctx->plane_state->address.type
2845b843c749SSergey Zigachev == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2846b843c749SSergey Zigachev pos_cpy.enable = false;
2847b843c749SSergey Zigachev
2848b843c749SSergey Zigachev if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2849b843c749SSergey Zigachev pos_cpy.enable = false;
2850b843c749SSergey Zigachev
2851b843c749SSergey Zigachev if (ipp->funcs->ipp_cursor_set_position)
2852b843c749SSergey Zigachev ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m);
2853b843c749SSergey Zigachev if (mi->funcs->set_cursor_position)
2854b843c749SSergey Zigachev mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m);
2855b843c749SSergey Zigachev }
2856b843c749SSergey Zigachev
2857*78973132SSergey Zigachev static
dce110_set_cursor_attribute(struct pipe_ctx * pipe_ctx)2858b843c749SSergey Zigachev void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2859b843c749SSergey Zigachev {
2860b843c749SSergey Zigachev struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2861b843c749SSergey Zigachev
2862b843c749SSergey Zigachev if (pipe_ctx->plane_res.ipp &&
2863b843c749SSergey Zigachev pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
2864b843c749SSergey Zigachev pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
2865b843c749SSergey Zigachev pipe_ctx->plane_res.ipp, attributes);
2866b843c749SSergey Zigachev
2867b843c749SSergey Zigachev if (pipe_ctx->plane_res.mi &&
2868b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
2869b843c749SSergey Zigachev pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
2870b843c749SSergey Zigachev pipe_ctx->plane_res.mi, attributes);
2871b843c749SSergey Zigachev
2872b843c749SSergey Zigachev if (pipe_ctx->plane_res.xfm &&
2873b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
2874b843c749SSergey Zigachev pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
2875b843c749SSergey Zigachev pipe_ctx->plane_res.xfm, attributes);
2876b843c749SSergey Zigachev }
2877b843c749SSergey Zigachev
ready_shared_resources(struct dc * dc,struct dc_state * context)2878b843c749SSergey Zigachev static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}
2879b843c749SSergey Zigachev
optimize_shared_resources(struct dc * dc)2880b843c749SSergey Zigachev static void optimize_shared_resources(struct dc *dc) {}
2881b843c749SSergey Zigachev
2882b843c749SSergey Zigachev static const struct hw_sequencer_funcs dce110_funcs = {
2883b843c749SSergey Zigachev .program_gamut_remap = program_gamut_remap,
2884b843c749SSergey Zigachev .program_csc_matrix = program_csc_matrix,
2885b843c749SSergey Zigachev .init_hw = init_hw,
2886b843c749SSergey Zigachev .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2887b843c749SSergey Zigachev .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2888b843c749SSergey Zigachev .update_plane_addr = update_plane_addr,
2889b843c749SSergey Zigachev .update_pending_status = dce110_update_pending_status,
2890b843c749SSergey Zigachev .set_input_transfer_func = dce110_set_input_transfer_func,
2891b843c749SSergey Zigachev .set_output_transfer_func = dce110_set_output_transfer_func,
2892b843c749SSergey Zigachev .power_down = dce110_power_down,
2893b843c749SSergey Zigachev .enable_accelerated_mode = dce110_enable_accelerated_mode,
2894b843c749SSergey Zigachev .enable_timing_synchronization = dce110_enable_timing_synchronization,
2895b843c749SSergey Zigachev .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
2896b843c749SSergey Zigachev .update_info_frame = dce110_update_info_frame,
2897b843c749SSergey Zigachev .enable_stream = dce110_enable_stream,
2898b843c749SSergey Zigachev .disable_stream = dce110_disable_stream,
2899b843c749SSergey Zigachev .unblank_stream = dce110_unblank_stream,
2900b843c749SSergey Zigachev .blank_stream = dce110_blank_stream,
2901b843c749SSergey Zigachev .enable_audio_stream = dce110_enable_audio_stream,
2902b843c749SSergey Zigachev .disable_audio_stream = dce110_disable_audio_stream,
2903b843c749SSergey Zigachev .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2904b843c749SSergey Zigachev .enable_display_power_gating = dce110_enable_display_power_gating,
2905b843c749SSergey Zigachev .disable_plane = dce110_power_down_fe,
2906b843c749SSergey Zigachev .pipe_control_lock = dce_pipe_control_lock,
2907b843c749SSergey Zigachev .set_bandwidth = dce110_set_bandwidth,
2908b843c749SSergey Zigachev .set_drr = set_drr,
2909b843c749SSergey Zigachev .get_position = get_position,
2910b843c749SSergey Zigachev .set_static_screen_control = set_static_screen_control,
2911b843c749SSergey Zigachev .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
2912b843c749SSergey Zigachev .enable_stream_timing = dce110_enable_stream_timing,
2913b843c749SSergey Zigachev .setup_stereo = NULL,
2914b843c749SSergey Zigachev .set_avmute = dce110_set_avmute,
2915b843c749SSergey Zigachev .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
2916b843c749SSergey Zigachev .ready_shared_resources = ready_shared_resources,
2917b843c749SSergey Zigachev .optimize_shared_resources = optimize_shared_resources,
2918b843c749SSergey Zigachev .pplib_apply_display_requirements = pplib_apply_display_requirements,
2919b843c749SSergey Zigachev .edp_backlight_control = hwss_edp_backlight_control,
2920b843c749SSergey Zigachev .edp_power_control = hwss_edp_power_control,
2921b843c749SSergey Zigachev .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
2922b843c749SSergey Zigachev .set_cursor_position = dce110_set_cursor_position,
2923b843c749SSergey Zigachev .set_cursor_attribute = dce110_set_cursor_attribute
2924b843c749SSergey Zigachev };
2925b843c749SSergey Zigachev
dce110_hw_sequencer_construct(struct dc * dc)2926b843c749SSergey Zigachev void dce110_hw_sequencer_construct(struct dc *dc)
2927b843c749SSergey Zigachev {
2928b843c749SSergey Zigachev dc->hwss = dce110_funcs;
2929b843c749SSergey Zigachev }
2930b843c749SSergey Zigachev
2931