summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_crtc.c132
-rw-r--r--linux-core/drm_crtc.h5
-rw-r--r--linux-core/drm_crtc_helper.c140
-rw-r--r--linux-core/drm_crtc_helper.h15
-rw-r--r--linux-core/intel_crt.c10
-rw-r--r--linux-core/intel_display.c2
-rw-r--r--linux-core/intel_dvo.c7
-rw-r--r--linux-core/intel_lvds.c11
-rw-r--r--linux-core/intel_sdvo.c9
-rw-r--r--linux-core/intel_tv.c9
10 files changed, 186 insertions, 154 deletions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index c4210fd4..74e526bd 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -286,136 +286,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
EXPORT_SYMBOL(drm_crtc_cleanup);
/**
- * drm_crtc_in_use - check if a given CRTC is in a mode_config
- * @crtc: CRTC to check
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Walk @crtc's DRM device's mode_config and see if it's in use.
- *
- * RETURNS:
- * True if @crtc is part of the mode_config, false otherwise.
- */
-bool drm_crtc_in_use(struct drm_crtc *crtc)
-{
- struct drm_encoder *encoder;
- struct drm_device *dev = crtc->dev;
- /* FIXME: Locking around list access? */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
- if (encoder->crtc == crtc)
- return true;
- return false;
-}
-EXPORT_SYMBOL(drm_crtc_in_use);
-
-/*
- * Detailed mode info for a standard 640x480@60Hz monitor
- */
-static struct drm_display_mode std_mode[] = {
- { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
- 752, 800, 0, 480, 490, 492, 525, 0,
- V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
-};
-
-/**
- * drm_crtc_probe_connector_modes - get complete set of display modes
- * @dev: DRM device
- * @maxX: max width for modes
- * @maxY: max height for modes
- *
- * LOCKING:
- * Caller must hold mode config lock.
- *
- * Based on @dev's mode_config layout, scan all the connectors and try to detect
- * modes on them. Modes will first be added to the connector's probed_modes
- * list, then culled (based on validity and the @maxX, @maxY parameters) and
- * put into the normal modes list.
- *
- * Intended to be used either at bootup time or when major configuration
- * changes have occurred.
- *
- * FIXME: take into account monitor limits
- */
-void drm_crtc_probe_single_connector_modes(struct drm_connector *connector, int maxX, int maxY)
-{
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode, *t;
- int ret;
- //if (maxX == 0 || maxY == 0)
- // TODO
-
- /* set all modes to the unverified state */
- list_for_each_entry_safe(mode, t, &connector->modes, head)
- mode->status = MODE_UNVERIFIED;
-
- connector->status = (*connector->funcs->detect)(connector);
-
- if (connector->status == connector_status_disconnected) {
- DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector));
- /* TODO set EDID to NULL */
- return;
- }
-
- ret = (*connector->funcs->get_modes)(connector);
-
- if (ret) {
- drm_mode_connector_list_update(connector);
- }
-
- if (maxX && maxY)
- drm_mode_validate_size(dev, &connector->modes, maxX,
- maxY, 0);
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- if (mode->status == MODE_OK)
- mode->status = (*connector->funcs->mode_valid)(connector,mode);
- }
-
-
- drm_mode_prune_invalid(dev, &connector->modes, TRUE);
-
- if (list_empty(&connector->modes)) {
- struct drm_display_mode *stdmode;
-
- DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector));
-
- /* Should we do this here ???
- * When no valid EDID modes are available we end up
- * here and bailed in the past, now we add a standard
- * 640x480@60Hz mode and carry on.
- */
- stdmode = drm_mode_duplicate(dev, &std_mode[0]);
- drm_mode_probed_add(connector, stdmode);
- drm_mode_list_concat(&connector->probed_modes,
- &connector->modes);
-
- DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
- drm_get_connector_name(connector));
- }
-
- drm_mode_sort(&connector->modes);
-
- DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
- list_for_each_entry_safe(mode, t, &connector->modes, head) {
- mode->vrefresh = drm_mode_vrefresh(mode);
-
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- drm_mode_debug_printmodeline(mode);
- }
-}
-
-void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY)
-{
- struct drm_connector *connector;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- drm_crtc_probe_single_connector_modes(connector, maxX, maxY);
- }
-}
-EXPORT_SYMBOL(drm_crtc_probe_connector_modes);
-
-
-/**
* drm_mode_probed_add - add a mode to the specified connector's probed mode list
* @connector: connector the new mode
* @mode: mode data
@@ -1109,7 +979,7 @@ int drm_mode_getconnector(struct drm_device *dev,
}
if (out_resp->count_modes == 0) {
- drm_crtc_probe_single_connector_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height);
+ connector->funcs->fill_modes(connector, dev->mode_config.max_width, dev->mode_config.max_height);
}
out_resp->connector_type = connector->connector_type;
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 14aa5038..6dbc88a4 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -380,13 +380,10 @@ struct drm_connector_funcs {
void (*save)(struct drm_connector *connector);
void (*restore)(struct drm_connector *connector);
enum drm_connector_status (*detect)(struct drm_connector *connector);
- int (*get_modes)(struct drm_connector *connector);
+ void (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
bool (*set_property)(struct drm_connector *connector, struct drm_property *property,
uint64_t val);
void (*destroy)(struct drm_connector *connector);
- int (*mode_valid)(struct drm_connector *connector,
- struct drm_display_mode *mode);
-
};
struct drm_encoder_funcs {
diff --git a/linux-core/drm_crtc_helper.c b/linux-core/drm_crtc_helper.c
index 82862b55..f1a72707 100644
--- a/linux-core/drm_crtc_helper.c
+++ b/linux-core/drm_crtc_helper.c
@@ -34,6 +34,136 @@
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
+/*
+ * Detailed mode info for a standard 640x480@60Hz monitor
+ */
+static struct drm_display_mode std_mode[] = {
+ { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
+ 752, 800, 0, 480, 490, 492, 525, 0,
+ V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
+};
+
+/**
+ * drm_helper_probe_connector_modes - get complete set of display modes
+ * @dev: DRM device
+ * @maxX: max width for modes
+ * @maxY: max height for modes
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Based on @dev's mode_config layout, scan all the connectors and try to detect
+ * modes on them. Modes will first be added to the connector's probed_modes
+ * list, then culled (based on validity and the @maxX, @maxY parameters) and
+ * put into the normal modes list.
+ *
+ * Intended to be used either at bootup time or when major configuration
+ * changes have occurred.
+ *
+ * FIXME: take into account monitor limits
+ */
+void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *mode, *t;
+ struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
+ int ret;
+
+ /* set all modes to the unverified state */
+ list_for_each_entry_safe(mode, t, &connector->modes, head)
+ mode->status = MODE_UNVERIFIED;
+
+ connector->status = (*connector->funcs->detect)(connector);
+
+ if (connector->status == connector_status_disconnected) {
+ DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector));
+ /* TODO set EDID to NULL */
+ return;
+ }
+
+ ret = (*connector_funcs->get_modes)(connector);
+
+ if (ret) {
+ drm_mode_connector_list_update(connector);
+ }
+
+ if (maxX && maxY)
+ drm_mode_validate_size(dev, &connector->modes, maxX,
+ maxY, 0);
+ list_for_each_entry_safe(mode, t, &connector->modes, head) {
+ if (mode->status == MODE_OK)
+ mode->status = (*connector_funcs->mode_valid)(connector,mode);
+ }
+
+
+ drm_mode_prune_invalid(dev, &connector->modes, TRUE);
+
+ if (list_empty(&connector->modes)) {
+ struct drm_display_mode *stdmode;
+
+ DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector));
+
+ /* Should we do this here ???
+ * When no valid EDID modes are available we end up
+ * here and bailed in the past, now we add a standard
+ * 640x480@60Hz mode and carry on.
+ */
+ stdmode = drm_mode_duplicate(dev, &std_mode[0]);
+ drm_mode_probed_add(connector, stdmode);
+ drm_mode_list_concat(&connector->probed_modes,
+ &connector->modes);
+
+ DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
+ drm_get_connector_name(connector));
+ }
+
+ drm_mode_sort(&connector->modes);
+
+ DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
+ list_for_each_entry_safe(mode, t, &connector->modes, head) {
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ drm_mode_debug_printmodeline(mode);
+ }
+}
+EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
+
+void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, uint32_t maxY)
+{
+ struct drm_connector *connector;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+ }
+}
+EXPORT_SYMBOL(drm_helper_probe_connector_modes);
+
+
+/**
+ * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
+ * @crtc: CRTC to check
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Walk @crtc's DRM device's mode_config and see if it's in use.
+ *
+ * RETURNS:
+ * True if @crtc is part of the mode_config, false otherwise.
+ */
+bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder;
+ struct drm_device *dev = crtc->dev;
+ /* FIXME: Locking around list access? */
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+ if (encoder->crtc == crtc)
+ return true;
+ return false;
+}
+EXPORT_SYMBOL(drm_helper_crtc_in_use);
+
/**
* drm_disable_unused_functions - disable unused objects
* @dev: DRM device
@@ -81,8 +211,8 @@ static void drm_pick_crtcs (struct drm_device *dev)
int found;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- connector->encoder->crtc = NULL;
-
+ connector->encoder->crtc = NULL;
+
/* Don't hook up connectors that are disconnected ??
*
* This is debateable. Do we want fixed /dev/fbX or
@@ -211,7 +341,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mo
adjusted_mode = drm_mode_duplicate(dev, mode);
- crtc->enabled = drm_crtc_in_use(crtc);
+ crtc->enabled = drm_helper_crtc_in_use(crtc);
if (!crtc->enabled)
return true;
@@ -456,7 +586,7 @@ bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
mutex_lock(&dev->mode_config.mutex);
- drm_crtc_probe_connector_modes(dev, 2048, 2048);
+ drm_helper_probe_connector_modes(dev, 2048, 2048);
drm_pick_crtcs(dev);
@@ -518,7 +648,7 @@ int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_connector *c
has_config = 1;
}
- drm_crtc_probe_connector_modes(dev, 2048, 2048);
+ drm_helper_probe_connector_modes(dev, 2048, 2048);
if (!has_config)
drm_pick_crtcs(dev);
diff --git a/linux-core/drm_crtc_helper.h b/linux-core/drm_crtc_helper.h
index 063d1f7a..80cb4b49 100644
--- a/linux-core/drm_crtc_helper.h
+++ b/linux-core/drm_crtc_helper.h
@@ -55,8 +55,14 @@ struct drm_encoder_helper_funcs {
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
};
-
+struct drm_connector_helper_funcs {
+ int (*get_modes)(struct drm_connector *connector);
+ int (*mode_valid)(struct drm_connector *connector,
+ struct drm_display_mode *mode);
+};
+
+extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
extern int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_connector *connector,
bool connected);
@@ -64,7 +70,7 @@ extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y);
-
+extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs)
{
crtc->helper_private = (void *)funcs;
@@ -75,6 +81,11 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder, const str
encoder->helper_private = (void *)funcs;
}
+static inline void drm_connector_helper_add(struct drm_connector *connector, const struct drm_connector_helper_funcs *funcs)
+{
+ connector->helper_private = (void *)funcs;
+}
+
#endif
diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c
index ec4c2bf9..21a1e7d7 100644
--- a/linux-core/intel_crt.c
+++ b/linux-core/intel_crt.c
@@ -237,13 +237,16 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
.save = intel_crt_save,
.restore = intel_crt_restore,
.detect = intel_crt_detect,
- .get_modes = intel_crt_get_modes,
+ .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_crt_destroy,
.set_property = intel_crt_set_property,
- .mode_valid = intel_crt_mode_valid,
-
};
+static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
+ .mode_valid = intel_crt_mode_valid,
+ .get_modes = intel_crt_get_modes,
+};
+
void intel_crt_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
@@ -283,6 +286,7 @@ void intel_crt_init(struct drm_device *dev)
connector->doublescan_allowed = 0;
drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
+ drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_sysfs_connector_add(connector);
diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c
index c1cb2bff..bbaa19d1 100644
--- a/linux-core/intel_display.c
+++ b/linux-core/intel_display.c
@@ -1184,7 +1184,7 @@ void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_
if (intel_output->load_detect_temp) {
encoder->crtc = NULL;
intel_output->load_detect_temp = FALSE;
- crtc->enabled = drm_crtc_in_use(crtc);
+ crtc->enabled = drm_helper_crtc_in_use(crtc);
drm_helper_disable_unused_functions(dev);
}
diff --git a/linux-core/intel_dvo.c b/linux-core/intel_dvo.c
index 364cd659..e895d5b6 100644
--- a/linux-core/intel_dvo.c
+++ b/linux-core/intel_dvo.c
@@ -335,9 +335,13 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = {
.save = intel_dvo_save,
.restore = intel_dvo_restore,
.detect = intel_dvo_detect,
- .get_modes = intel_dvo_get_modes,
.destroy = intel_dvo_destroy,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+};
+
+static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
.mode_valid = intel_dvo_mode_valid,
+ .get_modes = intel_dvo_get_modes,
};
void intel_dvo_enc_destroy(struct drm_encoder *encoder)
@@ -464,6 +468,7 @@ void intel_dvo_init(struct drm_device *dev)
break;
}
+ drm_connector_helper_add(connector, &intel_dvo_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c
index b83f3923..cbe8b53d 100644
--- a/linux-core/intel_lvds.c
+++ b/linux-core/intel_lvds.c
@@ -342,13 +342,17 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
.commit = intel_lvds_commit,
};
+static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
+ .get_modes = intel_lvds_get_modes,
+ .mode_valid = intel_lvds_mode_valid,
+};
+
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.save = intel_lvds_save,
.restore = intel_lvds_restore,
.detect = intel_lvds_detect,
- .get_modes = intel_lvds_get_modes,
+ .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_lvds_destroy,
- .mode_valid = intel_lvds_mode_valid,
};
@@ -361,6 +365,8 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
.destroy = intel_lvds_enc_destroy,
};
+
+
/**
* intel_lvds_init - setup LVDS connectors on this device
* @dev: drm device
@@ -395,6 +401,7 @@ void intel_lvds_init(struct drm_device *dev)
intel_output->type = INTEL_OUTPUT_LVDS;
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
+ drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = FALSE;
connector->doublescan_allowed = FALSE;
diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c
index 498ad989..d3ca2a20 100644
--- a/linux-core/intel_sdvo.c
+++ b/linux-core/intel_sdvo.c
@@ -983,11 +983,14 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
.save = intel_sdvo_save,
.restore = intel_sdvo_restore,
.detect = intel_sdvo_detect,
- .get_modes = intel_sdvo_get_modes,
+ .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_sdvo_destroy,
- .mode_valid = intel_sdvo_mode_valid,
};
+static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = {
+ .get_modes = intel_sdvo_get_modes,
+ .mode_valid = intel_sdvo_mode_valid,
+};
void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
{
@@ -1019,7 +1022,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
DRM_MODE_CONNECTOR_Unknown);
-
+ drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
intel_output->type = INTEL_OUTPUT_SDVO;
diff --git a/linux-core/intel_tv.c b/linux-core/intel_tv.c
index b13b035f..c3b5c093 100644
--- a/linux-core/intel_tv.c
+++ b/linux-core/intel_tv.c
@@ -1608,11 +1608,15 @@ static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
static const struct drm_connector_funcs intel_tv_connector_funcs = {
.save = intel_tv_save,
.restore = intel_tv_restore,
- .mode_valid = intel_tv_mode_valid,
.detect = intel_tv_detect,
- .get_modes = intel_tv_get_modes,
.destroy = intel_tv_destroy,
.set_property = intel_tv_set_property,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+};
+
+static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
+ .mode_valid = intel_tv_mode_valid,
+ .get_modes = intel_tv_get_modes,
};
void intel_tv_enc_destroy(struct drm_encoder *encoder)
@@ -1695,6 +1699,7 @@ intel_tv_init(struct drm_device *dev)
tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
drm_encoder_helper_add(&intel_output->enc, &intel_tv_helper_funcs);
+ drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
connector->interlace_allowed = FALSE;
connector->doublescan_allowed = FALSE;