From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/gpu/drm/drm_probe_helper.c | 167 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 118 insertions(+), 49 deletions(-)
diff --git a/kernel/drivers/gpu/drm/drm_probe_helper.c b/kernel/drivers/gpu/drm/drm_probe_helper.c
index c0b2613..d3f0d04 100644
--- a/kernel/drivers/gpu/drm/drm_probe_helper.c
+++ b/kernel/drivers/gpu/drm/drm_probe_helper.c
@@ -32,14 +32,16 @@
#include <linux/export.h>
#include <linux/moduleparam.h>
-#include <drm/drmP.h>
+#include <drm/drm_bridge.h>
#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_sysfs.h>
#include "drm_crtc_helper_internal.h"
@@ -84,26 +86,28 @@
return MODE_OK;
}
-static enum drm_mode_status
+static int
drm_mode_validate_pipeline(struct drm_display_mode *mode,
- struct drm_connector *connector)
+ struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ enum drm_mode_status *status)
{
struct drm_device *dev = connector->dev;
- enum drm_mode_status ret = MODE_OK;
struct drm_encoder *encoder;
- int i;
+ int ret;
/* Step 1: Validate against connector */
- ret = drm_connector_mode_valid(connector, mode);
- if (ret != MODE_OK)
+ ret = drm_connector_mode_valid(connector, mode, ctx, status);
+ if (ret || *status != MODE_OK)
return ret;
/* Step 2: Validate against encoders and crtcs */
- drm_connector_for_each_possible_encoder(connector, encoder, i) {
+ drm_connector_for_each_possible_encoder(connector, encoder) {
+ struct drm_bridge *bridge;
struct drm_crtc *crtc;
- ret = drm_encoder_mode_valid(encoder, mode);
- if (ret != MODE_OK) {
+ *status = drm_encoder_mode_valid(encoder, mode);
+ if (*status != MODE_OK) {
/* No point in continuing for crtc check as this encoder
* will not accept the mode anyway. If all encoders
* reject the mode then, at exit, ret will not be
@@ -111,8 +115,11 @@
continue;
}
- ret = drm_bridge_mode_valid(encoder->bridge, mode);
- if (ret != MODE_OK) {
+ bridge = drm_bridge_chain_get_first_bridge(encoder);
+ *status = drm_bridge_chain_mode_valid(bridge,
+ &connector->display_info,
+ mode);
+ if (*status != MODE_OK) {
/* There is also no point in continuing for crtc check
* here. */
continue;
@@ -122,17 +129,17 @@
if (!drm_encoder_crtc_ok(encoder, crtc))
continue;
- ret = drm_crtc_mode_valid(crtc, mode);
- if (ret == MODE_OK) {
+ *status = drm_crtc_mode_valid(crtc, mode);
+ if (*status == MODE_OK) {
/* If we get to this point there is at least
* one combination of encoder+crtc that works
* for this mode. Lets return now. */
- return ret;
+ return 0;
}
}
}
- return ret;
+ return 0;
}
static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
@@ -156,6 +163,8 @@
continue;
}
+ /* Mark the matching mode as being preferred by the user */
+ mode->type |= DRM_MODE_TYPE_USERDEF;
return 0;
}
@@ -191,16 +200,27 @@
return encoder_funcs->mode_valid(encoder, mode);
}
-enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+int
+drm_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode,
+ struct drm_modeset_acquire_ctx *ctx,
+ enum drm_mode_status *status)
{
const struct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
+ int ret = 0;
- if (!connector_funcs || !connector_funcs->mode_valid)
- return MODE_OK;
+ if (!connector_funcs)
+ *status = MODE_OK;
+ else if (connector_funcs->mode_valid_ctx)
+ ret = connector_funcs->mode_valid_ctx(connector, mode, ctx,
+ status);
+ else if (connector_funcs->mode_valid)
+ *status = connector_funcs->mode_valid(connector, mode);
+ else
+ *status = MODE_OK;
- return connector_funcs->mode_valid(connector, mode);
+ return ret;
}
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
@@ -285,6 +305,9 @@
if (WARN_ON(ret < 0))
ret = connector_status_unknown;
+ if (ret != connector->status)
+ connector->epoch_counter += 1;
+
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
@@ -318,11 +341,16 @@
return ret;
if (funcs->detect_ctx)
- return funcs->detect_ctx(connector, ctx, force);
+ ret = funcs->detect_ctx(connector, ctx, force);
else if (connector->funcs->detect)
- return connector->funcs->detect(connector, force);
+ ret = connector->funcs->detect(connector, force);
else
- return connector_status_connected;
+ ret = connector_status_connected;
+
+ if (ret != connector->status)
+ connector->epoch_counter += 1;
+
+ return ret;
}
EXPORT_SYMBOL(drm_helper_probe_detect);
@@ -370,8 +398,9 @@
* (if specified)
* - drm_mode_validate_flag() checks the modes against basic connector
* capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
- * - the optional &drm_connector_helper_funcs.mode_valid helper can perform
- * driver and/or sink specific checks
+ * - the optional &drm_connector_helper_funcs.mode_valid or
+ * &drm_connector_helper_funcs.mode_valid_ctx helpers can perform driver
+ * and/or sink specific checks
* - the optional &drm_crtc_helper_funcs.mode_valid,
* &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
* helpers can perform driver and/or source specific checks which are also
@@ -459,8 +488,9 @@
*/
dev->mode_config.delayed_event = true;
if (dev->mode_config.poll_enabled)
- schedule_delayed_work(&dev->mode_config.output_poll_work,
- 0);
+ mod_delayed_work(system_wq,
+ &dev->mode_config.output_poll_work,
+ 0);
}
/* Re-enable polling in case the global poll config changed. */
@@ -502,22 +532,39 @@
mode_flags |= DRM_MODE_FLAG_3D_MASK;
list_for_each_entry(mode, &connector->modes, head) {
- if (mode->status == MODE_OK)
- mode->status = drm_mode_validate_driver(dev, mode);
+ if (mode->status != MODE_OK)
+ continue;
- if (mode->status == MODE_OK)
- mode->status = drm_mode_validate_size(mode, maxX, maxY);
+ mode->status = drm_mode_validate_driver(dev, mode);
+ if (mode->status != MODE_OK)
+ continue;
- if (mode->status == MODE_OK)
- mode->status = drm_mode_validate_flag(mode, mode_flags);
+ mode->status = drm_mode_validate_size(mode, maxX, maxY);
+ if (mode->status != MODE_OK)
+ continue;
- if (mode->status == MODE_OK)
- mode->status = drm_mode_validate_pipeline(mode,
- connector);
+ mode->status = drm_mode_validate_flag(mode, mode_flags);
+ if (mode->status != MODE_OK)
+ continue;
- if (mode->status == MODE_OK)
- mode->status = drm_mode_validate_ycbcr420(mode,
- connector);
+ ret = drm_mode_validate_pipeline(mode, connector, &ctx,
+ &mode->status);
+ if (ret) {
+ drm_dbg_kms(dev,
+ "drm_mode_validate_pipeline failed: %d\n",
+ ret);
+
+ if (drm_WARN_ON_ONCE(dev, ret != -EDEADLK)) {
+ mode->status = MODE_ERROR;
+ } else {
+ drm_modeset_backoff(&ctx);
+ goto retry;
+ }
+ }
+
+ if (mode->status != MODE_OK)
+ continue;
+ mode->status = drm_mode_validate_ycbcr420(mode, connector);
}
prune:
@@ -528,9 +575,6 @@
if (list_empty(&connector->modes))
return 0;
-
- list_for_each_entry(mode, &connector->modes, head)
- mode->vrefresh = drm_mode_vrefresh(mode);
drm_mode_sort(&connector->modes);
@@ -580,6 +624,7 @@
struct drm_connector_list_iter conn_iter;
enum drm_connector_status old_status;
bool repoll = false, changed;
+ u64 old_epoch_counter;
if (!dev->mode_config.poll_enabled)
return;
@@ -616,8 +661,9 @@
repoll = true;
+ old_epoch_counter = connector->epoch_counter;
connector->status = drm_helper_probe_detect(connector, NULL, false);
- if (old_status != connector->status) {
+ if (old_epoch_counter != connector->epoch_counter) {
const char *old, *new;
/*
@@ -646,6 +692,9 @@
connector->base.id,
connector->name,
old, new);
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] epoch counter %llu -> %llu\n",
+ connector->base.id, connector->name,
+ old_epoch_counter, connector->epoch_counter);
changed = true;
}
@@ -775,6 +824,7 @@
struct drm_connector_list_iter conn_iter;
enum drm_connector_status old_status;
bool changed = false;
+ u64 old_epoch_counter;
if (!dev->mode_config.poll_enabled)
return false;
@@ -788,20 +838,39 @@
old_status = connector->status;
+ old_epoch_counter = connector->epoch_counter;
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id,
+ connector->name,
+ old_epoch_counter);
+
connector->status = drm_helper_probe_detect(connector, NULL, false);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.id,
connector->name,
drm_get_connector_status_name(old_status),
drm_get_connector_status_name(connector->status));
- if (old_status != connector->status)
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n",
+ connector->base.id,
+ connector->name,
+ connector->epoch_counter);
+
+ /*
+ * Check if epoch counter had changed, meaning that we need
+ * to send a uevent.
+ */
+ if (old_epoch_counter != connector->epoch_counter)
changed = true;
+
}
drm_connector_list_iter_end(&conn_iter);
mutex_unlock(&dev->mode_config.mutex);
- if (changed)
+ if (changed) {
drm_kms_helper_hotplug_event(dev);
+ DRM_DEBUG_KMS("Sent hotplug event\n");
+ }
return changed;
}
--
Gitblit v1.6.2