Esempio n. 1
0
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;
	}
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/*******************************************************************************
 * 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);
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
	}
}
Esempio n. 20
0
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;
}
Esempio n. 29
0
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;
}