bool dcn10_validate_bandwidth()

in drm/amd/display/dc/calcs/dcn_calcs.c [768:1339]


bool dcn10_validate_bandwidth(
		struct dc *dc,
		struct dc_state *context,
		bool fast_validate)
{
	/*
	 * we want a breakdown of the various stages of validation, which the
	 * perf_trace macro doesn't support
	 */
	BW_VAL_TRACE_SETUP();

	const struct resource_pool *pool = dc->res_pool;
	struct dcn_bw_internal_vars *v = &context->dcn_bw_vars;
	int i, input_idx, k;
	int vesa_sync_start, asic_blank_end, asic_blank_start;
	bool bw_limit_pass;
	float bw_limit;

	PERFORMANCE_TRACE_START();

	BW_VAL_TRACE_COUNT();

	if (dcn_bw_apply_registry_override(dc))
		dcn_bw_sync_calcs_and_dml(dc);

	memset(v, 0, sizeof(*v));
	DC_FP_START();

	v->sr_exit_time = dc->dcn_soc->sr_exit_time;
	v->sr_enter_plus_exit_time = dc->dcn_soc->sr_enter_plus_exit_time;
	v->urgent_latency = dc->dcn_soc->urgent_latency;
	v->write_back_latency = dc->dcn_soc->write_back_latency;
	v->percent_of_ideal_drambw_received_after_urg_latency =
			dc->dcn_soc->percent_of_ideal_drambw_received_after_urg_latency;

	v->dcfclkv_min0p65 = dc->dcn_soc->dcfclkv_min0p65;
	v->dcfclkv_mid0p72 = dc->dcn_soc->dcfclkv_mid0p72;
	v->dcfclkv_nom0p8 = dc->dcn_soc->dcfclkv_nom0p8;
	v->dcfclkv_max0p9 = dc->dcn_soc->dcfclkv_max0p9;

	v->max_dispclk_vmin0p65 = dc->dcn_soc->max_dispclk_vmin0p65;
	v->max_dispclk_vmid0p72 = dc->dcn_soc->max_dispclk_vmid0p72;
	v->max_dispclk_vnom0p8 = dc->dcn_soc->max_dispclk_vnom0p8;
	v->max_dispclk_vmax0p9 = dc->dcn_soc->max_dispclk_vmax0p9;

	v->max_dppclk_vmin0p65 = dc->dcn_soc->max_dppclk_vmin0p65;
	v->max_dppclk_vmid0p72 = dc->dcn_soc->max_dppclk_vmid0p72;
	v->max_dppclk_vnom0p8 = dc->dcn_soc->max_dppclk_vnom0p8;
	v->max_dppclk_vmax0p9 = dc->dcn_soc->max_dppclk_vmax0p9;

	v->socclk = dc->dcn_soc->socclk;

	v->fabric_and_dram_bandwidth_vmin0p65 = dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65;
	v->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72;
	v->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8;
	v->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9;

	v->phyclkv_min0p65 = dc->dcn_soc->phyclkv_min0p65;
	v->phyclkv_mid0p72 = dc->dcn_soc->phyclkv_mid0p72;
	v->phyclkv_nom0p8 = dc->dcn_soc->phyclkv_nom0p8;
	v->phyclkv_max0p9 = dc->dcn_soc->phyclkv_max0p9;

	v->downspreading = dc->dcn_soc->downspreading;
	v->round_trip_ping_latency_cycles = dc->dcn_soc->round_trip_ping_latency_cycles;
	v->urgent_out_of_order_return_per_channel = dc->dcn_soc->urgent_out_of_order_return_per_channel;
	v->number_of_channels = dc->dcn_soc->number_of_channels;
	v->vmm_page_size = dc->dcn_soc->vmm_page_size;
	v->dram_clock_change_latency = dc->dcn_soc->dram_clock_change_latency;
	v->return_bus_width = dc->dcn_soc->return_bus_width;

	v->rob_buffer_size_in_kbyte = dc->dcn_ip->rob_buffer_size_in_kbyte;
	v->det_buffer_size_in_kbyte = dc->dcn_ip->det_buffer_size_in_kbyte;
	v->dpp_output_buffer_pixels = dc->dcn_ip->dpp_output_buffer_pixels;
	v->opp_output_buffer_lines = dc->dcn_ip->opp_output_buffer_lines;
	v->pixel_chunk_size_in_kbyte = dc->dcn_ip->pixel_chunk_size_in_kbyte;
	v->pte_enable = dc->dcn_ip->pte_enable;
	v->pte_chunk_size = dc->dcn_ip->pte_chunk_size;
	v->meta_chunk_size = dc->dcn_ip->meta_chunk_size;
	v->writeback_chunk_size = dc->dcn_ip->writeback_chunk_size;
	v->odm_capability = dc->dcn_ip->odm_capability;
	v->dsc_capability = dc->dcn_ip->dsc_capability;
	v->line_buffer_size = dc->dcn_ip->line_buffer_size;
	v->is_line_buffer_bpp_fixed = dc->dcn_ip->is_line_buffer_bpp_fixed;
	v->line_buffer_fixed_bpp = dc->dcn_ip->line_buffer_fixed_bpp;
	v->max_line_buffer_lines = dc->dcn_ip->max_line_buffer_lines;
	v->writeback_luma_buffer_size = dc->dcn_ip->writeback_luma_buffer_size;
	v->writeback_chroma_buffer_size = dc->dcn_ip->writeback_chroma_buffer_size;
	v->max_num_dpp = dc->dcn_ip->max_num_dpp;
	v->max_num_writeback = dc->dcn_ip->max_num_writeback;
	v->max_dchub_topscl_throughput = dc->dcn_ip->max_dchub_topscl_throughput;
	v->max_pscl_tolb_throughput = dc->dcn_ip->max_pscl_tolb_throughput;
	v->max_lb_tovscl_throughput = dc->dcn_ip->max_lb_tovscl_throughput;
	v->max_vscl_tohscl_throughput = dc->dcn_ip->max_vscl_tohscl_throughput;
	v->max_hscl_ratio = dc->dcn_ip->max_hscl_ratio;
	v->max_vscl_ratio = dc->dcn_ip->max_vscl_ratio;
	v->max_hscl_taps = dc->dcn_ip->max_hscl_taps;
	v->max_vscl_taps = dc->dcn_ip->max_vscl_taps;
	v->under_scan_factor = dc->dcn_ip->under_scan_factor;
	v->pte_buffer_size_in_requests = dc->dcn_ip->pte_buffer_size_in_requests;
	v->dispclk_ramping_margin = dc->dcn_ip->dispclk_ramping_margin;
	v->max_inter_dcn_tile_repeaters = dc->dcn_ip->max_inter_dcn_tile_repeaters;
	v->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one =
			dc->dcn_ip->can_vstartup_lines_exceed_vsync_plus_back_porch_lines_minus_one;
	v->bug_forcing_luma_and_chroma_request_to_same_size_fixed =
			dc->dcn_ip->bug_forcing_luma_and_chroma_request_to_same_size_fixed;

	v->voltage[5] = dcn_bw_no_support;
	v->voltage[4] = dcn_bw_v_max0p9;
	v->voltage[3] = dcn_bw_v_max0p9;
	v->voltage[2] = dcn_bw_v_nom0p8;
	v->voltage[1] = dcn_bw_v_mid0p72;
	v->voltage[0] = dcn_bw_v_min0p65;
	v->fabric_and_dram_bandwidth_per_state[5] = v->fabric_and_dram_bandwidth_vmax0p9;
	v->fabric_and_dram_bandwidth_per_state[4] = v->fabric_and_dram_bandwidth_vmax0p9;
	v->fabric_and_dram_bandwidth_per_state[3] = v->fabric_and_dram_bandwidth_vmax0p9;
	v->fabric_and_dram_bandwidth_per_state[2] = v->fabric_and_dram_bandwidth_vnom0p8;
	v->fabric_and_dram_bandwidth_per_state[1] = v->fabric_and_dram_bandwidth_vmid0p72;
	v->fabric_and_dram_bandwidth_per_state[0] = v->fabric_and_dram_bandwidth_vmin0p65;
	v->dcfclk_per_state[5] = v->dcfclkv_max0p9;
	v->dcfclk_per_state[4] = v->dcfclkv_max0p9;
	v->dcfclk_per_state[3] = v->dcfclkv_max0p9;
	v->dcfclk_per_state[2] = v->dcfclkv_nom0p8;
	v->dcfclk_per_state[1] = v->dcfclkv_mid0p72;
	v->dcfclk_per_state[0] = v->dcfclkv_min0p65;
	v->max_dispclk[5] = v->max_dispclk_vmax0p9;
	v->max_dispclk[4] = v->max_dispclk_vmax0p9;
	v->max_dispclk[3] = v->max_dispclk_vmax0p9;
	v->max_dispclk[2] = v->max_dispclk_vnom0p8;
	v->max_dispclk[1] = v->max_dispclk_vmid0p72;
	v->max_dispclk[0] = v->max_dispclk_vmin0p65;
	v->max_dppclk[5] = v->max_dppclk_vmax0p9;
	v->max_dppclk[4] = v->max_dppclk_vmax0p9;
	v->max_dppclk[3] = v->max_dppclk_vmax0p9;
	v->max_dppclk[2] = v->max_dppclk_vnom0p8;
	v->max_dppclk[1] = v->max_dppclk_vmid0p72;
	v->max_dppclk[0] = v->max_dppclk_vmin0p65;
	v->phyclk_per_state[5] = v->phyclkv_max0p9;
	v->phyclk_per_state[4] = v->phyclkv_max0p9;
	v->phyclk_per_state[3] = v->phyclkv_max0p9;
	v->phyclk_per_state[2] = v->phyclkv_nom0p8;
	v->phyclk_per_state[1] = v->phyclkv_mid0p72;
	v->phyclk_per_state[0] = v->phyclkv_min0p65;
	v->synchronized_vblank = dcn_bw_no;
	v->ta_pscalculation = dcn_bw_override;
	v->allow_different_hratio_vratio = dcn_bw_yes;

	for (i = 0, input_idx = 0; i < pool->pipe_count; i++) {
		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];

		if (!pipe->stream)
			continue;
		/* skip all but first of split pipes */
		if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
			continue;

		v->underscan_output[input_idx] = false; /* taken care of in recout already*/
		v->interlace_output[input_idx] = false;

		v->htotal[input_idx] = pipe->stream->timing.h_total;
		v->vtotal[input_idx] = pipe->stream->timing.v_total;
		v->vactive[input_idx] = pipe->stream->timing.v_addressable +
				pipe->stream->timing.v_border_top + pipe->stream->timing.v_border_bottom;
		v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total
				- v->vactive[input_idx]
				- pipe->stream->timing.v_front_porch;
		v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_100hz/10000.0;
		if (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
			v->pixel_clock[input_idx] *= 2;
		if (!pipe->plane_state) {
			v->dcc_enable[input_idx] = dcn_bw_yes;
			v->source_pixel_format[input_idx] = dcn_bw_rgb_sub_32;
			v->source_surface_mode[input_idx] = dcn_bw_sw_4_kb_s;
			v->lb_bit_per_pixel[input_idx] = 30;
			v->viewport_width[input_idx] = pipe->stream->timing.h_addressable;
			v->viewport_height[input_idx] = pipe->stream->timing.v_addressable;
			/*
			 * for cases where we have no plane, we want to validate up to 1080p
			 * source size because here we are only interested in if the output
			 * timing is supported or not. if we cannot support native resolution
			 * of the high res display, we still want to support lower res up scale
			 * to native
			 */
			if (v->viewport_width[input_idx] > 1920)
				v->viewport_width[input_idx] = 1920;
			if (v->viewport_height[input_idx] > 1080)
				v->viewport_height[input_idx] = 1080;
			v->scaler_rec_out_width[input_idx] = v->viewport_width[input_idx];
			v->scaler_recout_height[input_idx] = v->viewport_height[input_idx];
			v->override_hta_ps[input_idx] = 1;
			v->override_vta_ps[input_idx] = 1;
			v->override_hta_pschroma[input_idx] = 1;
			v->override_vta_pschroma[input_idx] = 1;
			v->source_scan[input_idx] = dcn_bw_hor;

		} else {
			v->viewport_height[input_idx] =  pipe->plane_res.scl_data.viewport.height;
			v->viewport_width[input_idx] = pipe->plane_res.scl_data.viewport.width;
			v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width;
			v->scaler_recout_height[input_idx] = pipe->plane_res.scl_data.recout.height;
			if (pipe->bottom_pipe && pipe->bottom_pipe->plane_state == pipe->plane_state) {
				if (pipe->plane_state->rotation % 2 == 0) {
					int viewport_end = pipe->plane_res.scl_data.viewport.width
							+ pipe->plane_res.scl_data.viewport.x;
					int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.width
							+ pipe->bottom_pipe->plane_res.scl_data.viewport.x;

					if (viewport_end > viewport_b_end)
						v->viewport_width[input_idx] = viewport_end
							- pipe->bottom_pipe->plane_res.scl_data.viewport.x;
					else
						v->viewport_width[input_idx] = viewport_b_end
									- pipe->plane_res.scl_data.viewport.x;
				} else  {
					int viewport_end = pipe->plane_res.scl_data.viewport.height
						+ pipe->plane_res.scl_data.viewport.y;
					int viewport_b_end = pipe->bottom_pipe->plane_res.scl_data.viewport.height
						+ pipe->bottom_pipe->plane_res.scl_data.viewport.y;

					if (viewport_end > viewport_b_end)
						v->viewport_height[input_idx] = viewport_end
							- pipe->bottom_pipe->plane_res.scl_data.viewport.y;
					else
						v->viewport_height[input_idx] = viewport_b_end
									- pipe->plane_res.scl_data.viewport.y;
				}
				v->scaler_rec_out_width[input_idx] = pipe->plane_res.scl_data.recout.width
						+ pipe->bottom_pipe->plane_res.scl_data.recout.width;
			}

			if (pipe->plane_state->rotation % 2 == 0) {
				ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dc_fixpt_one.value
					|| v->scaler_rec_out_width[input_idx] == v->viewport_width[input_idx]);
				ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dc_fixpt_one.value
					|| v->scaler_recout_height[input_idx] == v->viewport_height[input_idx]);
			} else {
				ASSERT(pipe->plane_res.scl_data.ratios.horz.value != dc_fixpt_one.value
					|| v->scaler_recout_height[input_idx] == v->viewport_width[input_idx]);
				ASSERT(pipe->plane_res.scl_data.ratios.vert.value != dc_fixpt_one.value
					|| v->scaler_rec_out_width[input_idx] == v->viewport_height[input_idx]);
			}

			if (dc->debug.optimized_watermark) {
				/*
				 * this method requires us to always re-calculate watermark when dcc change
				 * between flip.
				 */
				v->dcc_enable[input_idx] = pipe->plane_state->dcc.enable ? dcn_bw_yes : dcn_bw_no;
			} else {
				/*
				 * allow us to disable dcc on the fly without re-calculating WM
				 *
				 * extra overhead for DCC is quite small.  for 1080p WM without
				 * DCC is only 0.417us lower (urgent goes from 6.979us to 6.562us)
				 */
				unsigned int bpe;

				v->dcc_enable[input_idx] = dc->res_pool->hubbub->funcs->dcc_support_pixel_format(
						pipe->plane_state->format, &bpe) ? dcn_bw_yes : dcn_bw_no;
			}

			v->source_pixel_format[input_idx] = tl_pixel_format_to_bw_defs(
					pipe->plane_state->format);
			v->source_surface_mode[input_idx] = tl_sw_mode_to_bw_defs(
					pipe->plane_state->tiling_info.gfx9.swizzle);
			v->lb_bit_per_pixel[input_idx] = tl_lb_bpp_to_int(pipe->plane_res.scl_data.lb_params.depth);
			v->override_hta_ps[input_idx] = pipe->plane_res.scl_data.taps.h_taps;
			v->override_vta_ps[input_idx] = pipe->plane_res.scl_data.taps.v_taps;
			v->override_hta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.h_taps_c;
			v->override_vta_pschroma[input_idx] = pipe->plane_res.scl_data.taps.v_taps_c;
			/*
			 * Spreadsheet doesn't handle taps_c is one properly,
			 * need to force Chroma to always be scaled to pass
			 * bandwidth validation.
			 */
			if (v->override_hta_pschroma[input_idx] == 1)
				v->override_hta_pschroma[input_idx] = 2;
			if (v->override_vta_pschroma[input_idx] == 1)
				v->override_vta_pschroma[input_idx] = 2;
			v->source_scan[input_idx] = (pipe->plane_state->rotation % 2) ? dcn_bw_vert : dcn_bw_hor;
		}
		if (v->is_line_buffer_bpp_fixed == dcn_bw_yes)
			v->lb_bit_per_pixel[input_idx] = v->line_buffer_fixed_bpp;
		v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/
		v->output_format[input_idx] = pipe->stream->timing.pixel_encoding ==
				PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444;
		v->output[input_idx] = pipe->stream->signal ==
				SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp;
		v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc;
		if (v->output[input_idx] == dcn_bw_hdmi) {
			switch (pipe->stream->timing.display_color_depth) {
			case COLOR_DEPTH_101010:
				v->output_deep_color[input_idx] = dcn_bw_encoder_10bpc;
				break;
			case COLOR_DEPTH_121212:
				v->output_deep_color[input_idx]  = dcn_bw_encoder_12bpc;
				break;
			case COLOR_DEPTH_161616:
				v->output_deep_color[input_idx]  = dcn_bw_encoder_16bpc;
				break;
			default:
				break;
			}
		}

		input_idx++;
	}
	v->number_of_active_planes = input_idx;

	scaler_settings_calculation(v);

	hack_bounding_box(v, &dc->debug, context);

	mode_support_and_system_configuration(v);

	/* Unhack dppclk: dont bother with trying to pipe split if we cannot maintain dpm0 */
	if (v->voltage_level != 0
			&& context->stream_count == 1
			&& dc->debug.force_single_disp_pipe_split) {
		v->max_dppclk[0] = v->max_dppclk_vmin0p65;
		mode_support_and_system_configuration(v);
	}

	if (v->voltage_level == 0 &&
			(dc->debug.sr_exit_time_dpm0_ns
				|| dc->debug.sr_enter_plus_exit_time_dpm0_ns)) {

		if (dc->debug.sr_enter_plus_exit_time_dpm0_ns)
			v->sr_enter_plus_exit_time =
				dc->debug.sr_enter_plus_exit_time_dpm0_ns / 1000.0f;
		if (dc->debug.sr_exit_time_dpm0_ns)
			v->sr_exit_time =  dc->debug.sr_exit_time_dpm0_ns / 1000.0f;
		context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = v->sr_enter_plus_exit_time;
		context->bw_ctx.dml.soc.sr_exit_time_us = v->sr_exit_time;
		mode_support_and_system_configuration(v);
	}

	display_pipe_configuration(v);

	for (k = 0; k <= v->number_of_active_planes - 1; k++) {
		if (v->source_scan[k] == dcn_bw_hor)
			v->swath_width_y[k] = v->viewport_width[k] / v->dpp_per_plane[k];
		else
			v->swath_width_y[k] = v->viewport_height[k] / v->dpp_per_plane[k];
	}
	for (k = 0; k <= v->number_of_active_planes - 1; k++) {
		if (v->source_pixel_format[k] == dcn_bw_rgb_sub_64) {
			v->byte_per_pixel_dety[k] = 8.0;
			v->byte_per_pixel_detc[k] = 0.0;
		} else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_32) {
			v->byte_per_pixel_dety[k] = 4.0;
			v->byte_per_pixel_detc[k] = 0.0;
		} else if (v->source_pixel_format[k] == dcn_bw_rgb_sub_16) {
			v->byte_per_pixel_dety[k] = 2.0;
			v->byte_per_pixel_detc[k] = 0.0;
		} else if (v->source_pixel_format[k] == dcn_bw_yuv420_sub_8) {
			v->byte_per_pixel_dety[k] = 1.0;
			v->byte_per_pixel_detc[k] = 2.0;
		} else {
			v->byte_per_pixel_dety[k] = 4.0f / 3.0f;
			v->byte_per_pixel_detc[k] = 8.0f / 3.0f;
		}
	}

	v->total_data_read_bandwidth = 0.0;
	for (k = 0; k <= v->number_of_active_planes - 1; k++) {
		v->read_bandwidth_plane_luma[k] = v->swath_width_y[k] * v->dpp_per_plane[k] *
				dcn_bw_ceil2(v->byte_per_pixel_dety[k], 1.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k];
		v->read_bandwidth_plane_chroma[k] = v->swath_width_y[k] / 2.0 * v->dpp_per_plane[k] *
				dcn_bw_ceil2(v->byte_per_pixel_detc[k], 2.0) / (v->htotal[k] / v->pixel_clock[k]) * v->v_ratio[k] / 2.0;
		v->total_data_read_bandwidth = v->total_data_read_bandwidth +
				v->read_bandwidth_plane_luma[k] + v->read_bandwidth_plane_chroma[k];
	}

	BW_VAL_TRACE_END_VOLTAGE_LEVEL();

	if (v->voltage_level != number_of_states_plus_one && !fast_validate) {
		float bw_consumed = v->total_bandwidth_consumed_gbyte_per_second;

		if (bw_consumed < v->fabric_and_dram_bandwidth_vmin0p65)
			bw_consumed = v->fabric_and_dram_bandwidth_vmin0p65;
		else if (bw_consumed < v->fabric_and_dram_bandwidth_vmid0p72)
			bw_consumed = v->fabric_and_dram_bandwidth_vmid0p72;
		else if (bw_consumed < v->fabric_and_dram_bandwidth_vnom0p8)
			bw_consumed = v->fabric_and_dram_bandwidth_vnom0p8;
		else
			bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9;

		if (bw_consumed < v->fabric_and_dram_bandwidth)
			if (dc->debug.voltage_align_fclk)
				bw_consumed = v->fabric_and_dram_bandwidth;

		display_pipe_configuration(v);
		/*calc_wm_sets_and_perf_params(context, v);*/
		/* Only 1 set is used by dcn since no noticeable
		 * performance improvement was measured and due to hw bug DEGVIDCN10-254
		 */
		dispclkdppclkdcfclk_deep_sleep_prefetch_parameters_watermarks_and_performance_calculation(v);

		context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns =
			v->stutter_exit_watermark * 1000;
		context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
				v->stutter_enter_plus_exit_watermark * 1000;
		context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns =
				v->dram_clock_change_watermark * 1000;
		context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = v->ptemeta_urgent_watermark * 1000;
		context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = v->urgent_watermark * 1000;
		context->bw_ctx.bw.dcn.watermarks.b = context->bw_ctx.bw.dcn.watermarks.a;
		context->bw_ctx.bw.dcn.watermarks.c = context->bw_ctx.bw.dcn.watermarks.a;
		context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a;

		context->bw_ctx.bw.dcn.clk.fclk_khz = (int)(bw_consumed * 1000000 /
				(ddr4_dram_factor_single_Channel * v->number_of_channels));
		if (bw_consumed == v->fabric_and_dram_bandwidth_vmin0p65)
			context->bw_ctx.bw.dcn.clk.fclk_khz = (int)(bw_consumed * 1000000 / 32);

		context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000);
		context->bw_ctx.bw.dcn.clk.dcfclk_khz = (int)(v->dcfclk * 1000);

		context->bw_ctx.bw.dcn.clk.dispclk_khz = (int)(v->dispclk * 1000);
		if (dc->debug.max_disp_clk == true)
			context->bw_ctx.bw.dcn.clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000);

		if (context->bw_ctx.bw.dcn.clk.dispclk_khz <
				dc->debug.min_disp_clk_khz) {
			context->bw_ctx.bw.dcn.clk.dispclk_khz =
					dc->debug.min_disp_clk_khz;
		}

		context->bw_ctx.bw.dcn.clk.dppclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz /
				v->dispclk_dppclk_ratio;
		context->bw_ctx.bw.dcn.clk.phyclk_khz = v->phyclk_per_state[v->voltage_level];
		switch (v->voltage_level) {
		case 0:
			context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
					(int)(dc->dcn_soc->max_dppclk_vmin0p65 * 1000);
			break;
		case 1:
			context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
					(int)(dc->dcn_soc->max_dppclk_vmid0p72 * 1000);
			break;
		case 2:
			context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
					(int)(dc->dcn_soc->max_dppclk_vnom0p8 * 1000);
			break;
		default:
			context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
					(int)(dc->dcn_soc->max_dppclk_vmax0p9 * 1000);
			break;
		}

		BW_VAL_TRACE_END_WATERMARKS();

		for (i = 0, input_idx = 0; i < pool->pipe_count; i++) {
			struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];

			/* skip inactive pipe */
			if (!pipe->stream)
				continue;
			/* skip all but first of split pipes */
			if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state)
				continue;

			pipe->pipe_dlg_param.vupdate_width = v->v_update_width_pix[input_idx];
			pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset_pix[input_idx];
			pipe->pipe_dlg_param.vready_offset = v->v_ready_offset_pix[input_idx];
			pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx];

			pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total;
			pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total;
			vesa_sync_start = pipe->stream->timing.v_addressable +
						pipe->stream->timing.v_border_bottom +
						pipe->stream->timing.v_front_porch;

			asic_blank_end = (pipe->stream->timing.v_total -
						vesa_sync_start -
						pipe->stream->timing.v_border_top)
			* (pipe->stream->timing.flags.INTERLACE ? 1 : 0);

			asic_blank_start = asic_blank_end +
						(pipe->stream->timing.v_border_top +
						pipe->stream->timing.v_addressable +
						pipe->stream->timing.v_border_bottom)
			* (pipe->stream->timing.flags.INTERLACE ? 1 : 0);

			pipe->pipe_dlg_param.vblank_start = asic_blank_start;
			pipe->pipe_dlg_param.vblank_end = asic_blank_end;

			if (pipe->plane_state) {
				struct pipe_ctx *hsplit_pipe = pipe->bottom_pipe;

				pipe->plane_state->update_flags.bits.full_update = 1;

				if (v->dpp_per_plane[input_idx] == 2 ||
					((pipe->stream->view_format ==
					  VIEW_3D_FORMAT_SIDE_BY_SIDE ||
					  pipe->stream->view_format ==
					  VIEW_3D_FORMAT_TOP_AND_BOTTOM) &&
					(pipe->stream->timing.timing_3d_format ==
					 TIMING_3D_FORMAT_TOP_AND_BOTTOM ||
					 pipe->stream->timing.timing_3d_format ==
					 TIMING_3D_FORMAT_SIDE_BY_SIDE))) {
					if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
						/* update previously split pipe */
						hsplit_pipe->pipe_dlg_param.vupdate_width = v->v_update_width_pix[input_idx];
						hsplit_pipe->pipe_dlg_param.vupdate_offset = v->v_update_offset_pix[input_idx];
						hsplit_pipe->pipe_dlg_param.vready_offset = v->v_ready_offset_pix[input_idx];
						hsplit_pipe->pipe_dlg_param.vstartup_start = v->v_startup[input_idx];

						hsplit_pipe->pipe_dlg_param.htotal = pipe->stream->timing.h_total;
						hsplit_pipe->pipe_dlg_param.vtotal = pipe->stream->timing.v_total;
						hsplit_pipe->pipe_dlg_param.vblank_start = pipe->pipe_dlg_param.vblank_start;
						hsplit_pipe->pipe_dlg_param.vblank_end = pipe->pipe_dlg_param.vblank_end;
					} else {
						/* pipe not split previously needs split */
						hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, pool, pipe);
						ASSERT(hsplit_pipe);
						split_stream_across_pipes(&context->res_ctx, pool, pipe, hsplit_pipe);
					}

					dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe, input_idx);
				} else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) {
					/* merge previously split pipe */
					pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
					if (hsplit_pipe->bottom_pipe)
						hsplit_pipe->bottom_pipe->top_pipe = pipe;
					hsplit_pipe->plane_state = NULL;
					hsplit_pipe->stream = NULL;
					hsplit_pipe->top_pipe = NULL;
					hsplit_pipe->bottom_pipe = NULL;
					/* Clear plane_res and stream_res */
					memset(&hsplit_pipe->plane_res, 0, sizeof(hsplit_pipe->plane_res));
					memset(&hsplit_pipe->stream_res, 0, sizeof(hsplit_pipe->stream_res));
					resource_build_scaling_params(pipe);
				}
				/* for now important to do this after pipe split for building e2e params */
				dcn_bw_calc_rq_dlg_ttu(dc, v, pipe, input_idx);
			}

			input_idx++;
		}
	} else if (v->voltage_level == number_of_states_plus_one) {
		BW_VAL_TRACE_SKIP(fail);
	} else if (fast_validate) {
		BW_VAL_TRACE_SKIP(fast);
	}

	if (v->voltage_level == 0) {
		context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us =
				dc->dcn_soc->sr_enter_plus_exit_time;
		context->bw_ctx.dml.soc.sr_exit_time_us = dc->dcn_soc->sr_exit_time;
	}

	/*
	 * BW limit is set to prevent display from impacting other system functions
	 */

	bw_limit = dc->dcn_soc->percent_disp_bw_limit * v->fabric_and_dram_bandwidth_vmax0p9;
	bw_limit_pass = (v->total_data_read_bandwidth / 1000.0) < bw_limit;

	DC_FP_END();

	PERFORMANCE_TRACE_END();
	BW_VAL_TRACE_FINISH();

	if (bw_limit_pass && v->voltage_level <= get_highest_allowed_voltage_level(
							dc->ctx->asic_id.chip_family,
							dc->ctx->asic_id.hw_internal_rev,
							dc->ctx->asic_id.pci_revision_id))
		return true;
	else
		return false;
}