| /* |
| * 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 <linux/delay.h> |
| |
| #include "dce110_transform_v.h" |
| #include "dm_services.h" |
| #include "dc.h" |
| #include "dce/dce_11_0_d.h" |
| #include "dce/dce_11_0_sh_mask.h" |
| |
| #define SCLV_PHASES 64 |
| #define DC_LOGGER \ |
| xfm->ctx->logger |
| |
| struct sclv_ratios_inits { |
| uint32_t h_int_scale_ratio_luma; |
| uint32_t h_int_scale_ratio_chroma; |
| uint32_t v_int_scale_ratio_luma; |
| uint32_t v_int_scale_ratio_chroma; |
| struct init_int_and_frac h_init_luma; |
| struct init_int_and_frac h_init_chroma; |
| struct init_int_and_frac v_init_luma; |
| struct init_int_and_frac v_init_chroma; |
| }; |
| |
| static void calculate_viewport( |
| const struct scaler_data *scl_data, |
| struct rect *luma_viewport, |
| struct rect *chroma_viewport) |
| { |
| /*Do not set chroma vp for rgb444 pixel format*/ |
| luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2; |
| luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2; |
| luma_viewport->width = |
| scl_data->viewport.width - scl_data->viewport.width % 2; |
| luma_viewport->height = |
| scl_data->viewport.height - scl_data->viewport.height % 2; |
| chroma_viewport->x = luma_viewport->x; |
| chroma_viewport->y = luma_viewport->y; |
| chroma_viewport->height = luma_viewport->height; |
| chroma_viewport->width = luma_viewport->width; |
| |
| if (scl_data->format == PIXEL_FORMAT_420BPP8) { |
| luma_viewport->height += luma_viewport->height % 2; |
| luma_viewport->width += luma_viewport->width % 2; |
| /*for 420 video chroma is 1/4 the area of luma, scaled |
| *vertically and horizontally |
| */ |
| chroma_viewport->x = luma_viewport->x / 2; |
| chroma_viewport->y = luma_viewport->y / 2; |
| chroma_viewport->height = luma_viewport->height / 2; |
| chroma_viewport->width = luma_viewport->width / 2; |
| } |
| } |
| |
| static void program_viewport( |
| struct dce_transform *xfm_dce, |
| struct rect *luma_view_port, |
| struct rect *chroma_view_port) |
| { |
| struct dc_context *ctx = xfm_dce->base.ctx; |
| uint32_t value = 0; |
| uint32_t addr = 0; |
| |
| if (luma_view_port->width != 0 && luma_view_port->height != 0) { |
| addr = mmSCLV_VIEWPORT_START; |
| value = 0; |
| set_reg_field_value( |
| value, |
| luma_view_port->x, |
| SCLV_VIEWPORT_START, |
| VIEWPORT_X_START); |
| set_reg_field_value( |
| value, |
| luma_view_port->y, |
| SCLV_VIEWPORT_START, |
| VIEWPORT_Y_START); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VIEWPORT_SIZE; |
| value = 0; |
| set_reg_field_value( |
| value, |
| luma_view_port->height, |
| SCLV_VIEWPORT_SIZE, |
| VIEWPORT_HEIGHT); |
| set_reg_field_value( |
| value, |
| luma_view_port->width, |
| SCLV_VIEWPORT_SIZE, |
| VIEWPORT_WIDTH); |
| dm_write_reg(ctx, addr, value); |
| } |
| |
| if (chroma_view_port->width != 0 && chroma_view_port->height != 0) { |
| addr = mmSCLV_VIEWPORT_START_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| chroma_view_port->x, |
| SCLV_VIEWPORT_START_C, |
| VIEWPORT_X_START_C); |
| set_reg_field_value( |
| value, |
| chroma_view_port->y, |
| SCLV_VIEWPORT_START_C, |
| VIEWPORT_Y_START_C); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VIEWPORT_SIZE_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| chroma_view_port->height, |
| SCLV_VIEWPORT_SIZE_C, |
| VIEWPORT_HEIGHT_C); |
| set_reg_field_value( |
| value, |
| chroma_view_port->width, |
| SCLV_VIEWPORT_SIZE_C, |
| VIEWPORT_WIDTH_C); |
| dm_write_reg(ctx, addr, value); |
| } |
| } |
| |
| /* |
| * Function: |
| * void setup_scaling_configuration |
| * |
| * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps |
| * Input: data |
| * |
| * Output: |
| * void |
| */ |
| static bool setup_scaling_configuration( |
| struct dce_transform *xfm_dce, |
| const struct scaler_data *data) |
| { |
| bool is_scaling_needed = false; |
| struct dc_context *ctx = xfm_dce->base.ctx; |
| uint32_t value = 0; |
| |
| set_reg_field_value(value, data->taps.h_taps - 1, |
| SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); |
| set_reg_field_value(value, data->taps.v_taps - 1, |
| SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); |
| set_reg_field_value(value, data->taps.h_taps_c - 1, |
| SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); |
| set_reg_field_value(value, data->taps.v_taps_c - 1, |
| SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); |
| dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value); |
| |
| value = 0; |
| if (data->taps.h_taps + data->taps.v_taps > 2) { |
| set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); |
| set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); |
| is_scaling_needed = true; |
| } else { |
| set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); |
| set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); |
| } |
| |
| if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { |
| set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); |
| set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); |
| is_scaling_needed = true; |
| } else if (data->format != PIXEL_FORMAT_420BPP8) { |
| set_reg_field_value( |
| value, |
| get_reg_field_value(value, SCLV_MODE, SCL_MODE), |
| SCLV_MODE, |
| SCL_MODE_C); |
| set_reg_field_value( |
| value, |
| get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), |
| SCLV_MODE, |
| SCL_PSCL_EN_C); |
| } else { |
| set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); |
| set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); |
| } |
| dm_write_reg(ctx, mmSCLV_MODE, value); |
| |
| value = 0; |
| /* |
| * 0 - Replaced out of bound pixels with black pixel |
| * (or any other required color) |
| * 1 - Replaced out of bound pixels with the edge pixel |
| */ |
| set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); |
| dm_write_reg(ctx, mmSCLV_CONTROL, value); |
| |
| return is_scaling_needed; |
| } |
| |
| /* |
| * Function: |
| * void program_overscan |
| * |
| * Purpose: Programs overscan border |
| * Input: overscan |
| * |
| * Output: void |
| */ |
| static void program_overscan( |
| struct dce_transform *xfm_dce, |
| const struct scaler_data *data) |
| { |
| uint32_t overscan_left_right = 0; |
| uint32_t overscan_top_bottom = 0; |
| |
| int overscan_right = data->h_active - data->recout.x - data->recout.width; |
| int overscan_bottom = data->v_active - data->recout.y - data->recout.height; |
| |
| if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) { |
| overscan_bottom += 2; |
| overscan_right += 2; |
| } |
| |
| if (overscan_right < 0) { |
| BREAK_TO_DEBUGGER(); |
| overscan_right = 0; |
| } |
| if (overscan_bottom < 0) { |
| BREAK_TO_DEBUGGER(); |
| overscan_bottom = 0; |
| } |
| |
| set_reg_field_value(overscan_left_right, data->recout.x, |
| EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); |
| |
| set_reg_field_value(overscan_left_right, overscan_right, |
| EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); |
| |
| set_reg_field_value(overscan_top_bottom, data->recout.y, |
| EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); |
| |
| set_reg_field_value(overscan_top_bottom, overscan_bottom, |
| EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); |
| |
| dm_write_reg(xfm_dce->base.ctx, |
| mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, |
| overscan_left_right); |
| |
| dm_write_reg(xfm_dce->base.ctx, |
| mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, |
| overscan_top_bottom); |
| } |
| |
| static void set_coeff_update_complete( |
| struct dce_transform *xfm_dce) |
| { |
| uint32_t value; |
| |
| value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE); |
| set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE); |
| dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value); |
| } |
| |
| static void program_multi_taps_filter( |
| struct dce_transform *xfm_dce, |
| int taps, |
| const uint16_t *coeffs, |
| enum ram_filter_type filter_type) |
| { |
| struct dc_context *ctx = xfm_dce->base.ctx; |
| int i, phase, pair; |
| int array_idx = 0; |
| int taps_pairs = (taps + 1) / 2; |
| int phases_to_program = SCLV_PHASES / 2 + 1; |
| |
| uint32_t select = 0; |
| uint32_t power_ctl, power_ctl_off; |
| |
| if (!coeffs) |
| return; |
| |
| /*We need to disable power gating on coeff memory to do programming*/ |
| power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL); |
| power_ctl_off = power_ctl; |
| set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS); |
| dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off); |
| |
| /*Wait to disable gating:*/ |
| for (i = 0; i < 10; i++) { |
| if (get_reg_field_value( |
| dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS), |
| DCFEV_MEM_PWR_STATUS, |
| SCLV_COEFF_MEM_PWR_STATE) == 0) |
| break; |
| |
| udelay(1); |
| } |
| |
| set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE); |
| |
| for (phase = 0; phase < phases_to_program; phase++) { |
| /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror |
| phase 0 is unique and phase N/2 is unique if N is even*/ |
| set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE); |
| for (pair = 0; pair < taps_pairs; pair++) { |
| uint32_t data = 0; |
| |
| set_reg_field_value(select, pair, |
| SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX); |
| |
| dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select); |
| |
| set_reg_field_value( |
| data, 1, |
| SCLV_COEF_RAM_TAP_DATA, |
| SCL_C_RAM_EVEN_TAP_COEF_EN); |
| set_reg_field_value( |
| data, coeffs[array_idx], |
| SCLV_COEF_RAM_TAP_DATA, |
| SCL_C_RAM_EVEN_TAP_COEF); |
| |
| if (taps % 2 && pair == taps_pairs - 1) { |
| set_reg_field_value( |
| data, 0, |
| SCLV_COEF_RAM_TAP_DATA, |
| SCL_C_RAM_ODD_TAP_COEF_EN); |
| array_idx++; |
| } else { |
| set_reg_field_value( |
| data, 1, |
| SCLV_COEF_RAM_TAP_DATA, |
| SCL_C_RAM_ODD_TAP_COEF_EN); |
| set_reg_field_value( |
| data, coeffs[array_idx + 1], |
| SCLV_COEF_RAM_TAP_DATA, |
| SCL_C_RAM_ODD_TAP_COEF); |
| |
| array_idx += 2; |
| } |
| |
| dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data); |
| } |
| } |
| |
| /*We need to restore power gating on coeff memory to initial state*/ |
| dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl); |
| } |
| |
| static void calculate_inits( |
| struct dce_transform *xfm_dce, |
| const struct scaler_data *data, |
| struct sclv_ratios_inits *inits, |
| struct rect *luma_viewport, |
| struct rect *chroma_viewport) |
| { |
| inits->h_int_scale_ratio_luma = |
| dc_fixpt_u2d19(data->ratios.horz) << 5; |
| inits->v_int_scale_ratio_luma = |
| dc_fixpt_u2d19(data->ratios.vert) << 5; |
| inits->h_int_scale_ratio_chroma = |
| dc_fixpt_u2d19(data->ratios.horz_c) << 5; |
| inits->v_int_scale_ratio_chroma = |
| dc_fixpt_u2d19(data->ratios.vert_c) << 5; |
| |
| inits->h_init_luma.integer = 1; |
| inits->v_init_luma.integer = 1; |
| inits->h_init_chroma.integer = 1; |
| inits->v_init_chroma.integer = 1; |
| } |
| |
| static void program_scl_ratios_inits( |
| struct dce_transform *xfm_dce, |
| struct sclv_ratios_inits *inits) |
| { |
| struct dc_context *ctx = xfm_dce->base.ctx; |
| uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; |
| uint32_t value = 0; |
| |
| set_reg_field_value( |
| value, |
| inits->h_int_scale_ratio_luma, |
| SCLV_HORZ_FILTER_SCALE_RATIO, |
| SCL_H_SCALE_RATIO); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VERT_FILTER_SCALE_RATIO; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->v_int_scale_ratio_luma, |
| SCLV_VERT_FILTER_SCALE_RATIO, |
| SCL_V_SCALE_RATIO); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->h_int_scale_ratio_chroma, |
| SCLV_HORZ_FILTER_SCALE_RATIO_C, |
| SCL_H_SCALE_RATIO_C); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->v_int_scale_ratio_chroma, |
| SCLV_VERT_FILTER_SCALE_RATIO_C, |
| SCL_V_SCALE_RATIO_C); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_HORZ_FILTER_INIT; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->h_init_luma.fraction, |
| SCLV_HORZ_FILTER_INIT, |
| SCL_H_INIT_FRAC); |
| set_reg_field_value( |
| value, |
| inits->h_init_luma.integer, |
| SCLV_HORZ_FILTER_INIT, |
| SCL_H_INIT_INT); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VERT_FILTER_INIT; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->v_init_luma.fraction, |
| SCLV_VERT_FILTER_INIT, |
| SCL_V_INIT_FRAC); |
| set_reg_field_value( |
| value, |
| inits->v_init_luma.integer, |
| SCLV_VERT_FILTER_INIT, |
| SCL_V_INIT_INT); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_HORZ_FILTER_INIT_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->h_init_chroma.fraction, |
| SCLV_HORZ_FILTER_INIT_C, |
| SCL_H_INIT_FRAC_C); |
| set_reg_field_value( |
| value, |
| inits->h_init_chroma.integer, |
| SCLV_HORZ_FILTER_INIT_C, |
| SCL_H_INIT_INT_C); |
| dm_write_reg(ctx, addr, value); |
| |
| addr = mmSCLV_VERT_FILTER_INIT_C; |
| value = 0; |
| set_reg_field_value( |
| value, |
| inits->v_init_chroma.fraction, |
| SCLV_VERT_FILTER_INIT_C, |
| SCL_V_INIT_FRAC_C); |
| set_reg_field_value( |
| value, |
| inits->v_init_chroma.integer, |
| SCLV_VERT_FILTER_INIT_C, |
| SCL_V_INIT_INT_C); |
| dm_write_reg(ctx, addr, value); |
| } |
| |
| static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) |
| { |
| if (taps == 4) |
| return get_filter_4tap_64p(ratio); |
| else if (taps == 2) |
| return get_filter_2tap_64p(); |
| else if (taps == 1) |
| return NULL; |
| else { |
| /* should never happen, bug */ |
| BREAK_TO_DEBUGGER(); |
| return NULL; |
| } |
| } |
| |
| static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm) |
| { |
| struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); |
| uint32_t value; |
| |
| value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL); |
| |
| /*Use all three pieces of memory always*/ |
| set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG); |
| /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ |
| set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL, |
| LB_MEMORY_SIZE); |
| |
| dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value); |
| |
| return true; |
| } |
| |
| static void dce110_xfmv_set_scaler( |
| struct transform *xfm, |
| const struct scaler_data *data) |
| { |
| struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); |
| bool is_scaling_required = false; |
| bool filter_updated = false; |
| const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c; |
| struct rect luma_viewport = {0}; |
| struct rect chroma_viewport = {0}; |
| |
| dce110_xfmv_power_up_line_buffer(xfm); |
| /* 1. Calculate viewport, viewport programming should happen after init |
| * calculations as they may require an adjustment in the viewport. |
| */ |
| |
| calculate_viewport(data, &luma_viewport, &chroma_viewport); |
| |
| /* 2. Program overscan */ |
| program_overscan(xfm_dce, data); |
| |
| /* 3. Program taps and configuration */ |
| is_scaling_required = setup_scaling_configuration(xfm_dce, data); |
| |
| if (is_scaling_required) { |
| /* 4. Calculate and program ratio, filter initialization */ |
| |
| struct sclv_ratios_inits inits = { 0 }; |
| |
| calculate_inits( |
| xfm_dce, |
| data, |
| &inits, |
| &luma_viewport, |
| &chroma_viewport); |
| |
| program_scl_ratios_inits(xfm_dce, &inits); |
| |
| coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert); |
| coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz); |
| coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c); |
| coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c); |
| |
| if (coeffs_v != xfm_dce->filter_v |
| || coeffs_v_c != xfm_dce->filter_v_c |
| || coeffs_h != xfm_dce->filter_h |
| || coeffs_h_c != xfm_dce->filter_h_c) { |
| /* 5. Program vertical filters */ |
| program_multi_taps_filter( |
| xfm_dce, |
| data->taps.v_taps, |
| coeffs_v, |
| FILTER_TYPE_RGB_Y_VERTICAL); |
| program_multi_taps_filter( |
| xfm_dce, |
| data->taps.v_taps_c, |
| coeffs_v_c, |
| FILTER_TYPE_CBCR_VERTICAL); |
| |
| /* 6. Program horizontal filters */ |
| program_multi_taps_filter( |
| xfm_dce, |
| data->taps.h_taps, |
| coeffs_h, |
| FILTER_TYPE_RGB_Y_HORIZONTAL); |
| program_multi_taps_filter( |
| xfm_dce, |
| data->taps.h_taps_c, |
| coeffs_h_c, |
| FILTER_TYPE_CBCR_HORIZONTAL); |
| |
| xfm_dce->filter_v = coeffs_v; |
| xfm_dce->filter_v_c = coeffs_v_c; |
| xfm_dce->filter_h = coeffs_h; |
| xfm_dce->filter_h_c = coeffs_h_c; |
| filter_updated = true; |
| } |
| } |
| |
| /* 7. Program the viewport */ |
| program_viewport(xfm_dce, &luma_viewport, &chroma_viewport); |
| |
| /* 8. Set bit to flip to new coefficient memory */ |
| if (filter_updated) |
| set_coeff_update_complete(xfm_dce); |
| } |
| |
| static void dce110_xfmv_reset(struct transform *xfm) |
| { |
| struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); |
| |
| xfm_dce->filter_h = NULL; |
| xfm_dce->filter_v = NULL; |
| xfm_dce->filter_h_c = NULL; |
| xfm_dce->filter_v_c = NULL; |
| } |
| |
| static void dce110_xfmv_set_gamut_remap( |
| struct transform *xfm, |
| const struct xfm_grph_csc_adjustment *adjust) |
| { |
| /* DO NOTHING*/ |
| } |
| |
| static void dce110_xfmv_set_pixel_storage_depth( |
| struct transform *xfm, |
| enum lb_pixel_depth depth, |
| const struct bit_depth_reduction_params *bit_depth_params) |
| { |
| struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); |
| int pixel_depth = 0; |
| int expan_mode = 0; |
| uint32_t reg_data = 0; |
| |
| switch (depth) { |
| case LB_PIXEL_DEPTH_18BPP: |
| pixel_depth = 2; |
| expan_mode = 1; |
| break; |
| case LB_PIXEL_DEPTH_24BPP: |
| pixel_depth = 1; |
| expan_mode = 1; |
| break; |
| case LB_PIXEL_DEPTH_30BPP: |
| pixel_depth = 0; |
| expan_mode = 1; |
| break; |
| case LB_PIXEL_DEPTH_36BPP: |
| pixel_depth = 3; |
| expan_mode = 0; |
| break; |
| default: |
| BREAK_TO_DEBUGGER(); |
| break; |
| } |
| |
| set_reg_field_value( |
| reg_data, |
| expan_mode, |
| LBV_DATA_FORMAT, |
| PIXEL_EXPAN_MODE); |
| |
| set_reg_field_value( |
| reg_data, |
| pixel_depth, |
| LBV_DATA_FORMAT, |
| PIXEL_DEPTH); |
| |
| dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data); |
| |
| if (!(xfm_dce->lb_pixel_depth_supported & depth)) { |
| /*we should use unsupported capabilities |
| * unless it is required by w/a*/ |
| DC_LOG_WARNING("%s: Capability not supported", |
| __func__); |
| } |
| } |
| |
| static const struct transform_funcs dce110_xfmv_funcs = { |
| .transform_reset = dce110_xfmv_reset, |
| .transform_set_scaler = dce110_xfmv_set_scaler, |
| .transform_set_gamut_remap = |
| dce110_xfmv_set_gamut_remap, |
| .opp_set_csc_default = dce110_opp_v_set_csc_default, |
| .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, |
| .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, |
| .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, |
| .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, |
| .transform_set_pixel_storage_depth = |
| dce110_xfmv_set_pixel_storage_depth, |
| .transform_get_optimal_number_of_taps = |
| dce_transform_get_optimal_number_of_taps |
| }; |
| /*****************************************/ |
| /* Constructor, Destructor */ |
| /*****************************************/ |
| |
| bool dce110_transform_v_construct( |
| struct dce_transform *xfm_dce, |
| struct dc_context *ctx) |
| { |
| xfm_dce->base.ctx = ctx; |
| |
| xfm_dce->base.funcs = &dce110_xfmv_funcs; |
| |
| xfm_dce->lb_pixel_depth_supported = |
| LB_PIXEL_DEPTH_18BPP | |
| LB_PIXEL_DEPTH_24BPP | |
| LB_PIXEL_DEPTH_30BPP | |
| LB_PIXEL_DEPTH_36BPP; |
| |
| xfm_dce->prescaler_on = true; |
| xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; |
| xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ |
| |
| return true; |
| } |