Example #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);
}
Example #2
0
static void hubp1_set_vm_context0_settings(struct hubp *hubp,
		const struct vm_context0_param *vm0)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
	/* pte base */
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, 0,
			VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_MSB, vm0->pte_base.high_part);
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, 0,
			VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LSB, vm0->pte_base.low_part);

	/* pte start */
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, 0,
			VM_CONTEXT0_PAGE_TABLE_START_ADDR_MSB, vm0->pte_start.high_part);
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, 0,
			VM_CONTEXT0_PAGE_TABLE_START_ADDR_LSB, vm0->pte_start.low_part);

	/* pte end */
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, 0,
			VM_CONTEXT0_PAGE_TABLE_END_ADDR_MSB, vm0->pte_end.high_part);
	REG_SET(DCN_VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, 0,
			VM_CONTEXT0_PAGE_TABLE_END_ADDR_LSB, vm0->pte_end.low_part);

	/* fault handling */
	REG_SET_2(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, 0,
			VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_MSB, vm0->fault_default.high_part,
			VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_SYSTEM, context0_default_system);
	REG_SET(DCN_VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, 0,
			VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR_LSB, vm0->fault_default.low_part);

	/* control: enable VM PTE*/
	REG_SET_2(DCN_VM_MX_L1_TLB_CNTL, 0,
			ENABLE_L1_TLB, 1,
			SYSTEM_ACCESS_MODE, 3);
}
Example #3
0
static void program_viewport(
	struct dce_transform *xfm_dce,
	const struct rect *view_port)
{
	REG_SET_2(VIEWPORT_START, 0,
			VIEWPORT_X_START, view_port->x,
			VIEWPORT_Y_START, view_port->y);

	REG_SET_2(VIEWPORT_SIZE, 0,
			VIEWPORT_HEIGHT, view_port->height,
			VIEWPORT_WIDTH, view_port->width);

	/* TODO: add stereo support */
}
Example #4
0
static void dce110_stream_encoder_set_mst_bandwidth(
	struct stream_encoder *enc,
	struct fixed31_32 avg_time_slots_per_mtp)
{
	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
	uint32_t x = dal_fixed31_32_floor(
		avg_time_slots_per_mtp);
	uint32_t y = dal_fixed31_32_ceil(
		dal_fixed31_32_shl(
			dal_fixed31_32_sub_int(
				avg_time_slots_per_mtp,
				x),
			26));

	{
		REG_SET_2(DP_MSE_RATE_CNTL, 0,
			DP_MSE_RATE_X, x,
			DP_MSE_RATE_Y, y);
	}

