static void set_legacy_input_gamma_mode(
	struct dce110_ipp *ipp80,
	bool is_legacy)
{
	const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL);
	uint32_t value = dm_read_reg(ipp80->base.ctx, addr);

	set_reg_field_value(
		value,
		!is_legacy,
		INPUT_GAMMA_CONTROL,
		GRPH_INPUT_GAMMA_MODE);

	dm_write_reg(ipp80->base.ctx, addr, value);
}
Esempio n. 2
0
void dce110_compressor_program_compressed_surface_address_and_pitch(
	struct compressor *compressor,
	struct compr_addr_and_pitch_params *params)
{
	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
	uint32_t value = 0;
	uint32_t fbc_pitch = 0;
	uint32_t compressed_surf_address_low_part =
		compressor->compr_surface_address.addr.low_part;

	/* Clear content first. */
	dm_write_reg(
		compressor->ctx,
		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
		0);
	dm_write_reg(compressor->ctx,
		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);

	/* Write address, HIGH has to be first. */
	dm_write_reg(compressor->ctx,
		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
		compressor->compr_surface_address.addr.high_part);
	dm_write_reg(compressor->ctx,
		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
		compressed_surf_address_low_part);

	fbc_pitch = align_to_chunks_number_per_line(params->source_view_width);

	if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
		fbc_pitch = fbc_pitch / 8;
	else
		DC_LOG_WARNING("%s: Unexpected DCE11 compression ratio",
			__func__);

	/* Clear content first. */
	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);

	/* Write FBC Pitch. */
	set_reg_field_value(
		value,
		fbc_pitch,
		GRPH_COMPRESS_PITCH,
		GRPH_COMPRESS_PITCH);
	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);

}
static bool set_dither(
	struct dce110_transform *xfm110,
	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)
{
	uint32_t dither_depth_bits = 0;
	uint32_t dither_mode_bits = 0;
	/*  zero out all bits */
	uint32_t value = 0;

	/* set up the fields */
	if (dither_enable)
		set_reg_field_value(
			value,
			1,
			DCP_SPATIAL_DITHER_CNTL,
			DCP_SPATIAL_DITHER_EN);

	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 */
		ASSERT_CRITICAL(false);
		return false;

	}
	set_reg_field_value(
		value,
		dither_mode_bits,
		DCP_SPATIAL_DITHER_CNTL,
		DCP_SPATIAL_DITHER_MODE);

	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 */
		ASSERT_CRITICAL(false);
		return false;
	}

	set_reg_field_value(
		value,
		dither_depth_bits,
		DCP_SPATIAL_DITHER_CNTL,
		DCP_SPATIAL_DITHER_DEPTH);

	if (frame_random_enable)
		set_reg_field_value(
			value,
			1,
			DCP_SPATIAL_DITHER_CNTL,
			DCP_FRAME_RANDOM_ENABLE);

	if (rgb_random_enable)
		set_reg_field_value(
			value,
			1,
			DCP_SPATIAL_DITHER_CNTL,
			DCP_RGB_RANDOM_ENABLE);

	if (highpass_random_enable)
		set_reg_field_value(
			value,
			1,
			DCP_SPATIAL_DITHER_CNTL,
			DCP_HIGHPASS_RANDOM_ENABLE);

	/*  write the register */
	dm_write_reg(xfm110->base.ctx,
				DCP_REG(mmDCP_SPATIAL_DITHER_CNTL),
				value);

	return true;
}
/**
 *******************************************************************************
 * 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

 * @return
 *     true if succeeds.
 *******************************************************************************
 */
