Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 329440
b: refs/heads/master
c: 9a93585
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Vetter committed Sep 6, 2012
1 parent 3299ffa commit 709c3fa
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1aa4b628ee63f55db96c7e820257b6e4948abb74
refs/heads/master: 9a935856992d68b9194f825ce6e115df7ecc5bca
174 changes: 130 additions & 44 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -6619,6 +6619,51 @@ intel_crtc_prepare_encoders(struct drm_device *dev)
}
}

/**
* intel_modeset_update_staged_output_state
*
* Updates the staged output configuration state, e.g. after we've read out the
* current hw state.
*/
static void intel_modeset_update_staged_output_state(struct drm_device *dev)
{
struct intel_encoder *encoder;
struct intel_connector *connector;

list_for_each_entry(connector, &dev->mode_config.connector_list,
base.head) {
connector->new_encoder =
to_intel_encoder(connector->base.encoder);
}

list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
encoder->new_crtc =
to_intel_crtc(encoder->base.crtc);
}
}

/**
* intel_modeset_commit_output_state
*
* This function copies the stage display pipe configuration to the real one.
*/
static void intel_modeset_commit_output_state(struct drm_device *dev)
{
struct intel_encoder *encoder;
struct intel_connector *connector;

list_for_each_entry(connector, &dev->mode_config.connector_list,
base.head) {
connector->base.encoder = &connector->new_encoder->base;
}

list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
encoder->base.crtc = &encoder->new_crtc->base;
}
}

bool intel_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *old_fb)
Expand Down Expand Up @@ -6785,8 +6830,8 @@ static void intel_set_config_restore_state(struct drm_device *dev,
struct intel_set_config *config)
{
struct drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_connector *connector;
struct intel_encoder *encoder;
struct intel_connector *connector;
int count;

count = 0;
Expand All @@ -6795,13 +6840,15 @@ static void intel_set_config_restore_state(struct drm_device *dev,
}

count = 0;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder->crtc = config->save_encoder_crtcs[count++];
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
encoder->new_crtc =
to_intel_crtc(config->save_encoder_crtcs[count++]);
}

count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
connector->encoder = config->save_connector_encoders[count++];
list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
connector->new_encoder =
to_intel_encoder(config->save_connector_encoders[count++]);
}
}

Expand Down Expand Up @@ -6840,73 +6887,106 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
}

static int
intel_set_config_update_output_state(struct drm_device *dev,
struct drm_mode_set *set,
struct intel_set_config *config)
intel_modeset_stage_output_state(struct drm_device *dev,
struct drm_mode_set *set,
struct intel_set_config *config)
{
struct drm_crtc *new_crtc;
struct drm_encoder *new_encoder;
struct drm_connector *connector;
struct intel_connector *connector;
struct intel_encoder *encoder;
int count, ro;

/* a) traverse passed in connector list and get encoders for them */
/* The upper layers ensure that we either disabl a crtc or have a list
* of connectors. For paranoia, double-check this. */
WARN_ON(!set->fb && (set->num_connectors != 0));
WARN_ON(set->fb && (set->num_connectors == 0));

count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
new_encoder = connector->encoder;
list_for_each_entry(connector, &dev->mode_config.connector_list,
base.head) {
/* Otherwise traverse passed in connector list and get encoders
* for them. */
for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == connector) {
new_encoder =
&intel_attached_encoder(connector)->base;
if (set->connectors[ro] == &connector->base) {
connector->new_encoder = connector->encoder;
break;
}
}

if (new_encoder != connector->encoder) {
/* If we disable the crtc, disable all its connectors. Also, if
* the connector is on the changing crtc but not on the new
* connector list, disable it. */
if ((!set->fb || ro == set->num_connectors) &&
connector->base.encoder &&
connector->base.encoder->crtc == set->crtc) {
connector->new_encoder = NULL;

DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
connector->base.base.id,
drm_get_connector_name(&connector->base));
}


if (&connector->new_encoder->base != connector->base.encoder) {
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
config->mode_changed = true;
/* If the encoder is reused for another connector, then
* the appropriate crtc will be set later.
*/
if (connector->encoder)
connector->encoder->crtc = NULL;
connector->encoder = new_encoder;
}

/* Disable all disconnected encoders. */
if (connector->base.status == connector_status_disconnected)
connector->new_encoder = NULL;
}
/* connector->new_encoder is now updated for all connectors. */

