summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/spl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/spl')
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.c1363
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_filters.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_filters.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.c351
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h35
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_scl_easf_filters.c1726
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_scl_easf_filters.h38
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_scl_filters.c91
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_scl_filters.h55
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_scl_filters_old.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h72
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_custom_float.c151
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_custom_float.h29
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_debug.h25
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.c497
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_fixpt31_32.h525
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/spl_os_types.h30
18 files changed, 4348 insertions, 697 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/spl/Makefile b/drivers/gpu/drm/amd/display/dc/spl/Makefile
index f8df85ea4d32..5edf3c6cf3e2 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/spl/Makefile
@@ -23,7 +23,7 @@
# Makefile for the 'spl' sub-component of DAL.
# It provides the scaling library interface.
-SPL = dc_spl.o dc_spl_scl_filters.o dc_spl_scl_filters_old.o dc_spl_isharp_filters.o
+SPL = dc_spl.o dc_spl_scl_filters.o dc_spl_scl_easf_filters.o dc_spl_isharp_filters.o dc_spl_filters.o spl_fixpt31_32.o spl_custom_float.o
AMD_DAL_SPL = $(addprefix $(AMDDALPATH)/dc/spl/,$(SPL))
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index 9eccdb38bed4..15f7eda903e6 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -4,9 +4,11 @@
#include "dc_spl.h"
#include "dc_spl_scl_filters.h"
+#include "dc_spl_scl_easf_filters.h"
#include "dc_spl_isharp_filters.h"
+#include "spl_debug.h"
-#define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
+#define IDENTITY_RATIO(ratio) (spl_fixpt_u2d19(ratio) == (1 << 19))
#define MIN_VIEWPORT_SIZE 12
static struct spl_rect intersect_rec(const struct spl_rect *r0, const struct spl_rect *r1)
@@ -107,26 +109,26 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
const struct spl_rect *stream_src = &spl_in->basic_out.src_rect;
const struct spl_rect *stream_dst = &spl_in->basic_out.dst_rect;
struct spl_rect rec_out = {0};
- struct fixed31_32 temp;
+ struct spl_fixed31_32 temp;
- temp = dc_fixpt_from_fraction(rec_in->x * (long long)stream_dst->width,
+ temp = spl_fixpt_from_fraction(rec_in->x * (long long)stream_dst->width,
stream_src->width);
- rec_out.x = stream_dst->x + dc_fixpt_round(temp);
+ rec_out.x = stream_dst->x + spl_fixpt_round(temp);
- temp = dc_fixpt_from_fraction(
+ temp = spl_fixpt_from_fraction(
(rec_in->x + rec_in->width) * (long long)stream_dst->width,
stream_src->width);
- rec_out.width = stream_dst->x + dc_fixpt_round(temp) - rec_out.x;
+ rec_out.width = stream_dst->x + spl_fixpt_round(temp) - rec_out.x;
- temp = dc_fixpt_from_fraction(rec_in->y * (long long)stream_dst->height,
+ temp = spl_fixpt_from_fraction(rec_in->y * (long long)stream_dst->height,
stream_src->height);
- rec_out.y = stream_dst->y + dc_fixpt_round(temp);
+ rec_out.y = stream_dst->y + spl_fixpt_round(temp);
- temp = dc_fixpt_from_fraction(
+ temp = spl_fixpt_from_fraction(
(rec_in->y + rec_in->height) * (long long)stream_dst->height,
stream_src->height);
- rec_out.height = stream_dst->y + dc_fixpt_round(temp) - rec_out.y;
+ rec_out.height = stream_dst->y + spl_fixpt_round(temp) - rec_out.y;
return rec_out;
}
@@ -144,7 +146,7 @@ static struct spl_rect calculate_mpc_slice_in_timing_active(
mpc_rec.x = plane_clip_rec->x + mpc_rec.width * mpc_slice_idx;
mpc_rec.height = plane_clip_rec->height;
mpc_rec.y = plane_clip_rec->y;
- ASSERT(mpc_slice_count == 1 ||
+ SPL_ASSERT(mpc_slice_count == 1 ||
spl_in->basic_out.view_format != SPL_VIEW_3D_SIDE_BY_SIDE ||
mpc_rec.width % 2 == 0);
@@ -157,7 +159,7 @@ static struct spl_rect calculate_mpc_slice_in_timing_active(
}
if (spl_in->basic_out.view_format == SPL_VIEW_3D_TOP_AND_BOTTOM) {
- ASSERT(mpc_rec.height % 2 == 0);
+ SPL_ASSERT(mpc_rec.height % 2 == 0);
mpc_rec.height /= 2;
}
return mpc_rec;
@@ -197,7 +199,7 @@ static struct spl_rect calculate_odm_slice_in_timing_active(struct spl_in *spl_i
return spl_in->basic_out.odm_slice_rect;
}
-static void spl_calculate_recout(struct spl_in *spl_in, struct spl_out *spl_out)
+static void spl_calculate_recout(struct spl_in *spl_in, struct spl_scratch *spl_scratch, struct spl_out *spl_out)
{
/*
* A plane clip represents the desired plane size and position in Stream
@@ -340,20 +342,23 @@ static void spl_calculate_recout(struct spl_in *spl_in, struct spl_out *spl_out)
/* shift the overlapping area so it is with respect to current
* ODM slice's position
*/
- spl_out->scl_data.recout = shift_rec(
+ spl_scratch->scl_data.recout = shift_rec(
&overlapping_area,
-odm_slice.x, -odm_slice.y);
- spl_out->scl_data.recout.height -=
+ spl_scratch->scl_data.recout.height -=
spl_in->debug.visual_confirm_base_offset;
- spl_out->scl_data.recout.height -=
+ spl_scratch->scl_data.recout.height -=
spl_in->debug.visual_confirm_dpp_offset;
} else
/* if there is no overlap, zero recout */
- memset(&spl_out->scl_data.recout, 0,
+ memset(&spl_scratch->scl_data.recout, 0,
sizeof(struct spl_rect));
}
+
/* Calculate scaling ratios */
-static void spl_calculate_scaling_ratios(struct spl_in *spl_in, struct spl_out *spl_out)
+static void spl_calculate_scaling_ratios(struct spl_in *spl_in,
+ struct spl_scratch *spl_scratch,
+ struct spl_out *spl_out)
{
const int in_w = spl_in->basic_out.src_rect.width;
const int in_h = spl_in->basic_out.src_rect.height;
@@ -364,59 +369,75 @@ static void spl_calculate_scaling_ratios(struct spl_in *spl_in, struct spl_out *
/*Swap surf_src height and width since scaling ratios are in recout rotation*/
if (spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_90 ||
spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_270)
- swap(surf_src.height, surf_src.width);
+ spl_swap(surf_src.height, surf_src.width);
- spl_out->scl_data.ratios.horz = dc_fixpt_from_fraction(
+ spl_scratch->scl_data.ratios.horz = spl_fixpt_from_fraction(
surf_src.width,
spl_in->basic_in.dst_rect.width);
- spl_out->scl_data.ratios.vert = dc_fixpt_from_fraction(
+ spl_scratch->scl_data.ratios.vert = spl_fixpt_from_fraction(
surf_src.height,
spl_in->basic_in.dst_rect.height);
if (spl_in->basic_out.view_format == SPL_VIEW_3D_SIDE_BY_SIDE)
- spl_out->scl_data.ratios.horz.value *= 2;
+ spl_scratch->scl_data.ratios.horz.value *= 2;
else if (spl_in->basic_out.view_format == SPL_VIEW_3D_TOP_AND_BOTTOM)
- spl_out->scl_data.ratios.vert.value *= 2;
+ spl_scratch->scl_data.ratios.vert.value *= 2;
- spl_out->scl_data.ratios.vert.value = div64_s64(
- spl_out->scl_data.ratios.vert.value * in_h, out_h);
- spl_out->scl_data.ratios.horz.value = div64_s64(
- spl_out->scl_data.ratios.horz.value * in_w, out_w);
+ spl_scratch->scl_data.ratios.vert.value = spl_div64_s64(
+ spl_scratch->scl_data.ratios.vert.value * in_h, out_h);
+ spl_scratch->scl_data.ratios.horz.value = spl_div64_s64(
+ spl_scratch->scl_data.ratios.horz.value * in_w, out_w);
- spl_out->scl_data.ratios.horz_c = spl_out->scl_data.ratios.horz;
- spl_out->scl_data.ratios.vert_c = spl_out->scl_data.ratios.vert;
+ spl_scratch->scl_data.ratios.horz_c = spl_scratch->scl_data.ratios.horz;
+ spl_scratch->scl_data.ratios.vert_c = spl_scratch->scl_data.ratios.vert;
if (spl_in->basic_in.format == SPL_PIXEL_FORMAT_420BPP8
|| spl_in->basic_in.format == SPL_PIXEL_FORMAT_420BPP10) {
- spl_out->scl_data.ratios.horz_c.value /= 2;
- spl_out->scl_data.ratios.vert_c.value /= 2;
+ spl_scratch->scl_data.ratios.horz_c.value /= 2;
+ spl_scratch->scl_data.ratios.vert_c.value /= 2;
}
- spl_out->scl_data.ratios.horz = dc_fixpt_truncate(
- spl_out->scl_data.ratios.horz, 19);
- spl_out->scl_data.ratios.vert = dc_fixpt_truncate(
- spl_out->scl_data.ratios.vert, 19);
- spl_out->scl_data.ratios.horz_c = dc_fixpt_truncate(
- spl_out->scl_data.ratios.horz_c, 19);
- spl_out->scl_data.ratios.vert_c = dc_fixpt_truncate(
- spl_out->scl_data.ratios.vert_c, 19);
+ spl_scratch->scl_data.ratios.horz = spl_fixpt_truncate(
+ spl_scratch->scl_data.ratios.horz, 19);
+ spl_scratch->scl_data.ratios.vert = spl_fixpt_truncate(
+ spl_scratch->scl_data.ratios.vert, 19);
+ spl_scratch->scl_data.ratios.horz_c = spl_fixpt_truncate(
+ spl_scratch->scl_data.ratios.horz_c, 19);
+ spl_scratch->scl_data.ratios.vert_c = spl_fixpt_truncate(
+ spl_scratch->scl_data.ratios.vert_c, 19);
+
+ /*
+ * Coefficient table and some registers are different based on ratio
+ * that is output/input. Currently we calculate input/output
+ * Store 1/ratio in recip_ratio for those lookups
+ */
+ spl_scratch->scl_data.recip_ratios.horz = spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.horz);
+ spl_scratch->scl_data.recip_ratios.vert = spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.vert);
+ spl_scratch->scl_data.recip_ratios.horz_c = spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.horz_c);
+ spl_scratch->scl_data.recip_ratios.vert_c = spl_fixpt_recip(
+ spl_scratch->scl_data.ratios.vert_c);
}
+
/* Calculate Viewport size */
-static void spl_calculate_viewport_size(struct spl_in *spl_in, struct spl_out *spl_out)
+static void spl_calculate_viewport_size(struct spl_in *spl_in, struct spl_scratch *spl_scratch)
{
- spl_out->scl_data.viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(spl_out->scl_data.ratios.horz,
- spl_out->scl_data.recout.width));
- spl_out->scl_data.viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(spl_out->scl_data.ratios.vert,
- spl_out->scl_data.recout.height));
- spl_out->scl_data.viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(spl_out->scl_data.ratios.horz_c,
- spl_out->scl_data.recout.width));
- spl_out->scl_data.viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(spl_out->scl_data.ratios.vert_c,
- spl_out->scl_data.recout.height));
+ spl_scratch->scl_data.viewport.width = spl_fixpt_ceil(spl_fixpt_mul_int(spl_scratch->scl_data.ratios.horz,
+ spl_scratch->scl_data.recout.width));
+ spl_scratch->scl_data.viewport.height = spl_fixpt_ceil(spl_fixpt_mul_int(spl_scratch->scl_data.ratios.vert,
+ spl_scratch->scl_data.recout.height));
+ spl_scratch->scl_data.viewport_c.width = spl_fixpt_ceil(spl_fixpt_mul_int(spl_scratch->scl_data.ratios.horz_c,
+ spl_scratch->scl_data.recout.width));
+ spl_scratch->scl_data.viewport_c.height = spl_fixpt_ceil(spl_fixpt_mul_int(spl_scratch->scl_data.ratios.vert_c,
+ spl_scratch->scl_data.recout.height));
if (spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_90 ||
spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_270) {
- swap(spl_out->scl_data.viewport.width, spl_out->scl_data.viewport.height);
- swap(spl_out->scl_data.viewport_c.width, spl_out->scl_data.viewport_c.height);
+ spl_swap(spl_scratch->scl_data.viewport.width, spl_scratch->scl_data.viewport.height);
+ spl_swap(spl_scratch->scl_data.viewport_c.width, spl_scratch->scl_data.viewport_c.height);
}
}
+
static void spl_get_vp_scan_direction(enum spl_rotation_angle rotation,
bool horizontal_mirror,
bool *orthogonal_rotation,
@@ -440,6 +461,7 @@ static void spl_get_vp_scan_direction(enum spl_rotation_angle rotation,
if (horizontal_mirror)
*flip_horz_scan_dir = !*flip_horz_scan_dir;
}
+
/*
* We completely calculate vp offset, size and inits here based entirely on scaling
* ratios and recout for pixel perfect pipe combine.
@@ -449,13 +471,13 @@ static void spl_calculate_init_and_vp(bool flip_scan_dir,
int recout_size,
int src_size,
int taps,
- struct fixed31_32 ratio,
- struct fixed31_32 init_adj,
- struct fixed31_32 *init,
+ struct spl_fixed31_32 ratio,
+ struct spl_fixed31_32 init_adj,
+ struct spl_fixed31_32 *init,
int *vp_offset,
int *vp_size)
{
- struct fixed31_32 temp;
+ struct spl_fixed31_32 temp;
int int_part;
/*
@@ -468,33 +490,33 @@ static void spl_calculate_init_and_vp(bool flip_scan_dir,
* init_bot = init + scaling_ratio
* to get pixel perfect combine add the fraction from calculating vp offset
*/
- temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full);
- *vp_offset = dc_fixpt_floor(temp);
+ temp = spl_fixpt_mul_int(ratio, recout_offset_within_recout_full);
+ *vp_offset = spl_fixpt_floor(temp);
temp.value &= 0xffffffff;
- *init = dc_fixpt_add(dc_fixpt_div_int(dc_fixpt_add_int(ratio, taps + 1), 2), temp);
- *init = dc_fixpt_add(*init, init_adj);
- *init = dc_fixpt_truncate(*init, 19);
+ *init = spl_fixpt_add(spl_fixpt_div_int(spl_fixpt_add_int(ratio, taps + 1), 2), temp);
+ *init = spl_fixpt_add(*init, init_adj);
+ *init = spl_fixpt_truncate(*init, 19);
/*
* If viewport has non 0 offset and there are more taps than covered by init then
* we should decrease the offset and increase init so we are never sampling
* outside of viewport.
*/
- int_part = dc_fixpt_floor(*init);
+ int_part = spl_fixpt_floor(*init);
if (int_part < taps) {
int_part = taps - int_part;
if (int_part > *vp_offset)
int_part = *vp_offset;
*vp_offset -= int_part;
- *init = dc_fixpt_add_int(*init, int_part);
+ *init = spl_fixpt_add_int(*init, int_part);
}
/*
* If taps are sampling outside of viewport at end of recout and there are more pixels
* available in the surface we should increase the viewport size, regardless set vp to
* only what is used.
*/
- temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1));
- *vp_size = dc_fixpt_floor(temp);
+ temp = spl_fixpt_add(*init, spl_fixpt_mul_int(ratio, recout_size - 1));
+ *vp_size = spl_fixpt_floor(temp);
if (*vp_size + *vp_offset > src_size)
*vp_size = src_size - *vp_offset;
@@ -509,15 +531,24 @@ static void spl_calculate_init_and_vp(bool flip_scan_dir,
static bool spl_is_yuv420(enum spl_pixel_format format)
{
- if ((format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN) &&
- (format <= SPL_PIXEL_FORMAT_VIDEO_END))
+ if ((format >= SPL_PIXEL_FORMAT_420BPP8) &&
+ (format <= SPL_PIXEL_FORMAT_420BPP10))
+ return true;
+
+ return false;
+}
+
+static bool spl_is_rgb8(enum spl_pixel_format format)
+{
+ if (format == SPL_PIXEL_FORMAT_ARGB8888)
return true;
return false;
}
/*Calculate inits and viewport */
-static void spl_calculate_inits_and_viewports(struct spl_in *spl_in, struct spl_out *spl_out)
+static void spl_calculate_inits_and_viewports(struct spl_in *spl_in,
+ struct spl_scratch *spl_scratch)
{
struct spl_rect src = spl_in->basic_in.src_rect;
struct spl_rect recout_dst_in_active_timing;
@@ -528,11 +559,11 @@ static void spl_calculate_inits_and_viewports(struct spl_in *spl_in, struct spl_
int vpc_div = (spl_in->basic_in.format == SPL_PIXEL_FORMAT_420BPP8
|| spl_in->basic_in.format == SPL_PIXEL_FORMAT_420BPP10) ? 2 : 1;
bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
- struct fixed31_32 init_adj_h = dc_fixpt_zero;
- struct fixed31_32 init_adj_v = dc_fixpt_zero;
+ struct spl_fixed31_32 init_adj_h = spl_fixpt_zero;
+ struct spl_fixed31_32 init_adj_v = spl_fixpt_zero;
recout_clip_in_active_timing = shift_rec(
- &spl_out->scl_data.recout, odm_slice.x, odm_slice.y);
+ &spl_scratch->scl_data.recout, odm_slice.x, odm_slice.y);
recout_dst_in_active_timing = calculate_plane_rec_in_timing_active(
spl_in, &spl_in->basic_in.dst_rect);
overlap_in_active_timing = intersect_rec(&recout_clip_in_active_timing,
@@ -555,8 +586,8 @@ static void spl_calculate_inits_and_viewports(struct spl_in *spl_in, struct spl_
&flip_horz_scan_dir);
if (orthogonal_rotation) {
- swap(src.width, src.height);
- swap(flip_vert_scan_dir, flip_horz_scan_dir);
+ spl_swap(src.width, src.height);
+ spl_swap(flip_vert_scan_dir, flip_horz_scan_dir);
}
if (spl_is_yuv420(spl_in->basic_in.format)) {
@@ -568,17 +599,17 @@ static void spl_calculate_inits_and_viewports(struct spl_in *spl_in, struct spl_
switch (spl_in->basic_in.cositing) {
case CHROMA_COSITING_LEFT:
- init_adj_h = dc_fixpt_zero;
- init_adj_v = dc_fixpt_from_fraction(sign, 2);
+ init_adj_h = spl_fixpt_zero;
+ init_adj_v = spl_fixpt_from_fraction(sign, 4);
break;
case CHROMA_COSITING_NONE:
- init_adj_h = dc_fixpt_from_fraction(sign, 2);
- init_adj_v = dc_fixpt_from_fraction(sign, 2);
+ init_adj_h = spl_fixpt_from_fraction(sign, 4);
+ init_adj_v = spl_fixpt_from_fraction(sign, 4);
break;
case CHROMA_COSITING_TOPLEFT:
default:
- init_adj_h = dc_fixpt_zero;
- init_adj_v = dc_fixpt_zero;
+ init_adj_h = spl_fixpt_zero;
+ init_adj_v = spl_fixpt_zero;
break;
}
}
@@ -586,59 +617,60 @@ static void spl_calculate_inits_and_viewports(struct spl_in *spl_in, struct spl_
spl_calculate_init_and_vp(
flip_horz_scan_dir,
recout_clip_in_recout_dst.x,
- spl_out->scl_data.recout.width,
+ spl_scratch->scl_data.recout.width,
src.width,
- spl_out->scl_data.taps.h_taps,
- spl_out->scl_data.ratios.horz,
- dc_fixpt_zero,
- &spl_out->scl_data.inits.h,
- &spl_out->scl_data.viewport.x,
- &spl_out->scl_data.viewport.width);
+ spl_scratch->scl_data.taps.h_taps,
+ spl_scratch->scl_data.ratios.horz,
+ spl_fixpt_zero,
+ &spl_scratch->scl_data.inits.h,
+ &spl_scratch->scl_data.viewport.x,
+ &spl_scratch->scl_data.viewport.width);
spl_calculate_init_and_vp(
flip_horz_scan_dir,
recout_clip_in_recout_dst.x,
- spl_out->scl_data.recout.width,
+ spl_scratch->scl_data.recout.width,
src.width / vpc_div,
- spl_out->scl_data.taps.h_taps_c,
- spl_out->scl_data.ratios.horz_c,
+ spl_scratch->scl_data.taps.h_taps_c,
+ spl_scratch->scl_data.ratios.horz_c,
init_adj_h,
- &spl_out->scl_data.inits.h_c,
- &spl_out->scl_data.viewport_c.x,
- &spl_out->scl_data.viewport_c.width);
+ &spl_scratch->scl_data.inits.h_c,
+ &spl_scratch->scl_data.viewport_c.x,
+ &spl_scratch->scl_data.viewport_c.width);
spl_calculate_init_and_vp(
flip_vert_scan_dir,
recout_clip_in_recout_dst.y,
- spl_out->scl_data.recout.height,
+ spl_scratch->scl_data.recout.height,
src.height,
- spl_out->scl_data.taps.v_taps,
- spl_out->scl_data.ratios.vert,
- dc_fixpt_zero,
- &spl_out->scl_data.inits.v,
- &spl_out->scl_data.viewport.y,
- &spl_out->scl_data.viewport.height);
+ spl_scratch->scl_data.taps.v_taps,
+ spl_scratch->scl_data.ratios.vert,
+ spl_fixpt_zero,
+ &spl_scratch->scl_data.inits.v,
+ &spl_scratch->scl_data.viewport.y,
+ &spl_scratch->scl_data.viewport.height);
spl_calculate_init_and_vp(
flip_vert_scan_dir,
recout_clip_in_recout_dst.y,
- spl_out->scl_data.recout.height,
+ spl_scratch->scl_data.recout.height,
src.height / vpc_div,
- spl_out->scl_data.taps.v_taps_c,
- spl_out->scl_data.ratios.vert_c,
+ spl_scratch->scl_data.taps.v_taps_c,
+ spl_scratch->scl_data.ratios.vert_c,
init_adj_v,
- &spl_out->scl_data.inits.v_c,
- &spl_out->scl_data.viewport_c.y,
- &spl_out->scl_data.viewport_c.height);
+ &spl_scratch->scl_data.inits.v_c,
+ &spl_scratch->scl_data.viewport_c.y,
+ &spl_scratch->scl_data.viewport_c.height);
if (orthogonal_rotation) {
- swap(spl_out->scl_data.viewport.x, spl_out->scl_data.viewport.y);
- swap(spl_out->scl_data.viewport.width, spl_out->scl_data.viewport.height);
- swap(spl_out->scl_data.viewport_c.x, spl_out->scl_data.viewport_c.y);
- swap(spl_out->scl_data.viewport_c.width, spl_out->scl_data.viewport_c.height);
+ spl_swap(spl_scratch->scl_data.viewport.x, spl_scratch->scl_data.viewport.y);
+ spl_swap(spl_scratch->scl_data.viewport.width, spl_scratch->scl_data.viewport.height);
+ spl_swap(spl_scratch->scl_data.viewport_c.x, spl_scratch->scl_data.viewport_c.y);
+ spl_swap(spl_scratch->scl_data.viewport_c.width, spl_scratch->scl_data.viewport_c.height);
}
- spl_out->scl_data.viewport.x += src.x;
- spl_out->scl_data.viewport.y += src.y;
- ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0);
- spl_out->scl_data.viewport_c.x += src.x / vpc_div;
- spl_out->scl_data.viewport_c.y += src.y / vpc_div;
+ spl_scratch->scl_data.viewport.x += src.x;
+ spl_scratch->scl_data.viewport.y += src.y;
+ SPL_ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0);
+ spl_scratch->scl_data.viewport_c.x += src.x / vpc_div;
+ spl_scratch->scl_data.viewport_c.y += src.y / vpc_div;
}
+
static void spl_handle_3d_recout(struct spl_in *spl_in, struct spl_rect *recout)
{
/*
@@ -647,7 +679,7 @@ static void spl_handle_3d_recout(struct spl_in *spl_in, struct spl_rect *recout)
* This may break with rotation, good thing we aren't mixing hw rotation and 3d
*/
if (spl_in->basic_in.mpc_combine_v) {
- ASSERT(spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_0 ||
+ SPL_ASSERT(spl_in->basic_in.rotation == SPL_ROTATION_ANGLE_0 ||
(spl_in->basic_out.view_format != SPL_VIEW_3D_TOP_AND_BOTTOM &&
spl_in->basic_out.view_format != SPL_VIEW_3D_SIDE_BY_SIDE));
if (spl_in->basic_out.view_format == SPL_VIEW_3D_TOP_AND_BOTTOM)
@@ -665,6 +697,7 @@ static void spl_clamp_viewport(struct spl_rect *viewport)
if (viewport->width < MIN_VIEWPORT_SIZE)
viewport->width = MIN_VIEWPORT_SIZE;
}
+
static bool spl_dscl_is_420_format(enum spl_pixel_format format)
{
if (format == SPL_PIXEL_FORMAT_420BPP8 ||
@@ -673,6 +706,7 @@ static bool spl_dscl_is_420_format(enum spl_pixel_format format)
else
return false;
}
+
static bool spl_dscl_is_video_format(enum spl_pixel_format format)
{
if (format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN
@@ -681,17 +715,21 @@ static bool spl_dscl_is_video_format(enum spl_pixel_format format)
else
return false;
}
+
static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in,
- const struct spl_scaler_data *data)
+ const struct spl_scaler_data *data,
+ bool enable_isharp, bool enable_easf)
{
- const long long one = dc_fixpt_one.value;
+ const long long one = spl_fixpt_one.value;
enum spl_pixel_format pixel_format = spl_in->basic_in.format;
+ /* Bypass if ratio is 1:1 with no ISHARP or force scale on */
if (data->ratios.horz.value == one
&& data->ratios.vert.value == one
&& data->ratios.horz_c.value == one
&& data->ratios.vert_c.value == one
- && !spl_in->basic_out.always_scale)
+ && !spl_in->basic_out.always_scale
+ && !enable_isharp)
return SCL_MODE_SCALING_444_BYPASS;
if (!spl_dscl_is_420_format(pixel_format)) {
@@ -700,69 +738,196 @@ static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in,
else
return SCL_MODE_SCALING_444_RGB_ENABLE;
}
- if (data->ratios.horz.value == one && data->ratios.vert.value == one)
- return SCL_MODE_SCALING_420_LUMA_BYPASS;
- if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
- return SCL_MODE_SCALING_420_CHROMA_BYPASS;
+
+ /* Bypass YUV if at 1:1 with no ISHARP or if doing 2:1 YUV
+ * downscale without EASF
+ */
+ if ((!enable_isharp) && (!enable_easf)) {
+ if (data->ratios.horz.value == one && data->ratios.vert.value == one)
+ return SCL_MODE_SCALING_420_LUMA_BYPASS;
+ if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
+ return SCL_MODE_SCALING_420_CHROMA_BYPASS;
+ }
return SCL_MODE_SCALING_420_YCBCR_ENABLE;
}
+
+static bool spl_choose_lls_policy(enum spl_pixel_format format,
+ enum spl_transfer_func_type tf_type,
+ enum spl_transfer_func_predefined tf_predefined_type,
+ enum linear_light_scaling *lls_pref)
+{
+ if (spl_is_yuv420(format)) {
+ *lls_pref = LLS_PREF_NO;
+ if ((tf_type == SPL_TF_TYPE_PREDEFINED) ||
+ (tf_type == SPL_TF_TYPE_DISTRIBUTED_POINTS))
+ return true;
+ } else { /* RGB or YUV444 */
+ if ((tf_type == SPL_TF_TYPE_PREDEFINED) ||
+ (tf_type == SPL_TF_TYPE_BYPASS)) {
+ *lls_pref = LLS_PREF_YES;
+ return true;
+ }
+ }
+ *lls_pref = LLS_PREF_NO;
+ return false;
+}
+
+/* Enable EASF ?*/
+static bool enable_easf(struct spl_in *spl_in, struct spl_scratch *spl_scratch)
+{
+ int vratio = 0;
+ int hratio = 0;
+ bool skip_easf = false;
+ bool lls_enable_easf = true;
+
+ if (spl_in->disable_easf)
+ skip_easf = true;
+
+ vratio = spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert);
+ hratio = spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz);
+
+ /*
+ * No EASF support for downscaling > 2:1
+ * EASF support for upscaling or downscaling up to 2:1
+ */
+ if ((vratio > 2) || (hratio > 2))
+ skip_easf = true;
+
+ /*
+ * If lls_pref is LLS_PREF_DONT_CARE, then use pixel format and transfer
+ * function to determine whether to use LINEAR or NONLINEAR scaling
+ */
+ if (spl_in->lls_pref == LLS_PREF_DONT_CARE)
+ lls_enable_easf = spl_choose_lls_policy(spl_in->basic_in.format,
+ spl_in->basic_in.tf_type, spl_in->basic_in.tf_predefined_type,
+ &spl_in->lls_pref);
+
+ if (!lls_enable_easf)
+ skip_easf = true;
+
+ /* Check for linear scaling or EASF preferred */
+ if (spl_in->lls_pref != LLS_PREF_YES && !spl_in->prefer_easf)
+ skip_easf = true;
+
+ return skip_easf;
+}
+
+static bool spl_get_isharp_en(struct spl_in *spl_in,
+ struct spl_scratch *spl_scratch)
+{
+ bool enable_isharp = false;
+ int vratio = 0;
+ int hratio = 0;
+ struct spl_taps taps = spl_scratch->scl_data.taps;
+
+ /* Return if adaptive sharpness is disabled */
+ if (spl_in->adaptive_sharpness.enable == false)
+ return enable_isharp;
+
+ vratio = spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert);
+ hratio = spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz);
+
+ /* No iSHARP support for downscaling */
+ if (vratio > 1 || hratio > 1)
+ return enable_isharp;
+
+ // Scaling is up to 1:1 (no scaling) or upscaling
+
+ /*
+ * Apply sharpness to all RGB surfaces and to
+ * NV12/P010 surfaces
+ */
+
+ /*
+ * Apply sharpness if supports horizontal taps 4,6 AND
+ * vertical taps 3, 4, 6
+ */
+ if ((taps.h_taps == 4 || taps.h_taps == 6) &&
+ (taps.v_taps == 3 || taps.v_taps == 4 || taps.v_taps == 6))
+ enable_isharp = true;
+
+ return enable_isharp;
+}
+
/* Calculate optimal number of taps */
static bool spl_get_optimal_number_of_taps(
- int max_downscale_src_width, struct spl_in *spl_in, struct spl_out *spl_out,
- const struct spl_taps *in_taps)
+ int max_downscale_src_width, struct spl_in *spl_in, struct spl_scratch *spl_scratch,
+ const struct spl_taps *in_taps, bool *enable_easf_v, bool *enable_easf_h,
+ bool *enable_isharp)
{
int num_part_y, num_part_c;
int max_taps_y, max_taps_c;
int min_taps_y, min_taps_c;
enum lb_memory_config lb_config;
+ bool skip_easf = false;
- if (spl_out->scl_data.viewport.width > spl_out->scl_data.h_active &&
+ if (spl_scratch->scl_data.viewport.width > spl_scratch->scl_data.h_active &&
max_downscale_src_width != 0 &&
- spl_out->scl_data.viewport.width > max_downscale_src_width)
+ spl_scratch->scl_data.viewport.width > max_downscale_src_width)
return false;
+
+ /* Check if we are using EASF or not */
+ skip_easf = enable_easf(spl_in, spl_scratch);
+
/*
* Set default taps if none are provided
* From programming guide: taps = min{ ceil(2*H_RATIO,1), 8} for downscaling
* taps = 4 for upscaling
*/
- if (in_taps->h_taps == 0) {
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.horz) > 1)
- spl_out->scl_data.taps.h_taps = min(2 * dc_fixpt_ceil(spl_out->scl_data.ratios.horz), 8);
- else
- spl_out->scl_data.taps.h_taps = 4;
- } else
- spl_out->scl_data.taps.h_taps = in_taps->h_taps;
- if (in_taps->v_taps == 0) {
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.vert) > 1)
- spl_out->scl_data.taps.v_taps = min(dc_fixpt_ceil(dc_fixpt_mul_int(
- spl_out->scl_data.ratios.vert, 2)), 8);
- else
- spl_out->scl_data.taps.v_taps = 4;
- } else
- spl_out->scl_data.taps.v_taps = in_taps->v_taps;
- if (in_taps->v_taps_c == 0) {
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.vert_c) > 1)
- spl_out->scl_data.taps.v_taps_c = min(dc_fixpt_ceil(dc_fixpt_mul_int(
- spl_out->scl_data.ratios.vert_c, 2)), 8);
- else
- spl_out->scl_data.taps.v_taps_c = 4;
- } else
- spl_out->scl_data.taps.v_taps_c = in_taps->v_taps_c;
- if (in_taps->h_taps_c == 0) {
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.horz_c) > 1)
- spl_out->scl_data.taps.h_taps_c = min(2 * dc_fixpt_ceil(spl_out->scl_data.ratios.horz_c), 8);
+ if (skip_easf) {
+ if (in_taps->h_taps == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz) > 1)
+ spl_scratch->scl_data.taps.h_taps = spl_min(2 * spl_fixpt_ceil(
+ spl_scratch->scl_data.ratios.horz), 8);
+ else
+ spl_scratch->scl_data.taps.h_taps = 4;
+ } else
+ spl_scratch->scl_data.taps.h_taps = in_taps->h_taps;
+ if (in_taps->v_taps == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 1)
+ spl_scratch->scl_data.taps.v_taps = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
+ spl_scratch->scl_data.ratios.vert, 2)), 8);
+ else
+ spl_scratch->scl_data.taps.v_taps = 4;
+ } else
+ spl_scratch->scl_data.taps.v_taps = in_taps->v_taps;
+ if (in_taps->v_taps_c == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) > 1)
+ spl_scratch->scl_data.taps.v_taps_c = spl_min(spl_fixpt_ceil(spl_fixpt_mul_int(
+ spl_scratch->scl_data.ratios.vert_c, 2)), 8);
+ else
+ spl_scratch->scl_data.taps.v_taps_c = 4;
+ } else
+ spl_scratch->scl_data.taps.v_taps_c = in_taps->v_taps_c;
+ if (in_taps->h_taps_c == 0) {
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.horz_c) > 1)
+ spl_scratch->scl_data.taps.h_taps_c = spl_min(2 * spl_fixpt_ceil(
+ spl_scratch->scl_data.ratios.horz_c), 8);
+ else
+ spl_scratch->scl_data.taps.h_taps_c = 4;
+ } else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
+ /* Only 1 and even h_taps_c are supported by hw */
+ spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c - 1;
else
- spl_out->scl_data.taps.h_taps_c = 4;
- } else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
- /* Only 1 and even h_taps_c are supported by hw */
- spl_out->scl_data.taps.h_taps_c = in_taps->h_taps_c - 1;
- else
- spl_out->scl_data.taps.h_taps_c = in_taps->h_taps_c;
+ spl_scratch->scl_data.taps.h_taps_c = in_taps->h_taps_c;
+ } else {
+ if (spl_is_yuv420(spl_in->basic_in.format)) {
+ spl_scratch->scl_data.taps.h_taps = 6;
+ spl_scratch->scl_data.taps.v_taps = 6;
+ spl_scratch->scl_data.taps.h_taps_c = 4;
+ spl_scratch->scl_data.taps.v_taps_c = 4;
+ } else { /* RGB */
+ spl_scratch->scl_data.taps.h_taps = 6;
+ spl_scratch->scl_data.taps.v_taps = 6;
+ spl_scratch->scl_data.taps.h_taps_c = 6;
+ spl_scratch->scl_data.taps.v_taps_c = 6;
+ }
+ }
/*Ensure we can support the requested number of vtaps*/
- min_taps_y = dc_fixpt_ceil(spl_out->scl_data.ratios.vert);
- min_taps_c = dc_fixpt_ceil(spl_out->scl_data.ratios.vert_c);
+ min_taps_y = spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert);
+ min_taps_c = spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c);
/* Use LB_MEMORY_CONFIG_3 for 4:2:0 */
if ((spl_in->basic_in.format == SPL_PIXEL_FORMAT_420BPP8)
@@ -771,16 +936,16 @@ static bool spl_get_optimal_number_of_taps(
else
lb_config = LB_MEMORY_CONFIG_0;
// Determine max vtap support by calculating how much line buffer can fit
- spl_in->funcs->spl_calc_lb_num_partitions(spl_in->basic_out.alpha_en, &spl_out->scl_data,
+ spl_in->funcs->spl_calc_lb_num_partitions(spl_in->basic_out.alpha_en, &spl_scratch->scl_data,
lb_config, &num_part_y, &num_part_c);
/* MAX_V_TAPS = MIN (NUM_LINES - MAX(CEILING(V_RATIO,1)-2, 0), 8) */
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.vert) > 2)
- max_taps_y = num_part_y - (dc_fixpt_ceil(spl_out->scl_data.ratios.vert) - 2);
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) > 2)
+ max_taps_y = num_part_y - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert) - 2);
else
max_taps_y = num_part_y;
- if (dc_fixpt_ceil(spl_out->scl_data.ratios.vert_c) > 2)
- max_taps_c = num_part_c - (dc_fixpt_ceil(spl_out->scl_data.ratios.vert_c) - 2);
+ if (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) > 2)
+ max_taps_c = num_part_c - (spl_fixpt_ceil(spl_scratch->scl_data.ratios.vert_c) - 2);
else
max_taps_c = num_part_c;
@@ -789,48 +954,108 @@ static bool spl_get_optimal_number_of_taps(
else if (max_taps_c < min_taps_c)
return false;