static bool set_round(
	struct dce110_transform *xfm110,
	enum dcp_out_trunc_round_mode mode,
	enum dcp_out_trunc_round_depth depth)
{
	uint32_t depth_bits = 0;
	uint32_t mode_bit = 0;
	/*  zero out all bits */
	uint32_t value = 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:
		/* Invalid dcp_out_trunc_round_depth */
		ASSERT_CRITICAL(false);
		return false;
	}

	set_reg_field_value(
		value,
		depth_bits,
		OUT_ROUND_CONTROL,
		OUT_ROUND_TRUNC_MODE);

	/*  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:
		/* Invalid dcp_out_trunc_round_mode */
		ASSERT_CRITICAL(false);
		return false;
	}

	depth_bits |= mode_bit << 3;

	set_reg_field_value(
		value,
		depth_bits,
		OUT_ROUND_CONTROL,
		OUT_ROUND_TRUNC_MODE);

	/*  write the register */
	dm_write_reg(xfm110->base.ctx,
				DCP_REG(mmOUT_ROUND_CONTROL),
				value);

	return true;
}
/**
 *******************************************************************************
 * set_clamp
 *
 * @param depth : bit depth to set the clamp to (should match denorm)
 *
 * @brief
 *     Programs clamp according to panel bit depth.
 *
 * @return
 *     true if succeeds
 *
 *******************************************************************************
 */
static bool set_clamp(
	struct dce110_transform *xfm110,
	enum dc_color_depth depth)
{
	uint32_t clamp_max = 0;

	/* At the clamp block the data will be MSB aligned, so we set the max
	 * clamp accordingly.
	 * For example, the max value for 6 bits MSB aligned (14 bit bus) would
	 * be "11 1111 0000 0000" in binary, so 0x3F00.
	 */
	switch (depth) {
	case COLOR_DEPTH_666:
		/* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
		clamp_max = 0x3F00;
		break;
	case COLOR_DEPTH_888:
		/* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
		clamp_max = 0x3FC0;
		break;
	case COLOR_DEPTH_101010:
		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
		clamp_max = 0x3FFC;
		break;
	case COLOR_DEPTH_121212:
		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
		clamp_max = 0x3FFF;
		break;
	default:
		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
		return false;
	}

	{
		uint32_t value = 0;
		/*  always set min to 0 */
			set_reg_field_value(
			value,
			0,
			OUT_CLAMP_CONTROL_B_CB,
			OUT_CLAMP_MIN_B_CB);

		set_reg_field_value(
			value,
			clamp_max,
			OUT_CLAMP_CONTROL_B_CB,
			OUT_CLAMP_MAX_B_CB);

		dm_write_reg(xfm110->base.ctx,
			DCP_REG(mmOUT_CLAMP_CONTROL_B_CB),
			value);
	}

	{
		uint32_t value = 0;
		/*  always set min to 0 */
		set_reg_field_value(
			value,
			0,
			OUT_CLAMP_CONTROL_G_Y,
			OUT_CLAMP_MIN_G_Y);

		set_reg_field_value(
			value,
			clamp_max,
			OUT_CLAMP_CONTROL_G_Y,
			OUT_CLAMP_MAX_G_Y);

		dm_write_reg(xfm110->base.ctx,
			DCP_REG(mmOUT_CLAMP_CONTROL_G_Y),
			value);
	}

	{
		uint32_t value = 0;
		/*  always set min to 0 */
		set_reg_field_value(
			value,
			0,
			OUT_CLAMP_CONTROL_R_CR,
			OUT_CLAMP_MIN_R_CR);

		set_reg_field_value(
			value,
			clamp_max,
			OUT_CLAMP_CONTROL_R_CR,
			OUT_CLAMP_MAX_R_CR);

		dm_write_reg(xfm110->base.ctx,
			DCP_REG(mmOUT_CLAMP_CONTROL_R_CR),
			value);
	}

