Here's a bunch of new stuff on top of my last atomic modeset/pageflip posting.
Highlights: - some bug fixes - started moving common property bits out of intel_atomic.c - hooked up the properties to some legacy code paths - non-blocking GPU synchronization
The GPU sync part could surely use some experienced peoples' attention. I didn't spend too much time on it, but based on some initial testing it seems to be working. Haven't stressed it that much though.
Oh and in patch 22 I left the default to blocking GPU sync, so if you want to try it, you actually have to go and poke /sys/module/drm/parameters/async_gpu to make it use the non-blocking sync code.
As usual my git repo has all the goods: https://gitorious.org/vsyrjala/linux/commits/drm_atomic_19
No changes to libdrm since the last time. Code is still here: https://gitorious.org/vsyrjala/drm/commits/drm_atomic_7
I also pushed a reasonably clean test app. It uses gbm to manage the buffers and GLES2 to render funky triangles. You can get it here: https://gitorious.org/vsyrjala/glplane
From: Ander Conselvan de Oliveira ander.conselvan.de.oliveira@intel.com
--- drivers/gpu/drm/drm_flip.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_flip.c b/drivers/gpu/drm/drm_flip.c index 6ccc3f8..a20e6a4 100644 --- a/drivers/gpu/drm/drm_flip.c +++ b/drivers/gpu/drm/drm_flip.c @@ -24,6 +24,7 @@ * Ville Syrjälä ville.syrjala@linux.intel.com */
+#include <linux/export.h> #include <drm/drm_flip.h>
static void drm_flip_driver_cleanup(struct work_struct *work) @@ -141,6 +142,7 @@ void drm_flip_helper_init(struct drm_flip_helper *helper, helper->driver = driver; helper->funcs = funcs; } +EXPORT_SYMBOL(drm_flip_helper_init);
void drm_flip_helper_clear(struct drm_flip_helper *helper) { @@ -176,6 +178,7 @@ void drm_flip_helper_clear(struct drm_flip_helper *helper) if (need_cleanup) queue_work(driver->wq, &driver->cleanup_work); } +EXPORT_SYMBOL(drm_flip_helper_clear);
void drm_flip_helper_fini(struct drm_flip_helper *helper) { @@ -186,6 +189,7 @@ void drm_flip_helper_fini(struct drm_flip_helper *helper) flush_work_sync(&driver->finish_work); flush_work_sync(&driver->cleanup_work); } +EXPORT_SYMBOL(drm_flip_helper_fini);
void drm_flip_helper_vblank(struct drm_flip_helper *helper) { @@ -223,6 +227,7 @@ void drm_flip_helper_vblank(struct drm_flip_helper *helper) if (need_cleanup) queue_work(driver->wq, &driver->cleanup_work); } +EXPORT_SYMBOL(drm_flip_helper_vblank);
void drm_flip_driver_init(struct drm_flip_driver *driver, const struct drm_flip_driver_funcs *funcs) @@ -239,6 +244,7 @@ void drm_flip_driver_init(struct drm_flip_driver *driver,
driver->wq = create_singlethread_workqueue("drm_flip"); } +EXPORT_SYMBOL(drm_flip_driver_init);
void drm_flip_driver_fini(struct drm_flip_driver *driver) { @@ -248,6 +254,7 @@ void drm_flip_driver_fini(struct drm_flip_driver *driver) WARN_ON(!list_empty(&driver->finish_list)); WARN_ON(!list_empty(&driver->cleanup_list)); } +EXPORT_SYMBOL(drm_flip_driver_fini);
void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver, struct list_head *flips) @@ -298,6 +305,7 @@ void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver, if (need_cleanup) queue_work(driver->wq, &driver->cleanup_work); } +EXPORT_SYMBOL(drm_flip_driver_schedule_flips);
void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver, struct list_head *flips) @@ -311,6 +319,7 @@ void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver, helper->funcs->prepare(flip); } } +EXPORT_SYMBOL(drm_flip_driver_prepare_flips);
void drm_flip_driver_complete_flips(struct drm_flip_driver *driver, struct list_head *flips) @@ -365,6 +374,7 @@ void drm_flip_driver_complete_flips(struct drm_flip_driver *driver, if (need_cleanup) queue_work(driver->wq, &driver->cleanup_work); } +EXPORT_SYMBOL(drm_flip_driver_complete_flips);
void drm_flip_init(struct drm_flip *flip, struct drm_flip_helper *helper) @@ -374,3 +384,4 @@ void drm_flip_init(struct drm_flip *flip, flip->finished = false; INIT_LIST_HEAD(&flip->list); } +EXPORT_SYMBOL(drm_flip_init);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Don't leave stale flips hanging around the sprites' flip helpers when the crtc is being disabled.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 41885fa..41fd0d5 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -2449,3 +2449,18 @@ void intel_atomic_handle_vblank(struct drm_device *dev, int pipe) drm_flip_helper_vblank(&intel_plane->flip_helper); } } + +void intel_atomic_clear_flips(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_plane *intel_plane; + int pipe = intel_crtc->pipe; + + drm_flip_helper_clear(&intel_crtc->flip_helper); + + list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) { + if (intel_plane->pipe == pipe) + drm_flip_helper_clear(&intel_plane->flip_helper); + } +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 43cff11..958b21b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3368,7 +3368,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) encoder->disable(encoder);
intel_crtc_wait_for_pending_flips(crtc); - drm_flip_helper_clear(&intel_crtc->flip_helper); + intel_atomic_clear_flips(crtc); drm_vblank_off(dev, pipe); intel_crtc_update_cursor(crtc, false);
@@ -3506,7 +3506,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
/* Give the overlay scaler a chance to disable if it's on this pipe */ intel_crtc_wait_for_pending_flips(crtc); - drm_flip_helper_clear(&intel_crtc->flip_helper); + intel_atomic_clear_flips(crtc); drm_vblank_off(dev, pipe); intel_crtc_dpms_overlay(intel_crtc, false); intel_crtc_update_cursor(crtc, false); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b9b96d3..8580ddd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -636,6 +636,7 @@ extern int intel_atomic_init(struct drm_device *dev); extern void intel_atomic_fini(struct drm_device *dev); extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file); extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe); +extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
extern void intel_enable_primary(struct drm_crtc *crtc); extern void intel_disable_primary(struct drm_crtc *crtc);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Move the property code around a bit to make it easier to move it out to the drm core later.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 423 ++++++++++++++++++++--------------- drivers/gpu/drm/i915/intel_drv.h | 3 + include/drm/drm_crtc.h | 12 + 3 files changed, 252 insertions(+), 186 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 41fd0d5..0e37cf5 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1473,87 +1473,6 @@ static int intel_atomic_check(struct drm_device *dev, void *state) return 0; }
-static void update_plane_props(struct drm_plane *plane) -{ - struct drm_mode_object *obj = &plane->base; - - drm_object_property_set_value(obj, prop_src_x, plane->src_x); - drm_object_property_set_value(obj, prop_src_y, plane->src_y); - drm_object_property_set_value(obj, prop_src_w, plane->src_w); - drm_object_property_set_value(obj, prop_src_h, plane->src_h); - - drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x); - drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y); - drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w); - drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h); - - drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0); - drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0); -} - -static int update_prop_connector_ids(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - uint64_t value = 0; - int i = 0; - uint32_t connector_ids[dev->mode_config.num_connector]; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder && connector->encoder->crtc == crtc) - connector_ids[i++] = connector->base.id; - } - - if (i) { - drm_property_blob_replace_data(crtc->connector_ids_blob, - i * sizeof connector_ids[0], connector_ids); - value = crtc->connector_ids_blob->base.id; - } else - drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL); - - drm_object_property_set_value(&crtc->base, prop_connector_ids, value); - - return 0; -} - -static int update_prop_mode(struct drm_crtc *crtc) -{ - uint64_t value = 0; - - if (crtc->enabled) { - struct drm_mode_modeinfo umode; - - drm_crtc_convert_to_umode(&umode, &crtc->mode); - drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode); - value = crtc->mode_blob->base.id; - } else - drm_property_blob_replace_data(crtc->mode_blob, 0, NULL); - - drm_object_property_set_value(&crtc->base, prop_mode, value); - - return 0; -} - -static void update_crtc_props(struct drm_crtc *crtc) -{ - struct drm_mode_object *obj = &crtc->base; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - drm_object_property_set_value(obj, prop_src_x, crtc->x); - drm_object_property_set_value(obj, prop_src_y, crtc->y); - - drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0); - - drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle); - drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x); - drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y); - drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width); - drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height); - - update_prop_mode(crtc); - update_prop_connector_ids(crtc); -} - static void update_props(struct drm_device *dev, struct intel_atomic_state *s) { @@ -1565,7 +1484,7 @@ static void update_props(struct drm_device *dev, if (!st->fb_dirty && !st->mode_dirty) continue;
- update_crtc_props(st->crtc); + intel_crtc_update_properties(st->crtc); }
for (i = 0; i < dev->mode_config.num_plane; i++) { @@ -1574,7 +1493,7 @@ static void update_props(struct drm_device *dev, if (!st->dirty) continue;
- update_plane_props(st->plane); + drm_plane_update_properties(st->plane); } }
@@ -1829,32 +1748,6 @@ static const struct drm_atomic_funcs intel_atomic_funcs = { .end = intel_atomic_end, };
-static struct { - struct drm_property **prop; - const char *name; - uint64_t min; - uint64_t max; -} props[] = { - { &prop_src_x, "SRC_X", 0, UINT_MAX }, - { &prop_src_y, "SRC_Y", 0, UINT_MAX }, - { &prop_src_w, "SRC_W", 0, UINT_MAX }, - { &prop_src_h, "SRC_H", 0, UINT_MAX }, - - { &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX }, - { &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX }, - { &prop_crtc_w, "CRTC_W", 0, INT_MAX }, - { &prop_crtc_h, "CRTC_H", 0, INT_MAX }, - - { &prop_fb_id, "FB_ID", 0, UINT_MAX }, - { &prop_crtc_id, "CRTC_ID", 0, UINT_MAX }, - - { &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX }, - { &prop_cursor_w, "CURSOR_W", 0, UINT_MAX }, - { &prop_cursor_h, "CURSOR_H", 0, UINT_MAX }, - { &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX }, - { &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX }, -}; - static void intel_flip_init(struct drm_device *dev); static void intel_flip_fini(struct drm_device *dev);
@@ -1862,71 +1755,25 @@ int intel_atomic_init(struct drm_device *dev) { struct drm_crtc *crtc; struct drm_plane *plane; - int ret = -ENOMEM; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(props); i++) { - *props[i].prop = - drm_property_create_range(dev, 0, props[i].name, - props[i].min, props[i].max); - if (!*props[i].prop) - goto out; - } - - /* FIXME create special object ID list property type? */ - prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); - if (!prop_connector_ids) - goto out; + int ret;
- prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); - if (!prop_mode) + ret = drm_mode_create_properties(dev); + if (ret) goto out;
list_for_each_entry(plane, &dev->mode_config.plane_list, head) { - struct drm_mode_object *obj = &plane->base; - - drm_object_attach_property(obj, prop_src_x, 0); - drm_object_attach_property(obj, prop_src_y, 0); - drm_object_attach_property(obj, prop_src_w, 0); - drm_object_attach_property(obj, prop_src_h, 0); - - drm_object_attach_property(obj, prop_crtc_x, 0); - drm_object_attach_property(obj, prop_crtc_y, 0); - drm_object_attach_property(obj, prop_crtc_w, 0); - drm_object_attach_property(obj, prop_crtc_h, 0); - - drm_object_attach_property(obj, prop_fb_id, 0); - drm_object_attach_property(obj, prop_crtc_id, 0); - - update_plane_props(plane); + drm_plane_attach_properties(plane); + drm_plane_update_properties(plane); }
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct drm_mode_object *obj = &crtc->base; - - drm_object_attach_property(obj, prop_src_x, 0); - drm_object_attach_property(obj, prop_src_y, 0); + intel_crtc_attach_properties(crtc);
- drm_object_attach_property(obj, prop_fb_id, 0); - drm_object_attach_property(obj, prop_mode, 0); - drm_object_attach_property(obj, prop_connector_ids, 0); - - drm_object_attach_property(obj, prop_cursor_id, 0); - drm_object_attach_property(obj, prop_cursor_x, 0); - drm_object_attach_property(obj, prop_cursor_y, 0); - drm_object_attach_property(obj, prop_cursor_w, 0); - drm_object_attach_property(obj, prop_cursor_h, 0); - - crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL); - if (!crtc->mode_blob) - goto out; - - crtc->connector_ids_blob = drm_property_create_blob(dev, 0, - dev->mode_config.num_connector * sizeof(uint32_t), NULL); - if (!crtc->connector_ids_blob) - goto out; + ret = drm_crtc_create_blobs(crtc); + if (ret) + goto destroy_props;
- update_crtc_props(crtc); + intel_crtc_update_properties(crtc); }
dev->driver->atomic_funcs = &intel_atomic_funcs; @@ -1935,12 +1782,9 @@ int intel_atomic_init(struct drm_device *dev)
return 0;
+ destroy_props: + drm_mode_destroy_properties(dev); out: - drm_property_destroy(dev, prop_mode); - drm_property_destroy(dev, prop_connector_ids); - - while (i--) - drm_property_destroy(dev, *props[i].prop);
return ret; } @@ -1952,24 +1796,10 @@ void intel_atomic_fini(struct drm_device *dev) intel_flip_fini(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - drm_property_destroy_blob(dev, crtc->mode_blob); - drm_property_destroy_blob(dev, crtc->connector_ids_blob); + drm_crtc_destroy_blobs(crtc); }
- drm_property_destroy(dev, prop_connector_ids); - drm_property_destroy(dev, prop_mode); - drm_property_destroy(dev, prop_crtc_id); - drm_property_destroy(dev, prop_fb_id); - - drm_property_destroy(dev, prop_crtc_h); - drm_property_destroy(dev, prop_crtc_w); - drm_property_destroy(dev, prop_crtc_y); - drm_property_destroy(dev, prop_crtc_x); - - drm_property_destroy(dev, prop_src_h); - drm_property_destroy(dev, prop_src_w); - drm_property_destroy(dev, prop_src_y); - drm_property_destroy(dev, prop_src_x); + drm_mode_destroy_properties(dev); }
enum { @@ -2464,3 +2294,224 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc) drm_flip_helper_clear(&intel_plane->flip_helper); } } + +static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_connector *connector; + uint64_t value = 0; + int i = 0; + uint32_t connector_ids[dev->mode_config.num_connector]; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->encoder && connector->encoder->crtc == crtc) + connector_ids[i++] = connector->base.id; + } + + if (i) { + drm_property_blob_replace_data(crtc->connector_ids_blob, + i * sizeof connector_ids[0], connector_ids); + value = crtc->connector_ids_blob->base.id; + } else + drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL); + + drm_object_property_set_value(&crtc->base, prop_connector_ids, value); +} + +static void drm_crtc_update_mode_property(struct drm_crtc *crtc) +{ + uint64_t value = 0; + + if (crtc->enabled) { + struct drm_mode_modeinfo umode; + + drm_crtc_convert_to_umode(&umode, &crtc->mode); + drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode); + value = crtc->mode_blob->base.id; + } else + drm_property_blob_replace_data(crtc->mode_blob, 0, NULL); + + drm_object_property_set_value(&crtc->base, prop_mode, value); +} + +void drm_crtc_update_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + + drm_object_property_set_value(obj, prop_src_x, crtc->x); + drm_object_property_set_value(obj, prop_src_y, crtc->y); + drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0); + + drm_crtc_update_mode_property(crtc); + drm_crtc_update_connector_ids_property(crtc); +} + +void intel_crtc_update_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + drm_crtc_update_properties(crtc); + + drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle); + drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x); + drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y); + drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width); + drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height); +} + +void drm_plane_update_properties(struct drm_plane *plane) +{ + struct drm_mode_object *obj = &plane->base; + + drm_object_property_set_value(obj, prop_src_x, plane->src_x); + drm_object_property_set_value(obj, prop_src_y, plane->src_y); + drm_object_property_set_value(obj, prop_src_w, plane->src_w); + drm_object_property_set_value(obj, prop_src_h, plane->src_h); + + drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x); + drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y); + drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w); + drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h); + + drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0); + drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0); +} + +int drm_crtc_create_blobs(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + + crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL); + if (!crtc->mode_blob) + return -ENOMEM; + + crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL); + if (!crtc->connector_ids_blob) + return -ENOMEM; + + return 0; +} + +void drm_crtc_destroy_blobs(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + + drm_property_destroy_blob(dev, crtc->mode_blob); + drm_property_destroy_blob(dev, crtc->connector_ids_blob); +} + +void drm_mode_destroy_properties(struct drm_device *dev) +{ + drm_property_destroy(dev, prop_connector_ids); + drm_property_destroy(dev, prop_mode); + drm_property_destroy(dev, prop_crtc_id); + drm_property_destroy(dev, prop_fb_id); + + drm_property_destroy(dev, prop_crtc_h); + drm_property_destroy(dev, prop_crtc_w); + drm_property_destroy(dev, prop_crtc_y); + drm_property_destroy(dev, prop_crtc_x); + + drm_property_destroy(dev, prop_src_h); + drm_property_destroy(dev, prop_src_w); + drm_property_destroy(dev, prop_src_y); + drm_property_destroy(dev, prop_src_x); +} + +static struct { + struct drm_property **prop; + const char *name; + uint64_t min; + uint64_t max; +} props[] = { + { &prop_src_x, "SRC_X", 0, UINT_MAX }, + { &prop_src_y, "SRC_Y", 0, UINT_MAX }, + { &prop_src_w, "SRC_W", 0, UINT_MAX }, + { &prop_src_h, "SRC_H", 0, UINT_MAX }, + + { &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX }, + { &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX }, + { &prop_crtc_w, "CRTC_W", 0, INT_MAX }, + { &prop_crtc_h, "CRTC_H", 0, INT_MAX }, + + { &prop_fb_id, "FB_ID", 0, UINT_MAX }, + { &prop_crtc_id, "CRTC_ID", 0, UINT_MAX }, + + { &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX }, + { &prop_cursor_w, "CURSOR_W", 0, UINT_MAX }, + { &prop_cursor_h, "CURSOR_H", 0, UINT_MAX }, + { &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX }, + { &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX }, +}; + +int drm_mode_create_properties(struct drm_device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(props); i++) { + *props[i].prop = drm_property_create_range(dev, 0, props[i].name, props[i].min, props[i].max); + if (!*props[i].prop) + goto out; + } + + /* FIXME create special object ID list property type? */ + prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); + if (!prop_connector_ids) + goto out; + + prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); + if (!prop_mode) + goto out; + + return 0; + + out: + drm_property_destroy(dev, prop_mode); + drm_property_destroy(dev, prop_connector_ids); + + while (i--) + drm_property_destroy(dev, *props[i].prop); + + return -ENOMEM; /* FIXME? */ +} + +void drm_plane_attach_properties(struct drm_plane *plane) +{ + struct drm_mode_object *obj = &plane->base; + + drm_object_attach_property(obj, prop_src_x, 0); + drm_object_attach_property(obj, prop_src_y, 0); + drm_object_attach_property(obj, prop_src_w, 0); + drm_object_attach_property(obj, prop_src_h, 0); + drm_object_attach_property(obj, prop_crtc_x, 0); + drm_object_attach_property(obj, prop_crtc_y, 0); + drm_object_attach_property(obj, prop_crtc_w, 0); + drm_object_attach_property(obj, prop_crtc_h, 0); + drm_object_attach_property(obj, prop_fb_id, 0); + drm_object_attach_property(obj, prop_crtc_id, 0); +} + +void drm_crtc_attach_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + + drm_object_attach_property(obj, prop_src_x, 0); + drm_object_attach_property(obj, prop_src_y, 0); + drm_object_attach_property(obj, prop_fb_id, 0); + drm_object_attach_property(obj, prop_mode, 0); + drm_object_attach_property(obj, prop_connector_ids, 0); +} + +void intel_crtc_attach_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + + drm_crtc_attach_properties(crtc); + + drm_object_attach_property(obj, prop_cursor_id, 0); + drm_object_attach_property(obj, prop_cursor_x, 0); + drm_object_attach_property(obj, prop_cursor_y, 0); + drm_object_attach_property(obj, prop_cursor_w, 0); + drm_object_attach_property(obj, prop_cursor_h, 0); +} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8580ddd..a229680 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -641,4 +641,7 @@ extern void intel_atomic_clear_flips(struct drm_crtc *crtc); extern void intel_enable_primary(struct drm_crtc *crtc); extern void intel_disable_primary(struct drm_crtc *crtc);
+extern void intel_crtc_attach_properties(struct drm_crtc *crtc); +extern void intel_crtc_update_properties(struct drm_crtc *crtc); + #endif /* __INTEL_DRV_H__ */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f37e8a7..13fb30a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1144,4 +1144,16 @@ struct drm_atomic_funcs { void (*end)(struct drm_device *dev, void *state); };
+extern int drm_mode_create_properties(struct drm_device *dev); +extern void drm_mode_destroy_properties(struct drm_device *dev); + +extern int drm_crtc_create_blobs(struct drm_crtc *crtc); +extern void drm_crtc_destroy_blobs(struct drm_crtc *crtc); + +extern void drm_crtc_attach_properties(struct drm_crtc *crtc); +extern void drm_plane_attach_properties(struct drm_plane *plane); + +extern void drm_crtc_update_properties(struct drm_crtc *crtc); +extern void drm_plane_update_properties(struct drm_plane *plane); + #endif /* __DRM_CRTC_H__ */
From: Ville Syrjälä ville.syrjala@linux.intel.com
Standard connector properties are kept in the mode_config structure. Move the CRTC and plane properties there as well.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 295 +++++++++++++++++++---------------- include/drm/drm_crtc.h | 19 +++ 2 files changed, 176 insertions(+), 138 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 0e37cf5..0def947 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -30,24 +30,6 @@
#include "intel_drv.h"
-static struct drm_property *prop_src_x; -static struct drm_property *prop_src_y; -static struct drm_property *prop_src_w; -static struct drm_property *prop_src_h; -static struct drm_property *prop_crtc_x; -static struct drm_property *prop_crtc_y; -static struct drm_property *prop_crtc_w; -static struct drm_property *prop_crtc_h; -static struct drm_property *prop_fb_id; -static struct drm_property *prop_crtc_id; -static struct drm_property *prop_mode; -static struct drm_property *prop_connector_ids; -static struct drm_property *prop_cursor_id; -static struct drm_property *prop_cursor_x; -static struct drm_property *prop_cursor_y; -static struct drm_property *prop_cursor_w; -static struct drm_property *prop_cursor_h; - struct intel_flip { struct drm_flip base; u32 vbl_count; @@ -368,27 +350,28 @@ static int plane_set(struct intel_atomic_state *s, uint64_t value) { struct drm_plane *plane = state->plane; + struct drm_mode_config *config = &plane->dev->mode_config; struct drm_mode_object *obj;
state->changed = true;
- if (prop == prop_src_x) { + if (prop == config->src_x_prop) { plane->src_x = value; - } else if (prop == prop_src_y) { + } else if (prop == config->src_y_prop) { plane->src_y = value; - } else if (prop == prop_src_w) { + } else if (prop == config->src_w_prop) { plane->src_w = value; - } else if (prop == prop_src_h) { + } else if (prop == config->src_h_prop) { plane->src_h = value; - } else if (prop == prop_crtc_x) { + } else if (prop == config->crtc_x_prop) { plane->crtc_x = value; - } else if (prop == prop_crtc_y) { + } else if (prop == config->crtc_y_prop) { plane->crtc_y = value; - } else if (prop == prop_crtc_w) { + } else if (prop == config->crtc_w_prop) { plane->crtc_w = value; - } else if (prop == prop_crtc_h) { + } else if (prop == config->crtc_h_prop) { plane->crtc_h = value; - } else if (prop == prop_crtc_id) { + } else if (prop == config->crtc_id_prop) { if (value) { obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_CRTC); if (!obj) { @@ -398,7 +381,7 @@ static int plane_set(struct intel_atomic_state *s, plane->crtc = obj_to_crtc(obj); } else plane->crtc = NULL; - } else if (prop == prop_fb_id) { + } else if (prop == config->fb_id_prop) { if (value) { obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_FB); if (!obj) { @@ -422,16 +405,17 @@ static int crtc_set(struct intel_atomic_state *s, uint64_t value, const void *blob_data) { struct drm_crtc *crtc = state->crtc; + struct drm_mode_config *config = &crtc->dev->mode_config; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_mode_object *obj;
state->changed = true;
- if (prop == prop_src_x) { + if (prop == config->src_x_prop) { crtc->x = value; - } else if (prop == prop_src_y) { + } else if (prop == config->src_y_prop) { crtc->y = value; - } else if (prop == prop_mode) { + } else if (prop == config->mode_prop) { const struct drm_mode_modeinfo *umode = blob_data;
if (value != 0 && value != sizeof *umode) { @@ -462,7 +446,7 @@ static int crtc_set(struct intel_atomic_state *s, drm_mode_destroy(crtc->dev, mode); } else crtc->enabled = false; - } else if (prop == prop_fb_id) { + } else if (prop == config->fb_id_prop) { if (value) { obj = drm_mode_object_find(crtc->dev, value, DRM_MODE_OBJECT_FB); if (!obj) { @@ -472,7 +456,7 @@ static int crtc_set(struct intel_atomic_state *s, crtc->fb = obj_to_fb(obj); } else crtc->fb = NULL; - } else if (prop == prop_connector_ids) { + } else if (prop == config->connector_ids_prop) { const uint32_t *ids = blob_data; uint64_t count_ids = value / sizeof(uint32_t); int ret; @@ -482,7 +466,7 @@ static int crtc_set(struct intel_atomic_state *s, return -EINVAL; }
- if (count_ids > crtc->dev->mode_config.num_connector) { + if (count_ids > config->num_connector) { DRM_DEBUG_KMS("Too many connectors specified\n"); return -ERANGE; } @@ -490,19 +474,19 @@ static int crtc_set(struct intel_atomic_state *s, ret = process_connectors(state, ids, count_ids); if (ret) return ret; - } else if (prop == prop_cursor_id) { + } else if (prop == config->cursor_id_prop) { intel_crtc->cursor_handle = value; - } else if (prop == prop_cursor_x) { + } else if (prop == config->cursor_x_prop) { intel_crtc->cursor_x = value; - } else if (prop == prop_cursor_y) { + } else if (prop == config->cursor_y_prop) { intel_crtc->cursor_y = value; - } else if (prop == prop_cursor_w) { + } else if (prop == config->cursor_w_prop) { if (value != 0 && value != 64) { DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n"); return -EINVAL; } intel_crtc->cursor_width = value; - } else if (prop == prop_cursor_h) { + } else if (prop == config->cursor_h_prop) { if (value != 0 && value != 64) { DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n"); return -EINVAL; @@ -2297,13 +2281,13 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; + struct drm_mode_config *config = &crtc->dev->mode_config; struct drm_connector *connector; uint64_t value = 0; int i = 0; - uint32_t connector_ids[dev->mode_config.num_connector]; + uint32_t connector_ids[config->num_connector];
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + list_for_each_entry(connector, &config->connector_list, head) { if (connector->encoder && connector->encoder->crtc == crtc) connector_ids[i++] = connector->base.id; } @@ -2315,11 +2299,12 @@ static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc) } else drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
- drm_object_property_set_value(&crtc->base, prop_connector_ids, value); + drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value); }
static void drm_crtc_update_mode_property(struct drm_crtc *crtc) { + struct drm_mode_config *config = &crtc->dev->mode_config; uint64_t value = 0;
if (crtc->enabled) { @@ -2331,16 +2316,17 @@ static void drm_crtc_update_mode_property(struct drm_crtc *crtc) } else drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
- drm_object_property_set_value(&crtc->base, prop_mode, value); + drm_object_property_set_value(&crtc->base, config->mode_prop, value); }
void drm_crtc_update_properties(struct drm_crtc *crtc) { struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config;
- drm_object_property_set_value(obj, prop_src_x, crtc->x); - drm_object_property_set_value(obj, prop_src_y, crtc->y); - drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0); + drm_object_property_set_value(obj, config->src_x_prop, crtc->x); + drm_object_property_set_value(obj, config->src_y_prop, crtc->y); + drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0);
drm_crtc_update_mode_property(crtc); drm_crtc_update_connector_ids_property(crtc); @@ -2349,33 +2335,35 @@ void drm_crtc_update_properties(struct drm_crtc *crtc) void intel_crtc_update_properties(struct drm_crtc *crtc) { struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config; struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
drm_crtc_update_properties(crtc);
- drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle); - drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x); - drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y); - drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width); - drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height); + drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle); + drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x); + drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y); + drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width); + drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height); }
void drm_plane_update_properties(struct drm_plane *plane) { struct drm_mode_object *obj = &plane->base; + struct drm_mode_config *config = &plane->dev->mode_config;
- drm_object_property_set_value(obj, prop_src_x, plane->src_x); - drm_object_property_set_value(obj, prop_src_y, plane->src_y); - drm_object_property_set_value(obj, prop_src_w, plane->src_w); - drm_object_property_set_value(obj, prop_src_h, plane->src_h); + drm_object_property_set_value(obj, config->src_x_prop, plane->src_x); + drm_object_property_set_value(obj, config->src_y_prop, plane->src_y); + drm_object_property_set_value(obj, config->src_w_prop, plane->src_w); + drm_object_property_set_value(obj, config->src_h_prop, plane->src_h);
- drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x); - drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y); - drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w); - drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h); + drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x); + drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y); + drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w); + drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h);
- drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0); - drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0); + drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0); + drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0); }
int drm_crtc_create_blobs(struct drm_crtc *crtc) @@ -2401,77 +2389,105 @@ void drm_crtc_destroy_blobs(struct drm_crtc *crtc) drm_property_destroy_blob(dev, crtc->connector_ids_blob); }
+void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop) +{ + drm_property_destroy(dev, *prop); + *prop = NULL; +} + void drm_mode_destroy_properties(struct drm_device *dev) { - drm_property_destroy(dev, prop_connector_ids); - drm_property_destroy(dev, prop_mode); - drm_property_destroy(dev, prop_crtc_id); - drm_property_destroy(dev, prop_fb_id); - - drm_property_destroy(dev, prop_crtc_h); - drm_property_destroy(dev, prop_crtc_w); - drm_property_destroy(dev, prop_crtc_y); - drm_property_destroy(dev, prop_crtc_x); - - drm_property_destroy(dev, prop_src_h); - drm_property_destroy(dev, prop_src_w); - drm_property_destroy(dev, prop_src_y); - drm_property_destroy(dev, prop_src_x); -} - -static struct { - struct drm_property **prop; - const char *name; - uint64_t min; - uint64_t max; -} props[] = { - { &prop_src_x, "SRC_X", 0, UINT_MAX }, - { &prop_src_y, "SRC_Y", 0, UINT_MAX }, - { &prop_src_w, "SRC_W", 0, UINT_MAX }, - { &prop_src_h, "SRC_H", 0, UINT_MAX }, - - { &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX }, - { &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX }, - { &prop_crtc_w, "CRTC_W", 0, INT_MAX }, - { &prop_crtc_h, "CRTC_H", 0, INT_MAX }, - - { &prop_fb_id, "FB_ID", 0, UINT_MAX }, - { &prop_crtc_id, "CRTC_ID", 0, UINT_MAX }, - - { &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX }, - { &prop_cursor_w, "CURSOR_W", 0, UINT_MAX }, - { &prop_cursor_h, "CURSOR_H", 0, UINT_MAX }, - { &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX }, - { &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX }, -}; + struct drm_mode_config *config = &dev->mode_config; + + drm_property_destroy_null(dev, &config->cursor_h_prop); + drm_property_destroy_null(dev, &config->cursor_w_prop); + drm_property_destroy_null(dev, &config->cursor_y_prop); + drm_property_destroy_null(dev, &config->cursor_x_prop); + drm_property_destroy_null(dev, &config->cursor_id_prop); + + drm_property_destroy_null(dev, &config->connector_ids_prop); + drm_property_destroy_null(dev, &config->mode_prop); + + drm_property_destroy_null(dev, &config->crtc_id_prop); + drm_property_destroy_null(dev, &config->fb_id_prop); + + drm_property_destroy_null(dev, &config->crtc_h_prop); + drm_property_destroy_null(dev, &config->crtc_w_prop); + drm_property_destroy_null(dev, &config->crtc_y_prop); + drm_property_destroy_null(dev, &config->crtc_x_prop); + + drm_property_destroy_null(dev, &config->src_h_prop); + drm_property_destroy_null(dev, &config->src_w_prop); + drm_property_destroy_null(dev, &config->src_y_prop); + drm_property_destroy_null(dev, &config->src_x_prop); +}
int drm_mode_create_properties(struct drm_device *dev) { - int i; + struct drm_mode_config *config = &dev->mode_config;
- for (i = 0; i < ARRAY_SIZE(props); i++) { - *props[i].prop = drm_property_create_range(dev, 0, props[i].name, props[i].min, props[i].max); - if (!*props[i].prop) - goto out; - } + config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX); + if (!config->src_x_prop) + goto out; + config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX); + if (!config->src_y_prop) + goto out; + config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX); + if (!config->src_w_prop) + goto out; + config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX); + if (!config->src_h_prop) + goto out; + + config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX); + if (!config->crtc_x_prop) + goto out; + config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX); + if (!config->crtc_y_prop) + goto out; + config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX); + if (!config->crtc_w_prop) + goto out; + config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX); + if (!config->crtc_h_prop) + goto out; + + config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX); + if (!config->fb_id_prop) + goto out; + config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX); + if (!config->crtc_id_prop) + goto out; + + config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX); + if (!config->cursor_id_prop) + goto out; + config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX); + if (!config->cursor_x_prop) + goto out; + config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX); + if (!config->cursor_y_prop) + goto out; + config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX); + if (!config->cursor_w_prop) + goto out; + config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX); + if (!config->cursor_h_prop) + goto out;
/* FIXME create special object ID list property type? */ - prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); - if (!prop_connector_ids) + config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); + if (!config->connector_ids_prop) goto out;
- prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); - if (!prop_mode) + config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); + if (!config->mode_prop) goto out;
return 0;
out: - drm_property_destroy(dev, prop_mode); - drm_property_destroy(dev, prop_connector_ids); - - while (i--) - drm_property_destroy(dev, *props[i].prop); + drm_mode_destroy_properties(dev);
return -ENOMEM; /* FIXME? */ } @@ -2479,39 +2495,42 @@ int drm_mode_create_properties(struct drm_device *dev) void drm_plane_attach_properties(struct drm_plane *plane) { struct drm_mode_object *obj = &plane->base; + struct drm_mode_config *config = &plane->dev->mode_config;
- drm_object_attach_property(obj, prop_src_x, 0); - drm_object_attach_property(obj, prop_src_y, 0); - drm_object_attach_property(obj, prop_src_w, 0); - drm_object_attach_property(obj, prop_src_h, 0); - drm_object_attach_property(obj, prop_crtc_x, 0); - drm_object_attach_property(obj, prop_crtc_y, 0); - drm_object_attach_property(obj, prop_crtc_w, 0); - drm_object_attach_property(obj, prop_crtc_h, 0); - drm_object_attach_property(obj, prop_fb_id, 0); - drm_object_attach_property(obj, prop_crtc_id, 0); + drm_object_attach_property(obj, config->src_x_prop, 0); + drm_object_attach_property(obj, config->src_y_prop, 0); + drm_object_attach_property(obj, config->src_w_prop, 0); + drm_object_attach_property(obj, config->src_h_prop, 0); + drm_object_attach_property(obj, config->crtc_x_prop, 0); + drm_object_attach_property(obj, config->crtc_y_prop, 0); + drm_object_attach_property(obj, config->crtc_w_prop, 0); + drm_object_attach_property(obj, config->crtc_h_prop, 0); + drm_object_attach_property(obj, config->fb_id_prop, 0); + drm_object_attach_property(obj, config->crtc_id_prop, 0); }
void drm_crtc_attach_properties(struct drm_crtc *crtc) { struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config;
- drm_object_attach_property(obj, prop_src_x, 0); - drm_object_attach_property(obj, prop_src_y, 0); - drm_object_attach_property(obj, prop_fb_id, 0); - drm_object_attach_property(obj, prop_mode, 0); - drm_object_attach_property(obj, prop_connector_ids, 0); + drm_object_attach_property(obj, config->src_x_prop, 0); + drm_object_attach_property(obj, config->src_y_prop, 0); + drm_object_attach_property(obj, config->fb_id_prop, 0); + drm_object_attach_property(obj, config->mode_prop, 0); + drm_object_attach_property(obj, config->connector_ids_prop, 0); }
void intel_crtc_attach_properties(struct drm_crtc *crtc) { struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config;
drm_crtc_attach_properties(crtc);
- drm_object_attach_property(obj, prop_cursor_id, 0); - drm_object_attach_property(obj, prop_cursor_x, 0); - drm_object_attach_property(obj, prop_cursor_y, 0); - drm_object_attach_property(obj, prop_cursor_w, 0); - drm_object_attach_property(obj, prop_cursor_h, 0); + drm_object_attach_property(obj, config->cursor_id_prop, 0); + drm_object_attach_property(obj, config->cursor_x_prop, 0); + drm_object_attach_property(obj, config->cursor_y_prop, 0); + drm_object_attach_property(obj, config->cursor_w_prop, 0); + drm_object_attach_property(obj, config->cursor_h_prop, 0); } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 13fb30a..c30665a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -834,6 +834,25 @@ struct drm_mode_config { struct drm_property *dithering_mode_property; struct drm_property *dirty_info_property;
+ /* CRTC/plane properties */ + struct drm_property *src_x_prop; + struct drm_property *src_y_prop; + struct drm_property *src_w_prop; + struct drm_property *src_h_prop; + struct drm_property *crtc_x_prop; + struct drm_property *crtc_y_prop; + struct drm_property *crtc_w_prop; + struct drm_property *crtc_h_prop; + struct drm_property *fb_id_prop; + struct drm_property *crtc_id_prop; + struct drm_property *mode_prop; + struct drm_property *connector_ids_prop; + struct drm_property *cursor_id_prop; + struct drm_property *cursor_x_prop; + struct drm_property *cursor_y_prop; + struct drm_property *cursor_w_prop; + struct drm_property *cursor_h_prop; + /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; };
From: Ville Syrjälä ville.syrjala@linux.intel.com
Keep the new CRTC properties when doing modeset through the legacy code paths.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_crtc_helper.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 80bbbda..4507aed 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -743,6 +743,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) kfree(save_connectors); kfree(save_encoders); kfree(save_crtcs); + + /* changes in one CRTC can affect the others */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + drm_crtc_update_properties(crtc); + return 0;
fail: @@ -771,6 +776,11 @@ fail: kfree(save_connectors); kfree(save_encoders); kfree(save_crtcs); + + /* changes in one CRTC can affect the others */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + drm_crtc_update_properties(crtc); + return ret; } EXPORT_SYMBOL(drm_crtc_helper_set_config);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Keep the new plane properties when doing operations through the legacy code paths.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_crtc.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4736cfe..f1fcb5e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -407,6 +407,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) /* disconnect the plane from the fb and crtc: */ plane->fb = NULL; plane->crtc = NULL; + + drm_plane_update_properties(plane); } }
@@ -1781,6 +1783,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data, plane->funcs->disable_plane(plane); plane->crtc = NULL; plane->fb = NULL; + + drm_plane_update_properties(plane); goto out; }
@@ -1864,6 +1868,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data, plane->src_y = plane_req->src_y; plane->src_w = plane_req->src_w; plane->src_h = plane_req->src_h; + + drm_plane_update_properties(plane); }
out:
From: Ville Syrjälä ville.syrjala@linux.intel.com
Update cursor related CRTC properties after a modeset. The cursor properties aren't handled by the drm core since not all CRTCs have cursors.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 958b21b..12d4e02 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5802,6 +5802,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, if (old_obj) intel_crtc_cursor_bo_unref(crtc, old_obj);
+ intel_crtc_update_properties(crtc); + return 0; }
@@ -5814,6 +5816,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
intel_crtc_update_cursor(crtc, true);
+ intel_crtc_update_properties(crtc); + return 0; }
@@ -6763,6 +6767,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
trace_i915_flip_request(intel_crtc->plane, obj);
+ intel_crtc_update_properties(crtc); + return 0;
cleanup_pending: @@ -7490,6 +7496,7 @@ next_encoder: static int intel_crtc_set_config(struct drm_mode_set *set) { struct drm_device *dev; + struct drm_crtc *crtc; struct drm_mode_set save_set; struct intel_set_config *config; int ret; @@ -7563,6 +7570,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
intel_set_config_free(config);
+ /* changes in one CRTC can affect the others */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + intel_crtc_update_properties(crtc); + return 0;
fail: @@ -7574,6 +7585,10 @@ fail: save_set.x, save_set.y, save_set.fb)) DRM_ERROR("failed to restore config after modeset failure\n");
+ /* changes in one CRTC can affect the others */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + intel_crtc_update_properties(crtc); + out_config: intel_set_config_free(config); return ret;
From: Ville Syrjälä ville.syrjala@linux.intel.com
Move some of the property code to drm_crtc.c since it should be shared by everyone.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_crtc.c | 235 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_atomic.c | 256 ---------------------------------- drivers/gpu/drm/i915/intel_display.c | 29 ++++ 3 files changed, 264 insertions(+), 256 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f1fcb5e..9836755 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4388,3 +4388,238 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
return ret; } + +static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc) +{ + struct drm_mode_config *config = &crtc->dev->mode_config; + struct drm_connector *connector; + uint64_t value = 0; + int i = 0; + uint32_t connector_ids[config->num_connector]; + + list_for_each_entry(connector, &config->connector_list, head) { + if (connector->encoder && connector->encoder->crtc == crtc) + connector_ids[i++] = connector->base.id; + } + + if (i) { + drm_property_blob_replace_data(crtc->connector_ids_blob, + i * sizeof connector_ids[0], connector_ids); + value = crtc->connector_ids_blob->base.id; + } else + drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL); + + drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value); +} + +static void drm_crtc_update_mode_property(struct drm_crtc *crtc) +{ + struct drm_mode_config *config = &crtc->dev->mode_config; + uint64_t value = 0; + + if (crtc->enabled) { + struct drm_mode_modeinfo umode; + + drm_crtc_convert_to_umode(&umode, &crtc->mode); + drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode); + value = crtc->mode_blob->base.id; + } else + drm_property_blob_replace_data(crtc->mode_blob, 0, NULL); + + drm_object_property_set_value(&crtc->base, config->mode_prop, value); +} + +void drm_crtc_update_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config; + + drm_object_property_set_value(obj, config->src_x_prop, crtc->x); + drm_object_property_set_value(obj, config->src_y_prop, crtc->y); + drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0); + + drm_crtc_update_mode_property(crtc); + drm_crtc_update_connector_ids_property(crtc); +} +EXPORT_SYMBOL(drm_crtc_update_properties); + +void drm_plane_update_properties(struct drm_plane *plane) +{ + struct drm_mode_object *obj = &plane->base; + struct drm_mode_config *config = &plane->dev->mode_config; + + drm_object_property_set_value(obj, config->src_x_prop, plane->src_x); + drm_object_property_set_value(obj, config->src_y_prop, plane->src_y); + drm_object_property_set_value(obj, config->src_w_prop, plane->src_w); + drm_object_property_set_value(obj, config->src_h_prop, plane->src_h); + + drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x); + drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y); + drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w); + drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h); + + drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0); + drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0); +} +EXPORT_SYMBOL(drm_plane_update_properties); + +int drm_crtc_create_blobs(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + + crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL); + if (!crtc->mode_blob) + return -ENOMEM; + + crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL); + if (!crtc->connector_ids_blob) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL(drm_crtc_create_blobs); + +void drm_crtc_destroy_blobs(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + + drm_property_destroy_blob(dev, crtc->mode_blob); + drm_property_destroy_blob(dev, crtc->connector_ids_blob); +} +EXPORT_SYMBOL(drm_crtc_destroy_blobs); + +static void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop) +{ + drm_property_destroy(dev, *prop); + *prop = NULL; +} + +void drm_mode_destroy_properties(struct drm_device *dev) +{ + struct drm_mode_config *config = &dev->mode_config; + + drm_property_destroy_null(dev, &config->cursor_h_prop); + drm_property_destroy_null(dev, &config->cursor_w_prop); + drm_property_destroy_null(dev, &config->cursor_y_prop); + drm_property_destroy_null(dev, &config->cursor_x_prop); + drm_property_destroy_null(dev, &config->cursor_id_prop); + + drm_property_destroy_null(dev, &config->connector_ids_prop); + drm_property_destroy_null(dev, &config->mode_prop); + + drm_property_destroy_null(dev, &config->crtc_id_prop); + drm_property_destroy_null(dev, &config->fb_id_prop); + + drm_property_destroy_null(dev, &config->crtc_h_prop); + drm_property_destroy_null(dev, &config->crtc_w_prop); + drm_property_destroy_null(dev, &config->crtc_y_prop); + drm_property_destroy_null(dev, &config->crtc_x_prop); + + drm_property_destroy_null(dev, &config->src_h_prop); + drm_property_destroy_null(dev, &config->src_w_prop); + drm_property_destroy_null(dev, &config->src_y_prop); + drm_property_destroy_null(dev, &config->src_x_prop); +} +EXPORT_SYMBOL(drm_mode_destroy_properties); + +int drm_mode_create_properties(struct drm_device *dev) +{ + struct drm_mode_config *config = &dev->mode_config; + + config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX); + if (!config->src_x_prop) + goto out; + config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX); + if (!config->src_y_prop) + goto out; + config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX); + if (!config->src_w_prop) + goto out; + config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX); + if (!config->src_h_prop) + goto out; + + config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX); + if (!config->crtc_x_prop) + goto out; + config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX); + if (!config->crtc_y_prop) + goto out; + config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX); + if (!config->crtc_w_prop) + goto out; + config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX); + if (!config->crtc_h_prop) + goto out; + + config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX); + if (!config->fb_id_prop) + goto out; + config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX); + if (!config->crtc_id_prop) + goto out; + + config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX); + if (!config->cursor_id_prop) + goto out; + config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX); + if (!config->cursor_x_prop) + goto out; + config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX); + if (!config->cursor_y_prop) + goto out; + config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX); + if (!config->cursor_w_prop) + goto out; + config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX); + if (!config->cursor_h_prop) + goto out; + + /* FIXME create special object ID list property type? */ + config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); + if (!config->connector_ids_prop) + goto out; + + config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); + if (!config->mode_prop) + goto out; + + return 0; + + out: + drm_mode_destroy_properties(dev); + + return -ENOMEM; /* FIXME? */ +} +EXPORT_SYMBOL(drm_mode_create_properties); + +void drm_plane_attach_properties(struct drm_plane *plane) +{ + struct drm_mode_object *obj = &plane->base; + struct drm_mode_config *config = &plane->dev->mode_config; + + drm_object_attach_property(obj, config->src_x_prop, 0); + drm_object_attach_property(obj, config->src_y_prop, 0); + drm_object_attach_property(obj, config->src_w_prop, 0); + drm_object_attach_property(obj, config->src_h_prop, 0); + drm_object_attach_property(obj, config->crtc_x_prop, 0); + drm_object_attach_property(obj, config->crtc_y_prop, 0); + drm_object_attach_property(obj, config->crtc_w_prop, 0); + drm_object_attach_property(obj, config->crtc_h_prop, 0); + drm_object_attach_property(obj, config->fb_id_prop, 0); + drm_object_attach_property(obj, config->crtc_id_prop, 0); +} +EXPORT_SYMBOL(drm_plane_attach_properties); + +void drm_crtc_attach_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config; + + drm_object_attach_property(obj, config->src_x_prop, 0); + drm_object_attach_property(obj, config->src_y_prop, 0); + drm_object_attach_property(obj, config->fb_id_prop, 0); + drm_object_attach_property(obj, config->mode_prop, 0); + drm_object_attach_property(obj, config->connector_ids_prop, 0); +} +EXPORT_SYMBOL(drm_crtc_attach_properties); diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 0def947..6dd07fb 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -2278,259 +2278,3 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc) drm_flip_helper_clear(&intel_plane->flip_helper); } } - -static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc) -{ - struct drm_mode_config *config = &crtc->dev->mode_config; - struct drm_connector *connector; - uint64_t value = 0; - int i = 0; - uint32_t connector_ids[config->num_connector]; - - list_for_each_entry(connector, &config->connector_list, head) { - if (connector->encoder && connector->encoder->crtc == crtc) - connector_ids[i++] = connector->base.id; - } - - if (i) { - drm_property_blob_replace_data(crtc->connector_ids_blob, - i * sizeof connector_ids[0], connector_ids); - value = crtc->connector_ids_blob->base.id; - } else - drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL); - - drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value); -} - -static void drm_crtc_update_mode_property(struct drm_crtc *crtc) -{ - struct drm_mode_config *config = &crtc->dev->mode_config; - uint64_t value = 0; - - if (crtc->enabled) { - struct drm_mode_modeinfo umode; - - drm_crtc_convert_to_umode(&umode, &crtc->mode); - drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode); - value = crtc->mode_blob->base.id; - } else - drm_property_blob_replace_data(crtc->mode_blob, 0, NULL); - - drm_object_property_set_value(&crtc->base, config->mode_prop, value); -} - -void drm_crtc_update_properties(struct drm_crtc *crtc) -{ - struct drm_mode_object *obj = &crtc->base; - struct drm_mode_config *config = &crtc->dev->mode_config; - - drm_object_property_set_value(obj, config->src_x_prop, crtc->x); - drm_object_property_set_value(obj, config->src_y_prop, crtc->y); - drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0); - - drm_crtc_update_mode_property(crtc); - drm_crtc_update_connector_ids_property(crtc); -} - -void intel_crtc_update_properties(struct drm_crtc *crtc) -{ - struct drm_mode_object *obj = &crtc->base; - struct drm_mode_config *config = &crtc->dev->mode_config; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - drm_crtc_update_properties(crtc); - - drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle); - drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x); - drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y); - drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width); - drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height); -} - -void drm_plane_update_properties(struct drm_plane *plane) -{ - struct drm_mode_object *obj = &plane->base; - struct drm_mode_config *config = &plane->dev->mode_config; - - drm_object_property_set_value(obj, config->src_x_prop, plane->src_x); - drm_object_property_set_value(obj, config->src_y_prop, plane->src_y); - drm_object_property_set_value(obj, config->src_w_prop, plane->src_w); - drm_object_property_set_value(obj, config->src_h_prop, plane->src_h); - - drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x); - drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y); - drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w); - drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h); - - drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0); - drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0); -} - -int drm_crtc_create_blobs(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - - crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL); - if (!crtc->mode_blob) - return -ENOMEM; - - crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL); - if (!crtc->connector_ids_blob) - return -ENOMEM; - - return 0; -} - -void drm_crtc_destroy_blobs(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - - drm_property_destroy_blob(dev, crtc->mode_blob); - drm_property_destroy_blob(dev, crtc->connector_ids_blob); -} - -void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop) -{ - drm_property_destroy(dev, *prop); - *prop = NULL; -} - -void drm_mode_destroy_properties(struct drm_device *dev) -{ - struct drm_mode_config *config = &dev->mode_config; - - drm_property_destroy_null(dev, &config->cursor_h_prop); - drm_property_destroy_null(dev, &config->cursor_w_prop); - drm_property_destroy_null(dev, &config->cursor_y_prop); - drm_property_destroy_null(dev, &config->cursor_x_prop); - drm_property_destroy_null(dev, &config->cursor_id_prop); - - drm_property_destroy_null(dev, &config->connector_ids_prop); - drm_property_destroy_null(dev, &config->mode_prop); - - drm_property_destroy_null(dev, &config->crtc_id_prop); - drm_property_destroy_null(dev, &config->fb_id_prop); - - drm_property_destroy_null(dev, &config->crtc_h_prop); - drm_property_destroy_null(dev, &config->crtc_w_prop); - drm_property_destroy_null(dev, &config->crtc_y_prop); - drm_property_destroy_null(dev, &config->crtc_x_prop); - - drm_property_destroy_null(dev, &config->src_h_prop); - drm_property_destroy_null(dev, &config->src_w_prop); - drm_property_destroy_null(dev, &config->src_y_prop); - drm_property_destroy_null(dev, &config->src_x_prop); -} - -int drm_mode_create_properties(struct drm_device *dev) -{ - struct drm_mode_config *config = &dev->mode_config; - - config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX); - if (!config->src_x_prop) - goto out; - config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX); - if (!config->src_y_prop) - goto out; - config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX); - if (!config->src_w_prop) - goto out; - config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX); - if (!config->src_h_prop) - goto out; - - config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX); - if (!config->crtc_x_prop) - goto out; - config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX); - if (!config->crtc_y_prop) - goto out; - config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX); - if (!config->crtc_w_prop) - goto out; - config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX); - if (!config->crtc_h_prop) - goto out; - - config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX); - if (!config->fb_id_prop) - goto out; - config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX); - if (!config->crtc_id_prop) - goto out; - - config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX); - if (!config->cursor_id_prop) - goto out; - config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX); - if (!config->cursor_x_prop) - goto out; - config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX); - if (!config->cursor_y_prop) - goto out; - config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX); - if (!config->cursor_w_prop) - goto out; - config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX); - if (!config->cursor_h_prop) - goto out; - - /* FIXME create special object ID list property type? */ - config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0); - if (!config->connector_ids_prop) - goto out; - - config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0); - if (!config->mode_prop) - goto out; - - return 0; - - out: - drm_mode_destroy_properties(dev); - - return -ENOMEM; /* FIXME? */ -} - -void drm_plane_attach_properties(struct drm_plane *plane) -{ - struct drm_mode_object *obj = &plane->base; - struct drm_mode_config *config = &plane->dev->mode_config; - - drm_object_attach_property(obj, config->src_x_prop, 0); - drm_object_attach_property(obj, config->src_y_prop, 0); - drm_object_attach_property(obj, config->src_w_prop, 0); - drm_object_attach_property(obj, config->src_h_prop, 0); - drm_object_attach_property(obj, config->crtc_x_prop, 0); - drm_object_attach_property(obj, config->crtc_y_prop, 0); - drm_object_attach_property(obj, config->crtc_w_prop, 0); - drm_object_attach_property(obj, config->crtc_h_prop, 0); - drm_object_attach_property(obj, config->fb_id_prop, 0); - drm_object_attach_property(obj, config->crtc_id_prop, 0); -} - -void drm_crtc_attach_properties(struct drm_crtc *crtc) -{ - struct drm_mode_object *obj = &crtc->base; - struct drm_mode_config *config = &crtc->dev->mode_config; - - drm_object_attach_property(obj, config->src_x_prop, 0); - drm_object_attach_property(obj, config->src_y_prop, 0); - drm_object_attach_property(obj, config->fb_id_prop, 0); - drm_object_attach_property(obj, config->mode_prop, 0); - drm_object_attach_property(obj, config->connector_ids_prop, 0); -} - -void intel_crtc_attach_properties(struct drm_crtc *crtc) -{ - struct drm_mode_object *obj = &crtc->base; - struct drm_mode_config *config = &crtc->dev->mode_config; - - drm_crtc_attach_properties(crtc); - - drm_object_attach_property(obj, config->cursor_id_prop, 0); - drm_object_attach_property(obj, config->cursor_x_prop, 0); - drm_object_attach_property(obj, config->cursor_y_prop, 0); - drm_object_attach_property(obj, config->cursor_w_prop, 0); - drm_object_attach_property(obj, config->cursor_h_prop, 0); -} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 12d4e02..0eccef3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8746,3 +8746,32 @@ intel_display_print_error_state(struct seq_file *m, } } #endif + +void intel_crtc_update_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + drm_crtc_update_properties(crtc); + + drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle); + drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x); + drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y); + drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width); + drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height); +} + +void intel_crtc_attach_properties(struct drm_crtc *crtc) +{ + struct drm_mode_object *obj = &crtc->base; + struct drm_mode_config *config = &crtc->dev->mode_config; + + drm_crtc_attach_properties(crtc); + + drm_object_attach_property(obj, config->cursor_id_prop, 0); + drm_object_attach_property(obj, config->cursor_x_prop, 0); + drm_object_attach_property(obj, config->cursor_y_prop, 0); + drm_object_attach_property(obj, config->cursor_w_prop, 0); + drm_object_attach_property(obj, config->cursor_h_prop, 0); +}
From: Ville Syrjälä ville.syrjala@linux.intel.com
All connectors use intel_best_encoder() as their best_encoder() func, so just call it directly w/o the indirection.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 6dd07fb..e58ec3f 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -152,8 +152,6 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i int i;
for (i = 0; i < count_ids; i++) { - struct drm_encoder *encoder; - const struct drm_connector_helper_funcs *connector_funcs; struct drm_mode_object *obj; int j;
@@ -169,9 +167,8 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i }
connector = obj_to_connector(obj); - connector_funcs = connector->helper_private;
- encoder = connector_funcs->best_encoder(connector); + encoder = intel_best_encoder(connector);
if (!drm_encoder_crtc_ok(encoder, crtc)) return -EINVAL; @@ -180,9 +177,6 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i }
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - const struct drm_connector_helper_funcs *connector_funcs = - connector->helper_private; - for (i = 0; i < count_ids; i++) { if (connector == connectors[i]) break; @@ -196,7 +190,7 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i continue; }
- encoder = connector_funcs->best_encoder(connector); + encoder = intel_best_encoder(connector);
connector->encoder = encoder; encoder->crtc = crtc;
From: Ville Syrjälä ville.syrjala@linux.intel.com
The i915 modeset logic requires that these be kept in sync with the other crtc and encoder pointers.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 2 ++ drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index e58ec3f..c5558cc 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1701,6 +1701,8 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
update_props(dev, s);
+ intel_modeset_update_staged_output_state(dev); + return 0; }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0eccef3..d310529 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6845,7 +6845,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder, * 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) +void intel_modeset_update_staged_output_state(struct drm_device *dev) { struct intel_encoder *encoder; struct intel_connector *connector; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a229680..4847170 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -644,4 +644,6 @@ extern void intel_disable_primary(struct drm_crtc *crtc); extern void intel_crtc_attach_properties(struct drm_crtc *crtc); extern void intel_crtc_update_properties(struct drm_crtc *crtc);
+extern void intel_modeset_update_staged_output_state(struct drm_device *dev); + #endif /* __INTEL_DRV_H__ */
From: Ville Syrjälä ville.syrjala@linux.intel.com
Update the connector DPMS state after atomic modeset operations.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index c5558cc..1fce359 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1475,6 +1475,36 @@ static void update_props(struct drm_device *dev, } }
+/* + * FIXME + * Perhaps atomic modeset shouldn't actually change the DPMS state, + * unless explicitly asked to do so. That's the way we treat everything + * else, so it makes sense. Although the dpms property is already a bit + * special in the legacy codepaths, so maybe we should follow the same + * pattern. Ie. a modeset forces DPMS to on (which is what we do here). + */ +static void update_connector_dpms(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + int dpms = connector->dpms; + + if (connector->encoder && connector->encoder->crtc == crtc) + dpms = DRM_MODE_DPMS_ON; + else if (!connector->encoder || !connector->encoder->crtc) + dpms = DRM_MODE_DPMS_OFF; + + if (connector->dpms == dpms) + continue; + + connector->dpms = dpms; + drm_connector_property_set_value(connector, + dev->mode_config.dpms_property, + dpms); + } +} + static void update_crtc(struct drm_device *dev, struct intel_atomic_state *s) { @@ -1494,6 +1524,7 @@ static void update_crtc(struct drm_device *dev, if (st->mode_dirty) { drm_calc_timestamping_constants(crtc); intel_crtc_update_sarea(crtc, crtc->enabled); + update_connector_dpms(dev, crtc); }
if (st->fb_dirty)
From: Ville Syrjälä ville.syrjala@linux.intel.com
The pending_flip counter is probably going to be remove entirely, along with i915_gem_execbuffer_wait_for_flips() so don't even try to use it.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 74 +---------------------------------- 1 files changed, 2 insertions(+), 72 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 1fce359..ac7fe88 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1536,45 +1536,9 @@ static void atomic_pipe_commit(struct drm_device *dev, struct intel_atomic_state *state, int pipe);
-static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *s) +static void apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *s) { struct intel_crtc *intel_crtc; - int i; - - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct intel_crtc_state *st = &s->crtc[i]; - struct intel_crtc *intel_crtc = to_intel_crtc(st->crtc); - struct drm_i915_gem_object *obj; - - if (!st->old.fb) - continue; - - obj = to_intel_framebuffer(st->old.fb)->obj; - - /* Only one bit per plane in pending_flips */ - if (atomic_read(&obj->pending_flip) & (1 << intel_crtc->plane)) - return -EBUSY; - } - - for (i = 0; i < dev->mode_config.num_plane; i++) { - struct intel_plane_state *st = &s->plane[i]; - struct intel_plane *intel_plane = to_intel_plane(st->plane); - struct drm_i915_gem_object *obj; - - if (!st->old.fb) - continue; - - obj = to_intel_framebuffer(st->old.fb)->obj; - - if (!st->old.fb) - continue; - - obj = to_intel_framebuffer(st->old.fb)->obj; - - /* Only one bit per plane in pending_flips */ - if (atomic_read(&obj->pending_flip) & (1 << (16 + intel_plane->pipe))) - return -EBUSY; - }
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) atomic_pipe_commit(dev, s, intel_crtc->pipe); @@ -1582,8 +1546,6 @@ static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state * /* don't restore the old state in end() */ s->dirty = false; s->restore_state = false; - - return 0; }
static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s) @@ -1695,12 +1657,7 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
/* try to apply in a non blocking manner */ if (s->flags & DRM_MODE_ATOMIC_NONBLOCK) { - ret = apply_nonblocking(dev, s); - if (ret) { - unpin_cursors(dev, s); - unpin_fbs(dev, s); - return ret; - } + apply_nonblocking(dev, s); } else { /* apply in a blocking manner */ ret = apply_config(dev, s); @@ -1823,7 +1780,6 @@ static void intel_flip_complete(struct drm_flip *flip) struct intel_flip *intel_flip = container_of(flip, struct intel_flip, base); struct drm_device *dev = intel_flip->crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = intel_flip->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; @@ -1841,18 +1797,6 @@ static void intel_flip_complete(struct drm_flip *flip)
if (intel_flip->vblank_ref) drm_vblank_put(dev, pipe); - - /* Possibly allow rendering to old_bo again */ - if (intel_flip->old_bo) { - if (intel_flip->plane) { - struct intel_plane *intel_plane = to_intel_plane(intel_flip->plane); - atomic_clear_mask(1 << (16 + intel_plane->pipe), &intel_flip->old_bo->pending_flip.counter); - } else - atomic_clear_mask(1 << intel_crtc->plane, &intel_flip->old_bo->pending_flip.counter); - - if (atomic_read(&intel_flip->old_bo->pending_flip) == 0) - wake_up(&dev_priv->pending_flip_queue); - } }
static void intel_flip_finish(struct drm_flip *flip) @@ -2193,13 +2137,6 @@ static void atomic_pipe_commit(struct drm_device *dev, mutex_lock(&dev->struct_mutex); drm_gem_object_reference(&intel_flip->old_bo->base); mutex_unlock(&dev->struct_mutex); - - /* - * Block clients from rendering to the new back buffer until - * the flip occurs and the object is no longer visible. - */ - atomic_set_mask(1 << intel_crtc->plane, - &intel_flip->old_bo->pending_flip.counter); }
list_add_tail(&intel_flip->base.list, &flips); @@ -2244,13 +2181,6 @@ static void atomic_pipe_commit(struct drm_device *dev, mutex_lock(&dev->struct_mutex); drm_gem_object_reference(&intel_flip->old_bo->base); mutex_unlock(&dev->struct_mutex); - - /* - * Block clients from rendering to the new back buffer until - * the flip occurs and the object is no longer visible. - */ - atomic_set_mask(1 << (16 + intel_plane->pipe), - &intel_flip->old_bo->pending_flip.counter); }
list_add_tail(&intel_flip->base.list, &flips);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Avoids a NULL pointer dereference if the atomic modeset fails.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index ac7fe88..98af0ae 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -726,7 +726,8 @@ static int pin_cursors(struct drm_device *dev, if (ret) goto unpin;
- st->cursor_pinned = true; + if (intel_crtc->cursor_bo) + st->cursor_pinned = true; }
return 0;
From: Ville Syrjälä ville.syrjala@linux.intel.com
We have more than one sprite, so a boolean simply won't cut it. Turn sprite_scaling_enabled into a bitmask and track the state of sprite scaler for each sprite independently.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 51b36c1..4cf0e15 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -473,7 +473,7 @@ typedef struct drm_i915_private {
/* overlay */ struct intel_overlay *overlay; - bool sprite_scaling_enabled; + unsigned int sprite_scaling_enabled;
/* LVDS info */ int backlight_level; /* restore backlight to this value */ diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 88fdd0d..97740ee 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -315,15 +315,16 @@ ivb_prepare_plane(struct drm_plane *plane) */ if (regs->scale & SPRITE_SCALE_ENABLE) { if (!dev_priv->sprite_scaling_enabled) { - dev_priv->sprite_scaling_enabled = true; + dev_priv->sprite_scaling_enabled |= 1 << pipe; intel_update_watermarks(dev); intel_wait_for_vblank(dev, pipe); } } else { - if (dev_priv->sprite_scaling_enabled) { - dev_priv->sprite_scaling_enabled = false; + if (dev_priv->sprite_scaling_enabled & (1 << pipe)) { + dev_priv->sprite_scaling_enabled &= ~(1 << pipe); /* potentially re-enable LP watermarks */ - intel_update_watermarks(dev); + if (!dev_priv->sprite_scaling_enabled) + intel_update_watermarks(dev); } } } @@ -359,7 +360,7 @@ ivb_disable_plane(struct drm_plane *plane) ivb_commit_plane(plane); POSTING_READ(SPRSURF(pipe));
- dev_priv->sprite_scaling_enabled = false; + dev_priv->sprite_scaling_enabled &= ~(1 << pipe); intel_update_watermarks(dev); }
From: Ander Conselvan de Oliveira ander.conselvan.de.oliveira@intel.com
intel_crtc->cursor_visible is only changed on the commit phase, so the check for visibility was considering the previous state. Change this to intel_crtc->cursor_handle instead. --- drivers/gpu/drm/i915/intel_atomic.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 98af0ae..c4cec40 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1304,7 +1304,7 @@ static int check_crtc(struct intel_crtc_state *s) } }
- if (intel_crtc->cursor_visible && + if (intel_crtc->cursor_handle && (intel_crtc->cursor_width != 64 || intel_crtc->cursor_height != 64)) { return -EINVAL;
From: Ville Syrjälä ville.syrjala@linux.intel.com
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index c4cec40..bfc0563 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -555,9 +555,9 @@ static void plane_compute_dirty(struct intel_atomic_state *s, return;
if (plane->src_x != state->old.src_x || - plane->src_y != state->old.src_x || - plane->src_w != state->old.src_x || - plane->src_h != state->old.src_x || + plane->src_y != state->old.src_y || + plane->src_w != state->old.src_w || + plane->src_h != state->old.src_h || plane->crtc_x != state->old.crtc_x || plane->crtc_y != state->old.crtc_y || plane->crtc_w != state->old.crtc_w ||
From: Ville Syrjälä ville.syrjala@linux.intel.com
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index bfc0563..a119896 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -1641,13 +1641,15 @@ static int intel_atomic_commit(struct drm_device *dev, void *state) struct intel_atomic_state *s = state; int ret;
- if (!s->dirty) - return 0; - ret = alloc_flip_data(dev, s); if (ret) return ret;
+ if (!s->dirty) { + queue_remaining_events(dev, s); + return 0; + } + ret = pin_fbs(dev, s); if (ret) return ret;
From: Ville Syrjälä ville.syrjala@linux.intel.com
Don't unpin the old fb after flips, unless a new fb was pinned, or we're disabling the plane/crtc.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index a119896..b795cb2 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -2133,8 +2133,10 @@ static void atomic_pipe_commit(struct drm_device *dev, intel_flip->old_cursor_bo = st->old.cursor_bo; }
- if (st->old.fb) { + if (st->old.fb) intel_flip->old_fb_id = st->old.fb->base.id; + + if (st->fb_dirty && st->old.fb) { intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
mutex_lock(&dev->struct_mutex); @@ -2177,8 +2179,10 @@ static void atomic_pipe_commit(struct drm_device *dev,
intel_plane->calc(plane, plane->fb, &st->coords);
- if (st->old.fb) { + if (st->old.fb) intel_flip->old_fb_id = st->old.fb->base.id; + + if (st->dirty && st->old.fb) { intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
mutex_lock(&dev->struct_mutex);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_crtc.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9836755..5f8dda8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2348,6 +2348,11 @@ int drm_mode_addfb2(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL;
+ if (r->flags & ~DRM_MODE_FB_INTERLACED) { + DRM_DEBUG_KMS("bad framebuffer flags %x\n", r->flags); + return -EINVAL; + } + if ((config->min_width > r->width) || (r->width > config->max_width)) { DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", r->width, config->min_width, config->max_width);
From: Ville Syrjälä ville.syrjala@linux.intel.com
After the atomic flip has been split up into individual flip requests for each scanout engine, put each such request into a FIFO. Then for each flip request add new request to the ring(s) in order to get an interrupt once the GPU has finished whatever it was doing with the new front buffer. Once the flip requests associated with the same atomic flip and the same pipe at the head of the queue are ready, pull them from the queue and issue the flips to the hardware.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 8 ++ drivers/gpu/drm/i915/i915_irq.c | 2 + drivers/gpu/drm/i915/intel_atomic.c | 187 ++++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 1 + 4 files changed, 182 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4cf0e15..87f5cba 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -885,6 +885,14 @@ typedef struct drm_i915_private { uint32_t hw_context_size;
struct drm_flip_driver flip_driver; + + struct { + struct list_head list; + spinlock_t lock; + struct work_struct work; + struct workqueue_struct *wq; + unsigned int next_flip_seq; + } flip; } drm_i915_private_t;
/* Iterate over initialised rings */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ee22e97..cec1ea6 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -343,6 +343,8 @@ static void notify_ring(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private;
+ intel_atomic_notify_ring(dev, ring); + if (ring->obj == NULL) return;
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index b795cb2..bfa6da6 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -42,6 +42,10 @@ struct intel_flip { struct drm_pending_atomic_event *event; uint32_t old_fb_id; struct list_head pending_head; + struct intel_ring_buffer *ring; + u32 seqno; + bool busy; + unsigned int flip_seq; };
struct intel_plane_state { @@ -801,6 +805,7 @@ static int pin_fbs(struct drm_device *dev, struct intel_atomic_state *s) { int i, ret; + bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK;
for (i = 0; i < dev->mode_config.num_crtc; i++) { struct intel_crtc_state *st = &s->crtc[i]; @@ -816,7 +821,7 @@ static int pin_fbs(struct drm_device *dev, obj = to_intel_framebuffer(crtc->fb)->obj;
mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); + ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL); mutex_unlock(&dev->struct_mutex);
if (ret) @@ -839,7 +844,7 @@ static int pin_fbs(struct drm_device *dev, obj = to_intel_framebuffer(plane->fb)->obj;
mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); + ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL); mutex_unlock(&dev->struct_mutex);
if (ret) @@ -2047,6 +2052,8 @@ static const struct drm_flip_driver_funcs intel_flip_driver_funcs = { .flush = intel_flip_driver_flush, };
+static void intel_atomic_process_flips_work(struct work_struct *work); + static void intel_flip_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2065,6 +2072,11 @@ static void intel_flip_init(struct drm_device *dev) list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) drm_flip_helper_init(&intel_plane->flip_helper, &dev_priv->flip_driver, &intel_flip_funcs); + + INIT_LIST_HEAD(&dev_priv->flip.list); + spin_lock_init(&dev_priv->flip.lock); + INIT_WORK(&dev_priv->flip.work, intel_atomic_process_flips_work); + dev_priv->flip.wq = create_singlethread_workqueue("intel_flip"); }
static void intel_flip_fini(struct drm_device *dev) @@ -2082,6 +2094,145 @@ static void intel_flip_fini(struct drm_device *dev) drm_flip_driver_fini(&dev_priv->flip_driver); }
+static void intel_atomic_postpone_flip(struct drm_device *dev, + struct intel_flip *intel_flip) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = intel_flip->ring; + int ret; + + intel_flip->busy = ring != NULL; + + list_move_tail(&intel_flip->base.list, &dev_priv->flip.list); + + if (!ring) + return; + + if (WARN_ON(!ring->irq_get(ring))) { + intel_flip->busy = false; + return; + } + + ret = i915_add_request(ring, NULL, &intel_flip->seqno); + if (WARN_ON(ret)) { + ring->irq_put(ring); + intel_flip->busy = false; + return; + } +} + +static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc, + struct list_head *flips) +{ + if (!intel_crtc->active) { + drm_flip_driver_complete_flips(&dev_priv->flip_driver, flips); + return; + } + + drm_flip_driver_prepare_flips(&dev_priv->flip_driver, flips); + + local_irq_disable(); + + intel_pipe_vblank_evade(&intel_crtc->base); + + drm_flip_driver_schedule_flips(&dev_priv->flip_driver, flips); + + local_irq_enable(); +} + +static bool intel_atomic_flips_ready(struct drm_device *dev, unsigned int flip_seq) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_flip *intel_flip; + + /* check if all flips w/ same flip_seq are ready */ + list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) { + if (intel_flip->flip_seq != flip_seq) + break; + + if (intel_flip->busy) + return false; + } + + return true; +} + +static void intel_atomic_process_flips_work(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, flip.work); + struct drm_device *dev = dev_priv->dev; + + for (;;) { + struct intel_flip *intel_flip, *next; + unsigned int flip_seq; + struct intel_crtc *intel_crtc; + LIST_HEAD(flips); + unsigned long flags; + + if (list_empty(&dev_priv->flip.list)) + return; + + spin_lock_irqsave(&dev_priv->flip.lock, flags); + + intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list); + flip_seq = intel_flip->flip_seq; + intel_crtc = to_intel_crtc(intel_flip->crtc); + + if (intel_atomic_flips_ready(dev, flip_seq)) { + list_for_each_entry_safe(intel_flip, next, &dev_priv->flip.list, base.list) { + if (intel_flip->flip_seq != flip_seq) + break; + list_move_tail(&intel_flip->base.list, &flips); + } + } + + spin_unlock_irqrestore(&dev_priv->flip.lock, flags); + + if (list_empty(&flips)) + return; + + mutex_lock(&dev->mode_config.mutex); + intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips); + mutex_unlock(&dev->mode_config.mutex); + } +} + +void intel_atomic_notify_ring(struct drm_device *dev, + struct intel_ring_buffer *ring) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_flip *intel_flip; + unsigned long flags; + u32 seqno; + + if (list_empty(&dev_priv->flip.list)) + return; + + seqno = ring->get_seqno(ring, false); + + spin_lock_irqsave(&dev_priv->flip.lock, flags); + + list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) { + if (ring != intel_flip->ring) + continue; + + if (intel_flip->busy && i915_seqno_passed(seqno, intel_flip->seqno)) { + intel_flip->busy = false; + ring->irq_put(ring); + } + } + + if (!list_empty(&dev_priv->flip.list)) { + intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list); + + if (intel_atomic_flips_ready(dev, intel_flip->flip_seq)) + queue_work(dev_priv->flip.wq, &dev_priv->flip.work); + } + + spin_unlock_irqrestore(&dev_priv->flip.lock, flags); +} + static void atomic_pipe_commit(struct drm_device *dev, struct intel_atomic_state *state, int pipe) @@ -2090,7 +2241,9 @@ static void atomic_pipe_commit(struct drm_device *dev, struct drm_i915_file_private *file_priv = state->file->driver_priv; LIST_HEAD(flips); int i; - bool pipe_enabled = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe))->active; + unsigned int flip_seq = dev_priv->flip.next_flip_seq++; + struct intel_flip *intel_flip, *next; + unsigned long flags;
for (i = 0; i < dev->mode_config.num_crtc; i++) { struct intel_crtc_state *st = &state->crtc[i]; @@ -2109,6 +2262,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
drm_flip_init(&intel_flip->base, &intel_crtc->flip_helper);
+ intel_flip->flip_seq = flip_seq; + if (st->event) { intel_flip->event = st->event; st->event = NULL; @@ -2121,6 +2276,9 @@ static void atomic_pipe_commit(struct drm_device *dev,
intel_flip->crtc = crtc;
+ if (crtc->fb) + intel_flip->ring = to_intel_framebuffer(crtc->fb)->obj->ring; + /* update primary_disabled befoer calc_plane() */ intel_crtc->primary_disabled = st->primary_disabled;
@@ -2164,6 +2322,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
drm_flip_init(&intel_flip->base, &intel_plane->flip_helper);
+ intel_flip->flip_seq = flip_seq; + if (st->event) { intel_flip->event = st->event; st->event = NULL; @@ -2177,6 +2337,9 @@ static void atomic_pipe_commit(struct drm_device *dev, intel_flip->crtc = intel_get_crtc_for_pipe(dev, pipe); intel_flip->plane = plane;
+ if (plane->fb) + intel_flip->ring = to_intel_framebuffer(plane->fb)->obj->ring; + intel_plane->calc(plane, plane->fb, &st->coords);
if (st->old.fb) @@ -2196,20 +2359,12 @@ static void atomic_pipe_commit(struct drm_device *dev, if (list_empty(&flips)) return;
- if (!pipe_enabled) { - drm_flip_driver_complete_flips(&dev_priv->flip_driver, &flips); - return; - } - - drm_flip_driver_prepare_flips(&dev_priv->flip_driver, &flips); + spin_lock_irqsave(&dev_priv->flip.lock, flags); + list_for_each_entry_safe(intel_flip, next, &flips, base.list) + intel_atomic_postpone_flip(dev, intel_flip); + spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
- local_irq_disable(); - - intel_pipe_vblank_evade(intel_get_crtc_for_pipe(dev, pipe)); - - drm_flip_driver_schedule_flips(&dev_priv->flip_driver, &flips); - - local_irq_enable(); + queue_work(dev_priv->flip.wq, &dev_priv->flip.work); }
void intel_atomic_handle_vblank(struct drm_device *dev, int pipe) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4847170..da16cc0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -637,6 +637,7 @@ extern void intel_atomic_fini(struct drm_device *dev); extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file); extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe); extern void intel_atomic_clear_flips(struct drm_crtc *crtc); +extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring);
extern void intel_enable_primary(struct drm_crtc *crtc); extern void intel_disable_primary(struct drm_crtc *crtc);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Add a module parameter that allows one to easily change between blocking and non-blocking GPU synchronization with atomic page flips.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_stub.c | 5 +++++ drivers/gpu/drm/i915/intel_atomic.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index c236fd2..52d5750 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -46,16 +46,21 @@ EXPORT_SYMBOL(drm_vblank_offdelay); unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ EXPORT_SYMBOL(drm_timestamp_precision);
+unsigned int drm_async_gpu = 0; /* 1 to enable async gpu wait */ +EXPORT_SYMBOL(drm_async_gpu); + MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); +MODULE_PARM_DESC(async_gpu, "Async GPU wait");
module_param_named(debug, drm_debug, int, 0600); module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); +module_param_named(async_gpu, drm_async_gpu, int, 0600);
struct idr drm_minors_idr;
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index bfa6da6..d3aa566 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -801,11 +801,13 @@ static void unpin_fbs(struct drm_device *dev, } }
+extern unsigned int drm_async_gpu; + static int pin_fbs(struct drm_device *dev, struct intel_atomic_state *s) { int i, ret; - bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK; + bool nonblock = drm_async_gpu && (s->flags & DRM_MODE_ATOMIC_NONBLOCK);
for (i = 0; i < dev->mode_config.num_crtc; i++) { struct intel_crtc_state *st = &s->crtc[i]; @@ -2359,6 +2361,12 @@ static void atomic_pipe_commit(struct drm_device *dev, if (list_empty(&flips)) return;
+ if (!drm_async_gpu) { + struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips); + return; + } + spin_lock_irqsave(&dev_priv->flip.lock, flags); list_for_each_entry_safe(intel_flip, next, &flips, base.list) intel_atomic_postpone_flip(dev, intel_flip);
From: Ville Syrjälä ville.syrjala@linux.intel.com
Print some information on how many flips are in the queue waiting for the GPU. There's no limit on the queue length currently.
Signed-off-by: Ville Syrjälä ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_atomic.c | 4 ++++ 2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 87f5cba..5c089b2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -892,6 +892,7 @@ typedef struct drm_i915_private { struct work_struct work; struct workqueue_struct *wq; unsigned int next_flip_seq; + unsigned int queue_len; } flip; } drm_i915_private_t;
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index d3aa566..d7cc978 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -2106,6 +2106,7 @@ static void intel_atomic_postpone_flip(struct drm_device *dev, intel_flip->busy = ring != NULL;
list_move_tail(&intel_flip->base.list, &dev_priv->flip.list); + dev_priv->flip.queue_len++;
if (!ring) return; @@ -2186,6 +2187,7 @@ static void intel_atomic_process_flips_work(struct work_struct *work) if (intel_flip->flip_seq != flip_seq) break; list_move_tail(&intel_flip->base.list, &flips); + dev_priv->flip.queue_len--; } }
@@ -2197,6 +2199,8 @@ static void intel_atomic_process_flips_work(struct work_struct *work) mutex_lock(&dev->mode_config.mutex); intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips); mutex_unlock(&dev->mode_config.mutex); + + DRM_DEBUG_KMS("flip queue length = %u\n", dev_priv->flip.queue_len); } }
dri-devel@lists.freedesktop.org