brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · b457c69 Raw
225 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */5 6#include <drm/drm_atomic.h>7#include <drm/drm_atomic_helper.h>8#include <drm/drm_atomic_uapi.h>9 10#include "i915_drv.h"11#include "intel_atomic.h"12#include "intel_crtc.h"13#include "intel_display_types.h"14#include "intel_load_detect.h"15 16/* VESA 640x480x72Hz mode to set on the pipe */17static const struct drm_display_mode load_detect_mode = {18	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,19		 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),20};21 22static int intel_modeset_disable_planes(struct drm_atomic_state *state,23					struct drm_crtc *crtc)24{25	struct drm_plane *plane;26	struct drm_plane_state *plane_state;27	int ret, i;28 29	ret = drm_atomic_add_affected_planes(state, crtc);30	if (ret)31		return ret;32 33	for_each_new_plane_in_state(state, plane, plane_state, i) {34		if (plane_state->crtc != crtc)35			continue;36 37		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);38		if (ret)39			return ret;40 41		drm_atomic_set_fb_for_plane(plane_state, NULL);42	}43 44	return 0;45}46 47struct drm_atomic_state *48intel_load_detect_get_pipe(struct drm_connector *connector,49			   struct drm_modeset_acquire_ctx *ctx)50{51	struct intel_display *display = to_intel_display(connector->dev);52	struct intel_encoder *encoder =53		intel_attached_encoder(to_intel_connector(connector));54	struct intel_crtc *possible_crtc;55	struct intel_crtc *crtc = NULL;56	struct drm_mode_config *config = &display->drm->mode_config;57	struct drm_atomic_state *state = NULL, *restore_state = NULL;58	struct drm_connector_state *connector_state;59	struct intel_crtc_state *crtc_state;60	int ret;61 62	drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",63		    connector->base.id, connector->name,64		    encoder->base.base.id, encoder->base.name);65 66	drm_WARN_ON(display->drm, !drm_modeset_is_locked(&config->connection_mutex));67 68	/*69	 * Algorithm gets a little messy:70	 *71	 *   - if the connector already has an assigned crtc, use it (but make72	 *     sure it's on first)73	 *74	 *   - try to find the first unused crtc that can drive this connector,75	 *     and use that if we find one76	 */77 78	/* See if we already have a CRTC for this connector */79	if (connector->state->crtc) {80		crtc = to_intel_crtc(connector->state->crtc);81 82		ret = drm_modeset_lock(&crtc->base.mutex, ctx);83		if (ret)84			goto fail;85 86		/* Make sure the crtc and connector are running */87		goto found;88	}89 90	/* Find an unused one (if possible) */91	for_each_intel_crtc(display->drm, possible_crtc) {92		if (!(encoder->base.possible_crtcs &93		      drm_crtc_mask(&possible_crtc->base)))94			continue;95 96		ret = drm_modeset_lock(&possible_crtc->base.mutex, ctx);97		if (ret)98			goto fail;99 100		if (possible_crtc->base.state->enable) {101			drm_modeset_unlock(&possible_crtc->base.mutex);102			continue;103		}104 105		crtc = possible_crtc;106		break;107	}108 109	/*110	 * If we didn't find an unused CRTC, don't use any.111	 */112	if (!crtc) {113		drm_dbg_kms(display->drm,114			    "no pipe available for load-detect\n");115		ret = -ENODEV;116		goto fail;117	}118 119found:120	state = drm_atomic_state_alloc(display->drm);121	restore_state = drm_atomic_state_alloc(display->drm);122	if (!state || !restore_state) {123		ret = -ENOMEM;124		goto fail;125	}126 127	state->acquire_ctx = ctx;128	to_intel_atomic_state(state)->internal = true;129 130	restore_state->acquire_ctx = ctx;131	to_intel_atomic_state(restore_state)->internal = true;132 133	connector_state = drm_atomic_get_connector_state(state, connector);134	if (IS_ERR(connector_state)) {135		ret = PTR_ERR(connector_state);136		goto fail;137	}138 139	ret = drm_atomic_set_crtc_for_connector(connector_state, &crtc->base);140	if (ret)141		goto fail;142 143	crtc_state = intel_atomic_get_crtc_state(state, crtc);144	if (IS_ERR(crtc_state)) {145		ret = PTR_ERR(crtc_state);146		goto fail;147	}148 149	crtc_state->uapi.active = true;150 151	ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi,152					   &load_detect_mode);153	if (ret)154		goto fail;155 156	ret = intel_modeset_disable_planes(state, &crtc->base);157	if (ret)158		goto fail;159 160	ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(restore_state, connector));161	if (!ret)162		ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, &crtc->base));163	if (!ret)164		ret = drm_atomic_add_affected_planes(restore_state, &crtc->base);165	if (ret) {166		drm_dbg_kms(display->drm,167			    "Failed to create a copy of old state to restore: %i\n",168			    ret);169		goto fail;170	}171 172	ret = drm_atomic_commit(state);173	if (ret) {174		drm_dbg_kms(display->drm,175			    "failed to set mode on load-detect pipe\n");176		goto fail;177	}178 179	drm_atomic_state_put(state);180 181	/* let the connector get through one full cycle before testing */182	intel_crtc_wait_for_next_vblank(crtc);183 184	return restore_state;185 186fail:187	if (state) {188		drm_atomic_state_put(state);189		state = NULL;190	}191	if (restore_state) {192		drm_atomic_state_put(restore_state);193		restore_state = NULL;194	}195 196	if (ret == -EDEADLK)197		return ERR_PTR(ret);198 199	return NULL;200}201 202void intel_load_detect_release_pipe(struct drm_connector *connector,203				    struct drm_atomic_state *state,204				    struct drm_modeset_acquire_ctx *ctx)205{206	struct intel_display *display = to_intel_display(connector->dev);207	struct intel_encoder *intel_encoder =208		intel_attached_encoder(to_intel_connector(connector));209	struct drm_encoder *encoder = &intel_encoder->base;210	int ret;211 212	drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",213		    connector->base.id, connector->name,214		    encoder->base.id, encoder->name);215 216	if (IS_ERR_OR_NULL(state))217		return;218 219	ret = drm_atomic_helper_commit_duplicated_state(state, ctx);220	if (ret)221		drm_dbg_kms(display->drm,222			    "Couldn't release load detect pipe: %i\n", ret);223	drm_atomic_state_put(state);224}225