Signed-off-by: Harry Wentland <harry.wentland at amd.com>
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 5 files changed, 6317 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h

diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile 
b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
new file mode 100644
index 000000000000..7f1916b79b88
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'calcs' sub-component of DAL.
+# It calculates Bandwidth and Watermarks values for HW programming
+#
+
+BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o
+
+AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
+
+AMD_DAL_FILES += $(AMD_DAL_BW_CALCS)
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c 
b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
new file mode 100644
index 000000000000..8faabbc12fd3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
@@ -0,0 +1,3941 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "bandwidth_calcs.h"
+
+/*******************************************************************************
+ * Private Functions
+ 
******************************************************************************/
+
+static void calculate_bandwidth(
+       const struct bw_calcs_dceip *dceip,
+       const struct bw_calcs_vbios *vbios,
+       const struct bw_calcs_mode_data_internal *mode_data,
+       struct bw_calcs_results *results)
+
+{
+       const int32_t pixels_per_chunk = 512;
+       const int32_t max_chunks_non_fbc_mode = 16;
+       const int32_t high = 2;
+       const int32_t mid = 1;
+       const int32_t low = 0;
+
+       int32_t i, j, k;
+       struct bw_fixed yclk[3];
+       struct bw_fixed sclk[3];
+       bool d0_underlay_enable;
+       bool d1_underlay_enable;
+       enum bw_defines sclk_message;
+       enum bw_defines yclk_message;
+       enum bw_defines v_filter_init_mode[maximum_number_of_surfaces];
+       enum bw_defines tiling_mode[maximum_number_of_surfaces];
+       enum bw_defines stereo_mode[maximum_number_of_surfaces];
+       enum bw_defines surface_type[maximum_number_of_surfaces];
+       enum bw_defines voltage;
+       enum bw_defines pipe_check;
+       enum bw_defines hsr_check;
+       enum bw_defines vsr_check;
+       enum bw_defines lb_size_check;
+       enum bw_defines fbc_check;
+       enum bw_defines rotation_check;
+       enum bw_defines mode_check;
+
+       yclk[low] = vbios->low_yclk;
+       yclk[mid] = vbios->high_yclk;
+       yclk[high] = vbios->high_yclk;
+       sclk[low] = vbios->low_sclk;
+       sclk[mid] = vbios->mid_sclk;
+       sclk[high] = vbios->high_sclk;
+       /* surface assignment:*/
+       /* 0: d0 underlay or underlay luma*/
+       /* 1: d0 underlay chroma*/
+       /* 2: d1 underlay or underlay luma*/
+       /* 3: d1 underlay chroma*/
+       /* 4: d0 graphics*/
+       /* 5: d1 graphics*/
+       /* 6: d2 graphics*/
+       /* 7: d3 graphics, same mode as d2*/
+       /* 8: d4 graphics, same mode as d2*/
+       /* 9: d5 graphics, same mode as d2*/
+       /* ...*/
+       /* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/
+       /* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/
+       /* underlay luma and chroma surface parameters from spreadsheet*/
+       if (mode_data->d0_underlay_mode == bw_def_none) {
+               d0_underlay_enable = 0;
+       } else {
+               d0_underlay_enable = 1;
+       }
+       if (mode_data->d1_underlay_mode == bw_def_none) {
+               d1_underlay_enable = 0;
+       } else {
+               d1_underlay_enable = 1;
+       }
+       results->number_of_underlay_surfaces = d0_underlay_enable
+               + d1_underlay_enable;
+       switch (mode_data->underlay_surface_type) {
+       case bw_def_420:
+               surface_type[0] = bw_def_underlay420_luma;
+               surface_type[2] = bw_def_underlay420_luma;
+               results->bytes_per_pixel[0] = 1;
+               results->bytes_per_pixel[2] = 1;
+               surface_type[1] = bw_def_underlay420_chroma;
+               surface_type[3] = bw_def_underlay420_chroma;
+               results->bytes_per_pixel[1] = 2;
+               results->bytes_per_pixel[3] = 2;
+               results->lb_size_per_component[0] =
+                       dceip->underlay420_luma_lb_size_per_component;
+               results->lb_size_per_component[1] =
+                       dceip->underlay420_chroma_lb_size_per_component;
+               results->lb_size_per_component[2] =
+                       dceip->underlay420_luma_lb_size_per_component;
+               results->lb_size_per_component[3] =
+                       dceip->underlay420_chroma_lb_size_per_component;
+               break;
+       case bw_def_422:
+               surface_type[0] = bw_def_underlay422;
+               surface_type[2] = bw_def_underlay422;
+               results->bytes_per_pixel[0] = 2;
+               results->bytes_per_pixel[2] = 2;
+               results->lb_size_per_component[0] =
+                       dceip->underlay422_lb_size_per_component;
+               results->lb_size_per_component[2] =
+                       dceip->underlay422_lb_size_per_component;
+               break;
+       default:
+               surface_type[0] = bw_def_underlay444;
+               surface_type[2] = bw_def_underlay444;
+               results->bytes_per_pixel[0] = 4;
+               results->bytes_per_pixel[2] = 4;
+               results->lb_size_per_component[0] =
+                       dceip->lb_size_per_component444;
+               results->lb_size_per_component[2] =
+                       dceip->lb_size_per_component444;
+               break;
+       }
+       if (d0_underlay_enable) {
+               switch (mode_data->underlay_surface_type) {
+               case bw_def_420:
+                       results->enable[0] = 1;
+                       results->enable[1] = 1;
+                       break;
+               default:
+                       results->enable[0] = 1;
+                       results->enable[1] = 0;
+                       break;
+               }
+       } else {
+               results->enable[0] = 0;
+               results->enable[1] = 0;
+       }
+       if (d1_underlay_enable) {
+               switch (mode_data->underlay_surface_type) {
+               case bw_def_420:
+                       results->enable[2] = 1;
+                       results->enable[3] = 1;
+                       break;
+               default:
+                       results->enable[2] = 1;
+                       results->enable[3] = 0;
+                       break;
+               }
+       } else {
+               results->enable[2] = 0;
+               results->enable[3] = 0;
+       }
+       results->use_alpha[0] = 0;
+       results->use_alpha[1] = 0;
+       results->use_alpha[2] = 0;
+       results->use_alpha[3] = 0;
+       results->scatter_gather_enable_for_pipe[0] =
+               vbios->scatter_gather_enable;
+       results->scatter_gather_enable_for_pipe[1] =
+               vbios->scatter_gather_enable;
+       results->scatter_gather_enable_for_pipe[2] =
+               vbios->scatter_gather_enable;
+       results->scatter_gather_enable_for_pipe[3] =
+               vbios->scatter_gather_enable;
+       results->interlace_mode[0] = mode_data->graphics_interlace_mode;
+       results->interlace_mode[1] = mode_data->graphics_interlace_mode;
+       results->interlace_mode[2] = mode_data->graphics_interlace_mode;
+       results->interlace_mode[3] = mode_data->graphics_interlace_mode;
+       results->h_total[0] = bw_int_to_fixed(mode_data->d0_htotal);
+       results->h_total[1] = bw_int_to_fixed(mode_data->d0_htotal);
+       results->h_total[2] = bw_int_to_fixed(mode_data->d1_htotal);
+       results->h_total[3] = bw_int_to_fixed(mode_data->d1_htotal);
+       results->pixel_rate[0] = mode_data->d0_pixel_rate;
+       results->pixel_rate[1] = mode_data->d0_pixel_rate;
+       results->pixel_rate[2] = mode_data->d1_pixel_rate;
+       results->pixel_rate[3] = mode_data->d1_pixel_rate;
+       results->src_width[0] = bw_int_to_fixed(mode_data->underlay_src_width);
+       results->src_width[1] = bw_int_to_fixed(mode_data->underlay_src_width);
+       results->src_width[2] = bw_int_to_fixed(mode_data->underlay_src_width);
+       results->src_width[3] = bw_int_to_fixed(mode_data->underlay_src_width);
+       results->src_height[0] = bw_int_to_fixed(
+               mode_data->underlay_src_height);
+       results->src_height[1] = bw_int_to_fixed(
+               mode_data->underlay_src_height);
+       results->src_height[2] = bw_int_to_fixed(
+               mode_data->underlay_src_height);
+       results->src_height[3] = bw_int_to_fixed(
+               mode_data->underlay_src_height);
+       results->pitch_in_pixels[0] = bw_int_to_fixed(
+               mode_data->underlay_pitch_in_pixels);
+       results->pitch_in_pixels[1] = bw_int_to_fixed(
+               mode_data->underlay_pitch_in_pixels);
+       results->pitch_in_pixels[2] = bw_int_to_fixed(
+               mode_data->underlay_pitch_in_pixels);
+       results->pitch_in_pixels[3] = bw_int_to_fixed(
+               mode_data->underlay_pitch_in_pixels);
+       results->scale_ratio[0] = mode_data->d0_underlay_scale_ratio;
+       results->scale_ratio[1] = mode_data->d0_underlay_scale_ratio;
+       results->scale_ratio[2] = mode_data->d1_underlay_scale_ratio;
+       results->scale_ratio[3] = mode_data->d1_underlay_scale_ratio;
+       results->h_taps[0] = bw_int_to_fixed(mode_data->underlay_htaps);
+       results->h_taps[1] = bw_int_to_fixed(mode_data->underlay_htaps);
+       results->h_taps[2] = bw_int_to_fixed(mode_data->underlay_htaps);
+       results->h_taps[3] = bw_int_to_fixed(mode_data->underlay_htaps);
+       results->v_taps[0] = bw_int_to_fixed(mode_data->underlay_vtaps);
+       results->v_taps[1] = bw_int_to_fixed(mode_data->underlay_vtaps);
+       results->v_taps[2] = bw_int_to_fixed(mode_data->underlay_vtaps);
+       results->v_taps[3] = bw_int_to_fixed(mode_data->underlay_vtaps);
+       results->rotation_angle[0] = bw_int_to_fixed(
+               mode_data->underlay_rotation_angle);
+       results->rotation_angle[1] = bw_int_to_fixed(
+               mode_data->underlay_rotation_angle);
+       results->rotation_angle[2] = bw_int_to_fixed(
+               mode_data->underlay_rotation_angle);
+       results->rotation_angle[3] = bw_int_to_fixed(
+               mode_data->underlay_rotation_angle);
+       if (mode_data->underlay_tiling_mode == bw_def_linear) {
+               tiling_mode[0] = bw_def_linear;
+               tiling_mode[1] = bw_def_linear;
+               tiling_mode[2] = bw_def_linear;
+               tiling_mode[3] = bw_def_linear;
+       } else {
+               tiling_mode[0] = bw_def_landscape;
+               tiling_mode[1] = bw_def_landscape;
+               tiling_mode[2] = bw_def_landscape;
+               tiling_mode[3] = bw_def_landscape;
+       }
+       stereo_mode[0] = mode_data->underlay_stereo_mode;
+       stereo_mode[1] = mode_data->underlay_stereo_mode;
+       stereo_mode[2] = mode_data->underlay_stereo_mode;
+       stereo_mode[3] = mode_data->underlay_stereo_mode;
+       results->lb_bpc[0] = mode_data->underlay_lb_bpc;
+       results->lb_bpc[1] = mode_data->underlay_lb_bpc;
+       results->lb_bpc[2] = mode_data->underlay_lb_bpc;
+       results->lb_bpc[3] = mode_data->underlay_lb_bpc;
+       results->compression_rate[0] = bw_int_to_fixed(1);
+       results->compression_rate[1] = bw_int_to_fixed(1);
+       results->compression_rate[2] = bw_int_to_fixed(1);
+       results->compression_rate[3] = bw_int_to_fixed(1);
+       results->access_one_channel_only[0] = 0;
+       results->access_one_channel_only[1] = 0;
+       results->access_one_channel_only[2] = 0;
+       results->access_one_channel_only[3] = 0;
+       results->cursor_width_pixels[0] = bw_int_to_fixed(0);
+       results->cursor_width_pixels[1] = bw_int_to_fixed(0);
+       results->cursor_width_pixels[2] = bw_int_to_fixed(0);
+       results->cursor_width_pixels[3] = bw_int_to_fixed(0);
+       /* graphics surface parameters from spreadsheet*/
+       for (i = 4; i <= maximum_number_of_surfaces - 3; i++) {
+               if (i < mode_data->number_of_displays + 4) {
+                       if (i == 4
+                               && mode_data->d0_underlay_mode
+                                       == bw_def_underlay_only) {
+                               results->enable[i] = 0;
+                               results->use_alpha[i] = 0;
+                       } else if (i == 4
+                               && mode_data->d0_underlay_mode
+                                       == bw_def_blend) {
+                               results->enable[i] = 1;
+                               results->use_alpha[i] = 1;
+                       } else if (i == 4) {
+                               results->enable[i] = 1;
+                               results->use_alpha[i] = 0;
+                       } else if (i == 5
+                               && mode_data->d1_underlay_mode
+                                       == bw_def_underlay_only) {
+                               results->enable[i] = 0;
+                               results->use_alpha[i] = 0;
+                       } else if (i == 5
+                               && mode_data->d1_underlay_mode
+                                       == bw_def_blend) {
+                               results->enable[i] = 1;
+                               results->use_alpha[i] = 1;
+                       } else {
+                               results->enable[i] = 1;
+                               results->use_alpha[i] = 0;
+                       }
+               } else {
+                       results->enable[i] = 0;
+                       results->use_alpha[i] = 0;
+               }
+               results->scatter_gather_enable_for_pipe[i] =
+                       vbios->scatter_gather_enable;
+               surface_type[i] = bw_def_graphics;
+               results->lb_size_per_component[i] =
+                       dceip->lb_size_per_component444;
+               results->bytes_per_pixel[i] =
+                       mode_data->graphics_bytes_per_pixel;
+               results->interlace_mode[i] = mode_data->graphics_interlace_mode;
+               results->h_taps[i] = bw_int_to_fixed(mode_data->graphics_htaps);
+               results->v_taps[i] = bw_int_to_fixed(mode_data->graphics_vtaps);
+               results->rotation_angle[i] = bw_int_to_fixed(
+                       mode_data->graphics_rotation_angle);
+               if (mode_data->graphics_tiling_mode == bw_def_linear) {
+                       tiling_mode[i] = bw_def_linear;
+               } else if (mode_data->graphics_rotation_angle == 0
+                       || mode_data->graphics_rotation_angle == 180) {
+                       tiling_mode[i] = bw_def_landscape;
+               } else {
+                       tiling_mode[i] = bw_def_portrait;
+               }
+               results->lb_bpc[i] = mode_data->graphics_lb_bpc;
+               if (i == 4) {
+                       if (mode_data->d0_fbc_enable
+                               && (dceip->argb_compression_support
+                                       || mode_data->d0_underlay_mode
+                                               != bw_def_blended)) {
+                               results->compression_rate[i] = bw_int_to_fixed(
+                                       vbios->average_compression_rate);
+                               results->access_one_channel_only[i] =
+                                       mode_data->d0_lpt_enable;
+                       } else {
+                               results->compression_rate[i] = bw_int_to_fixed(
+                                       1);
+                               results->access_one_channel_only[i] = 0;
+                       }
+                       results->h_total[i] = bw_int_to_fixed(
+                               mode_data->d0_htotal);
+                       results->pixel_rate[i] = mode_data->d0_pixel_rate;
+                       results->src_width[i] = bw_int_to_fixed(
+                               mode_data->d0_graphics_src_width);
+                       results->src_height[i] = bw_int_to_fixed(
+                               mode_data->d0_graphics_src_height);
+                       results->pitch_in_pixels[i] = bw_int_to_fixed(
+                               mode_data->d0_graphics_src_width);
+                       results->scale_ratio[i] =
+                               mode_data->d0_graphics_scale_ratio;
+                       stereo_mode[i] = mode_data->d0_graphics_stereo_mode;
+               } else if (i == 5) {
+                       results->compression_rate[i] = bw_int_to_fixed(1);
+                       results->access_one_channel_only[i] = 0;
+                       results->h_total[i] = bw_int_to_fixed(
+                               mode_data->d1_htotal);
+                       results->pixel_rate[i] = mode_data->d1_pixel_rate;
+                       results->src_width[i] = bw_int_to_fixed(
+                               mode_data->d1_graphics_src_width);
+                       results->src_height[i] = bw_int_to_fixed(
+                               mode_data->d1_graphics_src_height);
+                       results->pitch_in_pixels[i] = bw_int_to_fixed(
+                               mode_data->d1_graphics_src_width);
+                       results->scale_ratio[i] =
+                               mode_data->d1_graphics_scale_ratio;
+                       stereo_mode[i] = mode_data->d1_graphics_stereo_mode;
+               } else {
+                       results->compression_rate[i] = bw_int_to_fixed(1);
+                       results->access_one_channel_only[i] = 0;
+                       results->h_total[i] = bw_int_to_fixed(
+                               mode_data->d2_htotal);
+                       results->pixel_rate[i] = mode_data->d2_pixel_rate;
+                       results->src_width[i] = bw_int_to_fixed(
+                               mode_data->d2_graphics_src_width);
+                       results->src_height[i] = bw_int_to_fixed(
+                               mode_data->d2_graphics_src_height);
+                       results->pitch_in_pixels[i] = bw_int_to_fixed(
+                               mode_data->d2_graphics_src_width);
+                       results->scale_ratio[i] =
+                               mode_data->d2_graphics_scale_ratio;
+                       stereo_mode[i] = mode_data->d2_graphics_stereo_mode;
+               }
+               results->cursor_width_pixels[i] = bw_int_to_fixed(
+                       vbios->cursor_width);
+       }
+       /* display_write_back420*/
+       results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] 
=
+               0;
+       results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] 
=
+               0;
+       if (mode_data->d1_display_write_back_dwb_enable == 1) {
+               results->enable[maximum_number_of_surfaces - 2] = 1;
+               results->enable[maximum_number_of_surfaces - 1] = 1;
+       } else {
+               results->enable[maximum_number_of_surfaces - 2] = 0;
+               results->enable[maximum_number_of_surfaces - 1] = 0;
+       }
+       surface_type[maximum_number_of_surfaces - 2] =
+               bw_def_display_write_back420_luma;
+       surface_type[maximum_number_of_surfaces - 1] =
+               bw_def_display_write_back420_chroma;
+       results->lb_size_per_component[maximum_number_of_surfaces - 2] =
+               dceip->underlay420_luma_lb_size_per_component;
+       results->lb_size_per_component[maximum_number_of_surfaces - 1] =
+               dceip->underlay420_chroma_lb_size_per_component;
+       results->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1;
+       results->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2;
+       results->interlace_mode[maximum_number_of_surfaces - 2] =
+               mode_data->graphics_interlace_mode;
+       results->interlace_mode[maximum_number_of_surfaces - 1] =
+               mode_data->graphics_interlace_mode;
+       results->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+       results->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+       results->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+       results->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+       results->rotation_angle[maximum_number_of_surfaces - 2] =
+               bw_int_to_fixed(0);
+       results->rotation_angle[maximum_number_of_surfaces - 1] =
+               bw_int_to_fixed(0);
+       tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear;
+       tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear;
+       results->lb_bpc[maximum_number_of_surfaces - 2] = 8;
+       results->lb_bpc[maximum_number_of_surfaces - 1] = 8;
+       results->compression_rate[maximum_number_of_surfaces - 2] =
+               bw_int_to_fixed(1);
+       results->compression_rate[maximum_number_of_surfaces - 1] =
+               bw_int_to_fixed(1);
+       results->access_one_channel_only[maximum_number_of_surfaces - 2] = 0;
+       results->access_one_channel_only[maximum_number_of_surfaces - 1] = 0;
+       results->h_total[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+               mode_data->d1_htotal);
+       results->h_total[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+               mode_data->d1_htotal);
+       results->pixel_rate[maximum_number_of_surfaces - 2] =
+               mode_data->d1_pixel_rate;
+       results->pixel_rate[maximum_number_of_surfaces - 1] =
+               mode_data->d1_pixel_rate;
+       results->src_width[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+               mode_data->d1_graphics_src_width);
+       results->src_width[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+               mode_data->d1_graphics_src_width);
+       results->src_height[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+               mode_data->d1_graphics_src_height);
+       results->src_height[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+               mode_data->d1_graphics_src_height);
+       results->pitch_in_pixels[maximum_number_of_surfaces - 2] =
+               bw_int_to_fixed(mode_data->d1_graphics_src_width);
+       results->pitch_in_pixels[maximum_number_of_surfaces - 1] =
+               bw_int_to_fixed(mode_data->d1_graphics_src_width);
+       results->scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+               1);
+       results->scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+               1);
+       stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono;
+       stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono;
+       results->cursor_width_pixels[maximum_number_of_surfaces - 2] =
+               bw_int_to_fixed(0);
+       results->cursor_width_pixels[maximum_number_of_surfaces - 1] =
+               bw_int_to_fixed(0);
+       results->use_alpha[maximum_number_of_surfaces - 2] = 0;
+       results->use_alpha[maximum_number_of_surfaces - 1] = 0;
+       /*mode check calculations:*/
+       /* mode within dce ip capabilities*/
+       /* fbc*/
+       /* hsr*/
+       /* vsr*/
+       /* lb size*/
+       /*effective scaling source and ratios:*/
+       /*for graphics, non-stereo, non-interlace surfaces when the size of the 
source and destination are the same, only one tap is used*/
+       /*420 chroma has half the width, height, horizontal and vertical 
scaling ratios than luma*/
+       /*rotating an underlay surface swaps the width, height, horizontal and 
vertical scaling ratios*/
+       /*in top-bottom stereo mode there is 2:1 vertical downscaling for each 
eye*/
+       /*in side-by-side stereo mode there is 2:1 horizontal downscaling for 
each eye*/
+       /*in interlace mode there is 2:1 vertical downscaling for each field*/
+       /*in panning or bezel adjustment mode the source width has an extra 128 
pixels*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_equ(results->scale_ratio[i], bw_int_to_fixed(1))
+                               && surface_type[i] == bw_def_graphics
+                               && stereo_mode[i] == bw_def_mono
+                               && results->interlace_mode[i] == 0) {
+                               results->h_taps[i] = bw_int_to_fixed(1);
+                               results->v_taps[i] = bw_int_to_fixed(1);
+                       }
+                       if (surface_type[i]
+                               == bw_def_display_write_back420_chroma
+                               || surface_type[i]
+                                       == bw_def_underlay420_chroma) {
+                               results->pitch_in_pixels_after_surface_type[i] =
+                                       bw_div(
+                                               results->pitch_in_pixels[i],
+                                               bw_int_to_fixed(2));
+                               results->src_width_after_surface_type = bw_div(
+                                       results->src_width[i],
+                                       bw_int_to_fixed(2));
+                               results->src_height_after_surface_type = bw_div(
+                                       results->src_height[i],
+                                       bw_int_to_fixed(2));
+                               results->hsr_after_surface_type = bw_div(
+                                       results->scale_ratio[i],
+                                       bw_int_to_fixed(2));
+                               results->vsr_after_surface_type = bw_div(
+                                       results->scale_ratio[i],
+                                       bw_int_to_fixed(2));
+                       } else {
+                               results->pitch_in_pixels_after_surface_type[i] =
+                                       results->pitch_in_pixels[i];
+                               results->src_width_after_surface_type =
+                                       results->src_width[i];
+                               results->src_height_after_surface_type =
+                                       results->src_height[i];
+                               results->hsr_after_surface_type =
+                                       results->scale_ratio[i];
+                               results->vsr_after_surface_type =
+                                       results->scale_ratio[i];
+                       }
+                       if ((bw_equ(
+                               results->rotation_angle[i],
+                               bw_int_to_fixed(90))
+                               || bw_equ(
+                                       results->rotation_angle[i],
+                                       bw_int_to_fixed(270)))
+                               && surface_type[i] != bw_def_graphics) {
+                               results->src_width_after_rotation =
+                                       results->src_height_after_surface_type;
+                               results->src_height_after_rotation =
+                                       results->src_width_after_surface_type;
+                               results->hsr_after_rotation =
+                                       results->vsr_after_surface_type;
+                               results->vsr_after_rotation =
+                                       results->hsr_after_surface_type;
+                       } else {
+                               results->src_width_after_rotation =
+                                       results->src_width_after_surface_type;
+                               results->src_height_after_rotation =
+                                       results->src_height_after_surface_type;
+                               results->hsr_after_rotation =
+                                       results->hsr_after_surface_type;
+                               results->vsr_after_rotation =
+                                       results->vsr_after_surface_type;
+                       }
+                       switch (stereo_mode[i]) {
+                       case bw_def_top_bottom:
+                               results->source_width_pixels[i] =
+                                       results->src_width_after_rotation;
+                               results->source_height_pixels = bw_mul(
+                                       bw_int_to_fixed(2),
+                                       results->src_height_after_rotation);
+                               results->hsr_after_stereo =
+                                       results->hsr_after_rotation;
+                               results->vsr_after_stereo = bw_mul(
+                                       bw_int_to_fixed(1),
+                                       results->vsr_after_rotation);
+                               break;
+                       case bw_def_side_by_side:
+                               results->source_width_pixels[i] = bw_mul(
+                                       bw_int_to_fixed(2),
+                                       results->src_width_after_rotation);
+                               results->source_height_pixels =
+                                       results->src_height_after_rotation;
+                               results->hsr_after_stereo = bw_mul(
+                                       bw_int_to_fixed(1),
+                                       results->hsr_after_rotation);
+                               results->vsr_after_stereo =
+                                       results->vsr_after_rotation;
+                               break;
+                       default:
+                               results->source_width_pixels[i] =
+                                       results->src_width_after_rotation;
+                               results->source_height_pixels =
+                                       results->src_height_after_rotation;
+                               results->hsr_after_stereo =
+                                       results->hsr_after_rotation;
+                               results->vsr_after_stereo =
+                                       results->vsr_after_rotation;
+                               break;
+                       }
+                       results->hsr[i] = results->hsr_after_stereo;
+                       if (results->interlace_mode[i]) {
+                               results->vsr[i] = bw_mul(
+                                       results->vsr_after_stereo,
+                                       bw_int_to_fixed(2));
+                       } else {
+                               results->vsr[i] = results->vsr_after_stereo;
+                       }
+                       if (mode_data->panning_and_bezel_adjustment
+                               != bw_def_none) {
+                               results->source_width_rounded_up_to_chunks[i] =
+                                       bw_add(
+                                               bw_floor2(
+                                                       bw_sub(
+                                                               
results->source_width_pixels[i],
+                                                               bw_int_to_fixed(
+                                                                       1)),
+                                                       bw_int_to_fixed(128)),
+                                               bw_int_to_fixed(256));
+                       } else {
+                               results->source_width_rounded_up_to_chunks[i] =
+                                       bw_ceil2(
+                                               results->source_width_pixels[i],
+                                               bw_int_to_fixed(128));
+                       }
+                       results->source_height_rounded_up_to_chunks[i] =
+                               results->source_height_pixels;
+               }
+       }
+       /*mode support checks:*/
+       /*the number of graphics and underlay pipes is limited by the ip 
support*/
+       /*maximum horizontal and vertical scale ratio is 4, and should not 
exceed the number of taps*/
+       /*for downscaling with the pre-downscaler, the horizontal scale ratio 
must be more than the ceiling of one quarter of the number of taps*/
+       /*the pre-downscaler reduces the line buffer source by the horizontal 
scale ratio*/
+       /*the number of lines in the line buffer has to exceed the number of 
vertical taps*/
+       /*the size of the line in the line buffer is the product of the source 
width and the bits per component, rounded up to a multiple of 48*/
+       /*the size of the line in the line buffer in the case of 10 bit per 
component is the product of the source width rounded up to multiple of 8 and 
30.023438 / 3, rounded up to a multiple of 48*/
+       /*the size of the line in the line buffer in the case of 8 bit per 
component is the product of the source width rounded up to multiple of 8 and 
30.023438 / 3, rounded up to a multiple of 48*/
+       /*frame buffer compression is not supported with stereo mode, rotation, 
or non- 888 formats*/
+       /*rotation is not supported with linear of stereo modes*/
+       if (dceip->number_of_graphics_pipes >= mode_data->number_of_displays
+               && dceip->number_of_underlay_pipes
+                       >= results->number_of_underlay_surfaces
+               && !(dceip->display_write_back_supported == 0
+                       && mode_data->d1_display_write_back_dwb_enable == 1)) {
+               pipe_check = bw_def_ok;
+       } else {
+               pipe_check = bw_def_notok;
+       }
+       hsr_check = bw_def_ok;
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_neq(results->hsr[i], bw_int_to_fixed(1))) {
+                               if (bw_mtn(
+                                       results->hsr[i],
+                                       bw_int_to_fixed(4))) {
+                                       hsr_check = bw_def_hsr_mtn_4;
+                               } else {
+                                       if (bw_mtn(
+                                               results->hsr[i],
+                                               results->h_taps[i])) {
+                                               hsr_check =
+                                                       bw_def_hsr_mtn_h_taps;
+                                       } else {
+                                               if 
(dceip->pre_downscaler_enabled
+                                                       == 1
+                                                       && bw_mtn(
+                                                               results->hsr[i],
+                                                               bw_int_to_fixed(
+                                                                       1))
+                                                       && bw_leq(
+                                                               results->hsr[i],
+                                                               bw_ceil2(
+                                                                       bw_div(
+                                                                               
results->h_taps[i],
+                                                                               
bw_int_to_fixed(
+                                                                               
        4)),
+                                                                       
bw_int_to_fixed(
+                                                                               
1)))) {
+                                                       hsr_check =
+                                                               
bw_def_ceiling__h_taps_div_4___meq_hsr;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       vsr_check = bw_def_ok;
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_neq(results->vsr[i], bw_int_to_fixed(1))) {
+                               if (bw_mtn(
+                                       results->vsr[i],
+                                       bw_int_to_fixed(4))) {
+                                       vsr_check = bw_def_vsr_mtn_4;
+                               } else {
+                                       if (bw_mtn(
+                                               results->vsr[i],
+                                               results->v_taps[i])) {
+                                               vsr_check =
+                                                       bw_def_vsr_mtn_v_taps;
+                                       }
+                               }
+                       }
+               }
+       }
+       lb_size_check = bw_def_ok;
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if ((dceip->pre_downscaler_enabled
+                               && bw_mtn(results->hsr[i], 
bw_int_to_fixed(1)))) {
+                               results->source_width_in_lb = bw_div(
+                                       results->source_width_pixels[i],
+                                       results->hsr[i]);
+                       } else {
+                               results->source_width_in_lb =
+                                       results->source_width_pixels[i];
+                       }
+                       switch (results->lb_bpc[i]) {
+                       case 8:
+                               results->lb_line_pitch =
+                                       bw_ceil2(
+                                               bw_mul(
+                                                       bw_div(
+                                                               bw_frc_to_fixed(
+                                                                       
2401171875ULL,
+                                                                       
100000000),
+                                                               bw_int_to_fixed(
+                                                                       3)),
+                                                       bw_ceil2(
+                                                               
results->source_width_in_lb,
+                                                               bw_int_to_fixed(
+                                                                       8))),
+                                               bw_int_to_fixed(48));
+                               break;
+                       case 10:
+                               results->lb_line_pitch =
+                                       bw_ceil2(
+                                               bw_mul(
+                                                       bw_div(
+                                                               bw_frc_to_fixed(
+                                                                       
300234375,
+                                                                       
10000000),
+                                                               bw_int_to_fixed(
+                                                                       3)),
+                                                       bw_ceil2(
+                                                               
results->source_width_in_lb,
+                                                               bw_int_to_fixed(
+                                                                       8))),
+                                               bw_int_to_fixed(48));
+                               break;
+                       default:
+                               results->lb_line_pitch = bw_ceil2(
+                                       bw_mul(
+                                               bw_int_to_fixed(
+                                                       results->lb_bpc[i]),
+                                               results->source_width_in_lb),
+                                       bw_int_to_fixed(48));
+                               break;
+                       }
+                       results->lb_partitions[i] = bw_floor2(
+                               bw_div(
+                                       results->lb_size_per_component[i],
+                                       results->lb_line_pitch),
+                               bw_int_to_fixed(1));
+                       /*clamp the partitions to the maxium number supported 
by the lb*/
+                       if ((surface_type[i] != bw_def_graphics
+                               || 
dceip->graphics_lb_nodownscaling_multi_line_prefetching
+                                       == 1)) {
+                               results->lb_partitions_max[i] = bw_int_to_fixed(
+                                       10);
+                       } else {
+                               results->lb_partitions_max[i] = bw_int_to_fixed(
+                                       7);
+                       }
+                       results->lb_partitions[i] = bw_min2(
+                               results->lb_partitions_max[i],
+                               results->lb_partitions[i]);
+                       if (bw_mtn(
+                               bw_add(results->v_taps[i], bw_int_to_fixed(1)),
+                               results->lb_partitions[i])) {
+                               lb_size_check = bw_def_notok;
+                       }
+               }
+       }
+       if (mode_data->d0_fbc_enable
+               && (mode_data->graphics_rotation_angle == 90
+                       || mode_data->graphics_rotation_angle == 270
+                       || mode_data->d0_graphics_stereo_mode != bw_def_mono
+                       || mode_data->graphics_bytes_per_pixel != 4)) {
+               fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo;
+       } else {
+               fbc_check = bw_def_ok;
+       }
+       rotation_check = bw_def_ok;
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if ((bw_equ(
+                               results->rotation_angle[i],
+                               bw_int_to_fixed(90))
+                               || bw_equ(
+                                       results->rotation_angle[i],
+                                       bw_int_to_fixed(270)))
+                               && (tiling_mode[i] == bw_def_linear
+                                       || stereo_mode[i] != bw_def_mono)) {
+                               rotation_check =
+                                       bw_def_invalid_linear_or_stereo_mode;
+                       }
+               }
+       }
+       if (pipe_check == bw_def_ok && hsr_check == bw_def_ok
+               && vsr_check == bw_def_ok && lb_size_check == bw_def_ok
+               && fbc_check == bw_def_ok && rotation_check == bw_def_ok) {
+               mode_check = bw_def_ok;
+       } else {
+               mode_check = bw_def_notok;
+       }
+       /*memory request size and latency hiding:*/
+       /*request size is normally 64 byte, 2-line interleaved, with full 
latency hiding*/
+       /*the display write-back requests are single line*/
+       /*for tiled graphics surfaces, or undelay surfaces with width higher 
than the maximum size for full efficiency, request size is 32 byte in 8 and 16 
bpp or if the rotation is orthogonal to the tiling grain. only half is useful 
of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is 
orthogonal to the tiling grain.*/
+       /*for undelay surfaces with width lower than the maximum size for full 
efficiency, requests are 4-line interleaved in 16bpp if the rotation is 
parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding 
in 8bpp or if the rotation is orthogonal to the tiling grain.*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if ((bw_equ(
+                               results->rotation_angle[i],
+                               bw_int_to_fixed(90))
+                               || bw_equ(
+                                       results->rotation_angle[i],
+                                       bw_int_to_fixed(270)))) {
+                               if ((tiling_mode[i] == bw_def_portrait)) {
+                                       results->orthogonal_rotation[i] = 0;
+                               } else {
+                                       results->orthogonal_rotation[i] = 1;
+                               }
+                       } else {
+                               if ((tiling_mode[i] == bw_def_portrait)) {
+                                       results->orthogonal_rotation[i] = 1;
+                               } else {
+                                       results->orthogonal_rotation[i] = 0;
+                               }
+                       }
+                       if (bw_equ(
+                               results->rotation_angle[i],
+                               bw_int_to_fixed(90))
+                               || bw_equ(
+                                       results->rotation_angle[i],
+                                       bw_int_to_fixed(270))) {
+                               
results->underlay_maximum_source_efficient_for_tiling =
+                                       
dceip->underlay_maximum_height_efficient_for_tiling;
+                       } else {
+                               
results->underlay_maximum_source_efficient_for_tiling =
+                                       
dceip->underlay_maximum_width_efficient_for_tiling;
+                       }
+                       if (bw_equ(
+                               dceip->de_tiling_buffer,
+                               bw_int_to_fixed(0))) {
+                               if (surface_type[i]
+                                       == bw_def_display_write_back420_luma
+                                       || surface_type[i]
+                                               == 
bw_def_display_write_back420_chroma) {
+                                       results->bytes_per_request[i] =
+                                               bw_int_to_fixed(64);
+                                       results->useful_bytes_per_request[i] =
+                                               bw_int_to_fixed(64);
+                                       
results->lines_interleaved_in_mem_access[i] =
+                                               bw_int_to_fixed(1);
+                                       results->latency_hiding_lines[i] =
+                                               bw_int_to_fixed(1);
+                               } else if (tiling_mode[i] == bw_def_linear) {
+                                       results->bytes_per_request[i] =
+                                               bw_int_to_fixed(64);
+                                       results->useful_bytes_per_request[i] =
+                                               bw_int_to_fixed(64);
+                                       
results->lines_interleaved_in_mem_access[i] =
+                                               bw_int_to_fixed(2);
+                                       results->latency_hiding_lines[i] =
+                                               bw_int_to_fixed(2);
+                               } else {
+                                       if (surface_type[i] == bw_def_graphics
+                                               || (bw_mtn(
+                                                       
results->source_width_rounded_up_to_chunks[i],
+                                                       bw_ceil2(
+                                                               
results->underlay_maximum_source_efficient_for_tiling,
+                                                               bw_int_to_fixed(
+                                                                       
256))))) {
+                                               switch 
(results->bytes_per_pixel[i]) {
+                                               case 8:
+                                                       
results->lines_interleaved_in_mem_access[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       
results->latency_hiding_lines[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       if 
(results->orthogonal_rotation[i]) {
+                                                               
results->bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
32);
+                                                               
results->useful_bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
32);
+                                                       } else {
+                                                               
results->bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
64);
+                                                               
results->useful_bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
64);
+                                                       }
+                                                       break;
+                                               case 4:
+                                                       if 
(results->orthogonal_rotation[i]) {
+                                                               
results->lines_interleaved_in_mem_access[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               
results->latency_hiding_lines[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               
results->bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
32);
+                                                               
results->useful_bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
16);
+                                                       } else {
+                                                               
results->lines_interleaved_in_mem_access[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               
results->latency_hiding_lines[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               
results->bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
64);
+                                                               
results->useful_bytes_per_request[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
64);
+                                                       }
+                                                       break;
+                                               case 2:
+                                                       
results->lines_interleaved_in_mem_access[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       
results->latency_hiding_lines[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       
results->bytes_per_request[i] =
+                                                               bw_int_to_fixed(
+                                                                       32);
+                                                       
results->useful_bytes_per_request[i] =
+                                                               bw_int_to_fixed(
+                                                                       32);
+                                                       break;
+                                               default:
+                                                       
results->lines_interleaved_in_mem_access[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       
results->latency_hiding_lines[i] =
+                                                               bw_int_to_fixed(
+                                                                       2);
+                                                       
results->bytes_per_request[i] =
+                                                               bw_int_to_fixed(
+                                                                       32);
+                                                       
results->useful_bytes_per_request[i] =
+                                                               bw_int_to_fixed(
+                                                                       16);
+                                                       break;
+                                               }
+                                       } else {
+                                               results->bytes_per_request[i] =
+                                                       bw_int_to_fixed(64);
+                                               
results->useful_bytes_per_request[i] =
+                                                       bw_int_to_fixed(64);
+                                               if 
(results->orthogonal_rotation[i]) {
+                                                       
results->lines_interleaved_in_mem_access[i] =
+                                                               bw_int_to_fixed(
+                                                                       8);
+                                                       
results->latency_hiding_lines[i] =
+                                                               bw_int_to_fixed(
+                                                                       4);
+                                               } else {
+                                                       switch 
(results->bytes_per_pixel[i]) {
+                                                       case 4:
+                                                               
results->lines_interleaved_in_mem_access[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               
results->latency_hiding_lines[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
2);
+                                                               break;
+                                                       case 2:
+                                                               
results->lines_interleaved_in_mem_access[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
4);
+                                                               
results->latency_hiding_lines[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
4);
+                                                               break;
+                                                       default:
+                                                               
results->lines_interleaved_in_mem_access[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
8);
+                                                               
results->latency_hiding_lines[i] =
+                                                                       
bw_int_to_fixed(
+                                                                               
4);
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               results->bytes_per_request[i] = bw_int_to_fixed(
+                                       256);
+                               results->useful_bytes_per_request[i] =
+                                       bw_int_to_fixed(256);
+                               results->lines_interleaved_in_mem_access[i] =
+                                       bw_int_to_fixed(4);
+                               results->latency_hiding_lines[i] =
+                                       bw_int_to_fixed(4);
+                       }
+               }
+       }
+       /*requested peak bandwidth:*/
+       /*the peak request-per-second bandwidth is the product of the maximum 
source lines in per line out in the beginning and in the middle of the frame, 
the ratio of the source width to the line time, the ratio of line interleaving 
in memory to lines of latency hiding, and the ratio of bytes per pixel to 
useful bytes per request.*/
+       /*the peak bandwidth is the peak request-per-second bandwidth times the 
request size.*/
+       /*the line buffer lines in per line out in the beginning of the frame 
is the vertical filter initialization value rounded up to even and divided by 
the line times for initialization, which is normally three.*/
+       /*the line buffer lines in per line out in the middle of the frame is 
at least one, or the vertical scale ratio, rounded up to line pairs if not 
doing line buffer prefetching.*/
+       /*the non-prefetching rounding up of the vertical scale ratio can also 
be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern), 6/4 (for a 
0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/
+       /*the scaler vertical filter initialization value is calculated by the 
hardware as the floor of the average of the vertical scale ratio and the number 
of vertical taps increased by one.  add one more for possible odd line 
panning/bezel adjustment mode.*/
+       /*for the bottom interlace field an extra 50% of the vertical scale 
ratio is considered for this calculation.*/
+       /*in top-bottom stereo mode software has to set the filter 
initialization value manually and explicitly limit it to 4.  further, there is 
only one line time for initialization.*/
+       /*line buffer prefetching is done when the number of lines in the line 
buffer exceeds the number of taps plus the ceiling of the vertical scale 
ratio.*/
+       /*line buffer prefetching is not done when downscaling in the graphics 
pipe or for possible odd line panning/bezel adjustment mode.*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->v_filter_init[i] =
+                               bw_floor2(
+                                       bw_div(
+                                               (bw_add(
+                                                       bw_add(
+                                                               bw_add(
+                                                                       
bw_int_to_fixed(
+                                                                               
1),
+                                                                       
results->v_taps[i]),
+                                                               
results->vsr[i]),
+                                                       bw_mul(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
results->interlace_mode[i]),
+                                                                       
bw_frc_to_fixed(
+                                                                               
5,
+                                                                               
10)),
+                                                               
results->vsr[i]))),
+                                               bw_int_to_fixed(2)),
+                                       bw_int_to_fixed(1));
+                       if (mode_data->panning_and_bezel_adjustment
+                               == bw_def_any_lines) {
+                               results->v_filter_init[i] = bw_add(
+                                       results->v_filter_init[i],
+                                       bw_int_to_fixed(1));
+                       }
+                       if (stereo_mode[i] == bw_def_top_bottom) {
+                               v_filter_init_mode[i] = bw_def_manual;
+                               results->v_filter_init[i] = bw_min2(
+                                       results->v_filter_init[i],
+                                       bw_int_to_fixed(4));
+                       } else {
+                               v_filter_init_mode[i] = bw_def_auto;
+                       }
+                       if (stereo_mode[i] == bw_def_top_bottom) {
+                               results->num_lines_at_frame_start =
+                                       bw_int_to_fixed(1);
+                       } else {
+                               results->num_lines_at_frame_start =
+                                       bw_int_to_fixed(3);
+                       }
+                       if ((bw_mtn(results->vsr[i], bw_int_to_fixed(1))
+                               && surface_type[i] == bw_def_graphics)
+                               || mode_data->panning_and_bezel_adjustment
+                                       == bw_def_any_lines) {
+                               results->line_buffer_prefetch[i] = 0;
+                       } else if ((((dceip->underlay_downscale_prefetch_enabled
+                               == 1 && surface_type[i] != bw_def_graphics)
+                               || surface_type[i] == bw_def_graphics)
+                               && (bw_mtn(
+                                       results->lb_partitions[i],
+                                       bw_add(
+                                               results->v_taps[i],
+                                               bw_ceil2(
+                                                       results->vsr[i],
+                                                       
bw_int_to_fixed(1))))))) {
+                               results->line_buffer_prefetch[i] = 1;
+                       } else {
+                               results->line_buffer_prefetch[i] = 0;
+                       }
+                       
results->lb_lines_in_per_line_out_in_beginning_of_frame[i] =
+                               bw_div(
+                                       bw_ceil2(
+                                               results->v_filter_init[i],
+                                               bw_int_to_fixed(
+                                                       
dceip->lines_interleaved_into_lb)),
+                                       results->num_lines_at_frame_start);
+                       if (results->line_buffer_prefetch[i] == 1) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_max2(
+                                               bw_int_to_fixed(1),
+                                               results->vsr[i]);
+                       } else if (bw_leq(
+                               results->vsr[i],
+                               bw_int_to_fixed(1))) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_int_to_fixed(1);
+                       } else if (bw_leq(
+                               results->vsr[i],
+                               bw_int_to_fixed(4 / 3))) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_div(
+                                               bw_int_to_fixed(4),
+                                               bw_int_to_fixed(3));
+                       } else if (bw_leq(
+                               results->vsr[i],
+                               bw_int_to_fixed(6 / 4))) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_div(
+                                               bw_int_to_fixed(6),
+                                               bw_int_to_fixed(4));
+                       } else if (bw_leq(
+                               results->vsr[i],
+                               bw_int_to_fixed(2))) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_int_to_fixed(2);
+                       } else if (bw_leq(
+                               results->vsr[i],
+                               bw_int_to_fixed(3))) {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_int_to_fixed(3);
+                       } else {
+                               
results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+                                       bw_int_to_fixed(4);
+                       }
+                       if (results->line_buffer_prefetch[i] == 1
+                               || bw_equ(
+                                       
results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+                                       bw_int_to_fixed(2))
+                               || bw_equ(
+                                       
results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+                                       bw_int_to_fixed(4))) {
+                               
results->horizontal_blank_and_chunk_granularity_factor[i] =
+                                       bw_int_to_fixed(1);
+                       } else {
+                               
results->horizontal_blank_and_chunk_granularity_factor[i] =
+                                       bw_div(
+                                               results->h_total[i],
+                                               (bw_div(
+                                                       (bw_add(
+                                                               
results->h_total[i],
+                                                               bw_div(
+                                                                       (bw_sub(
+                                                                               
results->source_width_pixels[i],
+                                                                               
bw_int_to_fixed(
+                                                                               
        dceip->chunk_width))),
+                                                                       
results->hsr[i]))),
+                                                       bw_int_to_fixed(2))));
+                       }
+                       results->request_bandwidth[i] =
+                               bw_div(
+                                       bw_mul(
+                                               bw_div(
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       bw_mul(
+                                                                               
bw_max2(
+                                                                               
        results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+                                                                               
        results->lb_lines_in_per_line_out_in_middle_of_frame[i]),
+                                                                               
results->source_width_rounded_up_to_chunks[i]),
+                                                                       (bw_div(
+                                                                               
results->h_total[i],
+                                                                               
results->pixel_rate[i]))),
+                                                               bw_int_to_fixed(
+                                                                       
results->bytes_per_pixel[i])),
+                                                       
results->useful_bytes_per_request[i]),
+                                               
results->lines_interleaved_in_mem_access[i]),
+                                       results->latency_hiding_lines[i]);
+                       results->display_bandwidth[i] = bw_mul(
+                               results->request_bandwidth[i],
+                               results->bytes_per_request[i]);
+               }
+       }
+       /*outstanding chunk request limit*/
+       /*if underlay buffer sharing is enabled, the data buffer size for 
underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/
+       /*underlay buffer sharing mode is only permitted in orthogonal rotation 
modes.*/
+       /*if there is only one display enabled, the data buffer size for 
graphics is doubled.*/
+       /*the memory chunk size in bytes is 1024 for the writeback, and 256 
times the memory line interleaving and the bytes per pixel for graphics*/
+       /*and underlay.*/
+       /*the pipe chunk size uses 2 for line interleaving, except for the 
write back, in which case it is 1.*/
+       /*graphics and underlay data buffer size is adjusted (limited) using 
the outstanding chunk request limit if there is more than one*/
+       /*display enabled or if the dmif request buffer is not large enough for 
the total data buffer size.*/
+       /*the outstanding chunk request limit is the ceiling of the adjusted 
data buffer size divided by the chunk size in bytes*/
+       /*the adjusted data buffer size is the product of the display bandwidth 
and the minimum effective data buffer size in terms of time,*/
+       /*rounded up to the chunk size in bytes, but should not exceed the 
original data buffer size*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       switch (surface_type[i]) {
+                       case bw_def_display_write_back420_luma:
+                               results->data_buffer_size[i] =
+                                       bw_int_to_fixed(
+                                               
dceip->display_write_back420_luma_mcifwr_buffer_size);
+                               break;
+                       case bw_def_display_write_back420_chroma:
+                               results->data_buffer_size[i] =
+                                       bw_int_to_fixed(
+                                               
dceip->display_write_back420_chroma_mcifwr_buffer_size);
+                               break;
+                       case bw_def_underlay420_luma:
+                               results->data_buffer_size[i] = bw_int_to_fixed(
+                                       dceip->underlay_luma_dmif_size);
+                               break;
+                       case bw_def_underlay420_chroma:
+                               results->data_buffer_size[i] =
+                                       bw_div(
+                                               bw_int_to_fixed(
+                                                       
dceip->underlay_chroma_dmif_size),
+                                               bw_int_to_fixed(2));
+                               break;
+                       case bw_def_underlay422:
+                       case bw_def_underlay444:
+                               if (results->orthogonal_rotation[i] == 0) {
+                                       results->data_buffer_size[i] =
+                                               bw_int_to_fixed(
+                                                       
dceip->underlay_luma_dmif_size);
+                               } else {
+                                       results->data_buffer_size[i] =
+                                               bw_add(
+                                                       bw_int_to_fixed(
+                                                               
dceip->underlay_luma_dmif_size),
+                                                       bw_int_to_fixed(
+                                                               
dceip->underlay_chroma_dmif_size));
+                               }
+                               break;
+                       default:
+                               if (mode_data->number_of_displays == 1
+                                       && bw_equ(
+                                               dceip->de_tiling_buffer,
+                                               bw_int_to_fixed(0))) {
+                                       if (mode_data->d0_fbc_enable) {
+                                               results->data_buffer_size[i] =
+                                                       bw_mul(
+                                                               bw_int_to_fixed(
+                                                                       
dceip->max_dmif_buffer_allocated),
+                                                               bw_int_to_fixed(
+                                                                       
dceip->graphics_dmif_size));
+                                       } else {
+                                               /*the effective dmif buffer 
size in non-fbc mode is limited by the 16 entry chunk tracker*/
+                                               results->data_buffer_size[i] =
+                                                       bw_mul(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
max_chunks_non_fbc_mode),
+                                                                       
bw_int_to_fixed(
+                                                                               
pixels_per_chunk)),
+                                                               bw_int_to_fixed(
+                                                                       
results->bytes_per_pixel[i]));
+                                       }
+                               } else {
+                                       results->data_buffer_size[i] =
+                                               bw_int_to_fixed(
+                                                       
dceip->graphics_dmif_size);
+                               }
+                               break;
+                       }
+                       if (surface_type[i] == bw_def_display_write_back420_luma
+                               || surface_type[i]
+                                       == bw_def_display_write_back420_chroma) 
{
+                               results->memory_chunk_size_in_bytes[i] =
+                                       bw_int_to_fixed(1024);
+                               results->pipe_chunk_size_in_bytes[i] =
+                                       bw_int_to_fixed(1024);
+                       } else {
+                               results->memory_chunk_size_in_bytes[i] =
+                                       bw_mul(
+                                               bw_mul(
+                                                       bw_int_to_fixed(
+                                                               
dceip->chunk_width),
+                                                       
results->lines_interleaved_in_mem_access[i]),
+                                               bw_int_to_fixed(
+                                                       
results->bytes_per_pixel[i]));
+                               results->pipe_chunk_size_in_bytes[i] =
+                                       bw_mul(
+                                               bw_mul(
+                                                       bw_int_to_fixed(
+                                                               
dceip->chunk_width),
+                                                       bw_int_to_fixed(
+                                                               
dceip->lines_interleaved_into_lb)),
+                                               bw_int_to_fixed(
+                                                       
results->bytes_per_pixel[i]));
+                       }
+               }
+       }
+       results->min_dmif_size_in_time = bw_int_to_fixed(9999);
+       results->min_mcifwr_size_in_time = bw_int_to_fixed(9999);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               if (bw_ltn(
+                                       bw_div(
+                                               bw_div(
+                                                       bw_mul(
+                                                               
results->data_buffer_size[i],
+                                                               
results->bytes_per_request[i]),
+                                                       
results->useful_bytes_per_request[i]),
+                                               results->display_bandwidth[i]),
+                                       results->min_dmif_size_in_time)) {
+                                       results->min_dmif_size_in_time =
+                                               bw_div(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       
results->data_buffer_size[i],
+                                                                       
results->bytes_per_request[i]),
+                                                               
results->useful_bytes_per_request[i]),
+                                                       
results->display_bandwidth[i]);
+                               }
+                       } else {
+                               if (bw_ltn(
+                                       bw_div(
+                                               bw_div(
+                                                       bw_mul(
+                                                               
results->data_buffer_size[i],
+                                                               
results->bytes_per_request[i]),
+                                                       
results->useful_bytes_per_request[i]),
+                                               results->display_bandwidth[i]),
+                                       results->min_mcifwr_size_in_time)) {
+                                       results->min_mcifwr_size_in_time =
+                                               bw_div(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       
results->data_buffer_size[i],
+                                                                       
results->bytes_per_request[i]),
+                                                               
results->useful_bytes_per_request[i]),
+                                                       
results->display_bandwidth[i]);
+                               }
+                       }
+               }
+       }
+       results->total_requests_for_dmif_size = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]
+                       && surface_type[i] != bw_def_display_write_back420_luma
+                       && surface_type[i]
+                               != bw_def_display_write_back420_chroma) {
+                       results->total_requests_for_dmif_size = bw_add(
+                               results->total_requests_for_dmif_size,
+                               bw_div(
+                                       results->data_buffer_size[i],
+                                       results->useful_bytes_per_request[i]));
+               }
+       }
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma
+                               && 
dceip->limit_excessive_outstanding_dmif_requests
+                               && (mode_data->number_of_displays > 1
+                                       || bw_mtn(
+                                               
results->total_requests_for_dmif_size,
+                                               
dceip->dmif_request_buffer_size))) {
+                               results->adjusted_data_buffer_size[i] =
+                                       bw_min2(
+                                               results->data_buffer_size[i],
+                                               bw_ceil2(
+                                                       bw_mul(
+                                                               
results->min_dmif_size_in_time,
+                                                               
results->display_bandwidth[i]),
+                                                       
results->memory_chunk_size_in_bytes[i]));
+                       } else {
+                               results->adjusted_data_buffer_size[i] =
+                                       results->data_buffer_size[i];
+                       }
+               }
+       }
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if ((mode_data->number_of_displays == 1
+                               && results->number_of_underlay_surfaces == 0)) {
+                               /*set maximum chunk limit if only one graphic 
pipe is enabled*/
+                               results->outstanding_chunk_request_limit[i] =
+                                       bw_int_to_fixed(255);
+                       } else {
+                               results->outstanding_chunk_request_limit[i] =
+                                       bw_ceil2(
+                                               bw_div(
+                                                       
results->adjusted_data_buffer_size[i],
+                                                       
results->pipe_chunk_size_in_bytes[i]),
+                                               bw_int_to_fixed(1));
+                       }
+               }
+       }
+       /*outstanding pte request limit*/
+       /*in tiling mode with no rotation the sg pte requests are 8 useful 
pt_es, the sg row height is the page height and the sg page width x height is 
64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/
+       /*in tiling mode with rotation the sg pte requests are only one useful 
pte, and the sg row height is also the page height, but the sg page width and 
height are swapped*/
+       /*in linear mode the pte requests are 8 useful pt_es, the sg page width 
is 4096 divided by the bytes per pixel, the sg page height is 1, but there is 
just one row whose height is the lines of pte prefetching*/
+       /*the outstanding pte request limit is obtained by multiplying the 
outstanding chunk request limit by the peak pte request to eviction limiting 
ratio, rounding up to integer, multiplying by the pte requests per chunk, and 
rounding up to integer again*/
+       /*if not using peak pte request to eviction limiting, the outstanding 
pte request limit is the pte requests in the vblank*/
+       /*the pte requests in the vblank is the product of the number of pte 
request rows times the number of pte requests in a row*/
+       /*the number of pte requests in a row is the quotient of the source 
width divided by 256, multiplied by the pte requests per chunk, rounded up to 
even, multiplied by the scatter-gather row height and divided by the 
scatter-gather page height*/
+       /*the pte requests per chunk is 256 divided by the scatter-gather page 
width and the useful pt_es per pte request*/
+       if (mode_data->number_of_displays > 1
+               || (mode_data->graphics_rotation_angle != 0
+                       && mode_data->graphics_rotation_angle != 180)) {
+               results->peak_pte_request_to_eviction_ratio_limiting =
+                       
dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+       } else {
+               results->peak_pte_request_to_eviction_ratio_limiting =
+                       
dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+       }
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]
+                       && results->scatter_gather_enable_for_pipe[i] == 1) {
+                       if (tiling_mode[i] == bw_def_linear) {
+                               results->useful_pte_per_pte_request =
+                                       bw_int_to_fixed(8);
+                               results->scatter_gather_page_width[i] = bw_div(
+                                       bw_int_to_fixed(4096),
+                                       bw_int_to_fixed(
+                                               results->bytes_per_pixel[i]));
+                               results->scatter_gather_page_height[i] =
+                                       bw_int_to_fixed(1);
+                               results->scatter_gather_pte_request_rows =
+                                       bw_int_to_fixed(1);
+                               results->scatter_gather_row_height =
+                                       bw_int_to_fixed(
+                                               
dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode);
+                       } else if (bw_equ(
+                               results->rotation_angle[i],
+                               bw_int_to_fixed(0))
+                               || bw_equ(
+                                       results->rotation_angle[i],
+                                       bw_int_to_fixed(180))) {
+                               results->useful_pte_per_pte_request =
+                                       bw_int_to_fixed(8);
+                               switch (results->bytes_per_pixel[i]) {
+                               case 4:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(32);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(32);
+                                       break;
+                               case 2:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(64);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(32);
+                                       break;
+                               default:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(64);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(64);
+                                       break;
+                               }
+                               results->scatter_gather_pte_request_rows =
+                                       bw_int_to_fixed(
+                                               
dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+                               results->scatter_gather_row_height =
+                                       results->scatter_gather_page_height[i];
+                       } else {
+                               results->useful_pte_per_pte_request =
+                                       bw_int_to_fixed(1);
+                               switch (results->bytes_per_pixel[i]) {
+                               case 4:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(32);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(32);
+                                       break;
+                               case 2:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(32);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(64);
+                                       break;
+                               default:
+                                       results->scatter_gather_page_width[i] =
+                                               bw_int_to_fixed(64);
+                                       results->scatter_gather_page_height[i] =
+                                               bw_int_to_fixed(64);
+                                       break;
+                               }
+                               results->scatter_gather_pte_request_rows =
+                                       bw_int_to_fixed(
+                                               
dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+                               results->scatter_gather_row_height =
+                                       results->scatter_gather_page_height[i];
+                       }
+                       results->pte_request_per_chunk[i] = bw_div(
+                               bw_div(
+                                       bw_int_to_fixed(dceip->chunk_width),
+                                       results->scatter_gather_page_width[i]),
+                               results->useful_pte_per_pte_request);
+                       results->scatter_gather_pte_requests_in_row[i] =
+                               bw_div(
+                                       bw_mul(
+                                               bw_ceil2(
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       
results->source_width_rounded_up_to_chunks[i],
+                                                                       
bw_int_to_fixed(
+                                                                               
dceip->chunk_width)),
+                                                               
results->pte_request_per_chunk[i]),
+                                                       bw_int_to_fixed(1)),
+                                               
results->scatter_gather_row_height),
+                                       results->scatter_gather_page_height[i]);
+                       results->scatter_gather_pte_requests_in_vblank = bw_mul(
+                               results->scatter_gather_pte_request_rows,
+                               results->scatter_gather_pte_requests_in_row[i]);
+                       if (bw_equ(
+                               
results->peak_pte_request_to_eviction_ratio_limiting,
+                               bw_int_to_fixed(0))) {
+                               results->scatter_gather_pte_request_limit[i] =
+                                       
results->scatter_gather_pte_requests_in_vblank;
+                       } else {
+                               results->scatter_gather_pte_request_limit[i] =
+                                       bw_max2(
+                                               
dceip->minimum_outstanding_pte_request_limit,
+                                               bw_min2(
+                                                       
results->scatter_gather_pte_requests_in_vblank,
+                                                       bw_ceil2(
+                                                               bw_mul(
+                                                                       bw_mul(
+                                                                               
bw_div(
+                                                                               
        bw_ceil2(
+                                                                               
                results->adjusted_data_buffer_size[i],
+                                                                               
                results->memory_chunk_size_in_bytes[i]),
+                                                                               
        results->memory_chunk_size_in_bytes[i]),
+                                                                               
results->pte_request_per_chunk[i]),
+                                                                       
results->peak_pte_request_to_eviction_ratio_limiting),
+                                                               bw_int_to_fixed(
+                                                                       1))));
+                       }
+               }
+       }
+       /*pitch padding recommended for efficiency in linear mode*/
+       /*in linear mode graphics or underlay with scatter gather, a pitch that 
is a multiple of the channel interleave (256 bytes) times the channel-bank 
rotation is not efficient*/
+       /*if that is the case it is recommended to pad the pitch by at least 
256 pixels*/
+       results->inefficient_linear_pitch_in_bytes = bw_mul(
+               bw_mul(
+                       bw_int_to_fixed(256),
+                       bw_int_to_fixed(vbios->number_of_dram_banks)),
+               bw_int_to_fixed(vbios->number_of_dram_channels));
+       switch (mode_data->underlay_surface_type) {
+       case bw_def_420:
+               results->inefficient_underlay_pitch_in_pixels =
+                       results->inefficient_linear_pitch_in_bytes;
+               break;
+       case bw_def_422:
+               results->inefficient_underlay_pitch_in_pixels = bw_div(
+                       results->inefficient_linear_pitch_in_bytes,
+                       bw_int_to_fixed(2));
+               break;
+       default:
+               results->inefficient_underlay_pitch_in_pixels = bw_div(
+                       results->inefficient_linear_pitch_in_bytes,
+                       bw_int_to_fixed(4));
+               break;
+       }
+       if (mode_data->underlay_tiling_mode == bw_def_linear
+               && vbios->scatter_gather_enable == 1
+               && bw_equ(
+                       bw_mod(
+                               bw_int_to_fixed(
+                                       mode_data->underlay_pitch_in_pixels),
+                               results->inefficient_underlay_pitch_in_pixels),
+                       bw_int_to_fixed(0))) {
+               
results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+                       bw_int_to_fixed(256);
+       } else {
+               
results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+                       bw_int_to_fixed(0);
+       }
+       /*pixel transfer time*/
+       /*the dmif and mcifwr yclk(pclk) required is the one that allows the 
transfer of all pipe's data buffer size in memory in the time for data 
transfer*/
+       /*for dmif, pte and cursor requests have to be included.*/
+       /*the dram data requirement is doubled when the data request size in 
bytes is less than the dram channel width times the burst size (8)*/
+       /*the dram data requirement is also multiplied by the number of 
channels in the case of low power tiling*/
+       /*the page close-open time is determined by trc and the number of page 
close-opens*/
+       /*in tiled mode graphics or underlay with scatter-gather enabled the 
bytes per page close-open is the product of the memory line interleave times 
the maximum of the scatter-gather page width and the product of the tile width 
(8 pixels) times the number of channels times the number of banks.*/
+       /*in linear mode graphics or underlay with scatter-gather enabled and 
inefficient pitch, the bytes per page close-open is the line request 
alternation slice, because different lines are in completely different 4k 
address bases.*/
+       /*otherwise, the bytes page close-open is the chunk size because that 
is the arbitration slice.*/
+       /*pte requests are grouped by pte requests per chunk if that is more 
than 1. each group costs a page close-open time for dmif reads*/
+       /*cursor requests outstanding are limited to a group of two source 
lines. each group costs a page close-open time for dmif reads*/
+       /*the display reads and writes time for data transfer is the minimum 
data or cursor buffer size in time minus the mc urgent latency*/
+       /*the mc urgent latency is experienced more than one time if the number 
of dmif requests in the data buffer exceeds the request buffer size plus the 
request slots reserved for dmif in the dram channel arbiter queues*/
+       /*the dispclk required is the maximum for all surfaces of the maximum 
of the source pixels for first output pixel times the throughput factor, 
divided by the pixels per dispclk, and divided by the minimum latency hiding 
minus the dram speed/p-state change latency minus the burst time, and the 
source pixels for last output pixel, times the throughput factor, divided by 
the pixels per dispclk, and divided by the minimum latency hiding minus the 
dram speed/p-state change latency minus the burst time, plus the active time.*/
+       /*the data burst time is the maximum of the total page close-open time, 
total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the 
total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus 
bandwidth, each multiplied by its efficiency.*/
+       /*the source line transfer time is the maximum for all surfaces of the 
maximum of the burst time plus the urgent latency times the floor of the data 
required divided by the buffer size for the fist pixel, and the burst time plus 
the urgent latency times the floor of the data required divided by the buffer 
size for the last pixel plus the active time.*/
+       /*the source pixels for the first output pixel is 512 if the scaler 
vertical filter initialization value is greater than 2, and it is 4 times the 
source width if it is greater than 4.*/
+       /*the source pixels for the last output pixel is the source width times 
the scaler vertical filter initialization value rounded up to even*/
+       /*the source data for these pixels is the number of pixels times the 
bytes per pixel times the bytes per request divided by the useful bytes per 
request.*/
+       results->cursor_total_data = bw_int_to_fixed(0);
+       results->cursor_total_request_groups = bw_int_to_fixed(0);
+       results->scatter_gather_total_pte_requests = bw_int_to_fixed(0);
+       results->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->cursor_total_data =
+                               bw_add(
+                                       results->cursor_total_data,
+                                       bw_mul(
+                                               bw_mul(
+                                                       bw_int_to_fixed(2),
+                                                       
results->cursor_width_pixels[i]),
+                                               bw_int_to_fixed(4)));
+                       results->cursor_total_request_groups = bw_add(
+                               results->cursor_total_request_groups,
+                               bw_ceil2(
+                                       bw_div(
+                                               results->cursor_width_pixels[i],
+                                               dceip->cursor_chunk_width),
+                                       bw_int_to_fixed(1)));
+                       if (results->scatter_gather_enable_for_pipe[i]) {
+                               results->scatter_gather_total_pte_requests =
+                                       bw_add(
+                                               
results->scatter_gather_total_pte_requests,
+                                               
results->scatter_gather_pte_request_limit[i]);
+                               
results->scatter_gather_total_pte_request_groups =
+                                       bw_add(
+                                               
results->scatter_gather_total_pte_request_groups,
+                                               bw_ceil2(
+                                                       bw_div(
+                                                               
results->scatter_gather_pte_request_limit[i],
+                                                               bw_ceil2(
+                                                                       
results->pte_request_per_chunk[i],
+                                                                       
bw_int_to_fixed(
+                                                                               
1))),
+                                                       bw_int_to_fixed(1)));
+                       }
+               }
+       }
+       results->tile_width_in_pixels = bw_int_to_fixed(8);
+       results->dmif_total_number_of_data_request_page_close_open =
+               bw_int_to_fixed(0);
+       results->mcifwr_total_number_of_data_request_page_close_open =
+               bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (results->scatter_gather_enable_for_pipe[i] == 1
+                               && tiling_mode[i] != bw_def_linear) {
+                               results->bytes_per_page_close_open =
+                                       bw_mul(
+                                               
results->lines_interleaved_in_mem_access[i],
+                                               bw_max2(
+                                                       bw_mul(
+                                                               bw_mul(
+                                                                       bw_mul(
+                                                                               
bw_int_to_fixed(
+                                                                               
        results->bytes_per_pixel[i]),
+                                                                               
results->tile_width_in_pixels),
+                                                                       
bw_int_to_fixed(
+                                                                               
vbios->number_of_dram_banks)),
+                                                               bw_int_to_fixed(
+                                                                       
vbios->number_of_dram_channels)),
+                                                       bw_mul(
+                                                               bw_int_to_fixed(
+                                                                       
results->bytes_per_pixel[i]),
+                                                               
results->scatter_gather_page_width[i])));
+                       } else if (results->scatter_gather_enable_for_pipe[i]
+                               == 1 && tiling_mode[i] == bw_def_linear
+                               && bw_equ(
+                                       bw_mod(
+                                               (bw_mul(
+                                                       
results->pitch_in_pixels_after_surface_type[i],
+                                                       bw_int_to_fixed(
+                                                               
results->bytes_per_pixel[i]))),
+                                               
results->inefficient_linear_pitch_in_bytes),
+                                       bw_int_to_fixed(0))) {
+                               results->bytes_per_page_close_open =
+                                       
dceip->linear_mode_line_request_alternation_slice;
+                       } else {
+                               results->bytes_per_page_close_open =
+                                       results->memory_chunk_size_in_bytes[i];
+                       }
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               
results->dmif_total_number_of_data_request_page_close_open =
+                                       bw_add(
+                                               
results->dmif_total_number_of_data_request_page_close_open,
+                                               bw_div(
+                                                       bw_ceil2(
+                                                               
results->adjusted_data_buffer_size[i],
+                                                               
results->memory_chunk_size_in_bytes[i]),
+                                                       
results->bytes_per_page_close_open));
+                       } else {
+                               
results->mcifwr_total_number_of_data_request_page_close_open =
+                                       bw_add(
+                                               
results->mcifwr_total_number_of_data_request_page_close_open,
+                                               bw_div(
+                                                       bw_ceil2(
+                                                               
results->adjusted_data_buffer_size[i],
+                                                               
results->memory_chunk_size_in_bytes[i]),
+                                                       
results->bytes_per_page_close_open));
+                       }
+               }
+       }
+       results->dmif_total_page_close_open_time =
+               bw_div(
+                       bw_mul(
+                               (bw_add(
+                                       bw_add(
+                                               
results->dmif_total_number_of_data_request_page_close_open,
+                                               
results->scatter_gather_total_pte_request_groups),
+                                       results->cursor_total_request_groups)),
+                               vbios->trc),
+                       bw_int_to_fixed(1000));
+       results->mcifwr_total_page_close_open_time =
+               bw_div(
+                       bw_mul(
+                               
results->mcifwr_total_number_of_data_request_page_close_open,
+                               vbios->trc),
+                       bw_int_to_fixed(1000));
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->adjusted_data_buffer_size_in_memory[i] =
+                               bw_div(
+                                       bw_mul(
+                                               
results->adjusted_data_buffer_size[i],
+                                               results->bytes_per_request[i]),
+                                       results->useful_bytes_per_request[i]);
+               }
+       }
+       results->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               results->total_requests_for_adjusted_dmif_size =
+                                       bw_add(
+                                               
results->total_requests_for_adjusted_dmif_size,
+                                               bw_div(
+                                                       
results->adjusted_data_buffer_size[i],
+                                                       
results->useful_bytes_per_request[i]));
+                       }
+               }
+       }
+       if (dceip->dcfclk_request_generation == 1) {
+               results->total_dmifmc_urgent_trips = bw_int_to_fixed(1);
+       } else {
+               results->total_dmifmc_urgent_trips =
+                       bw_ceil2(
+                               bw_div(
+                                       
results->total_requests_for_adjusted_dmif_size,
+                                       (bw_add(
+                                               dceip->dmif_request_buffer_size,
+                                               bw_int_to_fixed(
+                                                       
vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel
+                                                               * 
vbios->number_of_dram_channels)))),
+                               bw_int_to_fixed(1));
+       }
+       results->total_dmifmc_urgent_latency = bw_mul(
+               vbios->dmifmc_urgent_latency,
+               results->total_dmifmc_urgent_trips);
+       results->total_display_reads_required_data = bw_int_to_fixed(0);
+       results->total_display_reads_required_dram_access_data =
+               bw_int_to_fixed(0);
+       results->total_display_writes_required_data = bw_int_to_fixed(0);
+       results->total_display_writes_required_dram_access_data =
+               bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               results->display_reads_required_data =
+                                       
results->adjusted_data_buffer_size_in_memory[i];
+                               
results->display_reads_required_dram_access_data =
+                                       bw_mul(
+                                               
results->adjusted_data_buffer_size_in_memory[i],
+                                               bw_ceil2(
+                                                       bw_div(
+                                                               bw_int_to_fixed(
+                                                                       
vbios->dram_channel_width_in_bits),
+                                                               
results->bytes_per_request[i]),
+                                                       bw_int_to_fixed(1)));
+                               if (results->access_one_channel_only[i]) {
+                                       
results->display_reads_required_dram_access_data =
+                                               bw_mul(
+                                                       
results->display_reads_required_dram_access_data,
+                                                       bw_int_to_fixed(
+                                                               
vbios->number_of_dram_channels));
+                               }
+                               results->total_display_reads_required_data =
+                                       bw_add(
+                                               
results->total_display_reads_required_data,
+                                               
results->display_reads_required_data);
+                               
results->total_display_reads_required_dram_access_data =
+                                       bw_add(
+                                               
results->total_display_reads_required_dram_access_data,
+                                               
results->display_reads_required_dram_access_data);
+                       } else {
+                               results->total_display_writes_required_data =
+                                       bw_add(
+                                               
results->total_display_writes_required_data,
+                                               
results->adjusted_data_buffer_size_in_memory[i]);
+                               
results->total_display_writes_required_dram_access_data =
+                                       bw_add(
+                                               
results->total_display_writes_required_dram_access_data,
+                                               bw_mul(
+                                                       
results->adjusted_data_buffer_size_in_memory[i],
+                                                       bw_ceil2(
+                                                               bw_div(
+                                                                       
bw_int_to_fixed(
+                                                                               
vbios->dram_channel_width_in_bits),
+                                                                       
results->bytes_per_request[i]),
+                                                               bw_int_to_fixed(
+                                                                       1))));
+                       }
+               }
+       }
+       results->total_display_reads_required_data = bw_add(
+               bw_add(
+                       results->total_display_reads_required_data,
+                       results->cursor_total_data),
+               bw_mul(
+                       results->scatter_gather_total_pte_requests,
+                       bw_int_to_fixed(64)));
+       results->total_display_reads_required_dram_access_data = bw_add(
+               bw_add(
+                       results->total_display_reads_required_dram_access_data,
+                       results->cursor_total_data),
+               bw_mul(
+                       results->scatter_gather_total_pte_requests,
+                       bw_int_to_fixed(64)));
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_mtn(
+                               results->v_filter_init[i],
+                               bw_int_to_fixed(4))) {
+                               results->src_pixels_for_first_output_pixel[i] =
+                                       bw_mul(
+                                               bw_int_to_fixed(4),
+                                               
results->source_width_rounded_up_to_chunks[i]);
+                       } else {
+                               if (bw_mtn(
+                                       results->v_filter_init[i],
+                                       bw_int_to_fixed(2))) {
+                                       
results->src_pixels_for_first_output_pixel[i] =
+                                               bw_int_to_fixed(512);
+                               } else {
+                                       
results->src_pixels_for_first_output_pixel[i] =
+                                               bw_int_to_fixed(0);
+                               }
+                       }
+                       results->src_data_for_first_output_pixel[i] =
+                               bw_div(
+                                       bw_mul(
+                                               bw_mul(
+                                                       
results->src_pixels_for_first_output_pixel[i],
+                                                       bw_int_to_fixed(
+                                                               
results->bytes_per_pixel[i])),
+                                               results->bytes_per_request[i]),
+                                       results->useful_bytes_per_request[i]);
+                       results->src_pixels_for_last_output_pixel[i] =
+                               bw_mul(
+                                       
results->source_width_rounded_up_to_chunks[i],
+                                       bw_max2(
+                                               bw_ceil2(
+                                                       
results->v_filter_init[i],
+                                                       bw_int_to_fixed(
+                                                               
dceip->lines_interleaved_into_lb)),
+                                               bw_mul(
+                                                       bw_ceil2(
+                                                               results->vsr[i],
+                                                               bw_int_to_fixed(
+                                                                       
dceip->lines_interleaved_into_lb)),
+                                                       
results->horizontal_blank_and_chunk_granularity_factor[i])));
+                       results->src_data_for_last_output_pixel[i] =
+                               bw_div(
+                                       bw_mul(
+                                               bw_mul(
+                                                       bw_mul(
+                                                               
results->source_width_rounded_up_to_chunks[i],
+                                                               bw_max2(
+                                                                       
bw_ceil2(
+                                                                               
results->v_filter_init[i],
+                                                                               
bw_int_to_fixed(
+                                                                               
        dceip->lines_interleaved_into_lb)),
+                                                                       
results->lines_interleaved_in_mem_access[i])),
+                                                       bw_int_to_fixed(
+                                                               
results->bytes_per_pixel[i])),
+                                               results->bytes_per_request[i]),
+                                       results->useful_bytes_per_request[i]);
+                       results->active_time[i] =
+                               bw_div(
+                                       bw_div(
+                                               
results->source_width_rounded_up_to_chunks[i],
+                                               results->hsr[i]),
+                                       results->pixel_rate[i]);
+               }
+       }
+       for (i = 0; i <= 2; i++) {
+               for (j = 0; j <= 2; j++) {
+                       results->dmif_burst_time[i][j] =
+                               bw_max3(
+                                       
results->dmif_total_page_close_open_time,
+                                       bw_div(
+                                               
results->total_display_reads_required_dram_access_data,
+                                               (bw_mul(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       yclk[i],
+                                                                       
bw_int_to_fixed(
+                                                                               
vbios->dram_channel_width_in_bits)),
+                                                               bw_int_to_fixed(
+                                                                       8)),
+                                                       bw_int_to_fixed(
+                                                               
vbios->number_of_dram_channels)))),
+                                       bw_div(
+                                               
results->total_display_reads_required_data,
+                                               (bw_mul(
+                                                       sclk[j],
+                                                       
vbios->data_return_bus_width))));
+                       if (mode_data->d1_display_write_back_dwb_enable == 1) {
+                               results->mcifwr_burst_time[i][j] =
+                                       bw_max3(
+                                               
results->mcifwr_total_page_close_open_time,
+                                               bw_div(
+                                                       
results->total_display_writes_required_dram_access_data,
+                                                       (bw_mul(
+                                                               bw_div(
+                                                                       bw_mul(
+                                                                               
yclk[i],
+                                                                               
bw_int_to_fixed(
+                                                                               
        vbios->dram_channel_width_in_bits)),
+                                                                       
bw_int_to_fixed(
+                                                                               
8)),
+                                                               bw_int_to_fixed(
+                                                                       
vbios->number_of_dram_channels)))),
+                                               bw_div(
+                                                       
results->total_display_writes_required_data,
+                                                       (bw_mul(
+                                                               sclk[j],
+                                                               
vbios->data_return_bus_width))));
+                       }
+               }
+       }
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               for (j = 0; j <= 2; j++) {
+                       for (k = 0; k <= 2; k++) {
+                               if (results->enable[i]) {
+                                       if (surface_type[i]
+                                               != 
bw_def_display_write_back420_luma
+                                               && surface_type[i]
+                                                       != 
bw_def_display_write_back420_chroma) {
+                                               
results->line_source_transfer_time[i][j][k] =
+                                                       bw_max2(
+                                                               bw_mul(
+                                                                       (bw_add(
+                                                                               
results->total_dmifmc_urgent_latency,
+                                                                               
results->dmif_burst_time[j][k])),
+                                                                       
bw_floor2(
+                                                                               
bw_div(
+                                                                               
        results->src_data_for_first_output_pixel[i],
+                                                                               
        results->adjusted_data_buffer_size_in_memory[i]),
+                                                                               
bw_int_to_fixed(
+                                                                               
        1))),
+                                                               bw_sub(
+                                                                       bw_mul(
+                                                                               
(bw_add(
+                                                                               
        results->total_dmifmc_urgent_latency,
+                                                                               
        results->dmif_burst_time[j][k])),
+                                                                               
bw_floor2(
+                                                                               
        bw_div(
+                                                                               
                results->src_data_for_last_output_pixel[i],
+                                                                               
                results->adjusted_data_buffer_size_in_memory[i]),
+                                                                               
        bw_int_to_fixed(
+                                                                               
                1))),
+                                                                       
results->active_time[i]));
+                                       } else {
+                                               
results->line_source_transfer_time[i][j][k] =
+                                                       bw_max2(
+                                                               bw_mul(
+                                                                       (bw_add(
+                                                                               
vbios->mcifwrmc_urgent_latency,
+                                                                               
results->mcifwr_burst_time[j][k])),
+                                                                       
bw_floor2(
+                                                                               
bw_div(
+                                                                               
        results->src_data_for_first_output_pixel[i],
+                                                                               
        results->adjusted_data_buffer_size_in_memory[i]),
+                                                                               
bw_int_to_fixed(
+                                                                               
        1))),
+                                                               bw_sub(
+                                                                       bw_mul(
+                                                                               
(bw_add(
+                                                                               
        vbios->mcifwrmc_urgent_latency,
+                                                                               
        results->mcifwr_burst_time[j][k])),
+                                                                               
bw_floor2(
+                                                                               
        bw_div(
+                                                                               
                results->src_data_for_last_output_pixel[i],
+                                                                               
                results->adjusted_data_buffer_size_in_memory[i]),
+                                                                               
        bw_int_to_fixed(
+                                                                               
                1))),
+                                                                       
results->active_time[i]));
+                                       }
+                               }
+                       }
+               }
+       }
+       /*cpu c-state and p-state change enable*/
+       /*for cpu p-state change to be possible for a yclk(pclk) and sclk level 
the dispclk required has to be enough for the blackout duration*/
+       /*for cpu c-state change to be possible for a yclk(pclk) and sclk level 
the dispclk required has to be enough for the blackout duration and recovery*/
+       /*condition for the blackout duration:*/
+       /* minimum latency hiding > blackout duration + dmif burst time + line 
source transfer time*/
+       /*condition for the blackout recovery:*/
+       /* recovery time >  dmif burst time + 2 * urgent latency*/
+       /* recovery time > (display bw * blackout duration  + (2 * urgent 
latency + dmif burst time)*dispclk - dmif size )*/
+       /*                  / (dispclk - display bw)*/
+       /*the minimum latency hiding is the minimum for all pipes of one screen 
line time, plus one more line time if doing lb prefetch, plus the dmif data 
buffer size equivalent in time, minus the urgent latency.*/
+       /*the minimum latency hiding is  further limited by the cursor.  the 
cursor latency hiding is the number of lines of the cursor buffer, minus one if 
the downscaling is less than two, or minus three if it is more*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_equ(
+                               
dceip->stutter_and_dram_clock_state_change_gated_before_cursor,
+                               bw_int_to_fixed(0))
+                               && bw_mtn(
+                                       results->cursor_width_pixels[i],
+                                       bw_int_to_fixed(0))) {
+                               if (bw_ltn(
+                                       results->vsr[i],
+                                       bw_int_to_fixed(2))) {
+                                       results->cursor_latency_hiding[i] =
+                                               bw_div(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       (bw_sub(
+                                                                               
dceip->cursor_dcp_buffer_lines,
+                                                                               
bw_int_to_fixed(
+                                                                               
        1))),
+                                                                       
results->h_total[i]),
+                                                               
results->vsr[i]),
+                                                       results->pixel_rate[i]);
+                               } else {
+                                       results->cursor_latency_hiding[i] =
+                                               bw_div(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       (bw_sub(
+                                                                               
dceip->cursor_dcp_buffer_lines,
+                                                                               
bw_int_to_fixed(
+                                                                               
        3))),
+                                                                       
results->h_total[i]),
+                                                               
results->vsr[i]),
+                                                       results->pixel_rate[i]);
+                               }
+                       } else {
+                               results->cursor_latency_hiding[i] =
+                                       bw_int_to_fixed(9999);
+                       }
+               }
+       }
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if 
(dceip->graphics_lb_nodownscaling_multi_line_prefetching
+                               == 1
+                               && (bw_equ(results->vsr[i], bw_int_to_fixed(1))
+                                       || (bw_leq(
+                                               results->vsr[i],
+                                               bw_frc_to_fixed(8, 10))
+                                               && bw_leq(
+                                                       results->v_taps[i],
+                                                       bw_int_to_fixed(2))
+                                               && results->lb_bpc[i] == 8))
+                               && surface_type[i] == bw_def_graphics) {
+                               results->minimum_latency_hiding[i] =
+                                       bw_sub(
+                                               bw_div(
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       (bw_add(
+                                                                               
bw_sub(
+                                                                               
        results->lb_partitions[i],
+                                                                               
        bw_int_to_fixed(
+                                                                               
                1)),
+                                                                               
bw_div(
+                                                                               
        bw_div(
+                                                                               
                results->data_buffer_size[i],
+                                                                               
                bw_int_to_fixed(
+                                                                               
                        results->bytes_per_pixel[i])),
+                                                                               
        results->source_width_pixels[i]))),
+                                                                       
results->vsr[i]),
+                                                               
results->h_total[i]),
+                                                       results->pixel_rate[i]),
+                                               
results->total_dmifmc_urgent_latency);
+                       } else {
+                               results->minimum_latency_hiding[i] =
+                                       bw_sub(
+                                               bw_div(
+                                                       bw_mul(
+                                                               (bw_add(
+                                                                       
bw_int_to_fixed(
+                                                                               
1
+                                                                               
        + results->line_buffer_prefetch[i]),
+                                                                       bw_div(
+                                                                               
bw_div(
+                                                                               
        bw_div(
+                                                                               
                results->data_buffer_size[i],
+                                                                               
                bw_int_to_fixed(
+                                                                               
                        results->bytes_per_pixel[i])),
+                                                                               
        results->source_width_pixels[i]),
+                                                                               
results->vsr[i]))),
+                                                               
results->h_total[i]),
+                                                       results->pixel_rate[i]),
+                                               
results->total_dmifmc_urgent_latency);
+                       }
+                       results->minimum_latency_hiding_with_cursor[i] =
+                               bw_min2(
+                                       results->minimum_latency_hiding[i],
+                                       results->cursor_latency_hiding[i]);
+               }
+       }
+       for (i = 0; i <= 2; i++) {
+               for (j = 0; j <= 2; j++) {
+                       results->blackout_duration_margin[i][j] =
+                               bw_int_to_fixed(9999);
+                       results->dispclk_required_for_blackout_duration[i][j] =
+                               bw_int_to_fixed(0);
+                       results->dispclk_required_for_blackout_recovery[i][j] =
+                               bw_int_to_fixed(0);
+                       for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+                               if (results->enable[k]
+                                       && bw_mtn(
+                                               vbios->blackout_duration,
+                                               bw_int_to_fixed(0))) {
+                                       if (surface_type[k]
+                                               != 
bw_def_display_write_back420_luma
+                                               && surface_type[k]
+                                                       != 
bw_def_display_write_back420_chroma) {
+                                               
results->blackout_duration_margin[i][j] =
+                                                       bw_min2(
+                                                               
results->blackout_duration_margin[i][j],
+                                                               bw_sub(
+                                                                       bw_sub(
+                                                                               
bw_sub(
+                                                                               
        results->minimum_latency_hiding_with_cursor[k],
+                                                                               
        vbios->blackout_duration),
+                                                                               
results->dmif_burst_time[i][j]),
+                                                                       
results->line_source_transfer_time[k][i][j]));
+                                               
results->dispclk_required_for_blackout_duration[i][j] =
+                                                       bw_max3(
+                                                               
results->dispclk_required_for_blackout_duration[i][j],
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_first_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_sub(
+                                                                               
bw_sub(
+                                                                               
        results->minimum_latency_hiding_with_cursor[k],
+                                                                               
        vbios->blackout_duration),
+                                                                               
results->dmif_burst_time[i][j]))),
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_last_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_add(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->minimum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->blackout_duration),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->active_time[k]))));
+                                               if (bw_leq(
+                                                       
vbios->maximum_blackout_recovery_time,
+                                                       bw_add(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
2),
+                                                                       
results->total_dmifmc_urgent_latency),
+                                                               
results->dmif_burst_time[i][j]))) {
+                                                       
results->dispclk_required_for_blackout_recovery[i][j] =
+                                                               bw_int_to_fixed(
+                                                                       9999);
+                                               } else if (bw_ltn(
+                                                       
results->adjusted_data_buffer_size[k],
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       bw_mul(
+                                                                               
results->display_bandwidth[k],
+                                                                               
results->useful_bytes_per_request[k]),
+                                                                       
results->bytes_per_request[k]),
+                                                               (bw_add(
+                                                                       
vbios->blackout_duration,
+                                                                       bw_add(
+                                                                               
bw_mul(
+                                                                               
        bw_int_to_fixed(
+                                                                               
                2),
+                                                                               
        results->total_dmifmc_urgent_latency),
+                                                                               
results->dmif_burst_time[i][j])))))) {
+                                                       
results->dispclk_required_for_blackout_recovery[i][j] =
+                                                               bw_max2(
+                                                                       
results->dispclk_required_for_blackout_recovery[i][j],
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        bw_div(
+                                                                               
                bw_div(
+                                                                               
                        (bw_sub(
+                                                                               
                                bw_mul(
+                                                                               
                                        bw_div(
+                                                                               
                                                bw_mul(
+                                                                               
                                                        
results->display_bandwidth[k],
+                                                                               
                                                        
results->useful_bytes_per_request[k]),
+                                                                               
                                                results->bytes_per_request[k]),
+                                                                               
                                        (bw_add(
+                                                                               
                                                vbios->blackout_duration,
+                                                                               
                                                
vbios->maximum_blackout_recovery_time))),
+                                                                               
                                results->adjusted_data_buffer_size[k])),
+                                                                               
                        bw_int_to_fixed(
+                                                                               
                                results->bytes_per_pixel[k])),
+                                                                               
                (bw_sub(
+                                                                               
                        vbios->maximum_blackout_recovery_time,
+                                                                               
                        bw_sub(
+                                                                               
                                bw_mul(
+                                                                               
                                        bw_int_to_fixed(
+                                                                               
                                                2),
+                                                                               
                                        results->total_dmifmc_urgent_latency),
+                                                                               
                                results->dmif_burst_time[i][j])))),
+                                                                               
        results->latency_hiding_lines[k]),
+                                                                               
results->lines_interleaved_in_mem_access[k]));
+                                               }
+                                       } else {
+                                               
results->blackout_duration_margin[i][j] =
+                                                       bw_min2(
+                                                               
results->blackout_duration_margin[i][j],
+                                                               bw_sub(
+                                                                       bw_sub(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->minimum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->blackout_duration),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->mcifwr_burst_time[i][j]),
+                                                                       
results->line_source_transfer_time[k][i][j]));
+                                               
results->dispclk_required_for_blackout_duration[i][j] =
+                                                       bw_max3(
+                                                               
results->dispclk_required_for_blackout_duration[i][j],
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_first_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_sub(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->minimum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->blackout_duration),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->mcifwr_burst_time[i][j]))),
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_last_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_add(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                bw_sub(
+                                                                               
                        results->minimum_latency_hiding_with_cursor[k],
+                                                                               
                        vbios->blackout_duration),
+                                                                               
                results->dmif_burst_time[i][j]),
+                                                                               
        results->mcifwr_burst_time[i][j]),
+                                                                               
results->active_time[k]))));
+                                               if (bw_ltn(
+                                                       
vbios->maximum_blackout_recovery_time,
+                                                       bw_add(
+                                                               bw_add(
+                                                                       bw_mul(
+                                                                               
bw_int_to_fixed(
+                                                                               
        2),
+                                                                               
vbios->mcifwrmc_urgent_latency),
+                                                                       
results->dmif_burst_time[i][j]),
+                                                               
results->mcifwr_burst_time[i][j]))) {
+                                                       
results->dispclk_required_for_blackout_recovery[i][j] =
+                                                               bw_int_to_fixed(
+                                                                       9999);
+                                               } else if (bw_ltn(
+                                                       
results->adjusted_data_buffer_size[k],
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       bw_mul(
+                                                                               
results->display_bandwidth[k],
+                                                                               
results->useful_bytes_per_request[k]),
+                                                                       
results->bytes_per_request[k]),
+                                                               (bw_add(
+                                                                       
vbios->blackout_duration,
+                                                                       bw_add(
+                                                                               
bw_mul(
+                                                                               
        bw_int_to_fixed(
+                                                                               
                2),
+                                                                               
        results->total_dmifmc_urgent_latency),
+                                                                               
results->dmif_burst_time[i][j])))))) {
+                                                       
results->dispclk_required_for_blackout_recovery[i][j] =
+                                                               bw_max2(
+                                                                       
results->dispclk_required_for_blackout_recovery[i][j],
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        bw_div(
+                                                                               
                bw_div(
+                                                                               
                        (bw_sub(
+                                                                               
                                bw_mul(
+                                                                               
                                        bw_div(
+                                                                               
                                                bw_mul(
+                                                                               
                                                        
results->display_bandwidth[k],
+                                                                               
                                                        
results->useful_bytes_per_request[k]),
+                                                                               
                                                results->bytes_per_request[k]),
+                                                                               
                                        (bw_add(
+                                                                               
                                                vbios->blackout_duration,
+                                                                               
                                                
vbios->maximum_blackout_recovery_time))),
+                                                                               
                                results->adjusted_data_buffer_size[k])),
+                                                                               
                        bw_int_to_fixed(
+                                                                               
                                results->bytes_per_pixel[k])),
+                                                                               
                (bw_sub(
+                                                                               
                        vbios->maximum_blackout_recovery_time,
+                                                                               
                        (bw_add(
+                                                                               
                                bw_mul(
+                                                                               
                                        bw_int_to_fixed(
+                                                                               
                                                2),
+                                                                               
                                        results->total_dmifmc_urgent_latency),
+                                                                               
                                results->dmif_burst_time[i][j]))))),
+                                                                               
        results->latency_hiding_lines[k]),
+                                                                               
results->lines_interleaved_in_mem_access[k]));
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       if (bw_mtn(
+               results->blackout_duration_margin[high][high],
+               bw_int_to_fixed(0))
+               && bw_ltn(
+                       
results->dispclk_required_for_blackout_duration[high][high],
+                       vbios->high_voltage_max_dispclk)) {
+               results->cpup_state_change_enable = bw_def_yes;
+               if (bw_ltn(
+                       
results->dispclk_required_for_blackout_recovery[high][high],
+                       vbios->high_voltage_max_dispclk)) {
+                       results->cpuc_state_change_enable = bw_def_yes;
+               } else {
+                       results->cpuc_state_change_enable = bw_def_no;
+               }
+       } else {
+               results->cpup_state_change_enable = bw_def_no;
+               results->cpuc_state_change_enable = bw_def_no;
+       }
+       /*nb p-state change enable*/
+       /*for dram speed/p-state change to be possible for a yclk(pclk) and 
sclk level there has to be positive margin and the dispclk required has to be 
below the maximum.*/
+       /*the dram speed/p-state change margin is the minimum for all surfaces 
of the maximum latency hiding minus the dram speed/p-state change latency, 
minus the dmif burst time, minus the source line transfer time*/
+       /*the maximum latency hiding is the minimum latency hiding plus one 
source line used for de-tiling in the line buffer, plus half the urgent 
latency*/
+       /*if stutter and dram clock state change are gated before cursor then 
the cursor latency hiding does not limit stutter or dram clock state change*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (mode_data->number_of_displays <= 1
+                               || mode_data->display_synchronization_enabled
+                                       == bw_def_yes) {
+                               results->maximum_latency_hiding[i] =
+                                       bw_int_to_fixed(450);
+                       } else {
+                               results->maximum_latency_hiding[i] =
+                                       bw_add(
+                                               
results->minimum_latency_hiding[i],
+                                               bw_add(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       bw_div(
+                                                                               
bw_int_to_fixed(
+                                                                               
        1),
+                                                                               
results->vsr[i]),
+                                                                       
results->h_total[i]),
+                                                               
results->pixel_rate[i]),
+                                                       bw_mul(
+                                                               bw_frc_to_fixed(
+                                                                       5,
+                                                                       10),
+                                                               
results->total_dmifmc_urgent_latency)));
+                       }
+                       results->maximum_latency_hiding_with_cursor[i] =
+                               bw_min2(
+                                       results->maximum_latency_hiding[i],
+                                       results->cursor_latency_hiding[i]);
+               }
+       }
+       for (i = 0; i <= 2; i++) {
+               for (j = 0; j <= 2; j++) {
+                       results->dram_speed_change_margin[i][j] =
+                               bw_int_to_fixed(9999);
+                       results->dispclk_required_for_dram_speed_change[i][j] =
+                               bw_int_to_fixed(0);
+                       for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+                               if (results->enable[k]) {
+                                       if (surface_type[k]
+                                               != 
bw_def_display_write_back420_luma
+                                               && surface_type[k]
+                                                       != 
bw_def_display_write_back420_chroma) {
+                                               
results->dram_speed_change_margin[i][j] =
+                                                       bw_min2(
+                                                               
results->dram_speed_change_margin[i][j],
+                                                               bw_sub(
+                                                                       bw_sub(
+                                                                               
bw_sub(
+                                                                               
        results->maximum_latency_hiding_with_cursor[k],
+                                                                               
        vbios->nbp_state_change_latency),
+                                                                               
results->dmif_burst_time[i][j]),
+                                                                       
results->line_source_transfer_time[k][i][j]));
+                                               
results->dispclk_required_for_dram_speed_change[i][j] =
+                                                       bw_max3(
+                                                               
results->dispclk_required_for_dram_speed_change[i][j],
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_first_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_sub(
+                                                                               
bw_sub(
+                                                                               
        results->maximum_latency_hiding_with_cursor[k],
+                                                                               
        vbios->nbp_state_change_latency),
+                                                                               
results->dmif_burst_time[i][j]))),
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_last_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_add(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->maximum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->nbp_state_change_latency),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->active_time[k]))));
+                                       } else {
+                                               
results->dram_speed_change_margin[i][j] =
+                                                       bw_min2(
+                                                               
results->dram_speed_change_margin[i][j],
+                                                               bw_sub(
+                                                                       bw_sub(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->maximum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->nbp_state_change_latency),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->mcifwr_burst_time[i][j]),
+                                                                       
results->line_source_transfer_time[k][i][j]));
+                                               
results->dispclk_required_for_dram_speed_change[i][j] =
+                                                       bw_max3(
+                                                               
results->dispclk_required_for_dram_speed_change[i][j],
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_first_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_sub(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                results->maximum_latency_hiding_with_cursor[k],
+                                                                               
                vbios->nbp_state_change_latency),
+                                                                               
        results->dmif_burst_time[i][j]),
+                                                                               
results->mcifwr_burst_time[i][j]))),
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->src_pixels_for_last_output_pixel[k],
+                                                                               
        dceip->display_pipe_throughput_factor),
+                                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                                       (bw_add(
+                                                                               
bw_sub(
+                                                                               
        bw_sub(
+                                                                               
                bw_sub(
+                                                                               
                        results->maximum_latency_hiding_with_cursor[k],
+                                                                               
                        vbios->nbp_state_change_latency),
+                                                                               
                results->dmif_burst_time[i][j]),
+                                                                               
        results->mcifwr_burst_time[i][j]),
+                                                                               
results->active_time[k]))));
+                                       }
+                               }
+                       }
+               }
+       }
+       if (bw_mtn(
+               results->dram_speed_change_margin[high][high],
+               bw_int_to_fixed(0))
+               && bw_ltn(
+                       
results->dispclk_required_for_dram_speed_change[high][high],
+                       vbios->high_voltage_max_dispclk)) {
+               results->nbp_state_change_enable = bw_def_yes;
+       } else {
+               results->nbp_state_change_enable = bw_def_no;
+       }
+       /*required yclk(pclk)*/
+       /*yclk requirement only makes sense if the dmif and mcifwr data total 
page close-open time is less than the time for data transfer and the total pte 
requests fit in the scatter-gather saw queque size*/
+       /*if that is the case, the yclk requirement is the maximum of the ones 
required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/
+       /*high yclk(pclk) has to be selected when dram speed/p-state change is 
not possible.*/
+       results->min_cursor_memory_interface_buffer_size_in_time =
+               bw_int_to_fixed(9999);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_mtn(
+                               results->cursor_width_pixels[i],
+                               bw_int_to_fixed(0))) {
+                               
results->min_cursor_memory_interface_buffer_size_in_time =
+                                       bw_min2(
+                                               
results->min_cursor_memory_interface_buffer_size_in_time,
+                                               bw_div(
+                                                       bw_mul(
+                                                               bw_div(
+                                                                       bw_div(
+                                                                               
dceip->cursor_memory_interface_buffer_pixels,
+                                                                               
results->cursor_width_pixels[i]),
+                                                                       
results->vsr[i]),
+                                                               
results->h_total[i]),
+                                                       
results->pixel_rate[i]));
+                       }
+               }
+       }
+       results->min_read_buffer_size_in_time = bw_min2(
+               results->min_cursor_memory_interface_buffer_size_in_time,
+               results->min_dmif_size_in_time);
+       results->display_reads_time_for_data_transfer = bw_sub(
+               results->min_read_buffer_size_in_time,
+               results->total_dmifmc_urgent_latency);
+       results->display_writes_time_for_data_transfer = bw_sub(
+               results->min_mcifwr_size_in_time,
+               vbios->mcifwrmc_urgent_latency);
+       results->dmif_required_dram_bandwidth = bw_div(
+               results->total_display_reads_required_dram_access_data,
+               results->display_reads_time_for_data_transfer);
+       results->mcifwr_required_dram_bandwidth = bw_div(
+               results->total_display_writes_required_dram_access_data,
+               results->display_writes_time_for_data_transfer);
+       results->required_dmifmc_urgent_latency_for_page_close_open = bw_div(
+               (bw_sub(
+                       results->min_read_buffer_size_in_time,
+                       results->dmif_total_page_close_open_time)),
+               results->total_dmifmc_urgent_trips);
+       results->required_mcifmcwr_urgent_latency = bw_sub(
+               results->min_mcifwr_size_in_time,
+               results->mcifwr_total_page_close_open_time);
+       if (bw_mtn(
+               results->scatter_gather_total_pte_requests,
+               dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+               results->required_dram_bandwidth_gbyte_per_second =
+                       bw_int_to_fixed(9999);
+               yclk_message =
+                       bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+               results->y_clk_level = high;
+               results->dram_bandwidth =
+                       bw_mul(
+                               bw_div(
+                                       bw_mul(
+                                               yclk[high],
+                                               bw_int_to_fixed(
+                                                       
vbios->dram_channel_width_in_bits)),
+                                       bw_int_to_fixed(8)),
+                               bw_int_to_fixed(
+                                       vbios->number_of_dram_channels));
+       } else if (bw_mtn(
+               vbios->dmifmc_urgent_latency,
+               results->required_dmifmc_urgent_latency_for_page_close_open)
+               || bw_mtn(
+                       vbios->mcifwrmc_urgent_latency,
+                       results->required_mcifmcwr_urgent_latency)) {
+               results->required_dram_bandwidth_gbyte_per_second =
+                       bw_int_to_fixed(9999);
+               yclk_message = bw_def_exceeded_allowed_page_close_open;
+               results->y_clk_level = high;
+               results->dram_bandwidth =
+                       bw_mul(
+                               bw_div(
+                                       bw_mul(
+                                               yclk[high],
+                                               bw_int_to_fixed(
+                                                       
vbios->dram_channel_width_in_bits)),
+                                       bw_int_to_fixed(8)),
+                               bw_int_to_fixed(
+                                       vbios->number_of_dram_channels));
+       } else {
+               results->required_dram_bandwidth_gbyte_per_second = bw_div(
+                       bw_max2(
+                               results->dmif_required_dram_bandwidth,
+                               results->mcifwr_required_dram_bandwidth),
+                       bw_int_to_fixed(1000));
+               if (bw_ltn(
+                       bw_mul(
+                               
results->required_dram_bandwidth_gbyte_per_second,
+                               bw_int_to_fixed(1000)),
+                       bw_mul(
+                               bw_div(
+                                       bw_mul(
+                                               yclk[low],
+                                               bw_int_to_fixed(
+                                                       
vbios->dram_channel_width_in_bits)),
+                                       bw_int_to_fixed(8)),
+                               bw_int_to_fixed(
+                                       vbios->number_of_dram_channels)))
+                       && (results->cpup_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[low][high],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[low][high],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && (results->cpuc_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[low][high],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[low][high],
+                                               vbios->high_voltage_max_dispclk)
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_recovery[low][high],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && bw_mtn(
+                               results->dram_speed_change_margin[low][high],
+                               bw_int_to_fixed(0))
+                       && bw_ltn(
+                               
results->dispclk_required_for_dram_speed_change[low][high],
+                               vbios->high_voltage_max_dispclk)) {
+                       yclk_message = bw_def_low;
+                       results->y_clk_level = low;
+                       results->dram_bandwidth =
+                               bw_mul(
+                                       bw_div(
+                                               bw_mul(
+                                                       yclk[low],
+                                                       bw_int_to_fixed(
+                                                               
vbios->dram_channel_width_in_bits)),
+                                               bw_int_to_fixed(8)),
+                                       bw_int_to_fixed(
+                                               
vbios->number_of_dram_channels));
+               } else if (bw_ltn(
+                       bw_mul(
+                               
results->required_dram_bandwidth_gbyte_per_second,
+                               bw_int_to_fixed(1000)),
+                       bw_mul(
+                               bw_div(
+                                       bw_mul(
+                                               yclk[high],
+                                               bw_int_to_fixed(
+                                                       
vbios->dram_channel_width_in_bits)),
+                                       bw_int_to_fixed(8)),
+                               bw_int_to_fixed(
+                                       vbios->number_of_dram_channels)))) {
+                       yclk_message = bw_def_high;
+                       results->y_clk_level = high;
+                       results->dram_bandwidth =
+                               bw_mul(
+                                       bw_div(
+                                               bw_mul(
+                                                       yclk[high],
+                                                       bw_int_to_fixed(
+                                                               
vbios->dram_channel_width_in_bits)),
+                                               bw_int_to_fixed(8)),
+                                       bw_int_to_fixed(
+                                               
vbios->number_of_dram_channels));
+               } else {
+                       yclk_message = bw_def_exceeded_allowed_maximum_bw;
+                       results->y_clk_level = high;
+                       results->dram_bandwidth =
+                               bw_mul(
+                                       bw_div(
+                                               bw_mul(
+                                                       yclk[high],
+                                                       bw_int_to_fixed(
+                                                               
vbios->dram_channel_width_in_bits)),
+                                               bw_int_to_fixed(8)),
+                                       bw_int_to_fixed(
+                                               
vbios->number_of_dram_channels));
+               }
+       }
+       /*required sclk*/
+       /*sclk requirement only makes sense if the total pte requests fit in 
the scatter-gather saw queque size*/
+       /*if that is the case, the sclk requirement is the maximum of the ones 
required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, 
unless that choice results in foresaking dram speed/nb p-state change.*/
+       /*the dmif and mcifwr sclk required is the one that allows the transfer 
of all pipe's data buffer size through the sclk bus in the time for data 
transfer*/
+       /*for dmif, pte and cursor requests have to be included.*/
+       results->dmif_required_sclk = bw_div(
+               bw_div(
+                       results->total_display_reads_required_data,
+                       results->display_reads_time_for_data_transfer),
+               vbios->data_return_bus_width);
+       results->mcifwr_required_sclk = bw_div(
+               bw_div(
+                       results->total_display_writes_required_data,
+                       results->display_writes_time_for_data_transfer),
+               vbios->data_return_bus_width);
+       if (bw_mtn(
+               results->scatter_gather_total_pte_requests,
+               dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+               results->required_sclk = bw_int_to_fixed(9999);
+               sclk_message =
+                       bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+               results->sclk_level = high;
+       } else if (bw_mtn(
+               vbios->dmifmc_urgent_latency,
+               results->required_dmifmc_urgent_latency_for_page_close_open)
+               || bw_mtn(
+                       vbios->mcifwrmc_urgent_latency,
+                       results->required_mcifmcwr_urgent_latency)) {
+               results->required_sclk = bw_int_to_fixed(9999);
+               sclk_message = bw_def_exceeded_allowed_page_close_open;
+               results->sclk_level = high;
+       } else {
+               results->required_sclk = bw_max2(
+                       results->dmif_required_sclk,
+                       results->mcifwr_required_sclk);
+               if (bw_ltn(results->required_sclk, sclk[low])
+                       && (results->cpup_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[results->y_clk_level][low],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && (results->cpuc_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[results->y_clk_level][low],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+                                               vbios->high_voltage_max_dispclk)
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_recovery[results->y_clk_level][low],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && (results->nbp_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->dram_speed_change_margin[results->y_clk_level][low],
+                                       bw_int_to_fixed(0))
+                                       && bw_leq(
+                                               
results->dispclk_required_for_dram_speed_change[results->y_clk_level][low],
+                                               
vbios->high_voltage_max_dispclk)))) {
+                       sclk_message = bw_def_low;
+                       results->sclk_level = low;
+               } else if (bw_ltn(results->required_sclk, sclk[mid])
+                       && (results->cpup_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[results->y_clk_level][mid],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && (results->cpuc_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->blackout_duration_margin[results->y_clk_level][mid],
+                                       bw_int_to_fixed(0))
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+                                               vbios->high_voltage_max_dispclk)
+                                       && bw_ltn(
+                                               
results->dispclk_required_for_blackout_recovery[results->y_clk_level][mid],
+                                               
vbios->high_voltage_max_dispclk)))
+                       && (results->nbp_state_change_enable == bw_def_no
+                               || (bw_mtn(
+                                       
results->dram_speed_change_margin[results->y_clk_level][mid],
+                                       bw_int_to_fixed(0))
+                                       && bw_leq(
+                                               
results->dispclk_required_for_dram_speed_change[results->y_clk_level][mid],
+                                               
vbios->high_voltage_max_dispclk)))) {
+                       sclk_message = bw_def_mid;
+                       results->sclk_level = mid;
+               } else if (bw_ltn(results->required_sclk, sclk[high])) {
+                       sclk_message = bw_def_high;
+                       results->sclk_level = high;
+               } else {
+                       sclk_message = bw_def_exceeded_allowed_maximum_sclk;
+                       results->sclk_level = high;
+               }
+       }
+       /*dispclk*/
+       /*if dispclk is set to the maximum, ramping is not required.  dispclk 
required without ramping is less than the dispclk required with ramping.*/
+       /*if dispclk required without ramping is more than the maximum dispclk, 
that is the dispclk required, and the mode is not supported*/
+       /*if that does not happen, but dispclk required with ramping is more 
than the maximum dispclk, dispclk required is just the maximum dispclk*/
+       /*if that does not happen either, dispclk required is the dispclk 
required with ramping.*/
+       /*dispclk required without ramping is the maximum of the one required 
for display pipe pixel throughput, for scaler throughput, for total read 
request thrrougput and for dram/np p-state change if enabled.*/
+       /*the display pipe pixel throughput is the maximum of lines in per line 
out in the beginning of the frame and lines in per line out in the middle of 
the frame multiplied by the horizontal blank and chunk granularity factor, 
altogether multiplied by the ratio of the source width to the line time, 
divided by the line buffer pixels per dispclk throughput, and multiplied by the 
display pipe throughput factor.*/
+       /*the horizontal blank and chunk granularity factor is the ratio of the 
line time divided by the line time minus half the horizontal blank and chunk 
time.  it applies when the lines in per line out is not 2 or 4.*/
+       /*the dispclk required for scaler throughput is the product of the 
pixel rate and the scaling limits factor.*/
+       /*the dispclk required for total read request throughput is the product 
of the peak request-per-second bandwidth and the dispclk cycles per request, 
divided by the request efficiency.*/
+       /*for the dispclk required with ramping, instead of multiplying just 
the pipe throughput by the display pipe throughput factor, we multiply the 
scaler and pipe throughput by the ramping factor.*/
+       /*the scaling limits factor is the product of the horizontal scale 
ratio, and the ratio of the vertical taps divided by the scaler efficiency 
clamped to at least 1.*/
+       /*the scaling limits factor itself it also clamped to at least 1*/
+       /*if doing downscaling with the pre-downscaler enabled, the horizontal 
scale ratio should not be considered above (use "1")*/
+       results->downspread_factor = bw_add(
+               bw_int_to_fixed(1),
+               bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100)));
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] == bw_def_graphics) {
+                               switch (results->lb_bpc[i]) {
+                               case 6:
+                                       results->v_scaler_efficiency =
+                                               
dceip->graphics_vscaler_efficiency6_bit_per_component;
+                                       break;
+                               case 8:
+                                       results->v_scaler_efficiency =
+                                               
dceip->graphics_vscaler_efficiency8_bit_per_component;
+                                       break;
+                               case 10:
+                                       results->v_scaler_efficiency =
+                                               
dceip->graphics_vscaler_efficiency10_bit_per_component;
+                                       break;
+                               default:
+                                       results->v_scaler_efficiency =
+                                               
dceip->graphics_vscaler_efficiency12_bit_per_component;
+                                       break;
+                               }
+                               if (results->use_alpha[i] == 1) {
+                                       results->v_scaler_efficiency =
+                                               bw_min2(
+                                                       
results->v_scaler_efficiency,
+                                                       
dceip->alpha_vscaler_efficiency);
+                               }
+                       } else {
+                               switch (results->lb_bpc[i]) {
+                               case 6:
+                                       results->v_scaler_efficiency =
+                                               
dceip->underlay_vscaler_efficiency6_bit_per_component;
+                                       break;
+                               case 8:
+                                       results->v_scaler_efficiency =
+                                               
dceip->underlay_vscaler_efficiency8_bit_per_component;
+                                       break;
+                               case 10:
+                                       results->v_scaler_efficiency =
+                                               
dceip->underlay_vscaler_efficiency10_bit_per_component;
+                                       break;
+                               default:
+                                       results->v_scaler_efficiency =
+                                               
dceip->underlay_vscaler_efficiency12_bit_per_component;
+                                       break;
+                               }
+                       }
+                       if (dceip->pre_downscaler_enabled
+                               && bw_mtn(
+                                       results->hsr[i],
+                                       bw_int_to_fixed(1))) {
+                               results->scaler_limits_factor =
+                                       bw_max2(
+                                               bw_div(
+                                                       results->v_taps[i],
+                                                       
results->v_scaler_efficiency),
+                                               bw_div(
+                                                       
results->source_width_rounded_up_to_chunks[i],
+                                                       results->h_total[i]));
+                       } else {
+                               results->scaler_limits_factor =
+                                       bw_max3(
+                                               bw_int_to_fixed(1),
+                                               bw_ceil2(
+                                                       bw_div(
+                                                               
results->h_taps[i],
+                                                               bw_int_to_fixed(
+                                                                       4)),
+                                                       bw_int_to_fixed(1)),
+                                               bw_mul(
+                                                       results->hsr[i],
+                                                       bw_max2(
+                                                               bw_div(
+                                                                       
results->v_taps[i],
+                                                                       
results->v_scaler_efficiency),
+                                                               bw_int_to_fixed(
+                                                                       1))));
+                       }
+                       results->display_pipe_pixel_throughput =
+                               bw_div(
+                                       bw_div(
+                                               bw_mul(
+                                                       bw_max2(
+                                                               
results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+                                                               bw_mul(
+                                                                       
results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+                                                                       
results->horizontal_blank_and_chunk_granularity_factor[i])),
+                                                       
results->source_width_rounded_up_to_chunks[i]),
+                                               (bw_div(
+                                                       results->h_total[i],
+                                                       
results->pixel_rate[i]))),
+                                       dceip->lb_write_pixels_per_dispclk);
+                       results->dispclk_required_without_ramping[i] =
+                               bw_mul(
+                                       results->downspread_factor,
+                                       bw_max2(
+                                               bw_mul(
+                                                       results->pixel_rate[i],
+                                                       
results->scaler_limits_factor),
+                                               bw_mul(
+                                                       
dceip->display_pipe_throughput_factor,
+                                                       
results->display_pipe_pixel_throughput)));
+                       results->dispclk_required_with_ramping[i] =
+                               bw_mul(
+                                       dceip->dispclk_ramping_factor,
+                                       bw_max2(
+                                               bw_mul(
+                                                       results->pixel_rate[i],
+                                                       
results->scaler_limits_factor),
+                                               
results->display_pipe_pixel_throughput));
+               }
+       }
+       results->total_dispclk_required_with_ramping = bw_int_to_fixed(0);
+       results->total_dispclk_required_without_ramping = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_ltn(
+                               results->total_dispclk_required_with_ramping,
+                               results->dispclk_required_with_ramping[i])) {
+                               results->total_dispclk_required_with_ramping =
+                                       
results->dispclk_required_with_ramping[i];
+                       }
+                       if (bw_ltn(
+                               results->total_dispclk_required_without_ramping,
+                               results->dispclk_required_without_ramping[i])) {
+                               results->total_dispclk_required_without_ramping 
=
+                                       
results->dispclk_required_without_ramping[i];
+                       }
+               }
+       }
+       results->total_read_request_bandwidth = bw_int_to_fixed(0);
+       results->total_write_request_bandwidth = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               results->total_read_request_bandwidth = bw_add(
+                                       results->total_read_request_bandwidth,
+                                       results->request_bandwidth[i]);
+                       } else {
+                               results->total_write_request_bandwidth = bw_add(
+                                       results->total_write_request_bandwidth,
+                                       results->request_bandwidth[i]);
+                       }
+               }
+       }
+       results->dispclk_required_for_total_read_request_bandwidth = bw_div(
+               bw_mul(
+                       results->total_read_request_bandwidth,
+                       dceip->dispclk_per_request),
+               dceip->request_efficiency);
+       if (dceip->dcfclk_request_generation == 0) {
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth =
+                       bw_max2(
+                               results->total_dispclk_required_with_ramping,
+                               
results->dispclk_required_for_total_read_request_bandwidth);
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth =
+                       bw_max2(
+                               results->total_dispclk_required_without_ramping,
+                               
results->dispclk_required_for_total_read_request_bandwidth);
+       } else {
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth =
+                       results->total_dispclk_required_with_ramping;
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth =
+                       results->total_dispclk_required_without_ramping;
+       }
+       if (results->cpuc_state_change_enable == bw_def_yes) {
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth =
+                       bw_max3(
+                               
results->total_dispclk_required_with_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+                               
results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth =
+                       bw_max3(
+                               
results->total_dispclk_required_without_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+                               
results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+       }
+       if (results->cpup_state_change_enable == bw_def_yes) {
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth =
+                       bw_max2(
+                               
results->total_dispclk_required_with_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth =
+                       bw_max2(
+                               
results->total_dispclk_required_without_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+       }
+       if (results->nbp_state_change_enable == bw_def_yes) {
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth =
+                       bw_max2(
+                               
results->total_dispclk_required_with_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth =
+                       bw_max2(
+                               
results->total_dispclk_required_without_ramping_with_request_bandwidth,
+                               
results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+       }
+       if (bw_ltn(
+               
results->total_dispclk_required_with_ramping_with_request_bandwidth,
+               vbios->high_voltage_max_dispclk)) {
+               results->dispclk =
+                       
results->total_dispclk_required_with_ramping_with_request_bandwidth;
+       } else if (bw_ltn(
+               
results->total_dispclk_required_without_ramping_with_request_bandwidth,
+               vbios->high_voltage_max_dispclk)) {
+               results->dispclk = vbios->high_voltage_max_dispclk;
+       } else {
+               results->dispclk =
+                       
results->total_dispclk_required_without_ramping_with_request_bandwidth;
+       }
+       /* required core voltage*/
+       /* the core voltage required is low if sclk, yclk(pclk)and dispclk are 
within the low limits*/
+       /* otherwise, the core voltage required is medium if yclk (pclk) is 
within the low limit and sclk and dispclk are within the medium limit*/
+       /* otherwise, the core voltage required is high if the three clocks are 
within the high limits*/
+       /* otherwise, or if the mode is not supported, core voltage requirement 
is not applicable*/
+       if (pipe_check == bw_def_notok) {
+               voltage = bw_def_na;
+       } else if (mode_check == bw_def_notok) {
+               voltage = bw_def_notok;
+       } else if (yclk_message == bw_def_low && sclk_message == bw_def_low
+               && bw_ltn(results->dispclk, vbios->low_voltage_max_dispclk)) {
+               voltage = bw_def_low;
+       } else if (yclk_message == bw_def_low
+               && (sclk_message == bw_def_low || sclk_message == bw_def_mid)
+               && bw_ltn(results->dispclk, vbios->mid_voltage_max_dispclk)) {
+               voltage = bw_def_mid;
+       } else if ((yclk_message == bw_def_low || yclk_message == bw_def_high)
+               && (sclk_message == bw_def_low || sclk_message == bw_def_mid
+                       || sclk_message == bw_def_high)
+               && bw_leq(results->dispclk, vbios->high_voltage_max_dispclk)) {
+               if (results->nbp_state_change_enable == bw_def_yes) {
+                       voltage = bw_def_high;
+               } else {
+                       voltage = bw_def_high_no_nbp_state_change;
+               }
+       } else {
+               voltage = bw_def_notok;
+       }
+       /*required blackout recovery time*/
+       results->blackout_recovery_time = bw_int_to_fixed(0);
+       for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+               if (results->enable[k]
+                       && bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))
+                       && results->cpup_state_change_enable == bw_def_yes) {
+                       if (surface_type[k] != bw_def_display_write_back420_luma
+                               && surface_type[k]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               results->blackout_recovery_time =
+                                       bw_max2(
+                                               results->blackout_recovery_time,
+                                               bw_add(
+                                                       bw_mul(
+                                                               bw_int_to_fixed(
+                                                                       2),
+                                                               
results->total_dmifmc_urgent_latency),
+                                                       
results->dmif_burst_time[results->y_clk_level][results->sclk_level]));
+                               if (bw_ltn(
+                                       results->adjusted_data_buffer_size[k],
+                                       bw_mul(
+                                               bw_div(
+                                                       bw_mul(
+                                                               
results->display_bandwidth[k],
+                                                               
results->useful_bytes_per_request[k]),
+                                                       
results->bytes_per_request[k]),
+                                               (bw_add(
+                                                       
vbios->blackout_duration,
+                                                       bw_add(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
2),
+                                                                       
results->total_dmifmc_urgent_latency),
+                                                               
results->dmif_burst_time[results->y_clk_level][results->sclk_level])))))) {
+                                       results->blackout_recovery_time =
+                                               bw_max2(
+                                                       
results->blackout_recovery_time,
+                                                       bw_div(
+                                                               (bw_add(
+                                                                       bw_mul(
+                                                                               
bw_div(
+                                                                               
        bw_mul(
+                                                                               
                results->display_bandwidth[k],
+                                                                               
                results->useful_bytes_per_request[k]),
+                                                                               
        results->bytes_per_request[k]),
+                                                                               
vbios->blackout_duration),
+                                                                       bw_sub(
+                                                                               
bw_div(
+                                                                               
        bw_mul(
+                                                                               
                bw_mul(
+                                                                               
                        bw_mul(
+                                                                               
                                (bw_add(
+                                                                               
                                        bw_mul(
+                                                                               
                                                bw_int_to_fixed(
+                                                                               
                                                        2),
+                                                                               
                                                
results->total_dmifmc_urgent_latency),
+                                                                               
                                        
results->dmif_burst_time[results->y_clk_level][results->sclk_level])),
+                                                                               
                                results->dispclk),
+                                                                               
                        bw_int_to_fixed(
+                                                                               
                                results->bytes_per_pixel[k])),
+                                                                               
                results->lines_interleaved_in_mem_access[k]),
+                                                                               
        results->latency_hiding_lines[k]),
+                                                                               
results->adjusted_data_buffer_size[k]))),
+                                                               (bw_sub(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        bw_mul(
+                                                                               
                results->dispclk,
+                                                                               
                bw_int_to_fixed(
+                                                                               
                        results->bytes_per_pixel[k])),
+                                                                               
        results->lines_interleaved_in_mem_access[k]),
+                                                                               
results->latency_hiding_lines[k]),
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->display_bandwidth[k],
+                                                                               
        results->useful_bytes_per_request[k]),
+                                                                               
results->bytes_per_request[k])))));
+                               }
+                       } else {
+                               results->blackout_recovery_time =
+                                       bw_max2(
+                                               results->blackout_recovery_time,
+                                               bw_add(
+                                                       bw_mul(
+                                                               bw_int_to_fixed(
+                                                                       2),
+                                                               
vbios->mcifwrmc_urgent_latency),
+                                                       
results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]));
+                               if (bw_ltn(
+                                       results->adjusted_data_buffer_size[k],
+                                       bw_mul(
+                                               bw_div(
+                                                       bw_mul(
+                                                               
results->display_bandwidth[k],
+                                                               
results->useful_bytes_per_request[k]),
+                                                       
results->bytes_per_request[k]),
+                                               (bw_add(
+                                                       
vbios->blackout_duration,
+                                                       bw_add(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
2),
+                                                                       
vbios->mcifwrmc_urgent_latency),
+                                                               
results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])))))) {
+                                       results->blackout_recovery_time =
+                                               bw_max2(
+                                                       
results->blackout_recovery_time,
+                                                       bw_div(
+                                                               (bw_add(
+                                                                       bw_mul(
+                                                                               
bw_div(
+                                                                               
        bw_mul(
+                                                                               
                results->display_bandwidth[k],
+                                                                               
                results->useful_bytes_per_request[k]),
+                                                                               
        results->bytes_per_request[k]),
+                                                                               
vbios->blackout_duration),
+                                                                       bw_sub(
+                                                                               
bw_div(
+                                                                               
        bw_mul(
+                                                                               
                bw_mul(
+                                                                               
                        bw_mul(
+                                                                               
                                (bw_add(
+                                                                               
                                        bw_add(
+                                                                               
                                                bw_mul(
+                                                                               
                                                        bw_int_to_fixed(
+                                                                               
                                                                2),
+                                                                               
                                                        
vbios->mcifwrmc_urgent_latency),
+                                                                               
                                                results->dmif_burst_time[i][j]),
+                                                                               
                                        
results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])),
+                                                                               
                                results->dispclk),
+                                                                               
                        bw_int_to_fixed(
+                                                                               
                                results->bytes_per_pixel[k])),
+                                                                               
                results->lines_interleaved_in_mem_access[k]),
+                                                                               
        results->latency_hiding_lines[k]),
+                                                                               
results->adjusted_data_buffer_size[k]))),
+                                                               (bw_sub(
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        bw_mul(
+                                                                               
                results->dispclk,
+                                                                               
                bw_int_to_fixed(
+                                                                               
                        results->bytes_per_pixel[k])),
+                                                                               
        results->lines_interleaved_in_mem_access[k]),
+                                                                               
results->latency_hiding_lines[k]),
+                                                                       bw_div(
+                                                                               
bw_mul(
+                                                                               
        results->display_bandwidth[k],
+                                                                               
        results->useful_bytes_per_request[k]),
+                                                                               
results->bytes_per_request[k])))));
+                               }
+                       }
+               }
+       }
+       /*sclk deep sleep*/
+       /*during self-refresh, sclk can be reduced to dispclk divided by the 
minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set 
to less than the request bandwidth.*/
+       /*the data fifo entry is 16 pixels for the writeback, 64 
bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation 
underlay,*/
+       /*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/
+       /*in parallel mode (underlay pipe), the data read from the dmifv buffer 
is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 
32 bpp - 64 bytes)*/
+       /*in orthogonal mode (underlay pipe), the data read from the dmifv 
buffer is fixed at 16 bytes.*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (surface_type[i] == bw_def_display_write_back420_luma
+                               || surface_type[i]
+                                       == bw_def_display_write_back420_chroma) 
{
+                               results->pixels_per_data_fifo_entry[i] =
+                                       bw_int_to_fixed(16);
+                       } else if (surface_type[i] == bw_def_graphics) {
+                               results->pixels_per_data_fifo_entry[i] = bw_div(
+                                       bw_int_to_fixed(64),
+                                       bw_int_to_fixed(
+                                               results->bytes_per_pixel[i]));
+                       } else if (results->orthogonal_rotation[i] == 0) {
+                               results->pixels_per_data_fifo_entry[i] =
+                                       bw_int_to_fixed(16);
+                       } else {
+                               results->pixels_per_data_fifo_entry[i] = bw_div(
+                                       bw_int_to_fixed(16),
+                                       bw_int_to_fixed(
+                                               results->bytes_per_pixel[i]));
+                       }
+               }
+       }
+       results->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_mtn(
+                               results->min_pixels_per_data_fifo_entry,
+                               results->pixels_per_data_fifo_entry[i])) {
+                               results->min_pixels_per_data_fifo_entry =
+                                       results->pixels_per_data_fifo_entry[i];
+                       }
+               }
+       }
+       results->sclk_deep_sleep = bw_max2(
+               bw_div(
+                       bw_mul(results->dispclk, bw_frc_to_fixed(115, 100)),
+                       results->min_pixels_per_data_fifo_entry),
+               results->total_read_request_bandwidth);
+       /*urgent, stutter and nb-p_state watermark*/
+       /*the urgent watermark is the maximum of the urgent trip time plus the 
pixel transfer time, the urgent trip times to get data for the first pixel, and 
the urgent trip times to get data for the last pixel.*/
+       /*the stutter exit watermark is the self refresh exit time plus the 
maximum of the data burst time plus the pixel transfer time, the data burst 
times to get data for the first pixel, and the data burst times to get data for 
the last pixel.  it does not apply to the writeback.*/
+       /*the nb p-state change watermark is the dram speed/p-state change time 
plus the maximum of the data burst time plus the pixel transfer time, the data 
burst times to get data for the first pixel, and the data burst times to get 
data for the last pixel.*/
+       /*the pixel transfer time is the maximum of the time to transfer the 
source pixels required for the first output pixel, and the time to transfer the 
pixels for the last output pixel minus the active line time.*/
+       /*blackout_duration is added to the urgent watermark*/
+       results->chunk_request_time = bw_int_to_fixed(0);
+       results->cursor_request_time = bw_int_to_fixed(0);
+       /*compute total time to request one chunk from each active display 
pipe*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->chunk_request_time =
+                               bw_add(
+                                       results->chunk_request_time,
+                                       (bw_div(
+                                               (bw_div(
+                                                       bw_int_to_fixed(
+                                                               pixels_per_chunk
+                                                                       * 
results->bytes_per_pixel[i]),
+                                                       
results->useful_bytes_per_request[i])),
+                                               bw_min2(
+                                                       
sclk[results->sclk_level],
+                                                       bw_div(
+                                                               
results->dispclk,
+                                                               bw_int_to_fixed(
+                                                                       2))))));
+               }
+       }
+       /*compute total time to request cursor data*/
+       results->cursor_request_time = (bw_div(
+               results->cursor_total_data,
+               (bw_mul(bw_int_to_fixed(32), sclk[results->sclk_level]))));
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->line_source_pixels_transfer_time =
+                               bw_max2(
+                                       bw_div(
+                                               bw_div(
+                                                       
results->src_pixels_for_first_output_pixel[i],
+                                                       
dceip->lb_write_pixels_per_dispclk),
+                                               (bw_div(
+                                                       results->dispclk,
+                                                       
dceip->display_pipe_throughput_factor))),
+                                       bw_sub(
+                                               bw_div(
+                                                       bw_div(
+                                                               
results->src_pixels_for_last_output_pixel[i],
+                                                               
dceip->lb_write_pixels_per_dispclk),
+                                                       (bw_div(
+                                                               
results->dispclk,
+                                                               
dceip->display_pipe_throughput_factor))),
+                                               results->active_time[i]));
+                       if (surface_type[i] != bw_def_display_write_back420_luma
+                               && surface_type[i]
+                                       != bw_def_display_write_back420_chroma) 
{
+                               results->urgent_watermark[i] =
+                                       bw_add(
+                                               bw_add(
+                                                       bw_add(
+                                                               bw_add(
+                                                                       bw_add(
+                                                                               
results->total_dmifmc_urgent_latency,
+                                                                               
results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+                                                                       bw_max2(
+                                                                               
results->line_source_pixels_transfer_time,
+                                                                               
results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+                                                               
vbios->blackout_duration),
+                                                       
results->chunk_request_time),
+                                               results->cursor_request_time);
+                               results->stutter_exit_watermark[i] =
+                                       bw_add(
+                                               bw_sub(
+                                                       
vbios->stutter_self_refresh_exit_latency,
+                                                       
results->total_dmifmc_urgent_latency),
+                                               results->urgent_watermark[i]);
+                               /*unconditionally remove black out time from 
the nb p_state watermark*/
+                               results->nbp_state_change_watermark[i] =
+                                       bw_sub(
+                                               bw_add(
+                                                       bw_sub(
+                                                               
vbios->nbp_state_change_latency,
+                                                               
results->total_dmifmc_urgent_latency),
+                                                       
results->urgent_watermark[i]),
+                                               vbios->blackout_duration);
+                       } else {
+                               results->urgent_watermark[i] =
+                                       bw_add(
+                                               bw_add(
+                                                       bw_add(
+                                                               bw_add(
+                                                                       bw_add(
+                                                                               
vbios->mcifwrmc_urgent_latency,
+                                                                               
results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]),
+                                                                       bw_max2(
+                                                                               
results->line_source_pixels_transfer_time,
+                                                                               
results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+                                                               
vbios->blackout_duration),
+                                                       
results->chunk_request_time),
+                                               results->cursor_request_time);
+                               results->stutter_exit_watermark[i] =
+                                       bw_int_to_fixed(0);
+                               results->nbp_state_change_watermark[i] =
+                                       bw_add(
+                                               bw_sub(
+                                                       bw_add(
+                                                               
vbios->nbp_state_change_latency,
+                                                               
results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+                                                       
vbios->mcifwrmc_urgent_latency),
+                                               results->urgent_watermark[i]);
+                       }
+               }
+       }
+       /*stutter mode enable*/
+       /*in the multi-display case the stutter exit watermark cannot exceed 
the cursor dcp buffer size*/
+       results->stutter_mode_enable = results->cpuc_state_change_enable;
+       if (mode_data->number_of_displays > 1) {
+               for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+                       if (results->enable[i]) {
+                               if (bw_mtn(
+                                       results->stutter_exit_watermark[i],
+                                       results->cursor_latency_hiding[i])) {
+                                       results->stutter_mode_enable =
+                                               bw_def_no;
+                               }
+                       }
+               }
+       }
+       /*performance metrics*/
+       /* display read access efficiency (%)*/
+       /* display write back access efficiency (%)*/
+       /* stutter efficiency (%)*/
+       /* extra underlay pitch recommended for efficiency (pixels)*/
+       /* immediate flip time (us)*/
+       /* latency for other clients due to urgent display read (us)*/
+       /* latency for other clients due to urgent display write (us)*/
+       /* average bandwidth consumed by display (no compression) (gb/s)*/
+       /* required dram  bandwidth (gb/s)*/
+       /* required sclk (m_hz)*/
+       /* required rd urgent latency (us)*/
+       /* nb p-state change margin (us)*/
+       /*dmif and mcifwr dram access efficiency*/
+       /*is the ratio between the ideal dram access time (which is the data 
buffer size in memory divided by the dram bandwidth), and the actual time which 
is the total page close-open time.  but it cannot exceed the dram efficiency 
provided by the memory subsystem*/
+       results->dmifdram_access_efficiency =
+               bw_min2(
+                       bw_div(
+                               bw_div(
+                                       
results->total_display_reads_required_dram_access_data,
+                                       results->dram_bandwidth),
+                               results->dmif_total_page_close_open_time),
+                       bw_int_to_fixed(1));
+       if (bw_mtn(
+               results->total_display_writes_required_dram_access_data,
+               bw_int_to_fixed(0))) {
+               results->mcifwrdram_access_efficiency =
+                       bw_min2(
+                               bw_div(
+                                       bw_div(
+                                               
results->total_display_writes_required_dram_access_data,
+                                               results->dram_bandwidth),
+                                       
results->mcifwr_total_page_close_open_time),
+                               bw_int_to_fixed(1));
+       } else {
+               results->mcifwrdram_access_efficiency = bw_int_to_fixed(0);
+       }
+       /*average bandwidth*/
+       /*the average bandwidth with no compression is the vertical active time 
is the source width times the bytes per pixel divided by the line time, 
multiplied by the vertical scale ratio and the ratio of bytes per request 
divided by the useful bytes per request.*/
+       /*the average bandwidth with compression is the same, divided by the 
compression ratio*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->average_bandwidth_no_compression[i] =
+                               bw_div(
+                                       bw_mul(
+                                               bw_mul(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       
results->source_width_rounded_up_to_chunks[i],
+                                                                       
bw_int_to_fixed(
+                                                                               
results->bytes_per_pixel[i])),
+                                                               (bw_div(
+                                                                       
results->h_total[i],
+                                                                       
results->pixel_rate[i]))),
+                                                       results->vsr[i]),
+                                               results->bytes_per_request[i]),
+                                       results->useful_bytes_per_request[i]);
+                       results->average_bandwidth[i] = bw_div(
+                               results->average_bandwidth_no_compression[i],
+                               results->compression_rate[i]);
+               }
+       }
+       results->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
+       results->total_average_bandwidth = bw_int_to_fixed(0);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->total_average_bandwidth_no_compression =
+                               bw_add(
+                                       
results->total_average_bandwidth_no_compression,
+                                       
results->average_bandwidth_no_compression[i]);
+                       results->total_average_bandwidth = bw_add(
+                               results->total_average_bandwidth,
+                               results->average_bandwidth[i]);
+               }
+       }
+       /*stutter efficiency*/
+       /*the stutter efficiency is the frame-average time in self-refresh 
divided by the frame-average stutter cycle duration.  only applies if the 
display write-back is not enabled.*/
+       /*the frame-average stutter cycle used is the minimum for all pipes of 
the frame-average data buffer size in time, times the compression rate*/
+       /*the frame-average time in self-refresh is the stutter cycle minus the 
self refresh exit latency and the burst time*/
+       /*the stutter cycle is the dmif buffer size reduced by the excess of 
the stutter exit watermark over the lb size in time.*/
+       /*the burst time is the data needed during the stutter cycle divided by 
the available bandwidth*/
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->stutter_cycle_duration[i] =
+                               bw_sub(
+                                       bw_mul(
+                                               bw_div(
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       bw_div(
+                                                                               
bw_div(
+                                                                               
        results->adjusted_data_buffer_size[i],
+                                                                               
        bw_int_to_fixed(
+                                                                               
                results->bytes_per_pixel[i])),
+                                                                               
results->source_width_rounded_up_to_chunks[i]),
+                                                                       
results->h_total[i]),
+                                                               
results->vsr[i]),
+                                                       results->pixel_rate[i]),
+                                               results->compression_rate[i]),
+                                       bw_max2(
+                                               bw_int_to_fixed(0),
+                                               bw_sub(
+                                                       
results->stutter_exit_watermark[i],
+                                                       bw_div(
+                                                               bw_mul(
+                                                                       
bw_int_to_fixed(
+                                                                               
(2
+                                                                               
        + results->line_buffer_prefetch[i])),
+                                                                       
results->h_total[i]),
+                                                               
results->pixel_rate[i]))));
+               }
+       }
+       results->total_stutter_cycle_duration = bw_int_to_fixed(9999);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       if (bw_mtn(
+                               results->total_stutter_cycle_duration,
+                               results->stutter_cycle_duration[i])) {
+                               results->total_stutter_cycle_duration =
+                                       results->stutter_cycle_duration[i];
+                       }
+               }
+       }
+       results->stutter_burst_time = bw_div(
+               bw_mul(
+                       results->total_stutter_cycle_duration,
+                       results->total_average_bandwidth),
+               bw_min2(
+                       (bw_mul(
+                               results->dram_bandwidth,
+                               results->dmifdram_access_efficiency)),
+                       bw_mul(
+                               sclk[results->sclk_level],
+                               vbios->data_return_bus_width)));
+       results->time_in_self_refresh = bw_sub(
+               bw_sub(
+                       results->total_stutter_cycle_duration,
+                       vbios->stutter_self_refresh_exit_latency),
+               results->stutter_burst_time);
+       if (mode_data->d1_display_write_back_dwb_enable == 1) {
+               results->stutter_efficiency = bw_int_to_fixed(0);
+       } else if (bw_ltn(results->time_in_self_refresh, bw_int_to_fixed(0))) {
+               results->stutter_efficiency = bw_int_to_fixed(0);
+       } else {
+               results->stutter_efficiency = bw_mul(
+                       bw_div(
+                               results->time_in_self_refresh,
+                               results->total_stutter_cycle_duration),
+                       bw_int_to_fixed(100));
+       }
+       /*immediate flip time*/
+       /*if scatter gather is enabled, the immediate flip takes a number of 
urgent memory trips equivalent to the pte requests in a row divided by the pte 
request limit.*/
+       /*otherwise, it may take just one urgenr memory trip*/
+       results->worst_number_of_trips_to_memory = bw_int_to_fixed(1);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]
+                       && results->scatter_gather_enable_for_pipe[i] == 1) {
+                       
results->number_of_trips_to_memory_for_getting_apte_row[i] =
+                               bw_ceil2(
+                                       bw_div(
+                                               
results->scatter_gather_pte_requests_in_row[i],
+                                               
results->scatter_gather_pte_request_limit[i]),
+                                       bw_int_to_fixed(1));
+                       if (bw_ltn(
+                               results->worst_number_of_trips_to_memory,
+                               
results->number_of_trips_to_memory_for_getting_apte_row[i])) {
+                               results->worst_number_of_trips_to_memory =
+                                       
results->number_of_trips_to_memory_for_getting_apte_row[i];
+                       }
+               }
+       }
+       results->immediate_flip_time = bw_mul(
+               results->worst_number_of_trips_to_memory,
+               results->total_dmifmc_urgent_latency);
+       /*worst latency for other clients*/
+       /*it is the urgent latency plus the urgent burst time*/
+       results->latency_for_non_dmif_clients =
+               bw_add(
+                       results->total_dmifmc_urgent_latency,
+                       
results->dmif_burst_time[results->y_clk_level][results->sclk_level]);
+       if (mode_data->d1_display_write_back_dwb_enable == 1) {
+               results->latency_for_non_mcifwr_clients = bw_add(
+                       vbios->mcifwrmc_urgent_latency,
+                       dceip->mcifwr_all_surfaces_burst_time);
+       } else {
+               results->latency_for_non_mcifwr_clients = bw_int_to_fixed(0);
+       }
+       /*dmif mc urgent latency suppported in high sclk and yclk*/
+       results->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div(
+               (bw_sub(
+                       results->min_read_buffer_size_in_time,
+                       results->dmif_burst_time[high][high])),
+               results->total_dmifmc_urgent_trips);
+       /*dram speed/p-state change margin*/
+       /*in the multi-display case the nb p-state change watermark cannot 
exceed the average lb size plus the dmif size or the cursor dcp buffer size*/
+       results->nbp_state_dram_speed_change_margin = bw_int_to_fixed(9999);
+       for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+               if (results->enable[i]) {
+                       results->nbp_state_dram_speed_change_margin =
+                               bw_min2(
+                                       
results->nbp_state_dram_speed_change_margin,
+                                       bw_sub(
+                                               
results->maximum_latency_hiding_with_cursor[i],
+                                               
results->nbp_state_change_watermark[i]));
+               }
+       }
+       /*sclk required vs urgent latency*/
+       for (i = 1; i <= 5; i++) {
+               
results->display_reads_time_for_data_transfer_and_urgent_latency =
+                       bw_sub(
+                               results->min_read_buffer_size_in_time,
+                               bw_mul(
+                                       results->total_dmifmc_urgent_trips,
+                                       bw_int_to_fixed(i)));
+               if (pipe_check == bw_def_ok
+                       && (bw_mtn(
+                               
results->display_reads_time_for_data_transfer_and_urgent_latency,
+                               results->dmif_total_page_close_open_time))) {
+                       results->dmif_required_sclk_for_urgent_latency[i] =
+                               bw_div(
+                                       bw_div(
+                                               
results->total_display_reads_required_data,
+                                               
results->display_reads_time_for_data_transfer_and_urgent_latency),
+                                       vbios->data_return_bus_width);
+               } else {
+                       results->dmif_required_sclk_for_urgent_latency[i] =
+                               bw_int_to_fixed(bw_def_na);
+               }
+       }
+}
+
+/*******************************************************************************
+ * Public functions
+ 
******************************************************************************/
+
+void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
+       struct bw_calcs_vbios *bw_vbios)
+{
+       struct bw_calcs_dceip dceip = {{ 0 }};
+       struct bw_calcs_vbios vbios = { 0 };
+
+       vbios.number_of_dram_channels = 2;
+       vbios.dram_channel_width_in_bits = 64;
+       vbios.number_of_dram_banks = 8;
+       vbios.high_yclk = bw_int_to_fixed(1600);
+       vbios.mid_yclk = bw_int_to_fixed(1600);
+       vbios.low_yclk = bw_frc_to_fixed(66666, 100);
+       vbios.low_sclk = bw_int_to_fixed(200);
+       vbios.mid_sclk = bw_int_to_fixed(300);
+       vbios.high_sclk = bw_frc_to_fixed(62609, 100);
+       vbios.low_voltage_max_dispclk = bw_int_to_fixed(352);
+       vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467);
+       vbios.high_voltage_max_dispclk = bw_int_to_fixed(643);
+       vbios.data_return_bus_width = bw_int_to_fixed(32);
+       vbios.trc = bw_int_to_fixed(50);
+       vbios.dmifmc_urgent_latency = bw_int_to_fixed(4);
+       vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10);
+       vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000);
+       vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10);
+       vbios.scatter_gather_enable = true;
+       vbios.down_spread_percentage = bw_frc_to_fixed(5, 10);
+       vbios.cursor_width = 32;
+       vbios.average_compression_rate = 4;
+       vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256;
+       vbios.blackout_duration = bw_int_to_fixed(18); /* us */
+       vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20);
+
+
+       dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
+       dceip.de_tiling_buffer = bw_int_to_fixed(0);
+       dceip.dcfclk_request_generation = 0;
+       dceip.lines_interleaved_into_lb = 2;
+       dceip.chunk_width = 256;
+       dceip.number_of_graphics_pipes = 3;
+       dceip.number_of_underlay_pipes = 1;
+       dceip.display_write_back_supported = false;
+       dceip.argb_compression_support = false;
+       dceip.underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(
+               35556, 10000);
+       dceip.underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+               34286, 10000);
+       dceip.underlay_vscaler_efficiency10_bit_per_component = 
bw_frc_to_fixed(32,
+               10);
+       dceip.underlay_vscaler_efficiency12_bit_per_component = 
bw_int_to_fixed(3);
+       dceip.graphics_vscaler_efficiency6_bit_per_component = 
bw_frc_to_fixed(35,
+               10);
+       dceip.graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+               34286, 10000);
+       dceip.graphics_vscaler_efficiency10_bit_per_component = 
bw_frc_to_fixed(32,
+               10);
+       dceip.graphics_vscaler_efficiency12_bit_per_component = 
bw_int_to_fixed(3);
+       dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3);
+       dceip.max_dmif_buffer_allocated = 2;
+       dceip.graphics_dmif_size = 12288;
+       dceip.underlay_luma_dmif_size = 19456;
+       dceip.underlay_chroma_dmif_size = 23552;
+       dceip.pre_downscaler_enabled = true;
+       dceip.underlay_downscale_prefetch_enabled = true;
+       dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1);
+       dceip.lb_size_per_component444 = bw_int_to_fixed(82176);
+       dceip.graphics_lb_nodownscaling_multi_line_prefetching = false;
+       dceip.stutter_and_dram_clock_state_change_gated_before_cursor =
+               bw_int_to_fixed(0);
+       dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed(82176);
+       dceip.underlay420_chroma_lb_size_per_component = 
bw_int_to_fixed(164352);
+       dceip.underlay422_lb_size_per_component = bw_int_to_fixed(82176);
+       dceip.cursor_chunk_width = bw_int_to_fixed(64);
+       dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4);
+       dceip.cursor_memory_interface_buffer_pixels = bw_int_to_fixed(64);
+       dceip.underlay_maximum_width_efficient_for_tiling = 
bw_int_to_fixed(1920);
+       dceip.underlay_maximum_height_efficient_for_tiling = 
bw_int_to_fixed(1080);
+       
dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display
 =
