drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
Extension
.c
Size
17589 bytes
Lines
555
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (second_preferred_memory_for_opp[i] == false) {
				second_preferred_memory_for_opp[i] = true;
				total_allocated++;
				if (total_required == total_allocated)
					break;
			}
		}
	}
	ASSERT(total_required == total_allocated);

	for (i = 0; i < MAX_PIPES; i++) {
		if (first_preferred_memory_for_opp[i])
			memory_bit_map |= 0x1 << (i * 2);
		if (second_preferred_memory_for_opp[i])
			memory_bit_map |= 0x2 << (i * 2);
	}

	return memory_bit_map;
}

void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id,
		int opp_cnt, int segment_width, int last_segment_width)
{
	struct optc *optc1 = DCN10TG_FROM_TG(optc);
	uint32_t h_active = segment_width * (opp_cnt - 1) + last_segment_width;
	uint32_t odm_mem_bit_map = decide_odm_mem_bit_map(
			opp_id, opp_cnt, h_active);

	REG_SET(OPTC_MEMORY_CONFIG, 0,
		OPTC_MEM_SEL, odm_mem_bit_map);

	switch (opp_cnt) {
	case 2: /* ODM Combine 2:1 */
		REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
				OPTC_NUM_OF_INPUT_SEGMENT, 1,
				OPTC_SEG0_SRC_SEL, opp_id[0],
				OPTC_SEG1_SRC_SEL, opp_id[1]);
		REG_UPDATE(OPTC_WIDTH_CONTROL,
					OPTC_SEGMENT_WIDTH, segment_width);

		REG_UPDATE(OTG_H_TIMING_CNTL,
				OTG_H_TIMING_DIV_MODE, H_TIMING_DIV_BY2);
		break;
	case 3: /* ODM Combine 3:1 */
		REG_SET_4(OPTC_DATA_SOURCE_SELECT, 0,
				OPTC_NUM_OF_INPUT_SEGMENT, 2,
				OPTC_SEG0_SRC_SEL, opp_id[0],
				OPTC_SEG1_SRC_SEL, opp_id[1],
				OPTC_SEG2_SRC_SEL, opp_id[2]);
		REG_UPDATE(OPTC_WIDTH_CONTROL,
				OPTC_SEGMENT_WIDTH, segment_width);
		REG_UPDATE(OPTC_WIDTH_CONTROL2,
				OPTC_SEGMENT_WIDTH_LAST,
				last_segment_width);
		/* In ODM combine 3:1 mode ODM packs 4 pixels per data transfer
		 * so OTG_H_TIMING_DIV_MODE should be configured to
		 * H_TIMING_DIV_BY4 even though ODM combines 3 OPP inputs, it
		 * outputs 4 pixels from single OPP at a time.
		 */
		REG_UPDATE(OTG_H_TIMING_CNTL,
				OTG_H_TIMING_DIV_MODE, H_TIMING_DIV_BY4);
		break;
	case 4: /* ODM Combine 4:1 */
		REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
				OPTC_NUM_OF_INPUT_SEGMENT, 3,
				OPTC_SEG0_SRC_SEL, opp_id[0],
				OPTC_SEG1_SRC_SEL, opp_id[1],
				OPTC_SEG2_SRC_SEL, opp_id[2],
				OPTC_SEG3_SRC_SEL, opp_id[3]);
		REG_UPDATE(OPTC_WIDTH_CONTROL,
					OPTC_SEGMENT_WIDTH, segment_width);
		REG_UPDATE(OTG_H_TIMING_CNTL,
				OTG_H_TIMING_DIV_MODE, H_TIMING_DIV_BY4);
		break;
	default:
		ASSERT(false);
	}
;
	optc1->opp_count = opp_cnt;
}

void optc401_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
{
	struct optc *optc1 = DCN10TG_FROM_TG(optc);

	REG_UPDATE(OTG_H_TIMING_CNTL,
			OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
}
/**
 * optc401_enable_crtc() - Enable CRTC

Annotation

Implementation Notes