drivers/gpu/drm/i915/display/intel_dp_mst.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/display/intel_dp_mst.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/intel_dp_mst.c
Extension
.c
Size
69751 bytes
Lines
2193
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 (!dsc_slice_count) {
			drm_dbg_kms(display->drm, "Can't get valid DSC slice count\n");

			return -ENOSPC;
		}
	}

	drm_WARN_ON(display->drm, min_bpp_x16 % bpp_step_x16 || max_bpp_x16 % bpp_step_x16);

	for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
		int local_bw_overhead;
		int link_bpp_x16;

		drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16));

		if (dsc && !intel_dp_dsc_valid_compressed_bpp(intel_dp, bpp_x16)) {
			/* SST must have validated the single bpp tried here already earlier. */
			drm_WARN_ON(display->drm, !is_mst);
			continue;
		}

		link_bpp_x16 = dsc ? bpp_x16 :
			intel_dp_output_format_link_bpp_x16(crtc_state->output_format,
							    fxp_q4_to_int(bpp_x16));

		local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state,
							     false, dsc_slice_count, link_bpp_x16);

		intel_dp_mst_compute_m_n(crtc_state,
					 local_bw_overhead,
					 link_bpp_x16,
					 &crtc_state->dp_m_n);

		if (is_mst) {
			int remote_bw_overhead;
			int remote_tu;
			fixed20_12 pbn;

			remote_bw_overhead = intel_dp_mst_bw_overhead(crtc_state,
								      true, dsc_slice_count, link_bpp_x16);

			/*
			 * The TU size programmed to the HW determines which slots in
			 * an MTP frame are used for this stream, which needs to match
			 * the payload size programmed to the first downstream branch
			 * device's payload table.
			 *
			 * Note that atm the payload's PBN value DRM core sends via
			 * the ALLOCATE_PAYLOAD side-band message matches the payload
			 * size (which it calculates from the PBN value) it programs
			 * to the first branch device's payload table. The allocation
			 * in the payload table could be reduced though (to
			 * crtc_state->dp_m_n.tu), provided that the driver doesn't
			 * enable SSC on the corresponding link.
			 */
			pbn.full = dfixed_const(intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock,
								      link_bpp_x16,
								      remote_bw_overhead));
			remote_tu = DIV_ROUND_UP(pbn.full, mst_state->pbn_div.full);

			/*
			 * Aligning the TUs ensures that symbols consisting of multiple
			 * (4) symbol cycles don't get split between two consecutive
			 * MTPs, as required by Bspec.
			 * TODO: remove the alignment restriction for 128b/132b links
			 * on some platforms, where Bspec allows this.
			 */
			remote_tu = ALIGN(remote_tu, 4 / crtc_state->lane_count);

			/*
			 * Also align PBNs accordingly, since MST core will derive its
			 * own copy of TU from the PBN in drm_dp_atomic_find_time_slots().
			 * The above comment about the difference between the PBN
			 * allocated for the whole path and the TUs allocated for the
			 * first branch device's link also applies here.
			 */
			pbn.full = remote_tu * mst_state->pbn_div.full;

			drm_WARN_ON(display->drm, remote_tu < crtc_state->dp_m_n.tu);
			crtc_state->dp_m_n.tu = remote_tu;

			slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst.mgr,
							      connector->mst.port,
							      dfixed_trunc(pbn));

			/* TODO: Check this already in drm_dp_atomic_find_time_slots(). */
			if (slots > mst_state->total_avail_slots)
				slots = -EINVAL;
		} else {
			/* Same as above for remote_tu */

Annotation

Implementation Notes