+               bw_frc_to_fixed(3, 10);
+       
dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation =
+               bw_int_to_fixed(25);
+       dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed(2);
+       dceip.maximum_total_outstanding_pte_requests_allowed_by_saw =
+               bw_int_to_fixed(128);
+       dceip.limit_excessive_outstanding_dmif_requests = true;
+       dceip.linear_mode_line_request_alternation_slice = bw_int_to_fixed(64);
+       dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32;
+       dceip.display_write_back420_luma_mcifwr_buffer_size = 12288;
+       dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192;
+       dceip.request_efficiency = bw_frc_to_fixed(8, 10);
+       dceip.dispclk_per_request = bw_int_to_fixed(2);
+       dceip.dispclk_ramping_factor = bw_frc_to_fixed(11, 10);
+       dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100);
+       dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2;
+       dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: 
this is a bug*/
+
+       *bw_dceip = dceip;
+       *bw_vbios = vbios;
+}
+
+/**
+ * Compare calculated (required) clocks against the clocks available at
+ * maximum voltage (max Performance Level).
+ */
+static bool is_display_configuration_supported(
+       const struct bw_calcs_vbios *vbios,
+       const struct bw_calcs_output *calcs_output)
+{
+       uint32_t int_max_clk;
+
+       int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk);
+       int_max_clk *= 1000; /* MHz to kHz */
+       if (calcs_output->dispclk_khz > int_max_clk)
+               return false;
+
+       int_max_clk = bw_fixed_to_int(vbios->high_sclk);
+       int_max_clk *= 1000; /* MHz to kHz */
+       if (calcs_output->required_sclk > int_max_clk)
+               return false;
+
+       return true;
+}
+
+/**
+ * Return:
+ *     true -  Display(s) configuration supported.
+ *             In this case 'calcs_output' contains data for HW programming
+ *     false - Display(s) configuration not supported (not enough bandwidth).
+ */
+
+bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_dceip *dceip,
+       const struct bw_calcs_vbios *vbios,
+       const struct bw_calcs_mode_data *mode_data,
+       struct bw_calcs_output *calcs_output)
+{
+       struct bw_calcs_results *bw_results_internal = dm_alloc(
+                               ctx, sizeof(struct bw_calcs_results));
+       struct bw_calcs_mode_data_internal *bw_data_internal =
+               dm_alloc(
+                       ctx, sizeof(struct bw_calcs_mode_data_internal));
+       switch (mode_data->number_of_displays) {
+       case (3):
+               bw_data_internal->d2_htotal =
+                       mode_data->displays_data[2].h_total;
+               bw_data_internal->d2_pixel_rate =
+                       mode_data->displays_data[2].pixel_rate;
+               bw_data_internal->d2_graphics_src_width =
+                       mode_data->displays_data[2].graphics_src_width;
+               bw_data_internal->d2_graphics_src_height =
+                       mode_data->displays_data[2].graphics_src_height;
+               bw_data_internal->d2_graphics_scale_ratio =
+                       mode_data->displays_data[2].graphics_scale_ratio;
+               bw_data_internal->d2_graphics_stereo_mode =
+                       mode_data->displays_data[2].graphics_stereo_mode;
+       case (2):
+               bw_data_internal->d1_display_write_back_dwb_enable = false;
+               bw_data_internal->d1_underlay_mode = bw_def_none;
+               bw_data_internal->d1_underlay_scale_ratio = bw_int_to_fixed(0);
+               bw_data_internal->d1_htotal =
+                       mode_data->displays_data[1].h_total;
+               bw_data_internal->d1_pixel_rate =
+                       mode_data->displays_data[1].pixel_rate;
+               bw_data_internal->d1_graphics_src_width =
+                       mode_data->displays_data[1].graphics_src_width;
+               bw_data_internal->d1_graphics_src_height =
+                       mode_data->displays_data[1].graphics_src_height;
+               bw_data_internal->d1_graphics_scale_ratio =
+                       mode_data->displays_data[1].graphics_scale_ratio;
+               bw_data_internal->d1_graphics_stereo_mode =
+                       mode_data->displays_data[1].graphics_stereo_mode;
+
+       case (1):
+               bw_data_internal->d0_fbc_enable =
+                       mode_data->displays_data[0].fbc_enable;
+               bw_data_internal->d0_lpt_enable =
+                       mode_data->displays_data[0].lpt_enable;
+               bw_data_internal->d0_underlay_mode =
+                       mode_data->displays_data[0].underlay_mode;
+               bw_data_internal->d0_underlay_scale_ratio = bw_int_to_fixed(0);
+               bw_data_internal->d0_htotal =
+                       mode_data->displays_data[0].h_total;
+               bw_data_internal->d0_pixel_rate =
+                       mode_data->displays_data[0].pixel_rate;
+               bw_data_internal->d0_graphics_src_width =
+                       mode_data->displays_data[0].graphics_src_width;
+               bw_data_internal->d0_graphics_src_height =
+                       mode_data->displays_data[0].graphics_src_height;
+               bw_data_internal->d0_graphics_scale_ratio =
+                       mode_data->displays_data[0].graphics_scale_ratio;
+               bw_data_internal->d0_graphics_stereo_mode =
+                       mode_data->displays_data[0].graphics_stereo_mode;
+
+       default:
+               /* data for all displays */
+               bw_data_internal->number_of_displays =
+                       mode_data->number_of_displays;
+               bw_data_internal->graphics_rotation_angle =
+                       mode_data->displays_data[0].graphics_rotation_angle;
+               bw_data_internal->underlay_rotation_angle =
+                       mode_data->displays_data[0].underlay_rotation_angle;
+               bw_data_internal->underlay_surface_type =
+                       mode_data->displays_data[0].underlay_surface_type;
+               bw_data_internal->panning_and_bezel_adjustment =
+                       
mode_data->displays_data[0].panning_and_bezel_adjustment;
+               bw_data_internal->graphics_tiling_mode =
+                       mode_data->displays_data[0].graphics_tiling_mode;
+               bw_data_internal->graphics_interlace_mode =
+                       mode_data->displays_data[0].graphics_interlace_mode;
+               bw_data_internal->graphics_bytes_per_pixel =
+                       mode_data->displays_data[0].graphics_bytes_per_pixel;
+               bw_data_internal->graphics_htaps =
+                       mode_data->displays_data[0].graphics_h_taps;
+               bw_data_internal->graphics_vtaps =
+                       mode_data->displays_data[0].graphics_v_taps;
+               bw_data_internal->graphics_lb_bpc =
+                       mode_data->displays_data[0].graphics_lb_bpc;
+               bw_data_internal->underlay_lb_bpc =
+                       mode_data->displays_data[0].underlay_lb_bpc;
+               bw_data_internal->underlay_tiling_mode =
+                       mode_data->displays_data[0].underlay_tiling_mode;
+               bw_data_internal->underlay_htaps =
+                       mode_data->displays_data[0].underlay_h_taps;
+               bw_data_internal->underlay_vtaps =
+                       mode_data->displays_data[0].underlay_v_taps;
+               bw_data_internal->underlay_src_width =
+                       mode_data->displays_data[0].underlay_src_width;
+               bw_data_internal->underlay_src_height =
+                       mode_data->displays_data[0].underlay_src_height;
+               bw_data_internal->underlay_pitch_in_pixels =
+                       mode_data->displays_data[0].underlay_pitch_in_pixels;
+               bw_data_internal->underlay_stereo_mode =
+                       mode_data->displays_data[0].underlay_stereo_mode;
+               bw_data_internal->display_synchronization_enabled =
+                       mode_data->display_synchronization_enabled;
+       }
+
+       if (bw_data_internal->number_of_displays != 0) {
+               uint8_t yclk_lvl, sclk_lvl;
+               struct bw_fixed high_sclk = vbios->high_sclk;
+               struct bw_fixed mid_sclk = vbios->mid_sclk;
+               struct bw_fixed low_sclk = vbios->low_sclk;
+               struct bw_fixed high_yclk = vbios->high_yclk;
+               struct bw_fixed mid_yclk = vbios->mid_yclk;
+               struct bw_fixed low_yclk = vbios->low_yclk;
+
+               calculate_bandwidth(dceip, vbios, bw_data_internal,
+                                                       bw_results_internal);
+
+               yclk_lvl = bw_results_internal->y_clk_level;
+               sclk_lvl = bw_results_internal->sclk_level;
+
+               calcs_output->all_displays_in_sync =
+                       mode_data->display_synchronization_enabled;
+               calcs_output->nbp_state_change_enable =
+                       bw_results_internal->nbp_state_change_enable;
+               calcs_output->cpuc_state_change_enable =
+                               bw_results_internal->cpuc_state_change_enable;
+               calcs_output->cpup_state_change_enable =
+                               bw_results_internal->cpup_state_change_enable;
+               calcs_output->stutter_mode_enable =
+                               bw_results_internal->stutter_mode_enable;
+               calcs_output->dispclk_khz =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->dispclk,
+                                       bw_int_to_fixed(1000)));
+               calcs_output->required_blackout_duration_us =
+                       bw_fixed_to_int(bw_add(bw_results_internal->
+                               blackout_duration_margin[yclk_lvl][sclk_lvl],
+                               vbios->blackout_duration));
+               calcs_output->required_sclk =
+                       
bw_fixed_to_int(bw_mul(bw_results_internal->required_sclk,
+                                       bw_int_to_fixed(1000)));
+               calcs_output->required_sclk_deep_sleep =
+                       
bw_fixed_to_int(bw_mul(bw_results_internal->sclk_deep_sleep,
+                                       bw_int_to_fixed(1000)));
+               if (yclk_lvl == 0)
+                       calcs_output->required_yclk = bw_fixed_to_int(
+                               bw_mul(low_yclk, bw_int_to_fixed(1000)));
+               else if (yclk_lvl == 1)
+                       calcs_output->required_yclk = bw_fixed_to_int(
+                               bw_mul(mid_yclk, bw_int_to_fixed(1000)));
+               else
+                       calcs_output->required_yclk = bw_fixed_to_int(
+                               bw_mul(high_yclk, bw_int_to_fixed(1000)));
+
+               /* units: nanosecond, 16bit storage. */
+               calcs_output->nbp_state_change_wm_ns[0].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               
nbp_state_change_watermark[4],bw_int_to_fixed(1000)));
+               calcs_output->nbp_state_change_wm_ns[1].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               nbp_state_change_watermark[5], 
bw_int_to_fixed(1000)));
+               calcs_output->nbp_state_change_wm_ns[2].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               nbp_state_change_watermark[6], 
bw_int_to_fixed(1000)));
+
+               calcs_output->stutter_exit_wm_ns[0].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[4], 
bw_int_to_fixed(1000)));
+               calcs_output->stutter_exit_wm_ns[1].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[5], 
bw_int_to_fixed(1000)));
+               calcs_output->stutter_exit_wm_ns[2].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[6], 
bw_int_to_fixed(1000)));
+
+               calcs_output->urgent_wm_ns[0].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[4], bw_int_to_fixed(1000)));
+               calcs_output->urgent_wm_ns[1].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[5], bw_int_to_fixed(1000)));
+               calcs_output->urgent_wm_ns[2].b_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[6], bw_int_to_fixed(1000)));
+
+               ((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk;
+               ((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk;
+               ((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk;
+               ((struct bw_calcs_vbios *)vbios)->mid_sclk = high_sclk;
+
+               calculate_bandwidth(dceip, vbios, bw_data_internal,
+                                                       bw_results_internal);
+
+               calcs_output->nbp_state_change_wm_ns[0].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               nbp_state_change_watermark[4], 
bw_int_to_fixed(1000)));
+               calcs_output->nbp_state_change_wm_ns[1].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               nbp_state_change_watermark[5], 
bw_int_to_fixed(1000)));
+               calcs_output->nbp_state_change_wm_ns[2].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               nbp_state_change_watermark[6], 
bw_int_to_fixed(1000)));
+
+               calcs_output->stutter_exit_wm_ns[0].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[4], 
bw_int_to_fixed(1000)));
+               calcs_output->stutter_exit_wm_ns[1].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[5], 
bw_int_to_fixed(1000)));
+               calcs_output->stutter_exit_wm_ns[2].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               stutter_exit_watermark[6], 
bw_int_to_fixed(1000)));
+
+               calcs_output->urgent_wm_ns[0].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[4], bw_int_to_fixed(1000)));
+               calcs_output->urgent_wm_ns[1].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[5], bw_int_to_fixed(1000)));
+               calcs_output->urgent_wm_ns[2].a_mark =
+                       bw_fixed_to_int(bw_mul(bw_results_internal->
+                               urgent_watermark[6], bw_int_to_fixed(1000)));
+
+               ((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk;
+               ((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk;
+               ((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk;
+               ((struct bw_calcs_vbios *)vbios)->mid_sclk = mid_sclk;
+       } else {
+               calcs_output->nbp_state_change_enable = true;
+               calcs_output->cpuc_state_change_enable = true;
+               calcs_output->cpup_state_change_enable = true;
+               calcs_output->stutter_mode_enable = true;
+               calcs_output->dispclk_khz = 0;
+               calcs_output->required_sclk = 0;
+       }
+
+       dm_free(ctx, bw_data_internal);
+       dm_free(ctx, bw_results_internal);
+
+       return is_display_configuration_supported(vbios, calcs_output);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c 
b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
new file mode 100644
index 000000000000..8a7a4c99fb5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "bw_fixed.h"
+
+
+#define BITS_PER_FRACTIONAL_PART 24
+
+#define MIN_I32 \
+       (int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART)))
+
+#define MAX_I32 \
+       (int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1)
+
+#define MIN_I64 \
+       (int64_t)(-(1LL << 63))
+
+#define MAX_I64 \
+       (int64_t)((1ULL << 63) - 1)
+
+
+#define FRACTIONAL_PART_MASK \
+       ((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_INTEGER_PART(x) \
+       ((x) >> BITS_PER_FRACTIONAL_PART)
+
+#define GET_FRACTIONAL_PART(x) \
+       (FRACTIONAL_PART_MASK & (x))
+
+static uint64_t abs_i64(int64_t arg)
+{
+       if (arg >= 0)
+               return (uint64_t)(arg);
+       else
+               return (uint64_t)(-arg);
+}
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct 
bw_fixed v3)
+{
+       return bw_min2(bw_min2(v1, v2), v3);
+}
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct 
bw_fixed v3)
+{
+       return bw_max2(bw_max2(v1, v2), v3);
+}
+
+struct bw_fixed bw_int_to_fixed(int64_t value)
+{
+       struct bw_fixed res;
+       ASSERT(value < MAX_I32 && value > MIN_I32);
+       res.value = value << BITS_PER_FRACTIONAL_PART;
+       return res;
+}
+
+int32_t bw_fixed_to_int(struct bw_fixed value)
+{
+       return GET_INTEGER_PART(value.value);
+}
+
+struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
+{
+       struct bw_fixed res;
+       bool arg1_negative = numerator < 0;
+       bool arg2_negative = denominator < 0;
+       uint64_t arg1_value;
+       uint64_t arg2_value;
+       uint64_t remainder;
+
+       /* determine integer part */
+       uint64_t res_value;
+
+       ASSERT(denominator != 0);
+
+       arg1_value = (uint64_t)abs_i64(numerator);
+       arg2_value = (uint64_t)abs_i64(denominator);
+       res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
+
+       ASSERT(res_value <= MAX_I32);
+
+       /* determine fractional part */
+       {
+               uint32_t i = BITS_PER_FRACTIONAL_PART;
+
+               do
+               {
+                       remainder <<= 1;
+
+                       res_value <<= 1;
+
+                       if (remainder >= arg2_value)
+                       {
+                               res_value |= 1;
+                               remainder -= arg2_value;
+                       }
+               } while (--i != 0);
+       }
+
+       /* round up LSB */
+       {
+               uint64_t summand = (remainder << 1) >= arg2_value;
+
+               ASSERT(res_value <= MAX_I64 - summand);
+
+               res_value += summand;
+       }
+
+       res.value = (int64_t)(res_value);
+
+       if (arg1_negative ^ arg2_negative)
+               res.value = -res.value;
+       return res;
+}
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return (arg1.value <= arg2.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return (arg2.value <= arg1.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_floor2(
+       const struct bw_fixed arg,
+       const struct bw_fixed significance)
+{
+       struct bw_fixed result;
+       int64_t multiplicand;
+       multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+       result.value = abs_i64(significance.value) * multiplicand;
+       ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
+       return result;
+}
+
+struct bw_fixed bw_ceil2(
+       const struct bw_fixed arg,
+       const struct bw_fixed significance)
+{
+       struct bw_fixed result;
+       int64_t multiplicand;
+
+       multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+       result.value = abs_i64(significance.value) * multiplicand;
+       if (abs_i64(result.value) < abs_i64(arg.value)) {
+               if (arg.value < 0)
+                       result.value -= abs_i64(significance.value);
+               else
+                       result.value += abs_i64(significance.value);
+       }
+       return result;
+}
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       struct bw_fixed res;
+
+       res.value = arg1.value + arg2.value;
+
+       return res;
+}
+
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       struct bw_fixed res;
+
+       res.value = arg1.value - arg2.value;
+
+       return res;
+}
+
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       struct bw_fixed res;
+
+       bool arg1_negative = arg1.value < 0;
+       bool arg2_negative = arg2.value < 0;
+
+       uint64_t arg1_value = abs_i64(arg1.value);
+       uint64_t arg2_value = abs_i64(arg2.value);
+
+       uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
+       uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
+
+       uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
+       uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
+
+       uint64_t tmp;
+
+       res.value = arg1_int * arg2_int;
+
+       ASSERT(res.value <= MAX_I32);
+
+       res.value <<= BITS_PER_FRACTIONAL_PART;
+
+       tmp = arg1_int * arg2_fra;
+
+       ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+       res.value += tmp;
+
+       tmp = arg2_int * arg1_fra;
+
+       ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+       res.value += tmp;
+
+       tmp = arg1_fra * arg2_fra;
+
+       tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+               (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
+
+       ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+       res.value += tmp;
+
+       if (arg1_negative ^ arg2_negative)
+               res.value = -res.value;
+       return res;
+}
+
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value);
+       return res;
+}
+
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       struct bw_fixed res;
+       div64_u64_rem(arg1.value, arg2.value, &res.value);
+       return res;
+}
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw)
+{
+       struct bw_fixed result = { 0 };
+
+       if (raw < 0) {
+               raw = -raw;
+               result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART));
+       } else {
+               result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART);
+       }
+
+       return result;
+}
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value == arg2.value;
+}
+
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value != arg2.value;
+}
+
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value <= arg2.value;
+}
+
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value >= arg2.value;
+}
+
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value < arg2.value;
+}
+
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+       return arg1.value > arg2.value;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c 
b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
new file mode 100644
index 000000000000..64ca20328315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
@@ -0,0 +1,1992 @@
+/* Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed31_32.h"
+
+#include "scaler_filter.h"
+
+enum {
+       DOWN_DB_SCALES = 8,
+       DOWN_DB_POINTS = 11,
+
+       UP_DB_SCALES = 1,
+       UP_DB_POINTS = 7,
+
+       MIN_SHARPNESS = -50,
+       MAX_SHARPNESS = 50,
+
+       CONST_DIVIDER = 10000000,
+
+       MAX_HOR_DOWNSCALE = 1666000, /* 1:6  */
+       MAX_VER_DOWNSCALE = 1666000, /* 1:6  */
+
+       MAX_HOR_UPSCALE = 160000000, /* 16:1 */
+       MAX_VER_UPSCALE = 160000000, /* 16:1 */
+
+       THRESHOLDRATIOLOW = 8000000, /* 0.8 */
+       THRESHOLDRATIOUP = 10000000, /* 1.0 */
+
+       DOWN_DB_FUZZY = -120411996, /* -12.041200 */
+       DOWN_DB_FLAT = -60205998, /* -6.020600 */
+       DOWN_DB_SHARP = -10000000, /* -1.000000 */
+
+       UP_DB_FUZZY = -60205998, /* -6.020600 */
+       UP_DB_FLAT = 0,
+       UP_DB_SHARP = 60205998 /* 6.020600 */
+};
+
+static inline struct fixed31_32 max_hor_downscale(void)
+{
+       return dal_fixed31_32_from_fraction(MAX_HOR_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_downscale(void)
+{
+       return dal_fixed31_32_from_fraction(MAX_VER_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_hor_upscale(void)
+{
+       return dal_fixed31_32_from_fraction(MAX_HOR_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_upscale(void)
+{
+       return dal_fixed31_32_from_fraction(MAX_VER_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_low(void)
+{
+       return dal_fixed31_32_from_fraction(THRESHOLDRATIOLOW, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_up(void)
+{
+       return dal_fixed31_32_from_fraction(THRESHOLDRATIOUP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_fuzzy(void)
+{
+       return dal_fixed31_32_from_fraction(DOWN_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_flat(void)
+{
+       return dal_fixed31_32_from_fraction(DOWN_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_sharp(void)
+{
+       return dal_fixed31_32_from_fraction(DOWN_DB_SHARP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_fuzzy(void)
+{
+       return dal_fixed31_32_from_fraction(UP_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_flat(void)
+{
+       return dal_fixed31_32_from_fraction(UP_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_sharp(void)
+{
+       return dal_fixed31_32_from_fraction(UP_DB_SHARP, CONST_DIVIDER);
+}
+
+static const int32_t
+       downscaling_db_table[][DOWN_DB_SCALES + 1][DOWN_DB_POINTS] = {
+       /* 3 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       14302719,       14302719,       14302719,
+                       10000000,       99999,          99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14302339,       14302339,       14302339,
+                       10000000,       4452010,        99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14302760,       14302760,       14302760,
+                       10000000,       7826979,        5258399,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14302819,       14302819,       14302819,
+                       10000000,       8669400,        7414469,
+                       4422729,        99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14302730,       14302730,       12791190,
+                       10000000,       9045640,        8180170,
+                       6477950,        4599249,        2019010,
+                       99999,          99999
+               },
+               {
+                       14302699,       14302699,       12067849,
+                       10000000,       9236029,        8541280,
+                       7252740,        6021010,        4820120,
+                       3511950,        1769340
+               },
+               {
+                       14302710,       14302710,       11783510,
+                       10000000,       9325690,        8704419,
+                       7595670,        6583020,        5652850,
+                       4749999,        3847680
+               },
+               {
+                       14302920,       14302920,       11709250,
+                       10000000,       9345560,        8754609,
+                       7692559,        6738259,        5878239,
+                       5057529,        4264070
+               }
+       },
+       /* 4 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       14308999,       14308999,       14308999,
+                       10000000,       99999,          99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14308999,       14308999,       14308999,
+                       10000000,       6311039,        99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14308999,       14308999,       14308999,
+                       10000000,       8526669,        6832849,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       14308999,       14308999,       12110630,
+                       10000000,       9117940,        8230940,
+                       6320130,        3719770,        99999,
+                       99999,          99999
+               },
+               {
+                       14308999,       14308999,       11474980,
+                       10000000,       9370139,        8771979,
+                       7601270,        6440780,        5249999,
+                       3887520,        2039040
+               },
+               {
+                       14308999,       13084859,       11179579,
+                       10000000,       9495180,        9016919,
+                       8134520,        7311699,        6560329,
+                       5845720,        5155519
+               },
+               {
+                       14308999,       12576600,       11048669,
+                       10000000,       9550499,        9132360,
+                       8368729,        7679399,        7073119,
+                       6520900,        6015530
+               },
+               {
+                       14308999,       12448530,       11007410,
+                       10000000,       9566799,        9165279,
+                       8435800,        7785279,        7215780,
+                       6701470,        6240640
+               }
+       },
+       /* 5 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       8971139,        8971139,        8971139,
+                       10000000,       99999,          99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       9466379,        9466379,        9466379,
+                       10000000,       5648760,        3834280,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       15000000,       15000000,       14550110,
+                       10000000,       7121120,        5994579,
+                       4314630,        2606149,        99999,
+                       99999,          99999
+               },
+               {
+                       15000000,       15000000,       13047469,
+                       10000000,       8368809,        7343569,
+                       5970299,        4924620,        4029389,
+                       3171139,        2276369
+               },
+               {
+                       15000000,       14157199,       11897679,
+                       10000000,       9166659,        8444600,
+                       7287240,        6374719,        5615460,
+                       4949580,        4350199
+               },
+               {
+                       15000000,       12877819,       11224579,
+                       10000000,       9488620,        9016109,
+                       8203780,        7500000,        6883730,
+                       6326839,        5818459
+               },
+               {
+                       14733040,       12233200,       10939040,
+                       10000000,       9608929,        9250000,
+                       8623390,        8076940,        7606369,
+                       7177749,        6785169
+               },
+               {
+                       14627330,       12046170,       10862360,
+                       10000000,       9639260,        9312710,
+                       8737679,        8242470,        7815709,
+                       7432209,        7082970
+               }
+       },
+       /* 6 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       8231559,        8231559,        8231559,
+                       10000000,       99999,          99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       8353310,        8353310,        8353310,
+                       10000000,       5504879,        4310710,
+                       870359,         99999,          99999,
+                       99999,          99999
+               },
+               {
+                       8643479,        8643479,        8643479,
+                       10000000,       6483510,        5768150,
+                       4630779,        3580690,        2501940,
+                       1015309,        99999
+               },
+               {
+                       15000000,       15000000,       13493930,
+                       10000000,       7516040,        6802409,
+                       5824409,        5080109,        4454280,
+                       3896749,        3386510
+               },
+               {
+                       15000000,       14055930,       12321079,
+                       10000000,       8872389,        8090410,
+                       7035570,        6281229,        5676810,
+                       5165010,        4717260
+               },
+               {
+                       15000000,       12915290,       11311399,
+                       10000000,       9460610,        8988440,
+                       8202149,        7548679,        6999999,
+                       6510639,        6065719
+               },
+               {
+                       14310129,       12140829,       10901659,
+                       10000000,       9635019,        9307180,
+                       8740929,        8263260,        7858849,
+                       7499330,        7170130
+               },
+               {
+                       13815449,       11911309,       10801299,
+                       10000000,       9669629,        9380580,
+                       8878319,        8452050,        8097199,
+                       7785030,        7504299
+               }
+       },
+       /* 7 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       10616660,       10616660,       10616660,
+                       10000000,       2646020,        99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       10099999,       10099999,       10099999,
+                       10000000,       4936839,        4112670,
+                       2729740,        896539,         99999,
+                       99999,          99999
+               },
+               {
+                       8345860,        8345860,        8345860,
+                       10000000,       6034079,        5371739,
+                       4466759,        3763799,        3155870,
+                       2588019,        2026730
+               },
+               {
+                       9298499,        9298499,        13768420,
+                       10000000,       7174239,        6524270,
+                       5670250,        5052099,        4549089,
+                       4115279,        3722150
+               },
+               {
+                       15000000,       14116940,       12563209,
+                       10000000,       8542140,        7782419,
+                       6865050,        6239479,        5758860,
+                       5351870,        4992800
+               },
+               {
+                       15000000,       12913750,       11306079,
+                       10000000,       9452580,        8969209,
+                       8168810,        7538409,        7029479,
+                       6603180,        6227809
+               },
+               {
+                       14390859,       11862809,       10757420,
+                       10000000,       9688709,        9404249,
+                       8904439,        8472480,        8099079,
+                       7765330,        7459110
+               },
+               {
+                       13752900,       11554559,       10637769,
+                       10000000,       9736120,        9499999,
+                       9079759,        8718389,        8408790,
+                       8134469,        7886120
+               }
+       },
+       /* 8 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       11277090,       11277090,       11277090,
+                       10000000,       2949059,        99999,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       11196039,       11196039,       11196039,
+                       10000000,       4627540,        4018869,
+                       3018769,        2000000,        250770,
+                       99999,          99999
+               },
+               {
+                       10878369,       10878369,       10878369,
+                       10000000,       5657230,        5118110,
+                       4372630,        3809120,        3337709,
+                       2919510,        2535369
+               },
+               {
+                       9090089,        9090089,        13961290,
+                       10000000,       6929969,        6334999,
+                       5569829,        5019649,        4584150,
+                       4208610,        3876540
+               },
+               {
+                       15000000,       14173229,       12732659,
+                       10000000,       8267070,        7575380,
+                       6764540,        6218209,        5803539,
+                       5454990,        5146239
+               },
+               {
+                       15000000,       12928279,       11292259,
+                       10000000,       9447429,        8954229,
+                       8141599,        7516989,        7039459,
+                       6649519,        6316819
+               },
+               {
+                       14661350,       11638879,       10665880,
+                       10000000,       9722669,        9464690,
+                       9013469,        8613470,        8266339,
+                       7949870,        7663450
+               },
+               {
+                       13861900,       11311980,       10543940,
+                       10000000,       9772019,        9565100,
+                       9198870,        8881340,        8609200,
+                       8365769,        8147500
+               }
+       },
+       /* 9 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {       10099999,       10099999,       10099999,
+                       10000000,       2939159,        1526470,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       11726609,       11726609,       11726609,
+                       10000000,       4329420,        3805609,
+                       3030480,        2363760,        1732099,
+                       980139,         99999
+               },
+               {
+                       10949269,       10949269,       10949269,
+                       10000000,       5452589,        4946640,
+                       4277969,        3790729,        3392640,
+                       3048950,        2750000
+               },
+               {
+                       8830279,        8830279,        14084529,
+                       10000000,       6743149,        6182519,
+                       5482980,        5000000,        4622060,
+                       4303340,        4022600
+               },
+               {
+                       9709150,        14111399,       12800760,
+                       10000000,       7989749,        7445629,
+                       6741260,        6241980,        5857459,
+                       5534989,        5255370
+               },
+               {
+                       15000000,       12830289,       11489900,
+                       10000000,       9302089,        8767340,
+                       8025540,        7500000,        7100800,
+                       6768149,        6481850
+               },
+               {
+                       14873609,       11576000,       10650579,
+                       10000000,       9731360,        9483649,
+                       9054650,        8680559,        8358049,
+                       8066400,        7802420
+               },
+               {
+                       12981410,       11185950,       10491620,
+                       10000000,       9795730,        9611030,
+                       9286710,        9007279,        8768100,
+                       8553469,        8361340
+               }
+       },
+       /* 10 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       8993279,        8993279,        8993279,
+                       10000000,       2921360,        1905619,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       9064850,        9064850,        9064850,
+                       10000000,       4095619,        3655839,
+                       3021000,        2500000,        2031680,
+                       1566990,        1055440
+               },
+               {
+                       11043460,       11043460,       11043460,
+                       10000000,       5287479,        4816150,
+                       4208439,        3769229,        3418970,
+                       3117449,        2850320
+               },
+               {
+                       8651900,        8651900,        14169909,
+                       10000000,       6596950,        6071490,
+                       5423219,        4980779,        4644620,
+                       4362219,        4114899
+               },
+               {
+                       9246050,        14055370,       12832759,
+                       10000000,       7831320,        7369570,
+                       6731680,        6262450,        5897690,
+                       5592269,        5328789
+               },
+               {
+                       15000000,       12770450,       11642129,
+                       10000000,       9120929,        8601920,
+                       7946630,        7490440,        7140589,
+                       6847490,        6593719
+               },
+               {
+                       14062479,       11541219,       10644329,
+                       10000000,       9736120,        9495139,
+                       9080520,        8724340,        8419489,
+                       8146359,        7899820
+               },
+               {
+                       12507469,       11102950,       10457479,
+                       10000000,       9811149,        9641249,
+                       9344969,        9090980,        8875219,
+                       8684499,        8513180
+               }
+       },
+       /* 11 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       10099509,       10099509,       10099509,
+                       10000000,       2788810,        2054850,
+                       99999,          99999,          99999,
+                       99999,          99999
+               },
+               {
+                       8872069,        8872069,        8872069,
+                       10000000,       3929649,        3522840,
+                       2963230,        2527720,        2157579,
+                       1823610,        1500000
+               },
+               {
+                       10099999,       10099999,       10099999,
+                       10000000,       5155599,        4712319,
+                       4154500,        3759450,        3448629,
+                       3183139,        2948490
+               },
+               {
+                       10511649,       10511649,       14216580,
+                       10000000,       6445930,        5988820,
+                       5401239,        4988409,        4673399,
+                       4410479,        4181599
+               },
+               {
+                       9170889,        14003310,       12949769,
+                       10000000,       7684900,        7250000,
+                       6670129,        6255810,        5934680,
+                       5664110,        5427970
+               },
+               {
+                       15000000,       12763030,       11734730,
+                       10000000,       8958870,        8478559,
+                       7893459,        7489529,        7179200,
+                       6917790,        6688359
+               },
+               {
+                       14634610,       11491880,       10619130,
+                       10000000,       9744859,        9509819,
+                       9102900,        8760340,        8463050,
+                       8202620,        7968729
+               },
+               {
+                       12415319,       10980290,       10405089,
+                       10000000,       9831910,        9680110,
+                       9413710,        9184579,        8987190,
+                       8813819,        8655819
+               }
+       },
+       /* 12 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       10832400,       10832400,       10832400,
+                       10000000,       2700819,        2115820,
+                       750000,         99999,          99999,
+                       99999,          99999
+               },
+               {
+                       10747549,       10747549,       10747549,
+                       10000000,       3781630,        3415020,
+                       2914879,        2537429,        2221180,
+                       1943199,        1688420
+               },
+               {
+                       11630790,       11630790,       11630790,
+                       10000000,       5047429,        4631519,
+                       4113860,        3750000,        3469760,
+                       3229379,        3016360
+               },
+               {
+                       10780229,       10780229,       10780229,
+                       10000000,       6340010,        5935009,
+                       5387600,        4995940,        4695929,
+                       4446829,        4231610
+               },
+               {
+                       9055669,        13968739,       13037070,
+                       10000000,       7556660,        7149490,
+                       6625509,        6250000,        5958870,
+                       5713790,        5500869
+               },
+               {
+                       14614900,       12760740,       11806739,
+                       10000000,       8824530,        8388419,
+                       7857400,        7489010,        7206150,
+                       6968010,        6759889
+               },
+               {
+                       14894100,       11451840,       10598870,
+                       10000000,       9750000,        9521099,
+                       9122239,        8784019,        8494700,
+                       8243309,        8018680
+               },
+               {
+                       12298769,       10886880,       10367530,
+                       10000000,       9846829,        9708030,
+                       9464049,        9252949,        9072539,
+                       8910980,        8766649
+               }
+       },
+       /* 13 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       10099999,       10099999,       10099999,
+                       10000000,       2574490,        2099110,
+                       1194889,        99999,          99999,
+                       99999,          99999
+               },
+               {
+                       10099999,       10099999,       10099999,
+                       10000000,       3679780,        3332070,
+                       2869139,        2530030,        2251899,
+                       2010450,        1793050
+               },
+               {
+                       9306690,        9306690,        9306690,
+                       10000000,       4964010,        4573009,
+                       4082309,        3742089,        3481810,
+                       3262990,        3070969
+               },
+               {
+                       10099999,       10099999,       10099999,
+                       10000000,       6217889,        5843269,
+                       5353810,        5000000,        4730190,
+                       4499999,        4301390
+               },
+               {
+                       8819990,        13964320,       13098440,
+                       10000000,       7454770,        7075160,
+                       6591439,        6250000,        5983970,
+                       5760229,        5564339
+               },
+               {
+                       14432849,       12727780,       11847709,
+                       10000000,       8695709,        8322049,
+                       7842620,        7500000,        7234820,
+                       7010849,        6814730
+               },
+               {
+                       15000000,       11440130,       10620100,
+                       10000000,       9742270,        9508739,
+                       9110010,        8782560,        8510140,
+                       8276290,        8069980
+               },
+               {
+                       12039999,       10825289,       10341939,
+                       10000000,       9858080,        9729740,
+                       9505100,        9310669,        9144560,
+                       8996559,        8862569
+               }
+       },
+       /* 14 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       9289590,        9289590,        9289590,
+                       10000000,       2485270,        2084970,
+                       1362659,        250000,         99999,
+                       99999,          99999
+               },
+               {
+                       9484500,        9484500,        9484500,
+                       10000000,       3593840,        3263100,
+                       2833609,        2519409,        2267650,
+                       2050379,        1856749
+               },
+               {
+                       9237130,        9237130,        9237130,
+                       10000000,       4898909,        4527629,
+                       4057880,        3734529,        3490320,
+                       3287230,        3111050
+               },
+               {
+                       9543399,        9543399,        9543399,
+                       10000000,       6110230,        5772359,
+                       5328080,        5007240,        4757330,
+                       4545379,        4359109
+               },
+               {
+                       9032660,        9032660,        9032660,
+                       10000000,       7373520,        7016940,
+                       6565740,        6250000,        6002650,
+                       5794939,        5610830
+               },
+               {
+                       14351329,       12697319,       11875350,
+                       10000000,       8606730,        8275989,
+                       7833449,        7510430,        7257339,
+                       7043970,        6857690
+               },
+               {
+                       13286800,       11436090,       10643019,
+                       10000000,       9729470,        9491149,
+                       9096930,        8778640,        8519319,
+                       8299450,        8104829
+               },
+               {
+                       11838380,       10778709,       10322740,
+                       10000000,       9866499,        9746059,
+                       9535790,        9354810,        9200339,
+                       9063839,        8940430
+               }
+       },
+       /* 15 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       9193199,        9193199,        9193199,
+                       10000000,       2400999,        2042409,
+                       1450179,        789309,         99999,
+                       99999,          99999
+               },
+               {
+                       10755189,       10755189,       10755189,
+                       10000000,       3532319,        3212479,
+                       2803660,        2510200,        2278629,
+                       2078720,        1899970
+               },
+               {
+                       8732669,        8732669,        8732669,
+                       10000000,       4821290,        4483030,
+                       4045079,        3737959,        3505080,
+                       3311960,        3143329
+               },
+               {
+                       9450280,        9450280,        9450280,
+                       10000000,       6040880,        5718960,
+                       5302609,        5004199,        4771710,
+                       4575310,        4404180
+               },
+               {
+                       10520930,       10520930,       10520930,
+                       10000000,       7298259,        6975160,
+                       6552690,        6250000,        6018469,
+                       5822089,        5648869
+               },
+               {
+                       14320160,       12683949,       11917040,
+                       10000000,       8541300,        8228710,
+                       7812070,        7509459,        7272909,
+                       7072560,        6895729
+               },
+               {
+                       15000000,       11434819,       10650700,
+                       10000000,       9723110,        9480339,
+                       9083300,        8771640,        8524850,
+                       8317480,        8135899
+               },
+               {
+                       11750520,       10722860,       10299190,
+                       10000000,       9875990,        9763770,
+                       9567070,        9397709,        9252669,
+                       9124029,        9008929
+               }
+       },
+       /* 16 tap downscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,
+                       0,              -10000000,      -20000000,
+                       -40000000,      -60209999,      -80000000,
+                       -100000000,     -120410003
+               },
+               {
+                       10612260,       10612260,       10612260,
+                       10000000,       2308720,        1999289,
+                       1495770,        1009820,        315460,
+                       99999,          99999
+               },
+               {
+                       9394969,        9394969,        9394969,
+                       10000000,       3462660,        3162190,
+                       2780120,        2508420,        2295179,
+                       2109449,        1943989
+               },
+               {
+                       10609409,       10609409,       10609409,
+                       10000000,       4749999,        4447000,
+                       4039109,        3746300,        3522360,
+                       3336620,        3177059
+               },
+               {
+                       9435039,        9435039,        9435039,
+                       10000000,       5978109,        5675160,
+                       5282300,        5000000,        4782429,
+                       4598149,        4438050
+               },
+               {
+                       10592620,       10592620,       10592620,
+                       10000000,       7244589,        6940630,
+                       6537730,        6250000,        6027920,
+                       5842260,        5680159
+               },
+               {
+                       14282959,       12678509,       11963449,
+                       10000000,       8484349,        8181620,
+                       7785459,        7500000,        7281309,
+                       7095699,        6932809
+               },
+               {
+                       15000000,       11434919,       10673819,
+                       10000000,       9708179,        9456859,
+                       9060000,        8760929,        8529940,
+                       8338279,        8172209
+               },
+               {
+                       11690390,       10668220,       10277210,
+                       10000000,       9884750,        9780330,
+                       9597110,        9439319,        9304260,
+                       9183580,        9075019
+               }
+       }
+};
+
+static const int32_t upscaling_db_table[][UP_DB_SCALES+1][UP_DB_POINTS] = {
+       /* 3 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       14302920,       14302920,       11709250,
+                       10000000,
+                       8754609,        7692559,        6738259
+               }
+       },
+       /*      4 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       14308999,       12448530,       11007410,
+                       10000000,       9165279,        8435800,
+                       7785279
+               }
+       },
+       /* 5 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       14627330,       12046170,       10862360,
+                       10000000,
+                       9312710,        8737679,        8242470
+               }
+       },
+       /* 6 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       13815449,       11911309,       10801299,
+                       10000000,
+                       9380580,        8878319,        8452050
+               }
+       },
+       /* 7 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       13752900,       11554559,       10637769,
+                       10000000,
+                       9499999,        9079759,        8718389
+               }
+       },
+       /* 8 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       13861900,       11311980,       10543940,
+                       10000000,
+                       9565100,        9198870,        8881340
+               }
+       },
+       /* 9 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       12981410,       11185950,       10491620,
+                       10000000,
+                       9611030,        9286710,        9007279
+               }
+       },
+       /* 10 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       12507469,       11102950,       10457479,
+                       10000000,
+                       9641249,        9344969,        9090980
+               }
+       },
+       /* 11 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       12415319,       10980290,       10405089,
+                       10000000,
+                       9680110,        9413710,        9184579
+               }
+       },
+       /* 12 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       12298769,       10886880,       10367530,
+                       10000000,
+                       9708030,        9464049,        9252949
+               }
+       },
+       /* 13 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       12039999,       10825289,       10341939,
+                       10000000,
+                       9729740,        9505100,        9310669
+               }
+       },
+       /* 14 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       11838380,       10778709,       10322740,
+                       10000000,
+                       9746059,        9535790,        9354810
+               }
+       },
+       /* 15 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       11750520,       10722860,       10299190,
+                       10000000,
+                       9763770,        9567070,        9397709
+               }
+       },
+       /* 16 tap upscaling */
+       {
+               {
+                       60209999,       40000000,       20000000,       0,
+                       -20000000,      -40000000,      -60209999
+               },
+               {
+                       11690390,       10668220,       10277210,
+                       10000000,
+                       9780330,        9597110,        9439319
+               }
+       }
+};
+
+static bool allocate_3d_storage(
+       struct dc_context *ctx,
+       struct fixed31_32 ****ptr,
+       int32_t numberof_tables,
+       int32_t numberof_rows,
+       int32_t numberof_columns)
+{
+       int32_t indexof_table = 0;
+       int32_t indexof_row = 0;
+
+       struct fixed31_32 ***tables = dm_alloc(
+               ctx,
+               numberof_tables * sizeof(struct fixed31_32 **));
+
+       if (!tables) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       while (indexof_table != numberof_tables) {
+               struct fixed31_32 **rows = dm_alloc(
+                       ctx,
+                       numberof_rows * sizeof(struct fixed31_32 *));
+
+               if (!rows) {
+                       BREAK_TO_DEBUGGER();
+                       --indexof_table;
+                       goto failure;
+               }
+
+               tables[indexof_table] = rows;
+
+               while (indexof_row != numberof_rows) {
+                       struct fixed31_32 *columns = dm_alloc(
+                               ctx,
+                               numberof_columns * sizeof(struct fixed31_32));
+
+                       if (!columns) {
+                               BREAK_TO_DEBUGGER();
+                               --indexof_row;
+                               goto failure;
+                       }
+
+                       rows[indexof_row] = columns;
+
+                       ++indexof_row;
+               }
+
+               indexof_row = 0;
+
+               ++indexof_table;
+       }
+
+       *ptr = tables;
+
+       return true;
+
+failure:
+
+       while (indexof_table >= 0) {
+               while (indexof_row >= 0) {
+                       dm_free(ctx, tables[indexof_table][indexof_row]);
+
+                       --indexof_row;
+               }
+
+               indexof_row = numberof_rows - 1;
+
+               dm_free(ctx, tables[indexof_table]);
+
+               --indexof_table;
+       }
+
+       dm_free(ctx, tables);
+
+       return false;
+}
+
+static void destroy_3d_storage(
+       struct dc_context *ctx,
+       struct fixed31_32 ****ptr,
+       uint32_t numberof_tables,
+       uint32_t numberof_rows)
+{
+       struct fixed31_32 ***tables = *ptr;
+
+       uint32_t indexof_table = 0;
+
+       if (!tables)
+               return;
+
+       while (indexof_table != numberof_tables) {
+               uint32_t indexof_row = 0;
+
+               while (indexof_row != numberof_rows) {
+                       dm_free(
+                               ctx, tables[indexof_table][indexof_row]);
+
+                       ++indexof_row;
+               };
+
+               dm_free(ctx, tables[indexof_table]);
+
+               ++indexof_table;
+       };
+
+       dm_free(ctx, tables);
+
+       *ptr = NULL;
+}
+
+static bool create_downscaling_table(
+       struct scaler_filter *filter)
+{
+       const int32_t numberof_tables =
+               ARRAY_SIZE(downscaling_db_table);
+       const int32_t numberof_rows =
+               ARRAY_SIZE(downscaling_db_table[0]);
+       const int32_t numberof_columns =
+               ARRAY_SIZE(downscaling_db_table[0][0]);
+
+       int32_t indexof_table = 0;
+
+       if (!allocate_3d_storage(filter->ctx, &filter->downscaling_table,
+               numberof_tables, numberof_rows, numberof_columns)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       while (indexof_table != numberof_tables) {
+               struct fixed31_32 **table =
+                       filter->downscaling_table[indexof_table];
+
+               int32_t indexof_row = 0;
+
+               while (indexof_row != numberof_rows) {
+                       struct fixed31_32 *row = table[indexof_row];
+
+                       int32_t indexof_column = 0;
+
+                       while (indexof_column != numberof_columns) {
+                               row[indexof_column] =
+dal_fixed31_32_from_fraction(
+       downscaling_db_table[indexof_table][indexof_row][indexof_column],
+       CONST_DIVIDER);
+
+                               ++indexof_column;
+                       }
+
+                       ++indexof_row;
+               }
+
+               ++indexof_table;
+       }
+
+       return true;
+}
+
+static inline void destroy_downscaling_table(
+       struct scaler_filter *filter)
+{
+       destroy_3d_storage(
+               filter->ctx,
+               &filter->downscaling_table,
+               ARRAY_SIZE(downscaling_db_table),
+               ARRAY_SIZE(downscaling_db_table[0]));
+}
+
+static bool create_upscaling_table(
+       struct scaler_filter *filter)
+{
+       const int32_t numberof_tables =
+               ARRAY_SIZE(upscaling_db_table);
+       const int32_t numberof_rows =
+               ARRAY_SIZE(upscaling_db_table[0]);
+       const int32_t numberof_columns =
+               ARRAY_SIZE(upscaling_db_table[0][0]);
+
+       int32_t indexof_table = 0;
+
+       if (!allocate_3d_storage(filter->ctx, &filter->upscaling_table,
+               numberof_tables, numberof_rows, numberof_columns)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       while (indexof_table != numberof_tables) {
+               struct fixed31_32 **table =
+                       filter->upscaling_table[indexof_table];
+
+               int32_t indexof_row = 0;
+
+               while (indexof_row != numberof_rows) {
+                       struct fixed31_32 *row = table[indexof_row];
+
+                       int32_t indexof_column = 0;
+
+                       while (indexof_column != numberof_columns) {
+                               row[indexof_column] =
+dal_fixed31_32_from_fraction(
+       upscaling_db_table[indexof_table][indexof_row][indexof_column],
+       CONST_DIVIDER);
+
+                               ++indexof_column;
+                       }
+
+                       ++indexof_row;
+               }
+
+               ++indexof_table;
+       }
+
+       return true;
+}
+
+static inline void destroy_upscaling_table(
+       struct scaler_filter *filter)
+{
+       destroy_3d_storage(
+               filter->ctx,
+               &filter->upscaling_table,
+               ARRAY_SIZE(upscaling_db_table),
+               ARRAY_SIZE(upscaling_db_table[0]));
+}
+
+static bool same_filter_required(
+       struct scaler_filter *filter,
+       const struct scaler_filter_params *params,
+       uint32_t src_size,
+       uint32_t dst_size)
+{
+       if (!filter->src_size)
+               return false;
+       if (!filter->dst_size)
+               return false;
+       if (filter->src_size != src_size)
+               return false;
+       if (filter->dst_size != dst_size)
+               return false;
+       if (filter->params.taps != params->taps)
+               return false;
+       if (filter->params.phases != params->phases)
+               return false;
+       if (filter->params.sharpness != params->sharpness)
+               return false;
+
+       return true;
+}
+
+/*
+ * @brief
+ *                                            (scale_max - scale_min)
+ * result = scale_min + (value - value_min) * -----------------------
+ *                                            (value_max - value_min)
+ */
+
+static struct fixed31_32 interpolate(
+       struct fixed31_32 value,
+       struct fixed31_32 value_min,
+       struct fixed31_32 value_max,
+       struct fixed31_32 scale_min,
+       struct fixed31_32 scale_max)
+{
+       return dal_fixed31_32_add(
+               scale_min,
+               dal_fixed31_32_div(
+                       dal_fixed31_32_mul(
+                               dal_fixed31_32_sub(
+                                       value,
+                                       value_min),
+                               dal_fixed31_32_sub(
+                                       scale_max,
+                                       scale_min)),
+                       dal_fixed31_32_sub(
+                               value_max,
+                               value_min)));
+}
+
+static bool map_sharpness(
+       struct scaler_filter *filter,
+       const struct scaler_filter_params *params,
+       uint32_t src_size,
+       uint32_t dst_size,
+       struct fixed31_32 *attenuation,
+       struct fixed31_32 *decibels_at_nyquist)
+{
+       struct fixed31_32 ratio = dal_fixed31_32_from_fraction(
+               dst_size,
+               src_size);
+
+       const struct fixed31_32 sharp_flat =
+               dal_fixed31_32_from_fraction(MIN_SHARPNESS + MAX_SHARPNESS, 2);
+
+       struct fixed31_32 sharp_max =
+               dal_fixed31_32_from_int(MAX_SHARPNESS);
+       struct fixed31_32 sharp_min =
+               dal_fixed31_32_from_int(MIN_SHARPNESS);
+
+       uint32_t index = params->taps - 3;
+
+       struct fixed31_32 ratio_low;
+       struct fixed31_32 ratio_up;
+
+       struct fixed31_32 db_min;
+       struct fixed31_32 db_flat;
+       struct fixed31_32 db_max;
+       struct fixed31_32 db_value;
+
+       uint32_t i0;
+       uint32_t i1;
+       uint32_t row0;
+       uint32_t row1;
+
+       int32_t sharp = params->sharpness;
+
+       if (sharp < MIN_SHARPNESS)
+               sharp = MIN_SHARPNESS;
+       else if (sharp > MAX_SHARPNESS)
+               sharp = MAX_SHARPNESS;
+
+       if (params->flags.bits.HORIZONTAL) {
+               if (dal_fixed31_32_lt(ratio, max_hor_downscale())) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               } else if (dal_fixed31_32_lt(
+                       max_hor_upscale(), ratio)) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+       } else {
+               if (dal_fixed31_32_lt(ratio, max_ver_downscale())) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               } else if (dal_fixed31_32_lt(
+                       max_ver_upscale(), ratio)) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+       }
+
+       if (dst_size >= src_size) {
+               if (sharp < 0) {
+                       db_max = up_db_flat();
+                       db_min = up_db_fuzzy();
+
+                       sharp_max = sharp_flat;
+               } else {
+                       db_max = up_db_sharp();
+                       db_min = up_db_flat();
+
+                       sharp_min = sharp_flat;
+               }
+
+               db_value = interpolate(
+                       dal_fixed31_32_from_int(sharp),
+                       sharp_min, sharp_max,
+                       db_min, db_max);
+
+               i0 = 0;
+
+               while (dal_fixed31_32_lt(
+                       db_value, filter->upscaling_table[index][0][i0]) &&
+                       (i0 < UP_DB_POINTS - 1))
+                       ++i0;
+
+               i1 = i0 + 1;
+
+               if (i0 == UP_DB_POINTS - 1)
+                       i1 = i0--;
+
+               sharp_max = filter->upscaling_table[index][1][i0];
+               sharp_min = filter->upscaling_table[index][1][i1];
+
+               db_max = filter->upscaling_table[index][0][i0];
+               db_min = filter->upscaling_table[index][0][i1];
+
+               *attenuation = interpolate(
+                       db_value,
+                       db_max, db_min,
+                       sharp_max, sharp_min);
+
+               *decibels_at_nyquist = db_value;
+
+               return true;
+       } else if ((5 * dst_size) < (src_size << 2)) {
+               if (sharp < 0) {
+                       db_max = down_db_flat();
+                       db_min = down_db_fuzzy();
+
+                       sharp_max = sharp_flat;
+               } else {
+                       db_max = down_db_sharp();
+                       db_min = down_db_flat();
+
+                       sharp_min = sharp_flat;
+               }
+
+               db_value = interpolate(
+                       dal_fixed31_32_from_int(sharp),
+                       sharp_min, sharp_max,
+                       db_min, db_max);
+       } else {
+               struct fixed31_32 db_value_min =
+                       filter->downscaling_table[index][0][0];
+
+               struct fixed31_32 db_value_max =
+                       filter->downscaling_table[index][0][DOWN_DB_POINTS - 1];
+
+               db_min = interpolate(
+                       ratio,
+                       threshold_ratio_low(), threshold_ratio_up(),
+                       down_db_fuzzy(), up_db_fuzzy());
+
+               db_flat = interpolate(
+                       ratio,
+                       threshold_ratio_low(), threshold_ratio_up(),
+                       down_db_flat(), up_db_flat());
+
+               db_max = interpolate(
+                       ratio,
+                       threshold_ratio_low(), threshold_ratio_up(),
+                       down_db_sharp(), up_db_sharp());
+
+               if (sharp < 0) {
+                       db_max = db_flat;
+
+                       db_value = interpolate(
+                               dal_fixed31_32_from_int(sharp),
+                               sharp_min, dal_fixed31_32_zero,
+                               db_min, db_max);
+               } else {
+                       db_min = db_flat;
+
+                       db_value = interpolate(
+                               dal_fixed31_32_from_int(sharp),
+                               dal_fixed31_32_zero, sharp_max,
+                               db_min, db_max);
+               }
+
+               if (dal_fixed31_32_lt(db_value_min, db_value))
+                       db_value = db_value_min;
+               else if (dal_fixed31_32_lt(db_value, db_value_max))
+                       db_value = db_value_max;
+       }
+
+       i1 = 0;
+
+       while (dal_fixed31_32_lt(db_value,
+               filter->downscaling_table[index][0][i1]) &&
+               (i1 < DOWN_DB_POINTS - 1))
+               ++i1;
+
+       if (i1 == 0)
+               i0 = i1++;
+       else
+               i0 = i1 - 1;
+
+       row0 = dal_fixed31_32_round(
+               dal_fixed31_32_mul_int(ratio, DOWN_DB_SCALES));
+
+       if (dal_fixed31_32_lt(
+               dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES), ratio)) {
+               row1 = row0 + 1;
+
+               if (row1 > DOWN_DB_SCALES) {
+                       row1 = DOWN_DB_SCALES;
+                       row0 = row1 - 1;
+               }
+       } else {
+               row1 = row0--;
+
+               if (row0 < 1) {
+                       row0 = 1;
+                       row1 = 2;
+               }
+       }
+
+       ratio_low = dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES);
+       ratio_up = dal_fixed31_32_from_fraction(row1, DOWN_DB_SCALES);
+
+       sharp_max = interpolate(
+               ratio,
+               ratio_low, ratio_up,
+               filter->downscaling_table[index][row0][i0],
+               filter->downscaling_table[index][row1][i0]);
+
+       sharp_min = interpolate(
+               ratio,
+               ratio_low, ratio_up,
+               filter->downscaling_table[index][row0][i1],
+               filter->downscaling_table[index][row1][i1]);
+
+       db_max = filter->downscaling_table[index][0][i0];
+       db_min = filter->downscaling_table[index][0][i1];
+
+       *attenuation = interpolate(
+               db_value,
+               db_max, db_min,
+               sharp_max, sharp_min);
+
+       *decibels_at_nyquist = db_value;
+
+       return true;
+}
+
+static inline struct fixed31_32 lanczos(
+       struct fixed31_32 x,
+       struct fixed31_32 a2)
+{
+       return dal_fixed31_32_mul(
+               dal_fixed31_32_sinc(x),
+               dal_fixed31_32_sinc(
+                       dal_fixed31_32_mul(x, a2)));
+}
+
+static bool generate_filter(
+       struct scaler_filter *filter,
+       const struct scaler_filter_params *params,
+       struct fixed31_32 attenuation,
+       struct fixed31_32 *ringing)
+{
+       uint32_t n = params->phases * params->taps;
+
+       uint32_t coefficients_quantity = n;
+       uint32_t coefficients_sum_quantity = params->phases;
+
+       uint32_t i;
+       uint32_t i_limit;
+       uint32_t j;
+       uint32_t m;
+
+       struct fixed31_32 attenby2;
+
+       struct fixed31_32 a_max = dal_fixed31_32_zero;
+       struct fixed31_32 a_min = dal_fixed31_32_zero;
+
+       if (filter->coefficients_quantity < coefficients_quantity) {
+               if (filter->coefficients) {
+                       dm_free(filter->ctx, filter->coefficients);
+
+                       filter->coefficients = NULL;
+                       filter->coefficients_quantity = 0;
+               }
+
+               filter->coefficients = dm_alloc(
+                       filter->ctx,
+                       coefficients_quantity * sizeof(struct fixed31_32));
+
+               if (!filter->coefficients) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+
+               filter->coefficients_quantity = coefficients_quantity;
+       }
+
+       i = 0;
+
+       while (i != filter->coefficients_quantity) {
+               filter->coefficients[i] = dal_fixed31_32_zero;
+
+               ++i;
+       }
+
+       if (filter->coefficients_sum_quantity < coefficients_sum_quantity) {
+               if (filter->coefficients_sum) {
+                       dm_free(filter->ctx, filter->coefficients_sum);
+
+                       filter->coefficients_sum = NULL;
+                       filter->coefficients_sum_quantity = 0;
+               }
+
+               filter->coefficients_sum = dm_alloc(
+                       filter->ctx,
+                       coefficients_sum_quantity * sizeof(struct fixed31_32));
+
+               if (!filter->coefficients_sum) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+
+               filter->coefficients_sum_quantity = coefficients_sum_quantity;
+       }
+
+       i = 0;
+
+       while (i != filter->coefficients_sum_quantity) {
+               filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+               ++i;
+       }
+
+       m = 0;
+
+       attenby2 = dal_fixed31_32_div_int(
+               dal_fixed31_32_mul_int(attenuation, params->taps), 2);
+
+       i = 1;
+
+       while (i <= params->taps) {
+               j = 0;
+
+               while (j != params->phases) {
+                       struct fixed31_32 x = dal_fixed31_32_mul(
+                               dal_fixed31_32_pi,
+                               dal_fixed31_32_from_fraction(
+                                       (int64_t)(m << 1) - n, n));
+
+                       uint32_t index =
+                               (params->taps - i) * params->phases + j;
+
+                       filter->coefficients[index] = lanczos(x, attenby2);
+
+                       ++m;
+
+                       ++j;
+               }
+
+               ++i;
+       }
+
+       i = 0;
+
+       while (i != params->phases) {
+               filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+               m = i;
+
+               j = 0;
+
+               while (j != params->taps) {
+                       filter->coefficients_sum[i] =
+                               dal_fixed31_32_add(
+                                       filter->coefficients_sum[i],
+                                       filter->coefficients[m]);
+
+                       m += params->phases;
+
+                       ++j;
+               }
+
+               ++i;
+       }
+
+       i = 0;
+
+       while (i != params->phases) {
+               m = i;
+
+               j = 0;
+
+               while (j != params->taps) {
+                       filter->coefficients[m] =
+                               dal_fixed31_32_div(
+                                       filter->coefficients[m],
+                                       filter->coefficients_sum[i]);
+
+                       m += params->phases;
+
+                       ++j;
+               }
+
+               ++i;
+       }
+
+       i = 0;
+       i_limit = (params->phases >> 1) + 1;
+
+       while (i != i_limit) {
+               m = i;
+
+               j = 0;
+
+               while (j != params->taps) {
+                       struct fixed31_32 tmp = filter->coefficients[m];
+
+                       filter->filter[i * params->taps + j] = tmp;
+
+                       if (dal_fixed31_32_lt(
+                               tmp, dal_fixed31_32_zero) &&
+                               dal_fixed31_32_lt(tmp, a_min))
+                               a_min = tmp;
+                       else if (dal_fixed31_32_lt(
+                               dal_fixed31_32_zero, tmp) &&
+                               dal_fixed31_32_lt(a_max, tmp))
+                               a_max = tmp;
+
+                       m += params->phases;
+
+                       ++j;
+               }
+
+               ++i;
+       }
+
+       if (dal_fixed31_32_eq(a_min, dal_fixed31_32_zero))
+               *ringing = dal_fixed31_32_from_int(100);
+       else
+               *ringing = dal_fixed31_32_min(
+                       dal_fixed31_32_abs(
+                               dal_fixed31_32_div(a_max, a_min)),
+                       dal_fixed31_32_from_int(100));
+
+       return true;
+}
+
+static bool construct_scaler_filter(
+       struct dc_context *ctx,
+       struct scaler_filter *filter)
+{
+       filter->src_size = 0;
+       filter->dst_size = 0;
+       filter->filter = NULL;
+       filter->integer_filter = NULL;
+       filter->filter_size_allocated = 0;
+       filter->filter_size_effective = 0;
+       filter->coefficients = NULL;
+       filter->coefficients_quantity = 0;
+       filter->coefficients_sum = NULL;
+       filter->coefficients_sum_quantity = 0;
+       filter->downscaling_table = NULL;
+       filter->upscaling_table = NULL;
+       filter->ctx = ctx;
+
+       if (!create_downscaling_table(filter)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       if (!create_upscaling_table(filter)) {
+               BREAK_TO_DEBUGGER();
+               destroy_downscaling_table(filter);
+               return false;
+       }
+
+       return true;
+}
+
+static void destruct_scaler_filter(
+       struct scaler_filter *filter)
+{
+       if (filter->coefficients_sum)
+               dm_free(filter->ctx, filter->coefficients_sum);
+
+       if (filter->coefficients)
+               dm_free(filter->ctx, filter->coefficients);
+
+       if (filter->integer_filter)
+               dm_free(filter->ctx, filter->integer_filter);
+
+       if (filter->filter)
+               dm_free(filter->ctx, filter->filter);
+
+       destroy_upscaling_table(filter);
+
+       destroy_downscaling_table(filter);
+}
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx)
+{
+       struct scaler_filter *filter =
+               dm_alloc(ctx, sizeof(struct scaler_filter));
+
+       if (!filter) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       if (construct_scaler_filter(ctx, filter))
+               return filter;
+
+       BREAK_TO_DEBUGGER();
+
+       dm_free(ctx, filter);
+
+       return NULL;
+}
+
+bool dal_scaler_filter_generate(
+       struct scaler_filter *filter,
+       const struct scaler_filter_params *params,
+       uint32_t src_size,
+       uint32_t dst_size)
+{
+       uint32_t filter_size_required;
+
+       struct fixed31_32 attenuation;
+       struct fixed31_32 decibels_at_nyquist;
+       struct fixed31_32 ringing;
+
+       if (!params) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       if ((params->taps < 3) || (params->taps > 16)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       if (!src_size || !dst_size) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       if (same_filter_required(filter, params, src_size, dst_size))
+               return true;
+
+       filter_size_required =
+               params->taps * ((params->phases >> 1) + 1);
+
+       if (filter_size_required > filter->filter_size_allocated) {
+               if (filter->filter) {
+                       dm_free(filter->ctx, filter->filter);
+
+                       filter->filter = 0;
+                       filter->filter_size_allocated = 0;
+               }
+
+               filter->filter = dm_alloc(
+                       filter->ctx,
+                       filter_size_required * sizeof(struct fixed31_32));
+
+               if (!filter->filter) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+
+               if (filter->integer_filter) {
+                       dm_free(filter->ctx, filter->integer_filter);
+
+                       filter->integer_filter = 0;
+               }
+
+               filter->integer_filter = dm_alloc(
+                       filter->ctx,
+                       filter_size_required * sizeof(uint32_t));
+
+               if (!filter->integer_filter) {
+                       BREAK_TO_DEBUGGER();
+                       return false;
+               }
+
+               filter->filter_size_allocated = filter_size_required;
+       }
+
+       filter->filter_size_effective = filter_size_required;
+
+       if (!map_sharpness(filter, params, src_size, dst_size,
+               &attenuation, &decibels_at_nyquist)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       if (!generate_filter(filter, params, attenuation, &ringing)) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       filter->params = *params;
+       filter->src_size = src_size;
+       filter->dst_size = dst_size;
+
+       return true;
+}
+
+const struct fixed31_32 *dal_scaler_filter_get(
+       const struct scaler_filter *filter,
+       uint32_t **data,
+       uint32_t *number)
+{
+       if (!number) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       if (!data) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       *number = filter->filter_size_effective;
+       *data = filter->integer_filter;
+
+       return filter->filter;
+}
+
+void dal_scaler_filter_destroy(
+       struct scaler_filter **filter)
+{
+       if (!filter || !*filter) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       destruct_scaler_filter(*filter);
+
+       dm_free((*filter)->ctx, *filter);
+
+       *filter = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h 
b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
new file mode 100644
index 000000000000..668691d6c6e6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
@@ -0,0 +1,74 @@
+/* Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_FILTER_H__
+#define __DAL_SCALER_FILTER_H__
+
+struct scaler_filter_params {
+       uint32_t taps; /* 3...16 */
+       uint32_t phases;
+       int32_t sharpness; /* -50...50 */
+       union {
+               struct {
+                       uint32_t HORIZONTAL:1;
+                       uint32_t RESERVED:31;
+               } bits;
+               uint32_t value;
+       } flags;
+};
+
+struct q31_32;
+
+struct scaler_filter {
+       struct scaler_filter_params params;
+       uint32_t src_size;
+       uint32_t dst_size;
+       struct fixed31_32 *filter;
+       uint32_t *integer_filter;
+       uint32_t filter_size_allocated;
+       uint32_t filter_size_effective;
+       struct fixed31_32 *coefficients;
+       uint32_t coefficients_quantity;
+       struct fixed31_32 *coefficients_sum;
+       uint32_t coefficients_sum_quantity;
+       struct fixed31_32 ***downscaling_table;
+       struct fixed31_32 ***upscaling_table;
+       struct dc_context *ctx;
+};
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx);
+void dal_scaler_filter_destroy(struct scaler_filter **ptr);
+
+bool dal_scaler_filter_generate(
+       struct scaler_filter *filter,
+       const struct scaler_filter_params *params,
+       uint32_t src_size,
+       uint32_t dst_size);
+
+const struct fixed31_32 *dal_scaler_filter_get(
+       const struct scaler_filter *filter,
+       uint32_t **data,
+       uint32_t *number);
+
+#endif
-- 
2.1.4

Reply via email to