drm/modesetting: move some connector functions to helper.

Migrated the output mode collection into the helper.
main
Dave Airlie 2008-06-02 11:12:28 +10:00
parent dba95ec343
commit 0dd000b578
10 changed files with 186 additions and 154 deletions

View File

@ -285,136 +285,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
@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;