static void program_overscan( struct dce_transform *xfm_dce, const struct scaler_data *data) { 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; } REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0, EXT_OVERSCAN_LEFT, data->recout.x, EXT_OVERSCAN_RIGHT, overscan_right); REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0, EXT_OVERSCAN_TOP, data->recout.y, EXT_OVERSCAN_BOTTOM, overscan_bottom); }
struct i2c_engine *dal_i2c_sw_engine_create( const struct i2c_sw_engine_create_arg *arg) { struct i2c_sw_engine *engine; if (!arg) { BREAK_TO_DEBUGGER(); return NULL; } engine = dm_alloc(sizeof(struct i2c_sw_engine)); if (!engine) { BREAK_TO_DEBUGGER(); return NULL; } if (dal_i2c_sw_engine_construct(engine, arg)) return &engine->base; BREAK_TO_DEBUGGER(); dm_free(engine); return NULL; }
/* * dal_asic_capability_create * * Creates asic capability based on DCE version. */ struct asic_capability *dal_asic_capability_create( struct hw_asic_id *init, struct dc_context *ctx) { struct asic_capability *cap; if (!init) { BREAK_TO_DEBUGGER(); return NULL; } cap = dm_alloc(sizeof(struct asic_capability)); if (!cap) { BREAK_TO_DEBUGGER(); return NULL; } if (construct(cap, init, ctx)) return cap; BREAK_TO_DEBUGGER(); dm_free(cap); return NULL; }
bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src( enum clock_source_id id, uint32_t *ref_clk_src_id) { if (ref_clk_src_id == NULL) { BREAK_TO_DEBUGGER(); return false; } switch (id) { case CLOCK_SOURCE_ID_PLL1: *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL; return true; case CLOCK_SOURCE_ID_PLL2: *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL; return true; case CLOCK_SOURCE_ID_DCPLL: *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL; return true; case CLOCK_SOURCE_ID_EXTERNAL: *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK; return true; case CLOCK_SOURCE_ID_UNDEFINED: *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID; return true; default: /* Unsupported clock source id */ BREAK_TO_DEBUGGER(); return false; } }
enum gpio_result dal_ddc_open( struct ddc *ddc, enum gpio_mode mode, enum gpio_ddc_config_type config_type) { enum gpio_result result; struct gpio_ddc_open_options data_options; struct gpio_ddc_open_options clock_options; struct gpio_config_data config_data; result = dal_gpio_open_ex(ddc->pin_data, mode, &data_options); if (result != GPIO_RESULT_OK) { BREAK_TO_DEBUGGER(); return result; } result = dal_gpio_open_ex(ddc->pin_clock, mode, &clock_options); if (result != GPIO_RESULT_OK) { BREAK_TO_DEBUGGER(); goto failure; } /* DDC clock and data pins should belong * to the same DDC block id, * we use the data pin to set the pad mode. */ if (mode == GPIO_MODE_INPUT) /* this is from detect_sink_type, * we need extra delay there */ config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; else config_data.type = GPIO_CONFIG_TYPE_DDC; config_data.config.ddc.type = config_type; config_data.config.ddc.data_en_bit_present = data_options.en_bit_present; config_data.config.ddc.clock_en_bit_present = clock_options.en_bit_present; result = dal_gpio_set_config(ddc->pin_data, &config_data); if (result == GPIO_RESULT_OK) return result; BREAK_TO_DEBUGGER(); dal_gpio_close(ddc->pin_clock); failure: dal_gpio_close(ddc->pin_data); return result; }
struct dc_sink *dc_link_add_remote_sink( struct dc_link *link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data) { struct dc_sink *dc_sink; enum dc_edid_status edid_status; if (len > MAX_EDID_BUFFER_SIZE) { dm_error("Max EDID buffer size breached!\n"); return NULL; } if (!init_data) { BREAK_TO_DEBUGGER(); return NULL; } if (!init_data->link) { BREAK_TO_DEBUGGER(); return NULL; } dc_sink = dc_sink_create(init_data); if (!dc_sink) return NULL; memmove(dc_sink->dc_edid.raw_edid, edid, len); dc_sink->dc_edid.length = len; if (!link_add_remote_sink_helper( link, dc_sink)) goto fail_add_sink; edid_status = dm_helpers_parse_edid_caps( link->ctx, &dc_sink->dc_edid, &dc_sink->edid_caps); if (edid_status != EDID_OK) goto fail; return dc_sink; fail: dc_link_remove_remote_sink(link, dc_sink); fail_add_sink: dc_sink_release(dc_sink); return NULL; }
/******************************************************************************* * set_round * * @brief * Programs Round/Truncate * * @param [in] mode :round or truncate * @param [in] depth :bit depth to round/truncate to OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode POSSIBLE VALUES: 00 - truncate to u0.12 01 - truncate to u0.11 02 - truncate to u0.10 03 - truncate to u0.9 04 - truncate to u0.8 05 - reserved 06 - truncate to u0.14 07 - truncate to u0.13 set_reg_field_value( value, clamp_max, OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR); 08 - round to u0.12 09 - round to u0.11 10 - round to u0.10 11 - round to u0.9 12 - round to u0.8 13 - reserved 14 - round to u0.14 15 - round to u0.13 ******************************************************************************/ static void set_round( struct dce_transform *xfm_dce, enum dcp_out_trunc_round_mode mode, enum dcp_out_trunc_round_depth depth) { int depth_bits = 0; int mode_bit = 0; /* set up bit depth */ switch (depth) { case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT: depth_bits = 6; break; case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT: depth_bits = 7; break; case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT: depth_bits = 0; break; case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT: depth_bits = 1; break; case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT: depth_bits = 2; break; case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT: depth_bits = 3; break; case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT: depth_bits = 4; break; default: depth_bits = 4; BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */ } /* set up round or truncate */ switch (mode) { case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE: mode_bit = 0; break; case DCP_OUT_TRUNC_ROUND_MODE_ROUND: mode_bit = 1; break; default: BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */ } depth_bits |= mode_bit << 3; REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits); }
static void set_dither( struct dce_transform *xfm_dce, bool dither_enable, enum dcp_spatial_dither_mode dither_mode, enum dcp_spatial_dither_depth dither_depth, bool frame_random_enable, bool rgb_random_enable, bool highpass_random_enable) { int dither_depth_bits = 0; int dither_mode_bits = 0; switch (dither_mode) { case DCP_SPATIAL_DITHER_MODE_AAAA: dither_mode_bits = 0; break; case DCP_SPATIAL_DITHER_MODE_A_AA_A: dither_mode_bits = 1; break; case DCP_SPATIAL_DITHER_MODE_AABBAABB: dither_mode_bits = 2; break; case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC: dither_mode_bits = 3; break; default: /* Invalid dcp_spatial_dither_mode */ BREAK_TO_DEBUGGER(); } switch (dither_depth) { case DCP_SPATIAL_DITHER_DEPTH_30BPP: dither_depth_bits = 0; break; case DCP_SPATIAL_DITHER_DEPTH_24BPP: dither_depth_bits = 1; break; default: /* Invalid dcp_spatial_dither_depth */ BREAK_TO_DEBUGGER(); } /* write the register */ REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0, DCP_SPATIAL_DITHER_EN, dither_enable, DCP_SPATIAL_DITHER_MODE, dither_mode_bits, DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits, DCP_FRAME_RANDOM_ENABLE, frame_random_enable, DCP_RGB_RANDOM_ENABLE, rgb_random_enable, DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable); }
struct ddc *dal_gpio_create_ddc( struct gpio_service *service, uint32_t offset, uint32_t mask, struct gpio_ddc_hw_info *info) { enum gpio_id id; uint32_t en; struct ddc *ddc; if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) return NULL; ddc = dm_alloc(sizeof(struct ddc)); if (!ddc) { BREAK_TO_DEBUGGER(); return NULL; } ddc->pin_data = dal_gpio_service_create_gpio_ex( service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); if (!ddc->pin_data) { BREAK_TO_DEBUGGER(); goto failure_1; } ddc->pin_clock = dal_gpio_service_create_gpio_ex( service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); if (!ddc->pin_clock) { BREAK_TO_DEBUGGER(); goto failure_2; } ddc->hw_info = *info; ddc->ctx = service->ctx; return ddc; failure_2: dal_gpio_service_destroy_gpio(&ddc->pin_data); failure_1: dm_free(ddc); return NULL; }
struct display_clock *dce120_disp_clk_create(struct dc_context *ctx) { struct dce_disp_clk *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); struct dm_pp_clock_levels_with_voltage clk_level_info = {0}; if (clk_dce == NULL) { BREAK_TO_DEBUGGER(); return NULL; } memcpy(clk_dce->max_clks_by_state, dce120_max_clks_by_state, sizeof(dce120_max_clks_by_state)); dce_disp_clk_construct( clk_dce, ctx, NULL, NULL, NULL); clk_dce->base.funcs = &dce120_funcs; /* new in dce120 */ if (!ctx->dc->debug.disable_pplib_clock_request && dm_pp_get_clock_levels_by_type_with_voltage( ctx, DM_PP_CLOCK_TYPE_DISPLAY_CLK, &clk_level_info) && clk_level_info.num_levels) clk_dce->max_displ_clk_in_khz = clk_level_info.data[clk_level_info.num_levels - 1].clocks_in_khz; else clk_dce->max_displ_clk_in_khz = 1133000; return &clk_dce->base; }
static bool dce_divider_range_construct( struct dce_divider_range *div_range, int range_start, int range_step, int did_min, int did_max) { div_range->div_range_start = range_start; div_range->div_range_step = range_step; div_range->did_min = did_min; div_range->did_max = did_max; if (div_range->div_range_step == 0) { div_range->div_range_step = 1; /*div_range_step cannot be zero*/ BREAK_TO_DEBUGGER(); } /* Calculate this based on the other inputs.*/ /* See DividerRange.h for explanation of */ /* the relationship between divider id (DID) and a divider.*/ /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ /* Maximum divider identified in this range = * (Number of Divider IDs)*Step size between dividers * + The start of this range.*/ div_range->div_range_end = (did_max - did_min) * range_step + range_start; return true; }
void dal_gpio_service_destroy( struct gpio_service **ptr) { if (!ptr || !*ptr) { BREAK_TO_DEBUGGER(); return; } /* free business storage */ { uint32_t index_of_id = 0; do { uint32_t *slot = (*ptr)->busyness[index_of_id]; if (slot) dm_free(slot); ++index_of_id; } while (index_of_id < GPIO_ID_COUNT); } dm_free(*ptr); *ptr = NULL; }
bool dal_bios_parser_init_cmd_tbl_helper( const struct command_table_helper **h, enum dce_version dce) { switch (dce) { case DCE_VERSION_8_0: case DCE_VERSION_8_1: case DCE_VERSION_8_3: *h = dal_cmd_tbl_helper_dce80_get_table(); return true; case DCE_VERSION_10_0: *h = dal_cmd_tbl_helper_dce110_get_table(); return true; case DCE_VERSION_11_0: *h = dal_cmd_tbl_helper_dce110_get_table(); return true; case DCE_VERSION_11_2: *h = dal_cmd_tbl_helper_dce112_get_table(); return true; default: /* Unsupported DCE */ BREAK_TO_DEBUGGER(); return false; } }
/* set the payload value for the unsolicited response */ static void set_unsolicited_response_payload( const struct hw_ctx_audio *hw_ctx, enum audio_payload payload) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
/* mute audio */ static void mute_azalia_audio( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
void dal_logger_close(struct log_entry *entry) { struct dal_logger *logger = entry->logger; if (logger && logger->open_count > 0) { logger->open_count--; } else { BREAK_TO_DEBUGGER(); goto cleanup; } /* --Flush log_entry buffer-- */ /* print to kernel console */ log_to_debug_console(entry); /* log internally for dsat */ log_to_internal_buffer(entry); /* TODO: Write end heading */ cleanup: if (entry->buf) { dm_free(entry->buf); entry->buf = NULL; entry->buf_offset = 0; entry->max_buf_bytes = 0; } }
void dal_logger_open( struct dal_logger *logger, struct log_entry *entry, /* out */ enum log_major major, enum log_minor minor) { if (!entry) { BREAK_TO_DEBUGGER(); return; } entry->major = LOG_MAJOR_COUNT; entry->minor = 0; entry->logger = logger; entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char)); entry->buf_offset = 0; entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char); logger->open_count++; entry->major = major; entry->minor = minor; log_heading(entry, major, minor); }
bool dal_hw_ddc_open( struct hw_gpio_pin *ptr, enum gpio_mode mode, void *options) { struct hw_ddc *pin = FROM_HW_GPIO_PIN(ptr); uint32_t en; if (!options) { BREAK_TO_DEBUGGER(); return false; } /* get the EN bit before overwriting it */ dal_hw_gpio_get_reg_value( ptr->ctx, &pin->base.pin_reg.DC_GPIO_DATA_EN, &en); ((struct gpio_ddc_open_options *)options)->en_bit_present = (en != 0); return dal_hw_gpio_open(ptr, mode, options); }
/* Same as dal_logger_write, except without open() and close(), which must * be done separately. */ void dal_logger_append( struct log_entry *entry, const char *msg, ...) { struct dal_logger *logger; if (!entry) { BREAK_TO_DEBUGGER(); return; } logger = entry->logger; if (logger && logger->open_count > 0 && dal_logger_should_log(logger, entry->major, entry->minor)) { uint32_t size; va_list args; char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE]; va_start(args, msg); size = dm_log_to_buffer( buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args); if (size < DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) { append_entry(entry, buffer, size); } else { append_entry(entry, "LOG_ERROR, line too long\n", 27); } va_end(args); } }
void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) { int i; if (!link->sink_count) { BREAK_TO_DEBUGGER(); return; } for (i = 0; i < link->sink_count; i++) { if (link->remote_sinks[i] == sink) { dc_sink_release(sink); link->remote_sinks[i] = NULL; /* shrink array to remove empty place */ while (i < link->sink_count - 1) { link->remote_sinks[i] = link->remote_sinks[i+1]; i++; } link->remote_sinks[i] = NULL; link->sink_count--; return; } } }
/* Assign GTC group and enable GTC value embedding */ static void enable_gtc_embedding_with_group( const struct hw_ctx_audio *hw_ctx, uint32_t groupNum, uint32_t audioLatency) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
/* setup HDMI audio */ static void setup_hdmi_audio( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, const struct audio_crtc_info *crtc_info) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
/* get current channel spliting */ static bool get_channel_splitting_mapping( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, struct audio_channel_associate_info *audio_mapping) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); return false; }
static void setup_audio_wall_dto( const struct hw_ctx_audio *hw_ctx, enum signal_type signal, const struct audio_crtc_info *crtc_info, const struct audio_pll_info *pll_info) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
/* enable channel splitting mapping */ static void setup_channel_splitting_mapping( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, enum signal_type signal, const struct audio_channel_associate_info *audio_mapping, bool enable) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); }
/* search pixel clock value for Azalia HDMI Audio */ static bool get_azalia_clock_info_hdmi( const struct hw_ctx_audio *hw_ctx, uint32_t crtc_pixel_clock_in_khz, uint32_t actual_pixel_clock_in_khz, struct azalia_clock_info *azalia_clock_info) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); return false; }
/* search pixel clock value for Azalia DP Audio */ static bool get_azalia_clock_info_dp( const struct hw_ctx_audio *hw_ctx, uint32_t requested_pixel_clock_in_khz, const struct audio_pll_info *pll_info, struct azalia_clock_info *azalia_clock_info) { /*DCE specific, must be implemented in derived*/ BREAK_TO_DEBUGGER(); return false; }
/* * dal_asic_capability_destroy * * Destroy allocated memory. */ void dal_asic_capability_destroy( struct asic_capability **cap) { if (!cap) { BREAK_TO_DEBUGGER(); return; } if (!*cap) { BREAK_TO_DEBUGGER(); return; } destruct(*cap); dm_free(*cap); *cap = NULL; }
void dal_line_buffer_destroy(struct line_buffer **lb) { if (lb == NULL || *lb == NULL) { BREAK_TO_DEBUGGER(); return; } (*lb)->funcs->destroy(lb); *lb = NULL; }
struct encoder_impl *dal_analog_encoder_crt_create( const struct encoder_init_data *init_data) { struct analog_encoder_crt *enc = dal_alloc(sizeof(struct analog_encoder_crt)); if (!enc) { BREAK_TO_DEBUGGER(); return NULL; } if (construct(enc, init_data)) return &enc->base.base; BREAK_TO_DEBUGGER(); dal_free(enc); return NULL; }