	/* wait for update to be completed on the link */
	/* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */
	/* is reset to 0 (not pending) */
	REG_WAIT(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING,
			0,
			10, DP_MST_UPDATE_MAX_RETRY);
}
Example #5
0
static bool setup_scaling_configuration(
	struct dce_transform *xfm_dce,
	const struct scaler_data *data)
{
	REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);

	if (data->taps.h_taps + data->taps.v_taps <= 2) {
		/* Set bypass */
		if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
			REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0);
		else
			REG_UPDATE(SCL_MODE, SCL_MODE, 0);
		return false;
	}

	REG_SET_2(SCL_TAP_CONTROL, 0,
			SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
			SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);

	if (data->format <= PIXEL_FORMAT_GRPH_END)
		REG_UPDATE(SCL_MODE, SCL_MODE, 1);
	else
		REG_UPDATE(SCL_MODE, SCL_MODE, 2);

	if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
		REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1);

	/* 1 - Replace out of bound pixels with edge */
	REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1);

	return true;
}
Example #6
0
static void hubp1_set_vm_system_aperture_settings(struct hubp *hubp,
		struct vm_system_aperture_param *apt)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
	PHYSICAL_ADDRESS_LOC mc_vm_apt_default;
	PHYSICAL_ADDRESS_LOC mc_vm_apt_low;
	PHYSICAL_ADDRESS_LOC mc_vm_apt_high;

	mc_vm_apt_default.quad_part = apt->sys_default.quad_part >> 12;
	mc_vm_apt_low.quad_part = apt->sys_low.quad_part >> 12;
	mc_vm_apt_high.quad_part = apt->sys_high.quad_part >> 12;

	REG_SET_2(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, 0,
		MC_VM_SYSTEM_APERTURE_DEFAULT_SYSTEM, aperture_default_system, /* 1 = system physical memory */
		MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, mc_vm_apt_default.high_part);
	REG_SET(DCN_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, 0,
		MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, mc_vm_apt_default.low_part);

	REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, 0,
			MC_VM_SYSTEM_APERTURE_LOW_ADDR_MSB, mc_vm_apt_low.high_part);
	REG_SET(DCN_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, 0,
			MC_VM_SYSTEM_APERTURE_LOW_ADDR_LSB, mc_vm_apt_low.low_part);

	REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, 0,
			MC_VM_SYSTEM_APERTURE_HIGH_ADDR_MSB, mc_vm_apt_high.high_part);
	REG_SET(DCN_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, 0,
			MC_VM_SYSTEM_APERTURE_HIGH_ADDR_LSB, mc_vm_apt_high.low_part);
}
Example #7
0
void hubp1_cursor_set_attributes(
		struct hubp *hubp,
		const struct dc_cursor_attributes *attr)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
	enum cursor_pitch hw_pitch = hubp1_get_cursor_pitch(attr->pitch);
	enum cursor_lines_per_chunk lpc = hubp1_get_lines_per_chunk(
			attr->width, attr->color_format);

	hubp->curs_attr = *attr;

	REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
			CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
	REG_UPDATE(CURSOR_SURFACE_ADDRESS,
			CURSOR_SURFACE_ADDRESS, attr->address.low_part);

	REG_UPDATE_2(CURSOR_SIZE,
			CURSOR_WIDTH, attr->width,
			CURSOR_HEIGHT, attr->height);

	REG_UPDATE_3(CURSOR_CONTROL,
			CURSOR_MODE, attr->color_format,
			CURSOR_PITCH, hw_pitch,
			CURSOR_LINES_PER_CHUNK, lpc);

	REG_SET_2(CURSOR_SETTINS, 0,
			/* no shift of the cursor HDL schedule */
			CURSOR0_DST_Y_OFFSET, 0,
			 /* used to shift the cursor chunk request deadline */
			CURSOR0_CHUNK_HDL_ADJUST, 3);
}
Example #8
0
/*****************************************************************************
 * set_clamp
 *
 * @param depth : bit depth to set the clamp to (should match denorm)
 *
 * @brief
 *     Programs clamp according to panel bit depth.
 *
 *******************************************************************************/
static void set_clamp(
	struct dce_transform *xfm_dce,
	enum dc_color_depth depth)
{
	int 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:
		clamp_max = 0x3FC0;
		BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */
	}
	REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0,
			OUT_CLAMP_MIN_B_CB, 0,
			OUT_CLAMP_MAX_B_CB, clamp_max);

	REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0,
			OUT_CLAMP_MIN_G_Y, 0,
			OUT_CLAMP_MAX_G_Y, clamp_max);

	REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0,
			OUT_CLAMP_MIN_R_CR, 0,
			OUT_CLAMP_MAX_R_CR, clamp_max);
}
Example #9
0
static void hubp1_setup_interdependent(
		struct hubp *hubp,
		struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
		struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);

	REG_SET_2(PREFETCH_SETTINS, 0,
		DST_Y_PREFETCH, dlg_attr->dst_y_prefetch,
		VRATIO_PREFETCH, dlg_attr->vratio_prefetch);

	REG_SET(PREFETCH_SETTINS_C, 0,
		VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c);

	REG_SET_2(VBLANK_PARAMETERS_0, 0,
		DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank,
		DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank);

	REG_SET(VBLANK_PARAMETERS_3, 0,
		REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l);

	REG_SET(VBLANK_PARAMETERS_4, 0,
		REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c);

	REG_SET_2(PER_LINE_DELIVERY_PRE, 0,
		REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l,
		REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c);

	REG_SET(DCN_SURF0_TTU_CNTL1, 0,
		REFCYC_PER_REQ_DELIVERY_PRE,
		ttu_attr->refcyc_per_req_delivery_pre_l);
	REG_SET(DCN_SURF1_TTU_CNTL1, 0,
		REFCYC_PER_REQ_DELIVERY_PRE,
		ttu_attr->refcyc_per_req_delivery_pre_c);
	REG_SET(DCN_CUR0_TTU_CNTL1, 0,
		REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0);

	REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0,
		MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank,
		QoS_LEVEL_FLIP, ttu_attr->qos_level_flip);
}
Example #10
0
static void program_scl_ratios_inits(
	struct dce_transform *xfm_dce,
	struct scl_ratios_inits *inits)
{

	REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
			SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);

	REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
			SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);

	REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
			SCL_H_INIT_INT, inits->h_init.integer,
			SCL_H_INIT_FRAC, inits->h_init.fraction);

	REG_SET_2(SCL_VERT_FILTER_INIT, 0,
			SCL_V_INIT_INT, inits->v_init.integer,
			SCL_V_INIT_FRAC, inits->v_init.fraction);

	REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
}
Example #11
0
void dce_pipe_control_lock(struct dc *dc,
		struct pipe_ctx *pipe,
		bool lock)
{
	uint32_t lock_val = lock ? 1 : 0;
	uint32_t dcp_grph, scl, blnd, update_lock_mode, val;
	struct dce_hwseq *hws = dc->hwseq;

	/* Not lock pipe when blank */
	if (lock && pipe->stream_res.tg->funcs->is_blanked &&
	    pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg))
		return;

	val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst],
			BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
			BLND_SCL_V_UPDATE_LOCK, &scl,
			BLND_BLND_V_UPDATE_LOCK, &blnd,
			BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);

	dcp_grph = lock_val;
	scl = lock_val;
	blnd = lock_val;
	update_lock_mode = lock_val;

	REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
			BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
			BLND_SCL_V_UPDATE_LOCK, scl);

	if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0)
		REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
				BLND_BLND_V_UPDATE_LOCK, blnd,
				BLND_V_UPDATE_LOCK_MODE, update_lock_mode);

	if (hws->wa.blnd_crtc_trigger) {
		if (!lock) {
			uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst]);
			REG_WRITE(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst], value);
		}
	}
}
Example #12
0
void min_set_viewport(
	struct hubp *hubp,
	const struct rect *viewport,
	const struct rect *viewport_c)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);

	REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION, 0,
		  PRI_VIEWPORT_WIDTH, viewport->width,
		  PRI_VIEWPORT_HEIGHT, viewport->height);

	REG_SET_2(DCSURF_PRI_VIEWPORT_START, 0,
		  PRI_VIEWPORT_X_START, viewport->x,
		  PRI_VIEWPORT_Y_START, viewport->y);

	/*for stereo*/
	REG_SET_2(DCSURF_SEC_VIEWPORT_DIMENSION, 0,
		  SEC_VIEWPORT_WIDTH, viewport->width,
		  SEC_VIEWPORT_HEIGHT, viewport->height);

	REG_SET_2(DCSURF_SEC_VIEWPORT_START, 0,
		  SEC_VIEWPORT_X_START, viewport->x,
		  SEC_VIEWPORT_Y_START, viewport->y);

	/* DC supports NV12 only at the moment */
	REG_SET_2(DCSURF_PRI_VIEWPORT_DIMENSION_C, 0,
		  PRI_VIEWPORT_WIDTH_C, viewport_c->width,
		  PRI_VIEWPORT_HEIGHT_C, viewport_c->height);

	REG_SET_2(DCSURF_PRI_VIEWPORT_START_C, 0,
		  PRI_VIEWPORT_X_START_C, viewport_c->x,
		  PRI_VIEWPORT_Y_START_C, viewport_c->y);
}
Example #13
0
static void program_gamut_remap(
	struct dce_transform *xfm_dce,
	const uint16_t *reg_val)
{
	if (reg_val) {
		REG_SET_2(GAMUT_REMAP_C11_C12, 0,
				GAMUT_REMAP_C11, reg_val[0],
				GAMUT_REMAP_C12, reg_val[1]);
		REG_SET_2(GAMUT_REMAP_C13_C14, 0,
				GAMUT_REMAP_C13, reg_val[2],
				GAMUT_REMAP_C14, reg_val[3]);
		REG_SET_2(GAMUT_REMAP_C21_C22, 0,
				GAMUT_REMAP_C21, reg_val[4],
				GAMUT_REMAP_C22, reg_val[5]);
		REG_SET_2(GAMUT_REMAP_C23_C24, 0,
				GAMUT_REMAP_C23, reg_val[6],
				GAMUT_REMAP_C24, reg_val[7]);
		REG_SET_2(GAMUT_REMAP_C31_C32, 0,
				GAMUT_REMAP_C31, reg_val[8],
				GAMUT_REMAP_C32, reg_val[9]);
		REG_SET_2(GAMUT_REMAP_C33_C34, 0,
				GAMUT_REMAP_C33, reg_val[10],
				GAMUT_REMAP_C34, reg_val[11]);

		REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1);
	} else
		REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0);

}
Example #14
0
static void program_color_matrix(
	struct dce_transform *xfm_dce,
	const struct out_csc_color_matrix *tbl_entry,
	enum grph_color_adjust_option options)
{
	{
		REG_SET_2(OUTPUT_CSC_C11_C12, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[0],
			OUTPUT_CSC_C12, tbl_entry->regval[1]);
	}
	{
		REG_SET_2(OUTPUT_CSC_C13_C14, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[2],
			OUTPUT_CSC_C12, tbl_entry->regval[3]);
	}
	{
		REG_SET_2(OUTPUT_CSC_C21_C22, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[4],
			OUTPUT_CSC_C12, tbl_entry->regval[5]);
	}
	{
		REG_SET_2(OUTPUT_CSC_C23_C24, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[6],
			OUTPUT_CSC_C12, tbl_entry->regval[7]);
	}
	{
		REG_SET_2(OUTPUT_CSC_C31_C32, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[8],
			OUTPUT_CSC_C12, tbl_entry->regval[9]);
	}
	{
		REG_SET_2(OUTPUT_CSC_C33_C34, 0,
			OUTPUT_CSC_C11, tbl_entry->regval[10],
			OUTPUT_CSC_C12, tbl_entry->regval[11]);
	}
}
Example #15
0
/* setup stream encoder in dp mode */
static void dce110_stream_encoder_dp_set_stream_attribute(
	struct stream_encoder *enc,
	struct dc_crtc_timing *crtc_timing,
	enum dc_color_space output_color_space)
{
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
	uint32_t h_active_start;
	uint32_t v_active_start;
	uint32_t misc0 = 0;
	uint32_t misc1 = 0;
	uint32_t h_blank;
	uint32_t h_back_porch;
	uint8_t synchronous_clock = 0; /* asynchronous mode */
	uint8_t colorimetry_bpc;
#endif

	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
	if (REG(DP_DB_CNTL))
		REG_UPDATE(DP_DB_CNTL, DP_DB_DISABLE, 1);
#endif

