bool dpp_get_optimal_number_of_taps( struct dpp *dpp, struct scaler_data *scl_data, const struct scaling_taps *in_taps) { uint32_t pixel_width; if (scl_data->viewport.width > scl_data->recout.width) pixel_width = scl_data->recout.width; else pixel_width = scl_data->viewport.width; /* TODO: add lb check */ /* No support for programming ratio of 4, drop to 3.99999.. */ if (scl_data->ratios.horz.value == (4ll << 32)) scl_data->ratios.horz.value--; if (scl_data->ratios.vert.value == (4ll << 32)) scl_data->ratios.vert.value--; if (scl_data->ratios.horz_c.value == (4ll << 32)) scl_data->ratios.horz_c.value--; if (scl_data->ratios.vert_c.value == (4ll << 32)) scl_data->ratios.vert_c.value--; /* Set default taps if none are provided */ if (in_taps->h_taps == 0) scl_data->taps.h_taps = 4; else scl_data->taps.h_taps = in_taps->h_taps; if (in_taps->v_taps == 0) scl_data->taps.v_taps = 4; else scl_data->taps.v_taps = in_taps->v_taps; if (in_taps->v_taps_c == 0) scl_data->taps.v_taps_c = 2; else scl_data->taps.v_taps_c = in_taps->v_taps_c; if (in_taps->h_taps_c == 0) scl_data->taps.h_taps_c = 2; /* Only 1 and even h_taps_c are supported by hw */ else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1) scl_data->taps.h_taps_c = in_taps->h_taps_c - 1; else scl_data->taps.h_taps_c = in_taps->h_taps_c; if (!dpp->ctx->dc->debug.always_scale) { if (IDENTITY_RATIO(scl_data->ratios.horz)) scl_data->taps.h_taps = 1; if (IDENTITY_RATIO(scl_data->ratios.vert)) scl_data->taps.v_taps = 1; /* * Spreadsheet doesn't handle taps_c is one properly, * need to force Chroma to always be scaled to pass * bandwidth validation. */ } return true; }
static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma) { uint32_t taps; if (IDENTITY_RATIO(ratio)) { return 1; } else if (in_taps != 0) { taps = in_taps; } else { taps = 4; } if (chroma) { taps /= 2; if (taps < 2) taps = 2; } return taps; }
bool dce_transform_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, const struct scaling_taps *in_taps) { struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); int pixel_width = scl_data->viewport.width; int max_num_of_lines; if (xfm_dce->prescaler_on && (scl_data->viewport.width > scl_data->recout.width)) pixel_width = scl_data->recout.width; max_num_of_lines = dce_transform_get_max_num_of_supported_lines( xfm_dce, scl_data->lb_params.depth, pixel_width); /* Fail if in_taps are impossible */ if (in_taps->v_taps >= max_num_of_lines) return false; /* * Set taps according to this policy (in this order) * - Use 1 for no scaling * - Use input taps * - Use 4 and reduce as required by line buffer size * - Decide chroma taps if chroma is scaled * * Ignore input chroma taps. Decide based on non-chroma */ scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false); scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false); scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true); scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true); if (!IDENTITY_RATIO(scl_data->ratios.vert)) { /* reduce v_taps if needed but ensure we have at least two */ if (in_taps->v_taps == 0 && max_num_of_lines <= scl_data->taps.v_taps && scl_data->taps.v_taps > 1) { scl_data->taps.v_taps = max_num_of_lines - 1; } if (scl_data->taps.v_taps <= 1) return false; } if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) { /* reduce chroma v_taps if needed but ensure we have at least two */ if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) { scl_data->taps.v_taps_c = max_num_of_lines - 1; } if (scl_data->taps.v_taps_c <= 1) return false; } /* we've got valid taps */ return true; }