111,7 → 111,17 |
{ |
struct drm_connector *connector; |
struct drm_device *dev = encoder->dev; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
|
/* |
* We can expect this mutex to be locked if we are not panicking. |
* Locking is currently fubar in the panic handler. |
*/ |
if (!oops_in_progress) { |
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
} |
|
drm_for_each_connector(connector, dev) |
if (connector->encoder == encoder) |
return true; |
return false; |
133,8 → 143,15 |
{ |
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) |
|
/* |
* We can expect this mutex to be locked if we are not panicking. |
* Locking is currently fubar in the panic handler. |
*/ |
if (!oops_in_progress) |
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
|
drm_for_each_encoder(encoder, dev) |
if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) |
return true; |
return false; |
144,10 → 161,9 |
static void |
drm_encoder_disable(struct drm_encoder *encoder) |
{ |
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; |
|
if (encoder->bridge) |
encoder->bridge->funcs->disable(encoder->bridge); |
drm_bridge_disable(encoder->bridge); |
|
if (encoder_funcs->disable) |
(*encoder_funcs->disable)(encoder); |
154,8 → 170,7 |
else |
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
|
if (encoder->bridge) |
encoder->bridge->funcs->post_disable(encoder->bridge); |
drm_bridge_post_disable(encoder->bridge); |
} |
|
static void __drm_helper_disable_unused_functions(struct drm_device *dev) |
165,7 → 180,7 |
|
drm_warn_on_modeset_not_all_locked(dev); |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
if (!drm_helper_encoder_in_use(encoder)) { |
drm_encoder_disable(encoder); |
/* disconnect encoder from any connector */ |
173,8 → 188,8 |
} |
} |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
drm_for_each_crtc(crtc, dev) { |
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
crtc->enabled = drm_helper_crtc_in_use(crtc); |
if (!crtc->enabled) { |
if (crtc_funcs->disable) |
212,10 → 227,10 |
static void |
drm_crtc_prepare_encoders(struct drm_device *dev) |
{ |
struct drm_encoder_helper_funcs *encoder_funcs; |
const struct drm_encoder_helper_funcs *encoder_funcs; |
struct drm_encoder *encoder; |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
encoder_funcs = encoder->helper_private; |
/* Disable unused encoders */ |
if (encoder->crtc == NULL) |
253,9 → 268,9 |
struct drm_framebuffer *old_fb) |
{ |
struct drm_device *dev = crtc->dev; |
struct drm_display_mode *adjusted_mode, saved_mode; |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
struct drm_encoder_helper_funcs *encoder_funcs; |
struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; |
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
const struct drm_encoder_helper_funcs *encoder_funcs; |
int saved_x, saved_y; |
bool saved_enabled; |
struct drm_encoder *encoder; |
275,6 → 290,7 |
} |
|
saved_mode = crtc->mode; |
saved_hwmode = crtc->hwmode; |
saved_x = crtc->x; |
saved_y = crtc->y; |
|
289,19 → 305,17 |
* adjust it according to limitations or connector properties, and also |
* a chance to reject the mode entirely. |
*/ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
|
if (encoder->crtc != crtc) |
continue; |
|
if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { |
ret = encoder->bridge->funcs->mode_fixup( |
encoder->bridge, mode, adjusted_mode); |
ret = drm_bridge_mode_fixup(encoder->bridge, |
mode, adjusted_mode); |
if (!ret) { |
DRM_DEBUG_KMS("Bridge fixup failed\n"); |
goto done; |
} |
} |
|
encoder_funcs = encoder->helper_private; |
if (!(ret = encoder_funcs->mode_fixup(encoder, mode, |
317,21 → 331,21 |
} |
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
|
crtc->hwmode = *adjusted_mode; |
|
/* Prepare the encoders and CRTCs before setting the mode. */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
|
if (encoder->crtc != crtc) |
continue; |
|
if (encoder->bridge) |
encoder->bridge->funcs->disable(encoder->bridge); |
drm_bridge_disable(encoder->bridge); |
|
encoder_funcs = encoder->helper_private; |
/* Disable the encoders as the first thing we do. */ |
encoder_funcs->prepare(encoder); |
|
if (encoder->bridge) |
encoder->bridge->funcs->post_disable(encoder->bridge); |
drm_bridge_post_disable(encoder->bridge); |
} |
|
drm_crtc_prepare_encoders(dev); |
345,7 → 359,7 |
if (!ret) |
goto done; |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
|
if (encoder->crtc != crtc) |
continue; |
356,32 → 370,25 |
encoder_funcs = encoder->helper_private; |
encoder_funcs->mode_set(encoder, mode, adjusted_mode); |
|
if (encoder->bridge && encoder->bridge->funcs->mode_set) |
encoder->bridge->funcs->mode_set(encoder->bridge, mode, |
adjusted_mode); |
drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode); |
} |
|
/* Now enable the clocks, plane, pipe, and connectors that we set up. */ |
crtc_funcs->commit(crtc); |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
|
if (encoder->crtc != crtc) |
continue; |
|
if (encoder->bridge) |
encoder->bridge->funcs->pre_enable(encoder->bridge); |
drm_bridge_pre_enable(encoder->bridge); |
|
encoder_funcs = encoder->helper_private; |
encoder_funcs->commit(encoder); |
|
if (encoder->bridge) |
encoder->bridge->funcs->enable(encoder->bridge); |
drm_bridge_enable(encoder->bridge); |
} |
|
/* Store real post-adjustment hardware mode. */ |
crtc->hwmode = *adjusted_mode; |
|
/* Calculate and store various constants which |
* are later needed by vblank and swap-completion |
* timestamping. They are derived from true hwmode. |
394,6 → 401,7 |
if (!ret) { |
crtc->enabled = saved_enabled; |
crtc->mode = saved_mode; |
crtc->hwmode = saved_hwmode; |
crtc->x = saved_x; |
crtc->y = saved_y; |
} |
410,11 → 418,11 |
struct drm_encoder *encoder; |
|
/* Decouple all encoders and their attached connectors from this crtc */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
if (encoder->crtc != crtc) |
continue; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
drm_for_each_connector(connector, dev) { |
if (connector->encoder != encoder) |
continue; |
|
455,7 → 463,7 |
bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
struct drm_connector *save_connectors, *connector; |
int count = 0, ro, fail = 0; |
struct drm_crtc_helper_funcs *crtc_funcs; |
const struct drm_crtc_helper_funcs *crtc_funcs; |
struct drm_mode_set save_set; |
int ret; |
int i; |
511,12 → 519,12 |
* restored, not the drivers personal bookkeeping. |
*/ |
count = 0; |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
save_encoders[count++] = *encoder; |
} |
|
count = 0; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
drm_for_each_connector(connector, dev) { |
save_connectors[count++] = *connector; |
} |
|
554,8 → 562,8 |
|
/* a) traverse passed in connector list and get encoders for them */ |
count = 0; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
struct drm_connector_helper_funcs *connector_funcs = |
drm_for_each_connector(connector, dev) { |
const struct drm_connector_helper_funcs *connector_funcs = |
connector->helper_private; |
new_encoder = connector->encoder; |
for (ro = 0; ro < set->num_connectors; ro++) { |
594,7 → 602,7 |
} |
|
count = 0; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
drm_for_each_connector(connector, dev) { |
if (!connector->encoder) |
continue; |
|
677,12 → 685,12 |
fail: |
/* Restore all previous data. */ |
count = 0; |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
*encoder = save_encoders[count++]; |
} |
|
count = 0; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
drm_for_each_connector(connector, dev) { |
*connector = save_connectors[count++]; |
} |
|
704,7 → 712,7 |
struct drm_connector *connector; |
struct drm_device *dev = encoder->dev; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
drm_for_each_connector(connector, dev) |
if (connector->encoder == encoder) |
if (connector->dpms < dpms) |
dpms = connector->dpms; |
715,26 → 723,22 |
static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) |
{ |
struct drm_bridge *bridge = encoder->bridge; |
struct drm_encoder_helper_funcs *encoder_funcs; |
const struct drm_encoder_helper_funcs *encoder_funcs; |
|
if (bridge) { |
if (mode == DRM_MODE_DPMS_ON) |
bridge->funcs->pre_enable(bridge); |
drm_bridge_pre_enable(bridge); |
else |
bridge->funcs->disable(bridge); |
} |
drm_bridge_disable(bridge); |
|
encoder_funcs = encoder->helper_private; |
if (encoder_funcs->dpms) |
encoder_funcs->dpms(encoder, mode); |
|
if (bridge) { |
if (mode == DRM_MODE_DPMS_ON) |
bridge->funcs->enable(bridge); |
drm_bridge_enable(bridge); |
else |
bridge->funcs->post_disable(bridge); |
drm_bridge_post_disable(bridge); |
} |
} |
|
static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) |
{ |
742,7 → 746,7 |
struct drm_connector *connector; |
struct drm_device *dev = crtc->dev; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
drm_for_each_connector(connector, dev) |
if (connector->encoder && connector->encoder->crtc == crtc) |
if (connector->dpms < dpms) |
dpms = connector->dpms; |
758,8 → 762,11 |
* implementing the DPMS connector attribute. It computes the new desired DPMS |
* state for all encoders and crtcs in the output mesh and calls the ->dpms() |
* callback provided by the driver appropriately. |
* |
* Returns: |
* Always returns 0. |
*/ |
void drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
int drm_helper_connector_dpms(struct drm_connector *connector, int mode) |
{ |
struct drm_encoder *encoder = connector->encoder; |
struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; |
766,7 → 773,7 |
int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; |
|
if (mode == connector->dpms) |
return; |
return 0; |
|
old_dpms = connector->dpms; |
connector->dpms = mode; |
777,7 → 784,7 |
/* from off to on, do crtc then encoder */ |
if (mode < old_dpms) { |
if (crtc) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
if (crtc_funcs->dpms) |
(*crtc_funcs->dpms) (crtc, |
drm_helper_choose_crtc_dpms(crtc)); |
791,7 → 798,7 |
if (encoder) |
drm_helper_encoder_dpms(encoder, encoder_dpms); |
if (crtc) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
if (crtc_funcs->dpms) |
(*crtc_funcs->dpms) (crtc, |
drm_helper_choose_crtc_dpms(crtc)); |
798,7 → 805,7 |
} |
} |
|
return; |
return 0; |
} |
EXPORT_SYMBOL(drm_helper_connector_dpms); |
|
820,6 → 827,7 |
for (i = 0; i < 4; i++) { |
fb->pitches[i] = mode_cmd->pitches[i]; |
fb->offsets[i] = mode_cmd->offsets[i]; |
fb->modifier[i] = mode_cmd->modifier[i]; |
} |
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
&fb->bits_per_pixel); |
852,12 → 860,12 |
{ |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
struct drm_crtc_helper_funcs *crtc_funcs; |
const struct drm_crtc_helper_funcs *crtc_funcs; |
int encoder_dpms; |
bool ret; |
|
drm_modeset_lock_all(dev); |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
drm_for_each_crtc(crtc, dev) { |
|
if (!crtc->enabled) |
continue; |
871,7 → 879,7 |
|
/* Turn off outputs that were already powered off */ |
if (drm_helper_choose_crtc_dpms(crtc)) { |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
drm_for_each_encoder(encoder, dev) { |
|
if(encoder->crtc != crtc) |
continue; |
917,46 → 925,49 |
struct drm_framebuffer *old_fb) |
{ |
struct drm_crtc_state *crtc_state; |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
int ret; |
|
if (crtc->funcs->atomic_duplicate_state) |
crtc_state = crtc->funcs->atomic_duplicate_state(crtc); |
else if (crtc->state) |
crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), |
GFP_KERNEL); |
else |
crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); |
else { |
if (!crtc->state) |
drm_atomic_helper_crtc_reset(crtc); |
|
crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc); |
} |
|
if (!crtc_state) |
return -ENOMEM; |
|
crtc_state->enable = true; |
crtc_state->planes_changed = true; |
crtc_state->mode_changed = true; |
drm_mode_copy(&crtc_state->mode, mode); |
ret = drm_atomic_set_mode_for_crtc(crtc_state, mode); |
if (ret) |
goto out; |
drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode); |
|
if (crtc_funcs->atomic_check) { |
ret = crtc_funcs->atomic_check(crtc, crtc_state); |
if (ret) { |
kfree(crtc_state); |
|
return ret; |
if (ret) |
goto out; |
} |
} |
|
swap(crtc->state, crtc_state); |
|
crtc_funcs->mode_set_nofb(crtc); |
|
ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); |
|
out: |
if (crtc_state) { |
if (crtc->funcs->atomic_destroy_state) |
crtc->funcs->atomic_destroy_state(crtc, crtc_state); |
else |
kfree(crtc_state); |
drm_atomic_helper_crtc_destroy_state(crtc, crtc_state); |
} |
|
return drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); |
return ret; |
} |
EXPORT_SYMBOL(drm_helper_crtc_mode_set); |
|
988,6 → 999,7 |
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); |
if (!plane_state) |
return -ENOMEM; |
plane_state->plane = plane; |
|
plane_state->crtc = crtc; |
drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); |