	/* set pixel encoding */
	switch (crtc_timing->pixel_encoding) {
	case PIXEL_ENCODING_YCBCR422:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
				DP_PIXEL_ENCODING_YCBCR422);
		break;
	case PIXEL_ENCODING_YCBCR444:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
				DP_PIXEL_ENCODING_YCBCR444);

		if (crtc_timing->flags.Y_ONLY)
			if (crtc_timing->display_color_depth != COLOR_DEPTH_666)
				/* HW testing only, no use case yet.
				 * Color depth of Y-only could be
				 * 8, 10, 12, 16 bits */
				REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
						DP_PIXEL_ENCODING_Y_ONLY);
		/* Note: DP_MSA_MISC1 bit 7 is the indicator
		 * of Y-only mode.
		 * This bit is set in HW if register
		 * DP_PIXEL_ENCODING is programmed to 0x4 */
		break;
	case PIXEL_ENCODING_YCBCR420:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
				DP_PIXEL_ENCODING_YCBCR420);
		if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN)
			REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1);

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
		if (enc110->se_mask->DP_VID_N_MUL)
			REG_UPDATE(DP_VID_TIMING, DP_VID_N_MUL, 1);
#endif
		break;
	default:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING,
				DP_PIXEL_ENCODING_RGB444);
		break;
	}

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
	if (REG(DP_MSA_MISC))
		misc1 = REG_READ(DP_MSA_MISC);