	return true;
}
static void program_gamut_remap(
	struct dce80_transform *xfm80,
	const uint16_t *reg_val)
{
	struct dc_context *ctx = xfm80->base.ctx;
	uint32_t value = 0;
	uint32_t addr = DCP_REG(mmGAMUT_REMAP_CONTROL);

	/* the register controls ovl also */
	value = dm_read_reg(ctx, addr);

	if (reg_val) {
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C11_C12);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[0],
				GAMUT_REMAP_C11_C12,
				GAMUT_REMAP_C11);
			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[1],
				GAMUT_REMAP_C11_C12,
				GAMUT_REMAP_C12);

			dm_write_reg(ctx, addr, reg_data);
		}
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C13_C14);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[2],
				GAMUT_REMAP_C13_C14,
				GAMUT_REMAP_C13);

			/* fixed S0.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[3],
				GAMUT_REMAP_C13_C14,
				GAMUT_REMAP_C14);

			dm_write_reg(ctx, addr, reg_data);
		}
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C21_C22);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[4],
				GAMUT_REMAP_C21_C22,
				GAMUT_REMAP_C21);

			/* fixed S0.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[5],
				GAMUT_REMAP_C21_C22,
				GAMUT_REMAP_C22);

			dm_write_reg(ctx, addr, reg_data);
		}
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C23_C24);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[6],
				GAMUT_REMAP_C23_C24,
				GAMUT_REMAP_C23);

			/* fixed S0.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[7],
				GAMUT_REMAP_C23_C24,
				GAMUT_REMAP_C24);

			dm_write_reg(ctx, addr, reg_data);
		}
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C31_C32);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[8],
				GAMUT_REMAP_C31_C32,
				GAMUT_REMAP_C31);

			/* fixed S0.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[9],
				GAMUT_REMAP_C31_C32,
				GAMUT_REMAP_C32);

			dm_write_reg(ctx, addr, reg_data);
		}
		{
			uint32_t reg_data = 0;
			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C33_C34);

			/* fixed S2.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[10],
				GAMUT_REMAP_C33_C34,
				GAMUT_REMAP_C33);

			/* fixed S0.13 format */
			set_reg_field_value(
				reg_data,
				reg_val[11],
				GAMUT_REMAP_C33_C34,
				GAMUT_REMAP_C34);

			dm_write_reg(ctx, addr, reg_data);
		}

		set_reg_field_value(
			value,
			1,
			GAMUT_REMAP_CONTROL,
			GRPH_GAMUT_REMAP_MODE);

	} else
		set_reg_field_value(
			value,
			0,
			GAMUT_REMAP_CONTROL,
			GRPH_GAMUT_REMAP_MODE);

	addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
	dm_write_reg(ctx, addr, value);

}
static void program_color_matrix(
	struct dce110_opp *opp110,
	const struct out_csc_color_matrix *tbl_entry,
	enum grph_color_adjust_option options)
{
	struct dc_context *ctx = opp110->base.ctx;
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[0],
			OUTPUT_CSC_C11_C12,
			OUTPUT_CSC_C11);

		set_reg_field_value(
			value,
			tbl_entry->regval[1],
			OUTPUT_CSC_C11_C12,
			OUTPUT_CSC_C12);

		dm_write_reg(ctx, addr, value);
	}
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[2],
			OUTPUT_CSC_C13_C14,
			OUTPUT_CSC_C13);
		/* fixed S0.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[3],
			OUTPUT_CSC_C13_C14,
			OUTPUT_CSC_C14);

		dm_write_reg(ctx, addr, value);
	}
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[4],
			OUTPUT_CSC_C21_C22,
			OUTPUT_CSC_C21);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[5],
			OUTPUT_CSC_C21_C22,
			OUTPUT_CSC_C22);

		dm_write_reg(ctx, addr, value);
	}
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[6],
			OUTPUT_CSC_C23_C24,
			OUTPUT_CSC_C23);
		/* fixed S0.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[7],
			OUTPUT_CSC_C23_C24,
			OUTPUT_CSC_C24);

		dm_write_reg(ctx, addr, value);
	}
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[8],
			OUTPUT_CSC_C31_C32,
			OUTPUT_CSC_C31);
		/* fixed S0.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[9],
			OUTPUT_CSC_C31_C32,
			OUTPUT_CSC_C32);

		dm_write_reg(ctx, addr, value);
	}
	{
		uint32_t value = 0;
		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
		/* fixed S2.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[10],
			OUTPUT_CSC_C33_C34,
			OUTPUT_CSC_C33);
		/* fixed S0.13 format */
		set_reg_field_value(
			value,
			tbl_entry->regval[11],
			OUTPUT_CSC_C33_C34,
			OUTPUT_CSC_C34);

		dm_write_reg(ctx, addr, value);
	}
}
static bool configure_graphics_mode(
	struct dce110_opp *opp110,
	enum csc_color_mode config,
	enum graphics_csc_adjust_type csc_adjust_type,
	enum dc_color_space color_space)
{
	struct dc_context *ctx = opp110->base.ctx;
	uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
	uint32_t value = dm_read_reg(ctx, addr);