/* Update crtc of enabled connectors. */
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
list_for_each_entry(connector, &dev->mode_config.connector_list,
base.head) {
if (!connector->new_encoder)
continue;

if (connector->encoder->crtc == set->crtc)
new_crtc = NULL;
else
new_crtc = connector->encoder->crtc;
new_crtc = connector->new_encoder->base.crtc;

for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == connector)
if (set->connectors[ro] == &connector->base)
new_crtc = set->crtc;
}

/* Make sure the new CRTC will work with the encoder */
if (new_crtc &&
!intel_encoder_crtc_ok(connector->encoder, new_crtc)) {
if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
new_crtc)) {
return -EINVAL;
}
if (new_crtc != connector->encoder->crtc) {
connector->encoder->new_crtc = to_intel_crtc(new_crtc);

DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
connector->base.base.id,
drm_get_connector_name(&connector->base),
new_crtc->base.id);
}

/* Check for any encoders that needs to be disabled. */
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
list_for_each_entry(connector,
&dev->mode_config.connector_list,
base.head) {
if (connector->new_encoder == encoder) {
WARN_ON(!connector->new_encoder->new_crtc);

goto next_encoder;
}
}
encoder->new_crtc = NULL;
next_encoder:
/* Only now check for crtc changes so we don't miss encoders
* that will be disabled. */
if (&encoder->new_crtc->base != encoder->base.crtc) {
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
config->mode_changed = true;
connector->encoder->crtc = new_crtc;
}
if (new_crtc) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
connector->base.id, drm_get_connector_name(connector),
new_crtc->base.id);
} else {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
connector->base.id, drm_get_connector_name(connector));
}
}
/* Now we've also updated encoder->new_crtc for all encoders. */

return 0;
}
Expand Down Expand Up @@ -6965,11 +7045,13 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
* such cases. */
intel_set_config_compute_mode_changes(set, config);

ret = intel_set_config_update_output_state(dev, set, config);
ret = intel_modeset_stage_output_state(dev, set, config);
if (ret)
goto fail;

if (config->mode_changed) {
intel_modeset_commit_output_state(dev);

set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
if (set->crtc->enabled) {
DRM_DEBUG_KMS("attempting to set mode from"
Expand Down Expand Up @@ -7015,6 +7097,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
fail:
intel_set_config_restore_state(dev, config);

intel_modeset_commit_output_state(dev);

/* Try to restore the config */
if (config->mode_changed &&
!intel_set_mode(save_set.crtc, save_set.mode,
Expand Down Expand Up @@ -7888,6 +7972,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
intel_sanitize_crtc(crtc);
}

intel_modeset_update_staged_output_state(dev);
}

void intel_modeset_gem_init(struct drm_device *dev)
Expand Down
16 changes: 16 additions & 0 deletions trunk/drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ struct intel_fbdev {

struct intel_encoder {
struct drm_encoder base;
/*
* The new crtc this encoder will be driven from. Only differs from
* base->crtc while a modeset is in progress.
*/
struct intel_crtc *new_crtc;

int type;
bool needs_tv_clock;
/*
Expand All @@ -153,7 +159,17 @@ struct intel_encoder {

struct intel_connector {
struct drm_connector base;
/*
* The fixed encoder this connector is connected to.
*/
struct intel_encoder *encoder;

/*
* The new encoder this connector will be driven. Only differs from
* encoder while a modeset is in progress.
*/
struct intel_encoder *new_encoder;

/* Reads out the current hw, returning true if the connector is enabled
* and active (i.e. dpms ON state). */
bool (*get_hw_state)(struct intel_connector *);
Expand Down

0 comments on commit 709c3fa

Please sign in to comment.