#endif

	/* set color depth */

	switch (crtc_timing->display_color_depth) {
	case COLOR_DEPTH_666:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
				0);
		break;
	case COLOR_DEPTH_888:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
				DP_COMPONENT_DEPTH_8BPC);
		break;
	case COLOR_DEPTH_101010:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
				DP_COMPONENT_DEPTH_10BPC);

		break;
	case COLOR_DEPTH_121212:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
				DP_COMPONENT_DEPTH_12BPC);
		break;
	default:
		REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
				DP_COMPONENT_DEPTH_6BPC);
		break;
	}

	/* set dynamic range and YCbCr range */
	if (enc110->se_mask->DP_DYN_RANGE && enc110->se_mask->DP_YCBCR_RANGE)
		REG_UPDATE_2(
			DP_PIXEL_FORMAT,
			DP_DYN_RANGE, 0,
			DP_YCBCR_RANGE, 0);

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
	switch (crtc_timing->display_color_depth) {
	case COLOR_DEPTH_666:
		colorimetry_bpc = 0;
		break;
	case COLOR_DEPTH_888:
		colorimetry_bpc = 1;
		break;
	case COLOR_DEPTH_101010:
		colorimetry_bpc = 2;
		break;
	case COLOR_DEPTH_121212:
		colorimetry_bpc = 3;
		break;
	default:
		colorimetry_bpc = 0;
		break;
	}

	misc0 = misc0 | synchronous_clock;
	misc0 = colorimetry_bpc << 5;

	if (REG(DP_MSA_TIMING_PARAM1)) {
		switch (output_color_space) {
		case COLOR_SPACE_SRGB:
			misc0 = misc0 | 0x0;
			misc1 = misc1 & ~0x80; /* bit7 = 0*/
			break;
		case COLOR_SPACE_SRGB_LIMITED:
			misc0 = misc0 | 0x8; /* bit3=1 */
			misc1 = misc1 & ~0x80; /* bit7 = 0*/
			break;
		case COLOR_SPACE_YCBCR601:
			misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */
			misc1 = misc1 & ~0x80; /* bit7 = 0*/
			if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
				misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
			else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
				misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
			break;
		case COLOR_SPACE_YCBCR709:
			misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */
			misc1 = misc1 & ~0x80; /* bit7 = 0*/
			if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
				misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */
			else if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR444)
				misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */
			break;
		case COLOR_SPACE_2020_RGB_FULLRANGE:
		case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
		case COLOR_SPACE_2020_YCBCR:
		case COLOR_SPACE_ADOBERGB:
		case COLOR_SPACE_UNKNOWN:
		case COLOR_SPACE_YCBCR601_LIMITED:
		case COLOR_SPACE_YCBCR709_LIMITED:
			/* do nothing */
			break;
		}

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
		if (REG(DP_MSA_COLORIMETRY))
			REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0);

		if (REG(DP_MSA_MISC))
			REG_WRITE(DP_MSA_MISC, misc1);   /* MSA_MISC1 */

	/* dcn new register
	 * dc_crtc_timing is vesa dmt struct. data from edid
	 */
		if (REG(DP_MSA_TIMING_PARAM1))
			REG_SET_2(DP_MSA_TIMING_PARAM1, 0,
					DP_MSA_HTOTAL, crtc_timing->h_total,
					DP_MSA_VTOTAL, crtc_timing->v_total);
#endif

		/* calcuate from vesa timing parameters
		 * h_active_start related to leading edge of sync
		 */

		h_blank = crtc_timing->h_total - crtc_timing->h_border_left -
				crtc_timing->h_addressable - crtc_timing->h_border_right;

		h_back_porch = h_blank - crtc_timing->h_front_porch -
				crtc_timing->h_sync_width;

		/* start at begining of left border */
		h_active_start = crtc_timing->h_sync_width + h_back_porch;


		v_active_start = crtc_timing->v_total - crtc_timing->v_border_top -
				crtc_timing->v_addressable - crtc_timing->v_border_bottom -
				crtc_timing->v_front_porch;


#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
		/* start at begining of left border */
		if (REG(DP_MSA_TIMING_PARAM2))
			REG_SET_2(DP_MSA_TIMING_PARAM2, 0,
				DP_MSA_HSTART, h_active_start,
				DP_MSA_VSTART, v_active_start);

		if (REG(DP_MSA_TIMING_PARAM3))
			REG_SET_4(DP_MSA_TIMING_PARAM3, 0,
					DP_MSA_HSYNCWIDTH,
					crtc_timing->h_sync_width,
					DP_MSA_HSYNCPOLARITY,
					!crtc_timing->flags.HSYNC_POSITIVE_POLARITY,
					DP_MSA_VSYNCWIDTH,
					crtc_timing->v_sync_width,
					DP_MSA_VSYNCPOLARITY,
					!crtc_timing->flags.VSYNC_POSITIVE_POLARITY);

		/* HWDITH include border or overscan */
		if (REG(DP_MSA_TIMING_PARAM4))
			REG_SET_2(DP_MSA_TIMING_PARAM4, 0,
				DP_MSA_HWIDTH, crtc_timing->h_border_left +
				crtc_timing->h_addressable + crtc_timing->h_border_right,
				DP_MSA_VHEIGHT, crtc_timing->v_border_top +
				crtc_timing->v_addressable + crtc_timing->v_border_bottom);
