linux/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c

/*
 * 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 "dm_services.h"

/* include DCE11 register header files */
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"

#include "dc_types.h"
#include "dc_bios_types.h"
#include "dc.h"

#include "include/grph_object_id.h"
#include "include/logger_interface.h"
#include "dce110_timing_generator.h"

#include "timing_generator.h"


#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET

#define MAX_H_TOTAL
#define MAX_V_TOTAL

#define CRTC_REG(reg)
#define DCP_REG(reg)

/* Flowing register offsets are same in files of
 * dce/dce_11_0_d.h
 * dce/vi_polaris10_p/vi_polaris10_d.h
 *
 * So we can create dce110 timing generator to use it.
 */


/*
* apply_front_porch_workaround
*
* This is a workaround for a bug that has existed since R5xx and has not been
* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
*/
static void dce110_timing_generator_apply_front_porch_workaround(
	struct timing_generator *tg,
	struct dc_crtc_timing *timing)
{}

/*
 *****************************************************************************
 *  Function: is_in_vertical_blank
 *
 *  @brief
 *     check the current status of CRTC to check if we are in Vertical Blank
 *     regioneased" state
 *
 *  @return
 *     true if currently in blank region, false otherwise
 *
 *****************************************************************************
 */
static bool dce110_timing_generator_is_in_vertical_blank(
		struct timing_generator *tg)
{}

void dce110_timing_generator_set_early_control(
		struct timing_generator *tg,
		uint32_t early_cntl)
{}

/*
 * Enable CRTC
 * Enable CRTC - call ASIC Control Object to enable Timing generator.
 */
bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
{}

void dce110_timing_generator_program_blank_color(
		struct timing_generator *tg,
		const struct tg_color *black_color)
{}

/*
 *****************************************************************************
 *  Function: disable_stereo
 *
 *  @brief
 *     Disables active stereo on controller
 *     Frame Packing need to be disabled in vBlank or when CRTC not running
 *****************************************************************************
 */
#if 0
@TODOSTEREO
static void disable_stereo(struct timing_generator *tg)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
	uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
	uint32_t value = 0;
	uint32_t test = 0;
	uint32_t field = 0;
	uint32_t struc_en = 0;
	uint32_t struc_stereo_sel_ovr = 0;

	value = dm_read_reg(tg->ctx, addr);
	struc_en = get_reg_field_value(
			value,
			CRTC_3D_STRUCTURE_CONTROL,
			CRTC_3D_STRUCTURE_EN);

	struc_stereo_sel_ovr = get_reg_field_value(
			value,
			CRTC_3D_STRUCTURE_CONTROL,
			CRTC_3D_STRUCTURE_STEREO_SEL_OVR);

	/*
	 * When disabling Frame Packing in 2 step mode, we need to program both
	 * registers at the same frame
	 * Programming it in the beginning of VActive makes sure we are ok
	 */

	if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
		tg->funcs->wait_for_vblank(tg);
		tg->funcs->wait_for_vactive(tg);
	}

	value = 0;
	dm_write_reg(tg->ctx, addr, value);

	addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
	dm_write_reg(tg->ctx, addr, value);
}
#endif

/*
 * disable_crtc - call ASIC Control Object to disable Timing generator.
 */
bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
{}

/*
 * program_horz_count_by_2
 * Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
 */
static void program_horz_count_by_2(
	struct timing_generator *tg,
	const struct dc_crtc_timing *timing)
{}

/*
 * program_timing_generator
 * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
 * Call ASIC Control Object to program Timings.
 */
bool dce110_timing_generator_program_timing_generator(
	struct timing_generator *tg,
	const struct dc_crtc_timing *dc_crtc_timing)
{}

/*
 *****************************************************************************
 *  Function: set_drr
 *
 *  @brief
 *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
 *
 *  @param [in] pHwCrtcTiming: point to H
 *  wCrtcTiming struct
 *****************************************************************************
 */
void dce110_timing_generator_set_drr(
	struct timing_generator *tg,
	const struct drr_params *params)
{}

void dce110_timing_generator_set_static_screen_control(
	struct timing_generator *tg,
	uint32_t event_triggers,
	uint32_t num_frames)
{}

/*
 * get_vblank_counter
 *
 * @brief
 * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
 * holds the counter of frames.
 *
 * @param
 * struct timing_generator *tg - [in] timing generator which controls the
 * desired CRTC
 *
 * @return
 * Counter of frames, which should equal to number of vblanks.
 */
uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
{}

/*
 *****************************************************************************
 *  Function: dce110_timing_generator_get_position
 *
 *  @brief
 *     Returns CRTC vertical/horizontal counters
 *
 *  @param [out] position
 *****************************************************************************
 */
void dce110_timing_generator_get_position(struct timing_generator *tg,
	struct crtc_position *position)
{}

/*
 *****************************************************************************
 *  Function: get_crtc_scanoutpos
 *
 *  @brief
 *     Returns CRTC vertical/horizontal counters
 *
 *  @param [out] vpos, hpos
 *****************************************************************************
 */
void dce110_timing_generator_get_crtc_scanoutpos(
	struct timing_generator *tg,
	uint32_t *v_blank_start,
	uint32_t *v_blank_end,
	uint32_t *h_position,
	uint32_t *v_position)
{}

