diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
| -rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 638 |
1 files changed, 500 insertions, 138 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index d820423fac32..67e095e398a3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -26,20 +26,23 @@ * Daniel Vetter <daniel.vetter@ffwll.ch> */ - +#include <linux/export.h> #include <linux/sync_file.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_mode.h> #include <drm/drm_print.h> #include <drm/drm_writeback.h> +#include <drm/drm_colorop.h> #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -61,7 +64,6 @@ EXPORT_SYMBOL(__drm_crtc_commit_free); * hardware and flipped to. * * Returns: - * * 0 on success, a negative error code otherwise. */ int drm_crtc_commit_wait(struct drm_crtc_commit *commit) @@ -74,7 +76,7 @@ int drm_crtc_commit_wait(struct drm_crtc_commit *commit) ret = wait_for_completion_timeout(&commit->hw_done, timeout); if (!ret) { - DRM_ERROR("hw_done timed out\n"); + drm_err(commit->crtc->dev, "hw_done timed out\n"); return -ETIMEDOUT; } @@ -84,7 +86,7 @@ int drm_crtc_commit_wait(struct drm_crtc_commit *commit) */ ret = wait_for_completion_timeout(&commit->flip_done, timeout); if (!ret) { - DRM_ERROR("flip_done timed out\n"); + drm_err(commit->crtc->dev, "flip_done timed out\n"); return -ETIMEDOUT; } @@ -106,6 +108,7 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state) kfree(state->connectors); kfree(state->crtcs); kfree(state->planes); + kfree(state->colorops); kfree(state->private_objs); } EXPORT_SYMBOL(drm_atomic_state_default_release); @@ -137,10 +140,20 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) sizeof(*state->planes), GFP_KERNEL); if (!state->planes) goto fail; + state->colorops = kcalloc(dev->mode_config.num_colorop, + sizeof(*state->colorops), GFP_KERNEL); + if (!state->colorops) + goto fail; + /* + * Because drm_atomic_state can be committed asynchronously we need our + * own reference and cannot rely on the on implied by drm_file in the + * ioctl call. + */ + drm_dev_get(dev); state->dev = dev; - DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state); + drm_dbg_atomic(dev, "Allocated atomic state %p\n", state); return 0; fail: @@ -191,7 +204,9 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) struct drm_mode_config *config = &dev->mode_config; int i; - DRM_DEBUG_ATOMIC("Clearing atomic state %p\n", state); + drm_dbg_atomic(dev, "Clearing atomic state %p\n", state); + + state->checked = false; for (i = 0; i < state->num_connector; i++) { struct drm_connector *connector = state->connectors[i].ptr; @@ -200,9 +215,9 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) continue; connector->funcs->atomic_destroy_state(connector, - state->connectors[i].state); + state->connectors[i].state_to_destroy); state->connectors[i].ptr = NULL; - state->connectors[i].state = NULL; + state->connectors[i].state_to_destroy = NULL; state->connectors[i].old_state = NULL; state->connectors[i].new_state = NULL; drm_connector_put(connector); @@ -215,10 +230,10 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) continue; crtc->funcs->atomic_destroy_state(crtc, - state->crtcs[i].state); + state->crtcs[i].state_to_destroy); state->crtcs[i].ptr = NULL; - state->crtcs[i].state = NULL; + state->crtcs[i].state_to_destroy = NULL; state->crtcs[i].old_state = NULL; state->crtcs[i].new_state = NULL; @@ -235,20 +250,34 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) continue; plane->funcs->atomic_destroy_state(plane, - state->planes[i].state); + state->planes[i].state_to_destroy); state->planes[i].ptr = NULL; - state->planes[i].state = NULL; + state->planes[i].state_to_destroy = NULL; state->planes[i].old_state = NULL; state->planes[i].new_state = NULL; } + for (i = 0; i < config->num_colorop; i++) { + struct drm_colorop *colorop = state->colorops[i].ptr; + + if (!colorop) + continue; + + drm_colorop_atomic_destroy_state(colorop, + state->colorops[i].state); + state->colorops[i].ptr = NULL; + state->colorops[i].state = NULL; + state->colorops[i].old_state = NULL; + state->colorops[i].new_state = NULL; + } + for (i = 0; i < state->num_private_objs; i++) { struct drm_private_obj *obj = state->private_objs[i].ptr; obj->funcs->atomic_destroy_state(obj, - state->private_objs[i].state); + state->private_objs[i].state_to_destroy); state->private_objs[i].ptr = NULL; - state->private_objs[i].state = NULL; + state->private_objs[i].state_to_destroy = NULL; state->private_objs[i].old_state = NULL; state->private_objs[i].new_state = NULL; } @@ -297,11 +326,12 @@ EXPORT_SYMBOL(drm_atomic_state_clear); void __drm_atomic_state_free(struct kref *ref) { struct drm_atomic_state *state = container_of(ref, typeof(*state), ref); - struct drm_mode_config *config = &state->dev->mode_config; + struct drm_device *dev = state->dev; + struct drm_mode_config *config = &dev->mode_config; drm_atomic_state_clear(state); - DRM_DEBUG_ATOMIC("Freeing atomic state %p\n", state); + drm_dbg_atomic(state->dev, "Freeing atomic state %p\n", state); if (config->funcs->atomic_state_free) { config->funcs->atomic_state_free(state); @@ -309,6 +339,8 @@ void __drm_atomic_state_free(struct kref *ref) drm_atomic_state_default_release(state); kfree(state); } + + drm_dev_put(dev); } EXPORT_SYMBOL(__drm_atomic_state_free); @@ -326,7 +358,6 @@ EXPORT_SYMBOL(__drm_atomic_state_free); * not created by userspace through an IOCTL call. * * Returns: - * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. @@ -339,8 +370,9 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, struct drm_crtc_state *crtc_state; WARN_ON(!state->acquire_ctx); + drm_WARN_ON(state->dev, state->checked); - crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); if (crtc_state) return crtc_state; @@ -352,14 +384,14 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, if (!crtc_state) return ERR_PTR(-ENOMEM); - state->crtcs[index].state = crtc_state; + state->crtcs[index].state_to_destroy = crtc_state; state->crtcs[index].old_state = crtc->state; state->crtcs[index].new_state = crtc_state; state->crtcs[index].ptr = crtc; crtc_state->state = state; - DRM_DEBUG_ATOMIC("Added [CRTC:%d:%s] %p state to %p\n", - crtc->base.id, crtc->name, crtc_state, state); + drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n", + crtc->base.id, crtc->name, crtc_state, state); return crtc_state; } @@ -379,8 +411,9 @@ static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, */ if (new_crtc_state->active && !new_crtc_state->enable) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] active without enabled\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(crtc->dev, + "[CRTC:%d:%s] active without enabled\n", + crtc->base.id, crtc->name); return -EINVAL; } @@ -390,15 +423,17 @@ static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, */ if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) && WARN_ON(new_crtc_state->enable && !new_crtc_state->mode_blob)) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] enabled without mode blob\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(crtc->dev, + "[CRTC:%d:%s] enabled without mode blob\n", + crtc->base.id, crtc->name); return -EINVAL; } if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) && WARN_ON(!new_crtc_state->enable && new_crtc_state->mode_blob)) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] disabled with mode blob\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(crtc->dev, + "[CRTC:%d:%s] disabled with mode blob\n", + crtc->base.id, crtc->name); return -EINVAL; } @@ -414,8 +449,9 @@ static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, */ if (new_crtc_state->event && !new_crtc_state->active && !old_crtc_state->active) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(crtc->dev, + "[CRTC:%d:%s] requesting event but off\n", + crtc->base.id, crtc->name); return -EINVAL; } @@ -460,26 +496,29 @@ static int drm_atomic_connector_check(struct drm_connector *connector, return 0; if (writeback_job->fb && !state->crtc) { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] framebuffer without CRTC\n", - connector->base.id, connector->name); + drm_dbg_atomic(connector->dev, + "[CONNECTOR:%d:%s] framebuffer without CRTC\n", + connector->base.id, connector->name); return -EINVAL; } if (state->crtc) - crtc_state = drm_atomic_get_existing_crtc_state(state->state, - state->crtc); + crtc_state = drm_atomic_get_new_crtc_state(state->state, + state->crtc); if (writeback_job->fb && !crtc_state->active) { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] has framebuffer, but [CRTC:%d] is off\n", - connector->base.id, connector->name, - state->crtc->base.id); + drm_dbg_atomic(connector->dev, + "[CONNECTOR:%d:%s] has framebuffer, but [CRTC:%d] is off\n", + connector->base.id, connector->name, + state->crtc->base.id); return -EINVAL; } if (!writeback_job->fb) { if (writeback_job->out_fence) { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n", - connector->base.id, connector->name); + drm_dbg_atomic(connector->dev, + "[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n", + connector->base.id, connector->name); return -EINVAL; } @@ -500,7 +539,6 @@ static int drm_atomic_connector_check(struct drm_connector *connector, * is consistent. * * Returns: - * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. @@ -513,13 +551,14 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane_state *plane_state; WARN_ON(!state->acquire_ctx); + drm_WARN_ON(state->dev, state->checked); /* the legacy pointers should never be set */ WARN_ON(plane->fb); WARN_ON(plane->old_fb); WARN_ON(plane->crtc); - plane_state = drm_atomic_get_existing_plane_state(state, plane); + plane_state = drm_atomic_get_new_plane_state(state, plane); if (plane_state) return plane_state; @@ -531,14 +570,14 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, if (!plane_state) return ERR_PTR(-ENOMEM); - state->planes[index].state = plane_state; + state->planes[index].state_to_destroy = plane_state; state->planes[index].ptr = plane; state->planes[index].old_state = plane->state; state->planes[index].new_state = plane_state; plane_state->state = state; - DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n", - plane->base.id, plane->name, plane_state, state); + drm_dbg_atomic(plane->dev, "Added [PLANE:%d:%s] %p state to %p\n", + plane->base.id, plane->name, plane_state, state); if (plane_state->crtc) { struct drm_crtc_state *crtc_state; @@ -553,6 +592,55 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_plane_state); +/** + * drm_atomic_get_colorop_state - get colorop state + * @state: global atomic state object + * @colorop: colorop to get state object for + * + * This function returns the colorop state for the given colorop, allocating it + * if needed. It will also grab the relevant plane lock to make sure that the + * state is consistent. + * + * Returns: + * + * Either the allocated state or the error code encoded into the pointer. When + * the error is EDEADLK then the w/w mutex code has detected a deadlock and the + * entire atomic sequence must be restarted. All other errors are fatal. + */ +struct drm_colorop_state * +drm_atomic_get_colorop_state(struct drm_atomic_state *state, + struct drm_colorop *colorop) +{ + int ret, index = drm_colorop_index(colorop); + struct drm_colorop_state *colorop_state; + + WARN_ON(!state->acquire_ctx); + + colorop_state = drm_atomic_get_new_colorop_state(state, colorop); + if (colorop_state) + return colorop_state; + + ret = drm_modeset_lock(&colorop->plane->mutex, state->acquire_ctx); + if (ret) + return ERR_PTR(ret); + + colorop_state = drm_atomic_helper_colorop_duplicate_state(colorop); + if (!colorop_state) + return ERR_PTR(-ENOMEM); + + state->colorops[index].state = colorop_state; + state->colorops[index].ptr = colorop; + state->colorops[index].old_state = colorop->state; + state->colorops[index].new_state = colorop_state; + colorop_state->state = state; + + drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d:%d] %p state to %p\n", + colorop->base.id, colorop->type, colorop_state, state); + + return colorop_state; +} +EXPORT_SYMBOL(drm_atomic_get_colorop_state); + static bool plane_switching_crtc(const struct drm_plane_state *old_plane_state, const struct drm_plane_state *new_plane_state) @@ -590,16 +678,15 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, unsigned int fb_width, fb_height; struct drm_mode_rect *clips; uint32_t num_clips; - int ret; /* either *both* CRTC and FB must be set, or neither */ if (crtc && !fb) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] CRTC set but no FB\n", - plane->base.id, plane->name); + drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] CRTC set but no FB\n", + plane->base.id, plane->name); return -EINVAL; } else if (fb && !crtc) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] FB set but no CRTC\n", - plane->base.id, plane->name); + drm_dbg_atomic(plane->dev, "[PLANE:%d:%s] FB set but no CRTC\n", + plane->base.id, plane->name); return -EINVAL; } @@ -609,20 +696,20 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, /* Check whether this plane is usable on this CRTC */ if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { - DRM_DEBUG_ATOMIC("Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n", - crtc->base.id, crtc->name, - plane->base.id, plane->name); + drm_dbg_atomic(plane->dev, + "Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n", + crtc->base.id, crtc->name, + plane->base.id, plane->name); return -EINVAL; } /* Check whether this plane supports the fb pixel format. */ - ret = drm_plane_check_pixel_format(plane, fb->format->format, - fb->modifier); - if (ret) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %p4cc, modifier 0x%llx\n", - plane->base.id, plane->name, - &fb->format->format, fb->modifier); - return ret; + if (!drm_plane_has_format(plane, fb->format->format, fb->modifier)) { + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid pixel format %p4cc, modifier 0x%llx\n", + plane->base.id, plane->name, + &fb->format->format, fb->modifier); + return -EINVAL; } /* Give drivers some help against integer overflows */ @@ -630,10 +717,11 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w || new_plane_state->crtc_h > INT_MAX || new_plane_state->crtc_y > INT_MAX - (int32_t) new_plane_state->crtc_h) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n", - plane->base.id, plane->name, - new_plane_state->crtc_w, new_plane_state->crtc_h, - new_plane_state->crtc_x, new_plane_state->crtc_y); + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n", + plane->base.id, plane->name, + new_plane_state->crtc_w, new_plane_state->crtc_h, + new_plane_state->crtc_x, new_plane_state->crtc_y); return -ERANGE; } @@ -645,22 +733,23 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, new_plane_state->src_x > fb_width - new_plane_state->src_w || new_plane_state->src_h > fb_height || new_plane_state->src_y > fb_height - new_plane_state->src_h) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid source coordinates " - "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", - plane->base.id, plane->name, - new_plane_state->src_w >> 16, - ((new_plane_state->src_w & 0xffff) * 15625) >> 10, - new_plane_state->src_h >> 16, - ((new_plane_state->src_h & 0xffff) * 15625) >> 10, - new_plane_state->src_x >> 16, - ((new_plane_state->src_x & 0xffff) * 15625) >> 10, - new_plane_state->src_y >> 16, - ((new_plane_state->src_y & 0xffff) * 15625) >> 10, - fb->width, fb->height); + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid source coordinates " + "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", + plane->base.id, plane->name, + new_plane_state->src_w >> 16, + ((new_plane_state->src_w & 0xffff) * 15625) >> 10, + new_plane_state->src_h >> 16, + ((new_plane_state->src_h & 0xffff) * 15625) >> 10, + new_plane_state->src_x >> 16, + ((new_plane_state->src_x & 0xffff) * 15625) >> 10, + new_plane_state->src_y >> 16, + ((new_plane_state->src_y & 0xffff) * 15625) >> 10, + fb->width, fb->height); return -ENOSPC; } - clips = drm_plane_get_damage_clips(new_plane_state); + clips = __drm_plane_get_damage_clips(new_plane_state); num_clips = drm_plane_get_damage_clips_count(new_plane_state); /* Make sure damage clips are valid and inside the fb. */ @@ -671,9 +760,10 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, clips->y1 < 0 || clips->x2 > fb_width || clips->y2 > fb_height) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid damage clip %d %d %d %d\n", - plane->base.id, plane->name, clips->x1, - clips->y1, clips->x2, clips->y2); + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] invalid damage clip %d %d %d %d\n", + plane->base.id, plane->name, clips->x1, + clips->y1, clips->x2, clips->y2); return -EINVAL; } clips++; @@ -681,14 +771,55 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, } if (plane_switching_crtc(old_plane_state, new_plane_state)) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] switching CRTC directly\n", - plane->base.id, plane->name); + drm_dbg_atomic(plane->dev, + "[PLANE:%d:%s] switching CRTC directly\n", + plane->base.id, plane->name); return -EINVAL; } return 0; } +static void drm_atomic_colorop_print_state(struct drm_printer *p, + const struct drm_colorop_state *state) +{ + struct drm_colorop *colorop = state->colorop; + + drm_printf(p, "colorop[%u]:\n", colorop->base.id); + drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type)); + if (colorop->bypass_property) + drm_printf(p, "\tbypass=%u\n", state->bypass); + + switch (colorop->type) { + case DRM_COLOROP_1D_CURVE: + drm_printf(p, "\tcurve_1d_type=%s\n", + drm_get_colorop_curve_1d_type_name(state->curve_1d_type)); + break; + case DRM_COLOROP_1D_LUT: + drm_printf(p, "\tsize=%d\n", colorop->size); + drm_printf(p, "\tinterpolation=%s\n", + drm_get_colorop_lut1d_interpolation_name(colorop->lut1d_interpolation)); + drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0); + break; + case DRM_COLOROP_CTM_3X4: + drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0); + break; + case DRM_COLOROP_MULTIPLIER: + drm_printf(p, "\tmultiplier=%llu\n", state->multiplier); + break; + case DRM_COLOROP_3D_LUT: + drm_printf(p, "\tsize=%d\n", colorop->size); + drm_printf(p, "\tinterpolation=%s\n", + drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation)); + drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0); + break; + default: + break; + } + + drm_printf(p, "\tnext=%d\n", colorop->next ? colorop->next->base.id : 0); +} + static void drm_atomic_plane_print_state(struct drm_printer *p, const struct drm_plane_state *state) { @@ -709,7 +840,9 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, drm_get_color_encoding_name(state->color_encoding)); drm_printf(p, "\tcolor-range=%s\n", drm_get_color_range_name(state->color_range)); - + drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); + drm_printf(p, "\tcolor-pipeline=%d\n", + state->color_pipeline ? state->color_pipeline->base.id : 0); if (plane->funcs->atomic_print_state) plane->funcs->atomic_print_state(p, state); } @@ -723,7 +856,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * clocks, scaler units, bandwidth and fifo limits shared among a group of * planes or CRTCs, and so on) it makes sense to model these as independent * objects. Drivers then need to do similar state tracking and commit ordering for - * such private (since not exposed to userpace) objects as the atomic core and + * such private (since not exposed to userspace) objects as the atomic core and * helpers already provide for connectors, planes and CRTCs. * * To make this easier on drivers the atomic core provides some support to track @@ -776,6 +909,8 @@ drm_atomic_private_obj_init(struct drm_device *dev, obj->state = state; obj->funcs = funcs; list_add_tail(&obj->head, &dev->mode_config.privobj_list); + + state->obj = obj; } EXPORT_SYMBOL(drm_atomic_private_obj_init); @@ -804,21 +939,23 @@ EXPORT_SYMBOL(drm_atomic_private_obj_fini); * object lock to make sure that the state is consistent. * * RETURNS: - * * Either the allocated state or the error code encoded into a pointer. */ struct drm_private_state * drm_atomic_get_private_obj_state(struct drm_atomic_state *state, struct drm_private_obj *obj) { - int index, num_objs, i, ret; + int index, num_objs, ret; size_t size; struct __drm_private_objs_state *arr; struct drm_private_state *obj_state; - for (i = 0; i < state->num_private_objs; i++) - if (obj == state->private_objs[i].ptr) - return state->private_objs[i].state; + WARN_ON(!state->acquire_ctx); + drm_WARN_ON(state->dev, state->checked); + + obj_state = drm_atomic_get_new_private_obj_state(state, obj); + if (obj_state) + return obj_state; ret = drm_modeset_lock(&obj->lock, state->acquire_ctx); if (ret) @@ -838,7 +975,7 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, if (!obj_state) return ERR_PTR(-ENOMEM); - state->private_objs[index].state = obj_state; + state->private_objs[index].state_to_destroy = obj_state; state->private_objs[index].old_state = obj->state; state->private_objs[index].new_state = obj_state; state->private_objs[index].ptr = obj; @@ -846,8 +983,9 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, state->num_private_objs = num_objs; - DRM_DEBUG_ATOMIC("Added new private object %p state %p to %p\n", - obj, obj_state, state); + drm_dbg_atomic(state->dev, + "Added new private object %p state %p to %p\n", + obj, obj_state, state); return obj_state; } @@ -862,7 +1000,7 @@ EXPORT_SYMBOL(drm_atomic_get_private_obj_state); * or NULL if the private_obj is not part of the global atomic state. */ struct drm_private_state * -drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj) { int i; @@ -884,7 +1022,7 @@ EXPORT_SYMBOL(drm_atomic_get_old_private_obj_state); * or NULL if the private_obj is not part of the global atomic state. */ struct drm_private_state * -drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj) { int i; @@ -912,11 +1050,14 @@ EXPORT_SYMBOL(drm_atomic_get_new_private_obj_state); * state). This is especially true in enable hooks because the pipeline has * changed. * + * If you don't have access to the atomic state, see + * drm_atomic_get_connector_for_encoder(). + * * Returns: The old connector connected to @encoder, or NULL if the encoder is * not connected. */ struct drm_connector * -drm_atomic_get_old_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_connector_state *conn_state; @@ -946,11 +1087,14 @@ EXPORT_SYMBOL(drm_atomic_get_old_connector_for_encoder); * attached to @encoder vs ones that do (and to inspect their state). This is * especially true in disable hooks because the pipeline will change. * + * If you don't have access to the atomic state, see + * drm_atomic_get_connector_for_encoder(). + * * Returns: The new connector connected to @encoder, or NULL if the encoder is * not connected. */ struct drm_connector * -drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_connector_state *conn_state; @@ -967,6 +1111,119 @@ drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder); /** + * drm_atomic_get_connector_for_encoder - Get connector currently assigned to an encoder + * @encoder: The encoder to find the connector of + * @ctx: Modeset locking context + * + * This function finds and returns the connector currently assigned to + * an @encoder. + * + * It is similar to the drm_atomic_get_old_connector_for_encoder() and + * drm_atomic_get_new_connector_for_encoder() helpers, but doesn't + * require access to the atomic state. If you have access to it, prefer + * using these. This helper is typically useful in situations where you + * don't have access to the atomic state, like detect, link repair, + * threaded interrupt handlers, or hooks from other frameworks (ALSA, + * CEC, etc.). + * + * Returns: + * The connector connected to @encoder, or an error pointer otherwise. + * When the error is EDEADLK, a deadlock has been detected and the + * sequence must be restarted. + */ +struct drm_connector * +drm_atomic_get_connector_for_encoder(const struct drm_encoder *encoder, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_connector_list_iter conn_iter; + struct drm_connector *out_connector = ERR_PTR(-EINVAL); + struct drm_connector *connector; + struct drm_device *dev = encoder->dev; + int ret; + + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); + if (ret) + return ERR_PTR(ret); + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (!connector->state) + continue; + + if (encoder == connector->state->best_encoder) { + out_connector = connector; + break; + } + } + drm_connector_list_iter_end(&conn_iter); + drm_modeset_unlock(&dev->mode_config.connection_mutex); + + return out_connector; +} +EXPORT_SYMBOL(drm_atomic_get_connector_for_encoder); + + +/** + * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder + * @state: Atomic state + * @encoder: The encoder to fetch the crtc state for + * + * This function finds and returns the crtc that was connected to @encoder + * as specified by the @state. + * + * Returns: The old crtc connected to @encoder, or NULL if the encoder is + * not connected. + */ +struct drm_crtc * +drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state, + struct drm_encoder *encoder) +{ + struct drm_connector *connector; + struct drm_connector_state *conn_state; + + connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + if (!connector) + return NULL; + + conn_state = drm_atomic_get_old_connector_state(state, connector); + if (!conn_state) + return NULL; + + return conn_state->crtc; +} +EXPORT_SYMBOL(drm_atomic_get_old_crtc_for_encoder); + +/** + * drm_atomic_get_new_crtc_for_encoder - Get new crtc for an encoder + * @state: Atomic state + * @encoder: The encoder to fetch the crtc state for + * + * This function finds and returns the crtc that will be connected to @encoder + * as specified by the @state. + * + * Returns: The new crtc connected to @encoder, or NULL if the encoder is + * not connected. + */ +struct drm_crtc * +drm_atomic_get_new_crtc_for_encoder(struct drm_atomic_state *state, + struct drm_encoder *encoder) +{ + struct drm_connector *connector; + struct drm_connector_state *conn_state; + + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); + if (!connector) + return NULL; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + return conn_state->crtc; +} +EXPORT_SYMBOL(drm_atomic_get_new_crtc_for_encoder); + +/** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object * @connector: connector to get state object for @@ -976,7 +1233,6 @@ EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder); * make sure that the state is consistent. * * Returns: - * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. @@ -990,6 +1246,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector_state *connector_state; WARN_ON(!state->acquire_ctx); + drm_WARN_ON(state->dev, state->checked); ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx); if (ret) @@ -1013,21 +1270,22 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, state->num_connector = alloc; } - if (state->connectors[index].state) - return state->connectors[index].state; + connector_state = drm_atomic_get_new_connector_state(state, connector); + if (connector_state) + return connector_state; connector_state = connector->funcs->atomic_duplicate_state(connector); if (!connector_state) return ERR_PTR(-ENOMEM); drm_connector_get(connector); - state->connectors[index].state = connector_state; + state->connectors[index].state_to_destroy = connector_state; state->connectors[index].old_state = connector->state; state->connectors[index].new_state = connector_state; state->connectors[index].ptr = connector; connector_state->state = state; - DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d:%s] %p state to %p\n", + drm_dbg_atomic(connector->dev, "Added [CONNECTOR:%d:%s] %p state to %p\n", connector->base.id, connector->name, connector_state, state); @@ -1052,6 +1310,21 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name); drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware); + drm_printf(p, "\tinterlace_allowed=%d\n", connector->interlace_allowed); + drm_printf(p, "\tycbcr_420_allowed=%d\n", connector->ycbcr_420_allowed); + drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc); + drm_printf(p, "\tcolorspace=%s\n", drm_get_colorspace_name(state->colorspace)); + + if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || + connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) { + drm_printf(p, "\tbroadcast_rgb=%s\n", + drm_hdmi_connector_get_broadcast_rgb_name(state->hdmi.broadcast_rgb)); + drm_printf(p, "\tis_limited_range=%c\n", state->hdmi.is_limited_range ? 'y' : 'n'); + drm_printf(p, "\toutput_bpc=%u\n", state->hdmi.output_bpc); + drm_printf(p, "\toutput_format=%s\n", + drm_hdmi_connector_get_output_format_name(state->hdmi.output_format)); + drm_printf(p, "\ttmds_char_rate=%llu\n", state->hdmi.tmds_char_rate); + } if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) if (state->writeback_job && state->writeback_job->fb) @@ -1071,7 +1344,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, * state is consistent. * * Returns: - * * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. @@ -1099,7 +1371,7 @@ EXPORT_SYMBOL(drm_atomic_get_bridge_state); * the bridge is not part of the global atomic state. */ struct drm_bridge_state * -drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge) { struct drm_private_state *obj_state; @@ -1121,7 +1393,7 @@ EXPORT_SYMBOL(drm_atomic_get_old_bridge_state); * the bridge is not part of the global atomic state. */ struct drm_bridge_state * -drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge) { struct drm_private_state *obj_state; @@ -1155,15 +1427,15 @@ drm_atomic_add_encoder_bridges(struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_bridge_state *bridge_state; - struct drm_bridge *bridge; if (!encoder) return 0; - DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n", - encoder->base.id, encoder->name, state); + drm_dbg_atomic(encoder->dev, + "Adding all bridges for [encoder:%d:%s] to %p\n", + encoder->base.id, encoder->name, state); - drm_for_each_bridge_in_chain(encoder, bridge) { + drm_for_each_bridge_in_chain_scoped(encoder, bridge) { /* Skip bridges that don't implement the atomic state hooks. */ if (!bridge->funcs->atomic_duplicate_state) continue; @@ -1213,8 +1485,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state, if (ret) return ret; - DRM_DEBUG_ATOMIC("Adding all current connectors for [CRTC:%d:%s] to %p\n", - crtc->base.id, crtc->name, state); + drm_dbg_atomic(crtc->dev, + "Adding all current connectors for [CRTC:%d:%s] to %p\n", + crtc->base.id, crtc->name, state); /* * Changed connectors are already in @state, so only need to look @@ -1267,8 +1540,9 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state, WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); - DRM_DEBUG_ATOMIC("Adding all current planes for [CRTC:%d:%s] to %p\n", - crtc->base.id, crtc->name, state); + drm_dbg_atomic(crtc->dev, + "Adding all current planes for [CRTC:%d:%s] to %p\n", + crtc->base.id, crtc->name, state); drm_for_each_plane_mask(plane, state->dev, old_crtc_state->plane_mask) { struct drm_plane_state *plane_state = @@ -1282,6 +1556,52 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state, EXPORT_SYMBOL(drm_atomic_add_affected_planes); /** + * drm_atomic_add_affected_colorops - add colorops for plane + * @state: atomic state + * @plane: DRM plane + * + * This function walks the current configuration and adds all colorops + * currently used by @plane to the atomic configuration @state. This is useful + * when an atomic commit also needs to check all currently enabled colorop on + * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane + * to avoid special code to force-enable all colorops. + * + * Since acquiring a colorop state will always also acquire the w/w mutex of the + * current plane for that colorop (if there is any) adding all the colorop states for + * a plane will not reduce parallelism of atomic updates. + * + * Returns: + * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK + * then the w/w mutex code has detected a deadlock and the entire atomic + * sequence must be restarted. All other errors are fatal. + */ +int +drm_atomic_add_affected_colorops(struct drm_atomic_state *state, + struct drm_plane *plane) +{ + struct drm_colorop *colorop; + struct drm_colorop_state *colorop_state; + + WARN_ON(!drm_atomic_get_new_plane_state(state, plane)); + + drm_dbg_atomic(plane->dev, + "Adding all current colorops for [PLANE:%d:%s] to %p\n", + plane->base.id, plane->name, state); + + drm_for_each_colorop(colorop, plane->dev) { + if (colorop->plane != plane) + continue; + + colorop_state = drm_atomic_get_colorop_state(state, colorop); + if (IS_ERR(colorop_state)) + return PTR_ERR(colorop_state); + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_add_affected_colorops); + +/** * drm_atomic_check_only - check whether a given config would work * @state: atomic configuration to check * @@ -1308,16 +1628,18 @@ int drm_atomic_check_only(struct drm_atomic_state *state) unsigned int affected_crtc = 0; int i, ret = 0; - DRM_DEBUG_ATOMIC("checking %p\n", state); + drm_dbg_atomic(dev, "checking %p\n", state); - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) - requested_crtc |= drm_crtc_mask(crtc); + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->enable) + requested_crtc |= drm_crtc_mask(crtc); + } for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { ret = drm_atomic_plane_check(old_plane_state, new_plane_state); if (ret) { - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n", - plane->base.id, plane->name); + drm_dbg_atomic(dev, "[PLANE:%d:%s] atomic core check failed\n", + plane->base.id, plane->name); return ret; } } @@ -1325,8 +1647,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state) for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { ret = drm_atomic_crtc_check(old_crtc_state, new_crtc_state); if (ret) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(dev, "[CRTC:%d:%s] atomic core check failed\n", + crtc->base.id, crtc->name); return ret; } } @@ -1334,8 +1656,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state) for_each_new_connector_in_state(state, conn, conn_state, i) { ret = drm_atomic_connector_check(conn, conn_state); if (ret) { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] atomic core check failed\n", - conn->base.id, conn->name); + drm_dbg_atomic(dev, "[CONNECTOR:%d:%s] atomic core check failed\n", + conn->base.id, conn->name); return ret; } } @@ -1344,8 +1666,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state) ret = config->funcs->atomic_check(state->dev, state); if (ret) { - DRM_DEBUG_ATOMIC("atomic driver check for %p failed: %d\n", - state, ret); + drm_dbg_atomic(dev, "atomic driver check for %p failed: %d\n", + state, ret); return ret; } } @@ -1353,15 +1675,17 @@ int drm_atomic_check_only(struct drm_atomic_state *state) if (!state->allow_modeset) { for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { - DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n", - crtc->base.id, crtc->name); + drm_dbg_atomic(dev, "[CRTC:%d:%s] requires full modeset\n", + crtc->base.id, crtc->name); return -EINVAL; } } } - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) - affected_crtc |= drm_crtc_mask(crtc); + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + if (new_crtc_state->enable) + affected_crtc |= drm_crtc_mask(crtc); + } /* * For commits that allow modesets drivers can add other CRTCs to the @@ -1374,12 +1698,15 @@ int drm_atomic_check_only(struct drm_atomic_state *state) * so compositors know what's going on. */ if (affected_crtc != requested_crtc) { - DRM_DEBUG_ATOMIC("driver added CRTC to commit: requested 0x%x, affected 0x%0x\n", - requested_crtc, affected_crtc); + drm_dbg_atomic(dev, + "driver added CRTC to commit: requested 0x%x, affected 0x%0x\n", + requested_crtc, affected_crtc); WARN(!state->allow_modeset, "adding CRTC not allowed without modesets: requested 0x%x, affected 0x%0x\n", requested_crtc, affected_crtc); } + state->checked = true; + return 0; } EXPORT_SYMBOL(drm_atomic_check_only); @@ -1401,13 +1728,17 @@ EXPORT_SYMBOL(drm_atomic_check_only); int drm_atomic_commit(struct drm_atomic_state *state) { struct drm_mode_config *config = &state->dev->mode_config; + struct drm_printer p = drm_info_printer(state->dev->dev); int ret; + if (drm_debug_enabled(DRM_UT_STATE)) + drm_atomic_print_new_state(state, &p); + ret = drm_atomic_check_only(state); if (ret) return ret; - DRM_DEBUG_ATOMIC("committing %p\n", state); + drm_dbg_atomic(state->dev, "committing %p\n", state); return config->funcs->atomic_commit(state->dev, state, false); } @@ -1436,7 +1767,7 @@ int drm_atomic_nonblocking_commit(struct drm_atomic_state *state) if (ret) return ret; - DRM_DEBUG_ATOMIC("committing %p nonblocking\n", state); + drm_dbg_atomic(state->dev, "committing %p nonblocking\n", state); return config->funcs->atomic_commit(state->dev, state, true); } @@ -1610,6 +1941,15 @@ commit: } EXPORT_SYMBOL(__drm_atomic_helper_set_config); +static void drm_atomic_private_obj_print_state(struct drm_printer *p, + const struct drm_private_state *state) +{ + struct drm_private_obj *obj = state->obj; + + if (obj->funcs->atomic_print_state) + obj->funcs->atomic_print_state(p, state); +} + /** * drm_atomic_print_new_state - prints drm atomic state * @state: atomic configuration to check @@ -1630,14 +1970,16 @@ void drm_atomic_print_new_state(const struct drm_atomic_state *state, struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *connector_state; + struct drm_private_obj *obj; + struct drm_private_state *obj_state; int i; if (!p) { - DRM_ERROR("invalid drm printer\n"); + drm_err(state->dev, "invalid drm printer\n"); return; } - DRM_DEBUG_ATOMIC("checking %p\n", state); + drm_dbg_atomic(state->dev, "checking %p\n", state); for_each_new_plane_in_state(state, plane, plane_state, i) drm_atomic_plane_print_state(p, plane_state); @@ -1647,6 +1989,9 @@ void drm_atomic_print_new_state(const struct drm_atomic_state *state, for_each_new_connector_in_state(state, connector, connector_state, i) drm_atomic_connector_print_state(p, connector_state); + + for_each_new_private_obj_in_state(state, obj, obj_state, i) + drm_atomic_private_obj_print_state(p, obj_state); } EXPORT_SYMBOL(drm_atomic_print_new_state); @@ -1654,14 +1999,24 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p, bool take_locks) { struct drm_mode_config *config = &dev->mode_config; + struct drm_colorop *colorop; struct drm_plane *plane; struct drm_crtc *crtc; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; + struct drm_private_obj *obj; if (!drm_drv_uses_atomic_modeset(dev)) return; + list_for_each_entry(colorop, &config->colorop_list, head) { + if (take_locks) + drm_modeset_lock(&colorop->plane->mutex, NULL); + drm_atomic_colorop_print_state(p, colorop->state); + if (take_locks) + drm_modeset_unlock(&colorop->plane->mutex); + } + list_for_each_entry(plane, &config->plane_list, head) { if (take_locks) drm_modeset_lock(&plane->mutex, NULL); @@ -1686,6 +2041,14 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p, if (take_locks) drm_modeset_unlock(&dev->mode_config.connection_mutex); drm_connector_list_iter_end(&conn_iter); + + list_for_each_entry(obj, &config->privobj_list, head) { + if (take_locks) + drm_modeset_lock(&obj->lock, NULL); + drm_atomic_private_obj_print_state(p, obj->state); + if (take_locks) + drm_modeset_unlock(&obj->lock); + } } /** @@ -1712,8 +2075,8 @@ EXPORT_SYMBOL(drm_state_dump); #ifdef CONFIG_DEBUG_FS static int drm_state_info(struct seq_file *m, void *data) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; + struct drm_debugfs_entry *entry = m->private; + struct drm_device *dev = entry->dev; struct drm_printer p = drm_seq_file_printer(m); __drm_state_dump(dev, &p, true); @@ -1722,14 +2085,13 @@ static int drm_state_info(struct seq_file *m, void *data) } /* any use in debugfs files to dump individual planes/crtc/etc? */ -static const struct drm_info_list drm_atomic_debugfs_list[] = { +static const struct drm_debugfs_info drm_atomic_debugfs_list[] = { {"state", drm_state_info, 0}, }; -void drm_atomic_debugfs_init(struct drm_minor *minor) +void drm_atomic_debugfs_init(struct drm_device *dev) { - drm_debugfs_create_files(drm_atomic_debugfs_list, - ARRAY_SIZE(drm_atomic_debugfs_list), - minor->debugfs_root, minor); + drm_debugfs_add_files(dev, drm_atomic_debugfs_list, + ARRAY_SIZE(drm_atomic_debugfs_list)); } #endif |