#endif
	}
#endif
}
Example #16
0
static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce,
						const struct pwl_params *params)
{
	const struct gamma_curve *curve;

	REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0,
		  REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x,
		  REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0);

	REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0,
		REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope);

	REG_SET(REGAMMA_CNTLA_END_CNTL1, 0,
		REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x);

	REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0,
		  REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y,
		  REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope);

	curve = params->arr_curve_points;

	REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
	curve += 2;

	REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0,
		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
}
Example #17
0
void hubp1_program_deadline(
		struct hubp *hubp,
		struct _vcs_dpi_display_dlg_regs_st *dlg_attr,
		struct _vcs_dpi_display_ttu_regs_st *ttu_attr)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);

	/* DLG - Per hubp */
	REG_SET_2(BLANK_OFFSET_0, 0,
		REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end,
		DLG_V_BLANK_END, dlg_attr->dlg_vblank_end);

	REG_SET(BLANK_OFFSET_1, 0,
		MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start);

	REG_SET(DST_DIMENSIONS, 0,
		REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal);

	REG_SET_2(DST_AFTER_SCALER, 0,
		REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler,
		DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler);

	REG_SET(REF_FREQ_TO_PIX_FREQ, 0,
		REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq);

	/* DLG - Per luma/chroma */
	REG_SET(VBLANK_PARAMETERS_1, 0,
		REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l);

	if (REG(NOM_PARAMETERS_0))
		REG_SET(NOM_PARAMETERS_0, 0,
			DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l);

	if (REG(NOM_PARAMETERS_1))
		REG_SET(NOM_PARAMETERS_1, 0,
			REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l);

	REG_SET(NOM_PARAMETERS_4, 0,
		DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l);

	REG_SET(NOM_PARAMETERS_5, 0,
		REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l);

	REG_SET_2(PER_LINE_DELIVERY, 0,
		REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l,
		REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c);

	REG_SET(VBLANK_PARAMETERS_2, 0,
		REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c);

	if (REG(NOM_PARAMETERS_2))
		REG_SET(NOM_PARAMETERS_2, 0,
			DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c);

	if (REG(NOM_PARAMETERS_3))
		REG_SET(NOM_PARAMETERS_3, 0,
			REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c);

	REG_SET(NOM_PARAMETERS_6, 0,
		DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c);

	REG_SET(NOM_PARAMETERS_7, 0,
		REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c);

	/* TTU - per hubp */
	REG_SET_2(DCN_TTU_QOS_WM, 0,
		QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm,
		QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm);

	/* TTU - per luma/chroma */
	/* Assumed surf0 is luma and 1 is chroma */

	REG_SET_3(DCN_SURF0_TTU_CNTL0, 0,
		REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l,
		QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l,
		QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l);

	REG_SET_3(DCN_SURF1_TTU_CNTL0, 0,
		REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c,
		QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c,
		QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c);

	REG_SET_3(DCN_CUR0_TTU_CNTL0, 0,
		REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0,
		QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0,
		QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0);
}
Example #18
0
static void dce_transform_set_scaler(
	struct transform *xfm,
	const struct scaler_data *data)
{
	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
	bool is_scaling_required;
	bool filter_updated = false;
	const uint16_t *coeffs_v, *coeffs_h;

	/*Use all three pieces of memory always*/
	REG_SET_2(LB_MEMORY_CTRL, 0,
			LB_MEMORY_CONFIG, 0,
			LB_MEMORY_SIZE, xfm_dce->lb_memory_size);

	/* Clear SCL_F_SHARP_CONTROL value to 0 */
	REG_WRITE(SCL_F_SHARP_CONTROL, 0);

	/* 1. Program overscan */
	program_overscan(xfm_dce, data);

	/* 2. Program taps and configuration */
	is_scaling_required = setup_scaling_configuration(xfm_dce, data);

	if (is_scaling_required) {
		/* 3. Calculate and program ratio, filter initialization */
		struct scl_ratios_inits inits = { 0 };

		calculate_inits(xfm_dce, data, &inits);

		program_scl_ratios_inits(xfm_dce, &inits);

		coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
		coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);

		if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
			/* 4. Program vertical filters */
			if (xfm_dce->filter_v == NULL)
				REG_SET(SCL_VERT_FILTER_CONTROL, 0,
						SCL_V_2TAP_HARDCODE_COEF_EN, 0);
			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,
					coeffs_v,
					FILTER_TYPE_ALPHA_VERTICAL);

			/* 5. Program horizontal filters */
			if (xfm_dce->filter_h == NULL)
				REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
						SCL_H_2TAP_HARDCODE_COEF_EN, 0);
			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,
					coeffs_h,
					FILTER_TYPE_ALPHA_HORIZONTAL);

			xfm_dce->filter_v = coeffs_v;
			xfm_dce->filter_h = coeffs_h;
			filter_updated = true;
		}
	}

	/* 6. Program the viewport */
	program_viewport(xfm_dce, &data->viewport);

	/* 7. Set bit to flip to new coefficient memory */
	if (filter_updated)
		REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1);

	REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en);
}
Example #19
0
void hubp1_cursor_set_position(
		struct hubp *hubp,
		const struct dc_cursor_position *pos,
		const struct dc_cursor_mi_param *param)
{
	struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
	int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
	int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
	int x_hotspot = pos->x_hotspot;
	int y_hotspot = pos->y_hotspot;
	uint32_t dst_x_offset;
	uint32_t cur_en = pos->enable ? 1 : 0;

	/*
	 * Guard aganst cursor_set_position() from being called with invalid
	 * attributes
	 *
	 * TODO: Look at combining cursor_set_position() and
	 * cursor_set_attributes() into cursor_update()
	 */
	if (hubp->curs_attr.address.quad_part == 0)
		return;

	if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
		src_x_offset = pos->y - pos->y_hotspot - param->viewport.x;
		y_hotspot = pos->x_hotspot;
		x_hotspot = pos->y_hotspot;
	}

	if (param->mirror) {
		x_hotspot = param->viewport.width - x_hotspot;
		src_x_offset = param->viewport.x + param->viewport.width - src_x_offset;
	}

	dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
	dst_x_offset *= param->ref_clk_khz;
	dst_x_offset /= param->pixel_clk_khz;

	ASSERT(param->h_scale_ratio.value);

	if (param->h_scale_ratio.value)
		dst_x_offset = dc_fixpt_floor(dc_fixpt_div(
				dc_fixpt_from_int(dst_x_offset),
				param->h_scale_ratio));

	if (src_x_offset >= (int)param->viewport.width)
		cur_en = 0;  /* not visible beyond right edge*/

	if (src_x_offset + (int)hubp->curs_attr.width <= 0)
		cur_en = 0;  /* not visible beyond left edge*/

	if (src_y_offset >= (int)param->viewport.height)
		cur_en = 0;  /* not visible beyond bottom edge*/

	if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
		cur_en = 0;  /* not visible beyond top edge*/

	if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
		hubp->funcs->set_cursor_attributes(hubp, &hubp->curs_attr);

	REG_UPDATE(CURSOR_CONTROL,
			CURSOR_ENABLE, cur_en);

	REG_SET_2(CURSOR_POSITION, 0,
			CURSOR_X_POSITION, pos->x,
			CURSOR_Y_POSITION, pos->y);

	REG_SET_2(CURSOR_HOT_SPOT, 0,
			CURSOR_HOT_SPOT_X, x_hotspot,
			CURSOR_HOT_SPOT_Y, y_hotspot);

	REG_SET(CURSOR_DST_OFFSET, 0,
			CURSOR_DST_X_OFFSET, dst_x_offset);
	/* TODO Handle surface pixel formats other than 4:4:4 */
}
Example #20
0
static bool process_transaction(
	struct dce_i2c_hw *dce_i2c_hw,
	struct i2c_request_transaction_data *request)
{
	uint32_t length = request->length;
	uint8_t *buffer = request->data;