/* TODO: is it safe to assume that mask/shift of Primary and Underlay
 * are the same?
 * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
 * guaranteed? */
void dce110_timing_generator_program_blanking(
	struct timing_generator *tg,
	const struct dc_crtc_timing *timing)
{}

void dce110_timing_generator_set_test_pattern(
	struct timing_generator *tg,
	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
	 * because this is not DP-specific (which is probably somewhere in DP
	 * encoder) */
	enum controller_dp_test_pattern test_pattern,
	enum dc_color_depth color_depth)
{}

/*
 * dce110_timing_generator_validate_timing
 * The timing generators support a maximum display size of is 8192 x 8192 pixels,
 * including both active display and blanking periods. Check H Total and V Total.
 */
bool dce110_timing_generator_validate_timing(
	struct timing_generator *tg,
	const struct dc_crtc_timing *timing,
	enum signal_type signal)
{}

/*
 * Wait till we are at the beginning of VBlank.
 */
void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
{}

/*
 * Wait till we are in VActive (anywhere in VActive)
 */
void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
{}

/*
 *****************************************************************************
 *  Function: dce110_timing_generator_setup_global_swap_lock
 *
 *  @brief
 *     Setups Global Swap Lock group for current pipe
 *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
 *
 *  @param [in] gsl_params: setup data
 *****************************************************************************
 */
void dce110_timing_generator_setup_global_swap_lock(
	struct timing_generator *tg,
	const struct dcp_gsl_params *gsl_params)
{}

void dce110_timing_generator_tear_down_global_swap_lock(
	struct timing_generator *tg)
{}
/*
 *****************************************************************************
 *  Function: is_counter_moving
 *
 *  @brief
 *     check if the timing generator is currently going
 *
 *  @return
 *     true if currently going, false if currently paused or stopped.
 *
 *****************************************************************************
 */
bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
{}

void dce110_timing_generator_enable_advanced_request(
	struct timing_generator *tg,
	bool enable,
	const struct dc_crtc_timing *timing)
{}

/*TODO: Figure out if we need this function. */
void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
		bool lock)
{}

void dce110_timing_generator_enable_reset_trigger(
	struct timing_generator *tg,
	int source_tg_inst)
{}

void dce110_timing_generator_enable_crtc_reset(
		struct timing_generator *tg,
		int source_tg_inst,
		struct crtc_trigger_info *crtc_tp)
{}
void dce110_timing_generator_disable_reset_trigger(
	struct timing_generator *tg)
{}

/*
 *****************************************************************************
 *  @brief
 *     Checks whether CRTC triggered reset occurred
 *
 *  @return
 *     true if triggered reset occurred, false otherwise
 *****************************************************************************
 */
bool dce110_timing_generator_did_triggered_reset_occur(
	struct timing_generator *tg)
{}

/*
 * dce110_timing_generator_disable_vga
 * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
 * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
 */
void dce110_timing_generator_disable_vga(
	struct timing_generator *tg)
{}

/*
 * set_overscan_color_black
 *
 * @param :black_color is one of the color space
 *    :this routine will set overscan black color according to the color space.
 * @return none
 */
void dce110_timing_generator_set_overscan_color_black(
	struct timing_generator *tg,
	const struct tg_color *color)
{}

void dce110_tg_program_blank_color(struct timing_generator *tg,
		const struct tg_color *black_color)
{}

void dce110_tg_set_overscan_color(struct timing_generator *tg,
	const struct tg_color *overscan_color)
{}

void dce110_tg_program_timing(struct timing_generator *tg,
	const struct dc_crtc_timing *timing,
	int vready_offset,
	int vstartup_start,
	int vupdate_offset,
	int vupdate_width,
	const enum signal_type signal,
	bool use_vbios)
{}

bool dce110_tg_is_blanked(struct timing_generator *tg)
{}

void dce110_tg_set_blank(struct timing_generator *tg,
		bool enable_blanking)
{}

bool dce110_tg_validate_timing(struct timing_generator *tg,
	const struct dc_crtc_timing *timing)
{}

/* "Container" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
 *
 * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
 *   container rate.
 *
 * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
 *   halved to maintain the correct pixel rate.
 *
 * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
 *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
 *
 */
bool dce110_is_two_pixels_per_container(const struct dc_crtc_timing *timing)
{}

void dce110_tg_wait_for_state(struct timing_generator *tg,
	enum crtc_state state)
{}

void dce110_tg_set_colors(struct timing_generator *tg,
	const struct tg_color *blank_color,
	const struct tg_color *overscan_color)
{}

/* Gets first line of blank region of the display timing for CRTC
 * and programms is as a trigger to fire vertical interrupt
 */
bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
{}

static bool dce110_is_tg_enabled(struct timing_generator *tg)
{}

bool dce110_configure_crc(struct timing_generator *tg,
			  const struct crc_params *params)
{}

bool dce110_get_crc(struct timing_generator *tg,
		    uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{}

static const struct timing_generator_funcs dce110_tg_funcs =;

void dce110_timing_generator_construct(
	struct dce110_timing_generator *tg110,
	struct dc_context *ctx,
	uint32_t instance,
	const struct dce110_timing_generator_offsets *offsets)
{}