drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
Extension
.c
Size
31220 bytes
Lines
990
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 (idx >= AMDGPU_DM_MAX_CRTC) {
			drm_warn(adev_to_drm(adev),
				"%s connected connectors exceed max crtc\n",
				__func__);
			mutex_unlock(&ddev->mode_config.mutex);
			return;
		}

		aconnector = to_amdgpu_dm_connector(connector);

		sort_connector[idx] = aconnector;
		idx++;
		connector_cnt++;
	}
	drm_connector_list_iter_end(&iter);

	/* sort connectors by link_enc_hw_instance first */
	for (idx = connector_cnt; idx > 1 ; idx--) {
		for (idx_2 = 0; idx_2 < (idx - 1); idx_2++) {
			if (sort_connector[idx_2]->dc_link->link_enc_hw_inst >
			    sort_connector[idx_2 + 1]->dc_link->link_enc_hw_inst)
				swap(sort_connector[idx_2], sort_connector[idx_2 + 1]);
		}
	}

	/*
	 * Sort mst connectors by RAD. mst connectors with the same enc_hw_instance are already
	 * sorted together above.
	 */
	for (idx = 0; idx < connector_cnt; /*Do nothing*/) {
		if (sort_connector[idx]->mst_root) {
			uint8_t i, j, k;
			uint8_t mst_con_cnt = 1;

			for (idx_2 = (idx + 1); idx_2 < connector_cnt; idx_2++) {
				if (sort_connector[idx_2]->mst_root == sort_connector[idx]->mst_root)
					mst_con_cnt++;
				else
					break;
			}

			for (i = mst_con_cnt; i > 1; i--) {
				for (j = idx; j < (idx + i - 2); j++) {
					int mstb_lct = sort_connector[j]->mst_output_port->parent->lct;
					int next_mstb_lct = sort_connector[j + 1]->mst_output_port->parent->lct;
					u8 *rad;
					u8 *next_rad;
					bool swap = false;

					/* Sort by mst tree depth first. Then compare RAD if depth is the same*/
					if (mstb_lct > next_mstb_lct) {
						swap = true;
					} else if (mstb_lct == next_mstb_lct) {
						if (mstb_lct == 1) {
							if (sort_connector[j]->mst_output_port->port_num > sort_connector[j + 1]->mst_output_port->port_num)
								swap = true;
						} else if (mstb_lct > 1) {
							rad = sort_connector[j]->mst_output_port->parent->rad;
							next_rad = sort_connector[j + 1]->mst_output_port->parent->rad;

							for (k = 0; k < mstb_lct - 1; k++) {
								int shift = (k % 2) ? 0 : 4;
								int port_num = (rad[k / 2] >> shift) & 0xf;
								int next_port_num = (next_rad[k / 2] >> shift) & 0xf;

								if (port_num > next_port_num) {
									swap = true;
									break;
								}
							}
						} else {
							DRM_ERROR("MST LCT shouldn't be set as < 1");
							mutex_unlock(&ddev->mode_config.mutex);
							return;
						}
					}

					if (swap)
						swap(sort_connector[j], sort_connector[j + 1]);
				}
			}

			idx += mst_con_cnt;
		} else {
			idx++;
		}
	}

	/* Complete sorting. Assign relavant result to dm->secure_display_ctx.phy_id_mapping[]*/
	memset(dm->secure_display_ctx.phy_id_mapping, 0, sizeof(dm->secure_display_ctx.phy_id_mapping));

Annotation

Implementation Notes