	bool last_transaction = false;
	uint32_t value = 0;

	last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
			(request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
			(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));


	switch (dce_i2c_hw->transaction_count) {
	case 0:
		REG_UPDATE_5(DC_I2C_TRANSACTION0,
				 DC_I2C_STOP_ON_NACK0, 1,
				 DC_I2C_START0, 1,
				 DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
				 DC_I2C_COUNT0, length,
				 DC_I2C_STOP0, last_transaction ? 1 : 0);
		break;
	case 1:
		REG_UPDATE_5(DC_I2C_TRANSACTION1,
				 DC_I2C_STOP_ON_NACK0, 1,
				 DC_I2C_START0, 1,
				 DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
				 DC_I2C_COUNT0, length,
				 DC_I2C_STOP0, last_transaction ? 1 : 0);
		break;
	case 2:
		REG_UPDATE_5(DC_I2C_TRANSACTION2,
				 DC_I2C_STOP_ON_NACK0, 1,
				 DC_I2C_START0, 1,
				 DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
				 DC_I2C_COUNT0, length,
				 DC_I2C_STOP0, last_transaction ? 1 : 0);
		break;
	case 3:
		REG_UPDATE_5(DC_I2C_TRANSACTION3,
				 DC_I2C_STOP_ON_NACK0, 1,
				 DC_I2C_START0, 1,
				 DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
				 DC_I2C_COUNT0, length,
				 DC_I2C_STOP0, last_transaction ? 1 : 0);
		break;
	default:
		/* TODO Warning ? */
		break;
	}