	set_reg_field_value(
		value,
		0,
		OUTPUT_CSC_CONTROL,
		OUTPUT_CSC_GRPH_MODE);

	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
			set_reg_field_value(
				value,
				4,
				OUTPUT_CSC_CONTROL,
				OUTPUT_CSC_GRPH_MODE);
		} else {

			switch (color_space) {
			case COLOR_SPACE_SRGB:
				/* by pass */
				set_reg_field_value(
					value,
					0,
					OUTPUT_CSC_CONTROL,
					OUTPUT_CSC_GRPH_MODE);
				break;
			case COLOR_SPACE_SRGB_LIMITED:
				/* TV RGB */
				set_reg_field_value(
					value,
					1,
					OUTPUT_CSC_CONTROL,
					OUTPUT_CSC_GRPH_MODE);
				break;
			case COLOR_SPACE_YCBCR601:
			case COLOR_SPACE_YPBPR601:
			case COLOR_SPACE_YCBCR601_LIMITED:
				/* YCbCr601 */
				set_reg_field_value(
					value,
					2,
					OUTPUT_CSC_CONTROL,
					OUTPUT_CSC_GRPH_MODE);
				break;
			case COLOR_SPACE_YCBCR709:
			case COLOR_SPACE_YPBPR709:
			case COLOR_SPACE_YCBCR709_LIMITED:
				/* YCbCr709 */
				set_reg_field_value(
					value,
					3,
					OUTPUT_CSC_CONTROL,
					OUTPUT_CSC_GRPH_MODE);
				break;
			default:
				return false;
			}
		}
	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
		switch (color_space) {
		case COLOR_SPACE_SRGB:
			/* by pass */
			set_reg_field_value(
				value,
				0,
				OUTPUT_CSC_CONTROL,
				OUTPUT_CSC_GRPH_MODE);
			break;
		case COLOR_SPACE_SRGB_LIMITED:
			/* TV RGB */
			set_reg_field_value(
				value,
				1,
				OUTPUT_CSC_CONTROL,
				OUTPUT_CSC_GRPH_MODE);
			break;
		case COLOR_SPACE_YCBCR601:
		case COLOR_SPACE_YPBPR601:
		case COLOR_SPACE_YCBCR601_LIMITED:
			/* YCbCr601 */
			set_reg_field_value(
				value,
				2,
				OUTPUT_CSC_CONTROL,
				OUTPUT_CSC_GRPH_MODE);
			break;
		case COLOR_SPACE_YCBCR709:
		case COLOR_SPACE_YPBPR709:
		case COLOR_SPACE_YCBCR709_LIMITED:
			 /* YCbCr709 */
			set_reg_field_value(
				value,
				3,
				OUTPUT_CSC_CONTROL,
				OUTPUT_CSC_GRPH_MODE);
			break;
		default:
			return false;
		}

	} else
		/* by pass */
		set_reg_field_value(
			value,
			0,
			OUTPUT_CSC_CONTROL,
			OUTPUT_CSC_GRPH_MODE);

	addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
	dm_write_reg(ctx, addr, value);

	return true;
}