	/* Write the I2C address and I2C data
	 * into the hardware circular buffer, one byte per entry.
	 * As an example, the 7-bit I2C slave address for CRT monitor
	 * for reading DDC/EDID information is 0b1010001.
	 * For an I2C send operation, the LSB must be programmed to 0;
	 * for I2C receive operation, the LSB must be programmed to 1.
	 */
	if (dce_i2c_hw->transaction_count == 0) {
		value = REG_SET_4(DC_I2C_DATA, 0,
				  DC_I2C_DATA_RW, false,
				  DC_I2C_DATA, request->address,
				  DC_I2C_INDEX, 0,
				  DC_I2C_INDEX_WRITE, 1);
		dce_i2c_hw->buffer_used_write = 0;
	} else
		value = REG_SET_2(DC_I2C_DATA, 0,
			  DC_I2C_DATA_RW, false,
			  DC_I2C_DATA, request->address);

	dce_i2c_hw->buffer_used_write++;

	if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
		while (length) {
			REG_SET_2(DC_I2C_DATA, value,
				  DC_I2C_INDEX_WRITE, 0,
				  DC_I2C_DATA, *buffer++);
			dce_i2c_hw->buffer_used_write++;
			--length;
		}
	}

	++dce_i2c_hw->transaction_count;
	dce_i2c_hw->buffer_used_bytes += length + 1;

	return last_transaction;
}
Example #21
0
static bool process_transaction(
	struct i2c_hw_engine_dce110 *hw_engine,
	struct i2c_request_transaction_data *request)
{
	uint32_t length = request->length;
	uint8_t *buffer = request->data;
	uint32_t value = 0;

	bool last_transaction = false;

	struct dc_context *ctx = NULL;

	ctx = hw_engine->base.base.base.ctx;



	switch (hw_engine->transaction_count) {
	case 0:
		SET_I2C_TRANSACTION(0);
		break;
	case 1:
		SET_I2C_TRANSACTION(1);
		break;
	case 2:
		SET_I2C_TRANSACTION(2);
		break;
	case 3:
		SET_I2C_TRANSACTION(3);
		break;
	default:
		/* TODO Warning ? */
		break;
	}


	/* Write the I2C address and I2C data
	 * into the hardware circular buffer, one byte per entry.
	 * As an example, the 7-bit I2C slave address for CRT monitor
	 * for reading DDC/EDID information is 0b1010001.
	 * For an I2C send operation, the LSB must be programmed to 0;
	 * for I2C receive operation, the LSB must be programmed to 1. */
	if (hw_engine->transaction_count == 0) {
		value = REG_SET_4(DC_I2C_DATA, 0,
				  DC_I2C_DATA_RW, false,
				  DC_I2C_DATA, request->address,
				  DC_I2C_INDEX, 0,
				  DC_I2C_INDEX_WRITE, 1);
		hw_engine->buffer_used_write = 0;
	} else
		value = REG_SET_2(DC_I2C_DATA, 0,
				  DC_I2C_DATA_RW, false,
				  DC_I2C_DATA, request->address);

	hw_engine->buffer_used_write++;

	if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
		while (length) {
			REG_SET_2(DC_I2C_DATA, value,
					DC_I2C_INDEX_WRITE, 0,
					DC_I2C_DATA, *buffer++);
			hw_engine->buffer_used_write++;
			--length;
		}
	}

	++hw_engine->transaction_count;
	hw_engine->buffer_used_bytes += length + 1;

	return last_transaction;
}