From c44ef60e437019b8ca1dab8b4d2e8761fd4ce1e9 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Thu, 25 Jun 2015 18:35:05 +0300 Subject: drm/i915/gtt: Allow >= 4GB sizes for vm. We can have exactly 4GB sized ppgtt with 32bit system. size_t is inadequate for this. v2: Convert a lot more places (Daniel) Signed-off-by: Mika Kuoppala Reviewed-by: Michel Thierry Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/drm') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index b08bdade6002..9e9bddaa58a5 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -3,8 +3,8 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H -void intel_gtt_get(size_t *gtt_total, size_t *stolen_size, - phys_addr_t *mappable_base, unsigned long *mappable_end); +void intel_gtt_get(u64 *gtt_total, size_t *stolen_size, + phys_addr_t *mappable_base, u64 *mappable_end); int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, struct agp_bridge_data *bridge); -- cgit v1.2.3 From 0e975980d435d58df2d430d688b8c18778b42218 Mon Sep 17 00:00:00 2001 From: Peter Antoine Date: Tue, 23 Jun 2015 08:18:49 +0100 Subject: drm: Turn off Legacy Context Functions The context functions are not used by the i915 driver and should not be used by modeset drivers. These driver functions contain several bugs and security holes. This change makes these functions optional can be turned on by a setting, they are turned off by default for modeset driver with the exception of the nouvea driver that may require them with an old version of libdrm. The previous attempt was commit 7c510133d93dd6f15ca040733ba7b2891ed61fd1 Author: Daniel Vetter Date: Thu Aug 8 15:41:21 2013 +0200 drm: mark context support as a legacy subsystem but this had to be reverted commit c21eb21cb50d58e7cbdcb8b9e7ff68b85cfa5095 Author: Dave Airlie Date: Fri Sep 20 08:32:59 2013 +1000 Revert "drm: mark context support as a legacy subsystem" v2: remove returns from void function, and formatting (Daniel Vetter) v3: - s/Nova/nouveau/ in the commit message, and add references to the previous attempts - drop the part touching the drm hw lock, that should be a separate patch. Signed-off-by: Peter Antoine (v2) Cc: Peter Antoine (v2) Reviewed-by: Peter Antoine Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_context.c | 48 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_drv.c | 13 ++++++---- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 ++- include/drm/drmP.h | 23 +++++++++-------- 4 files changed, 70 insertions(+), 17 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 9b23525c0ed0..32958dabd7b0 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -53,6 +53,10 @@ struct drm_ctx_list { */ void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle) { + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return; + mutex_lock(&dev->struct_mutex); idr_remove(&dev->ctx_idr, ctx_handle); mutex_unlock(&dev->struct_mutex); @@ -87,6 +91,10 @@ static int drm_legacy_ctxbitmap_next(struct drm_device * dev) */ int drm_legacy_ctxbitmap_init(struct drm_device * dev) { + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + idr_init(&dev->ctx_idr); return 0; } @@ -101,6 +109,10 @@ int drm_legacy_ctxbitmap_init(struct drm_device * dev) */ void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) { + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return; + mutex_lock(&dev->struct_mutex); idr_destroy(&dev->ctx_idr); mutex_unlock(&dev->struct_mutex); @@ -119,6 +131,10 @@ void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file) { struct drm_ctx_list *pos, *tmp; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return; + mutex_lock(&dev->ctxlist_mutex); list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) { @@ -161,6 +177,10 @@ int drm_legacy_getsareactx(struct drm_device *dev, void *data, struct drm_local_map *map; struct drm_map_list *_entry; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + mutex_lock(&dev->struct_mutex); map = idr_find(&dev->ctx_idr, request->ctx_id); @@ -205,6 +225,10 @@ int drm_legacy_setsareactx(struct drm_device *dev, void *data, struct drm_local_map *map = NULL; struct drm_map_list *r_list = NULL; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map @@ -305,6 +329,10 @@ int drm_legacy_resctx(struct drm_device *dev, void *data, struct drm_ctx ctx; int i; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + if (res->count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { @@ -335,6 +363,10 @@ int drm_legacy_addctx(struct drm_device *dev, void *data, struct drm_ctx_list *ctx_entry; struct drm_ctx *ctx = data; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + ctx->handle = drm_legacy_ctxbitmap_next(dev); if (ctx->handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ @@ -378,6 +410,10 @@ int drm_legacy_getctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + /* This is 0, because we don't handle any context flags */ ctx->flags = 0; @@ -400,6 +436,10 @@ int drm_legacy_switchctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); return drm_context_switch(dev, dev->last_context, ctx->handle); } @@ -420,6 +460,10 @@ int drm_legacy_newctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); drm_context_switch_complete(dev, file_priv, ctx->handle); @@ -442,6 +486,10 @@ int drm_legacy_rmctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; + if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && + drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + DRM_DEBUG("%d\n", ctx->handle); if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b7bf4ce8c012..838657503113 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -582,11 +582,14 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver, if (drm_ht_create(&dev->map_hash, 12)) goto err_minors; - ret = drm_legacy_ctxbitmap_init(dev); - if (ret) { - DRM_ERROR("Cannot allocate memory for context bitmap.\n"); - goto err_ht; - } + if (drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) || + !drm_core_check_feature(dev, DRIVER_MODESET)) + ret = drm_legacy_ctxbitmap_init(dev); + if (ret) { + DRM_ERROR( + "Cannot allocate memory for context bitmap.\n"); + goto err_ht; + } if (drm_core_check_feature(dev, DRIVER_GEM)) { ret = drm_gem_init(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 89049335b738..9624b3827c34 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -941,7 +941,8 @@ static struct drm_driver driver_stub = { .driver_features = DRIVER_USE_AGP | - DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER, + DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | + DRIVER_KMS_LEGACY_CONTEXT, .load = nouveau_drm_load, .unload = nouveau_drm_unload, diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 48db6a56975f..3dc7c16c18f2 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -137,17 +137,18 @@ void drm_err(const char *format, ...); /*@{*/ /* driver capabilities and requirements mask */ -#define DRIVER_USE_AGP 0x1 -#define DRIVER_PCI_DMA 0x8 -#define DRIVER_SG 0x10 -#define DRIVER_HAVE_DMA 0x20 -#define DRIVER_HAVE_IRQ 0x40 -#define DRIVER_IRQ_SHARED 0x80 -#define DRIVER_GEM 0x1000 -#define DRIVER_MODESET 0x2000 -#define DRIVER_PRIME 0x4000 -#define DRIVER_RENDER 0x8000 -#define DRIVER_ATOMIC 0x10000 +#define DRIVER_USE_AGP 0x1 +#define DRIVER_PCI_DMA 0x8 +#define DRIVER_SG 0x10 +#define DRIVER_HAVE_DMA 0x20 +#define DRIVER_HAVE_IRQ 0x40 +#define DRIVER_IRQ_SHARED 0x80 +#define DRIVER_GEM 0x1000 +#define DRIVER_MODESET 0x2000 +#define DRIVER_PRIME 0x4000 +#define DRIVER_RENDER 0x8000 +#define DRIVER_ATOMIC 0x10000 +#define DRIVER_KMS_LEGACY_CONTEXT 0x20000 /***********************************************************************/ /** \name Macros to make printk easier */ -- cgit v1.2.3 From 4ea50e99bd3501aea394aa7a9e9bd3115faabf37 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:24 +0200 Subject: drm: Simplify drm_for_each_legacy_plane arguments No need to pass the planelist when everyone just uses dev->mode_config.plane_list anyway. I want to add a pile more of iterators with unified (obj, dev) arguments. This is just prep. Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 +- include/drm/drm_crtc.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0d3e01434860..5004c4a46a9e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2356,7 +2356,7 @@ static void ilk_compute_wm_parameters(struct drm_crtc *crtc, p->pri.horiz_pixels = intel_crtc->config->pipe_src_w; p->cur.horiz_pixels = intel_crtc->base.cursor->state->crtc_w; - drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { + drm_for_each_legacy_plane(plane, dev) { struct intel_plane *intel_plane = to_intel_plane(plane); if (intel_plane->pipe == pipe) { diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 859ccb658601..e9272b0a8592 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -248,7 +248,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc) lcdc_write(sdev, LDDDSR, value); /* Setup planes. */ - drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { + drm_for_each_legacy_plane(plane, dev) { if (plane->crtc == crtc) shmob_drm_plane_setup(plane); } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 57ca8cc383a6..5cf0e6c3fc41 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1579,8 +1579,8 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev, } /* Plane list iterator for legacy (overlay only) planes. */ -#define drm_for_each_legacy_plane(plane, planelist) \ - list_for_each_entry(plane, planelist, head) \ +#define drm_for_each_legacy_plane(plane, dev) \ + list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ if (plane->type == DRM_PLANE_TYPE_OVERLAY) #endif /* __DRM_CRTC_H__ */ -- cgit v1.2.3 From 6295d607ad34ee4e43aab3f20714c2ef7a6adea1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:25 +0200 Subject: drm: Add modeset object iterators And roll them out across drm_* files. The point here isn't code prettification (it helps with that too) but that some of these lists aren't static any more. And having macros will gives us a convenient place to put locking checks into. I didn't add an iterator for props since that's only used by a list_for_each_entry_safe in the driver teardown code. Search&replace was done with the below cocci spatch. Note that there's a bunch more places that didn't match and which would need some manual changes, but I've intentially left these out for this mostly automated patch. iterator name drm_for_each_crtc; struct drm_crtc *crtc; struct drm_device *dev; expression head; @@ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc (crtc, dev) { ... } @@ iterator name drm_for_each_encoder; struct drm_encoder *encoder; struct drm_device *dev; expression head; @@ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder (encoder, dev) { ... } @@ iterator name drm_for_each_fb; struct drm_framebuffer *fb; struct drm_device *dev; expression head; @@ - list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + drm_for_each_fb (fb, dev) { ... } @@ iterator name drm_for_each_connector; struct drm_connector *connector; struct drm_device *dev; expression head; @@ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector (connector, dev) { ... } Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 21 ++++++++------------- drivers/gpu/drm/drm_crtc_helper.c | 34 +++++++++++++++++----------------- drivers/gpu/drm/drm_fb_helper.c | 10 +++++----- drivers/gpu/drm/drm_of.c | 2 +- drivers/gpu/drm/drm_probe_helper.c | 6 +++--- include/drm/drm_crtc.h | 15 +++++++++++++++ 6 files changed, 49 insertions(+), 39 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 9c978d9de3b8..9b05dc76379e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -615,7 +615,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) if (atomic_read(&fb->refcount.refcount) > 1) { drm_modeset_lock_all(dev); /* remove from any CRTC */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(crtc, dev) { if (crtc->primary->fb == fb) { /* should turn off the crtc */ memset(&set, 0, sizeof(struct drm_mode_set)); @@ -627,7 +627,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) } } - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + drm_for_each_plane(plane, dev) { if (plane->fb == fb) drm_plane_force_disable(plane); } @@ -1305,7 +1305,7 @@ drm_plane_from_index(struct drm_device *dev, int idx) struct drm_plane *plane; unsigned int i = 0; - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + drm_for_each_plane(plane, dev) { if (i == idx) return plane; i++; @@ -1838,8 +1838,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, copied = 0; crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; if (!mode_group) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, - head) { + drm_for_each_crtc(crtc, dev) { DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); if (put_user(crtc->base.id, crtc_id + copied)) { ret = -EFAULT; @@ -1865,9 +1864,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, copied = 0; encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; if (!mode_group) { - list_for_each_entry(encoder, - &dev->mode_config.encoder_list, - head) { + drm_for_each_encoder(encoder, dev) { DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, encoder->name); if (put_user(encoder->base.id, encoder_id + @@ -1896,9 +1893,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, copied = 0; connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; if (!mode_group) { - list_for_each_entry(connector, - &dev->mode_config.connector_list, - head) { + drm_for_each_connector(connector, dev) { DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); @@ -2187,7 +2182,7 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) /* For atomic drivers only state objects are synchronously updated and * protected by modeset locks, so check those first. */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { if (!connector->state) continue; @@ -5393,7 +5388,7 @@ void drm_mode_config_reset(struct drm_device *dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { connector->status = connector_status_unknown; if (connector->funcs->reset) diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 393114df88a3..30254fb249fe 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -180,7 +180,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev) drm_warn_on_modeset_not_all_locked(dev); - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (!drm_helper_encoder_in_use(encoder)) { drm_encoder_disable(encoder); /* disconnect encoder from any connector */ @@ -188,7 +188,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev) } } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(crtc, dev) { const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; crtc->enabled = drm_helper_crtc_in_use(crtc); if (!crtc->enabled) { @@ -230,7 +230,7 @@ drm_crtc_prepare_encoders(struct drm_device *dev) const struct drm_encoder_helper_funcs *encoder_funcs; struct drm_encoder *encoder; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { encoder_funcs = encoder->helper_private; /* Disable unused encoders */ if (encoder->crtc == NULL) @@ -305,7 +305,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, * adjust it according to limitations or connector properties, and also * a chance to reject the mode entirely. */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (encoder->crtc != crtc) continue; @@ -334,7 +334,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, crtc->hwmode = *adjusted_mode; /* Prepare the encoders and CRTCs before setting the mode. */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (encoder->crtc != crtc) continue; @@ -359,7 +359,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!ret) goto done; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (encoder->crtc != crtc) continue; @@ -376,7 +376,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, /* Now enable the clocks, plane, pipe, and connectors that we set up. */ crtc_funcs->commit(crtc); - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (encoder->crtc != crtc) continue; @@ -418,11 +418,11 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) struct drm_encoder *encoder; /* Decouple all encoders and their attached connectors from this crtc */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if (encoder->crtc != crtc) continue; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { if (connector->encoder != encoder) continue; @@ -519,12 +519,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) * restored, not the drivers personal bookkeeping. */ count = 0; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { save_encoders[count++] = *encoder; } count = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { save_connectors[count++] = *connector; } @@ -562,7 +562,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) /* a) traverse passed in connector list and get encoders for them */ count = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; new_encoder = connector->encoder; @@ -602,7 +602,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } count = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { if (!connector->encoder) continue; @@ -685,12 +685,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) fail: /* Restore all previous data. */ count = 0; - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { *encoder = save_encoders[count++]; } count = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { *connector = save_connectors[count++]; } @@ -862,7 +862,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) bool ret; drm_modeset_lock_all(dev); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(crtc, dev) { if (!crtc->enabled) continue; @@ -876,7 +876,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) /* Turn off outputs that were already powered off */ if (drm_helper_choose_crtc_dpms(crtc)) { - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + drm_for_each_encoder(encoder, dev) { if(encoder->crtc != crtc) continue; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index cac422916c7a..3630d92c9738 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -98,7 +98,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) struct drm_connector *connector; int i; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { struct drm_fb_helper_connector *fb_helper_connector; fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); @@ -269,7 +269,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_crtc *c; - list_for_each_entry(c, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(c, dev) { if (crtc->base.id == c->base.id) return c->primary->fb; } @@ -321,7 +321,7 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) drm_warn_on_modeset_not_all_locked(dev); - list_for_each_entry(plane, &dev->mode_config.plane_list, head) { + drm_for_each_plane(plane, dev) { if (plane->type != DRM_PLANE_TYPE_PRIMARY) drm_plane_force_disable(plane); @@ -458,7 +458,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) if (dev->primary->master) return false; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(crtc, dev) { if (crtc->primary->fb) crtcs_bound++; if (crtc->primary->fb == fb_helper->fb) @@ -655,7 +655,7 @@ int drm_fb_helper_init(struct drm_device *dev, } i = 0; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(crtc, dev) { fb_helper->crtc_info[i].mode_set.crtc = crtc; i++; } diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index aaa130736bf8..be3884073ea4 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -19,7 +19,7 @@ static uint32_t drm_crtc_port_mask(struct drm_device *dev, unsigned int index = 0; struct drm_crtc *tmp; - list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { + drm_for_each_crtc(tmp, dev) { if (tmp->port == port) return 1 << index; diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 04203c0d2ecb..64d85c1bd18b 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -312,7 +312,7 @@ static void output_poll_execute(struct work_struct *work) goto out; mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { /* Ignore forced connectors. */ if (connector->force) @@ -413,7 +413,7 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) return; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) poll = true; @@ -495,7 +495,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) return false; mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_for_each_connector(connector, dev) { /* Only handle HPD capable connectors. */ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 5cf0e6c3fc41..7c95a7df6065 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1583,4 +1583,19 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev, list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ if (plane->type == DRM_PLANE_TYPE_OVERLAY) +#define drm_for_each_plane(plane, dev) \ + list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) + +#define drm_for_each_crtc(crtc, dev) \ + list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head) + +#define drm_for_each_connector(connector, dev) \ + list_for_each_entry(connector, &(dev)->mode_config.connector_list, head) + +#define drm_for_each_encoder(encoder, dev) \ + list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head) + +#define drm_for_each_fb(fb, dev) \ + list_for_each_entry(fb, &(dev)->mode_config.fb_list, head) + #endif /* __DRM_CRTC_H__ */ -- cgit v1.2.3 From 7a3f3d6667f5f9ffd1517f6b21d64bbf5312042c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:28 +0200 Subject: drm: Check locking in drm_for_each_connector Because of DP MST connectors can now be hotplugged and we must hold the right lock when walking the connector lists. Enforce this by checking the locking in our shiny new list walking macros. v2: Extract the locking check into a small static inline helper to help readability. This will be more important when we make the read list access rules more complicated in later patches. Inspired by comments from Chris. Unfortunately, due to header loops around the definition of struct drm_device the function interface is a bit funny. v3: Encoders aren't hotadded/removed. For each dp mst encoder we statically create one fake encoder per pipe so that we can support as many mst sinks as the hw can (Dave). Cc: Chris Wilson Cc: Dave Airlie Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7c95a7df6065..499562274353 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1589,8 +1589,18 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev, #define drm_for_each_crtc(crtc, dev) \ list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head) +static inline void +assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config) +{ + WARN_ON(!mutex_is_locked(&mode_config->mutex)); +} + #define drm_for_each_connector(connector, dev) \ - list_for_each_entry(connector, &(dev)->mode_config.connector_list, head) + for (assert_drm_connector_list_read_locked(&(dev)->mode_config), \ + connector = list_first_entry(&(dev)->mode_config.connector_list, \ + struct drm_connector, head); \ + &connector->head != (&(dev)->mode_config.connector_list); \ + connector = list_next_entry(connector, head)) #define drm_for_each_encoder(encoder, dev) \ list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head) -- cgit v1.2.3 From 4676ba0be756b2b02b9737147713d458042962f7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:30 +0200 Subject: drm: Check locking in drm_for_each_fb Ever since framebuffers are reference counted we have a special lock for the global fb list. Make sure users of that list do hold that lock when using the new iterators. Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 499562274353..10547be5684a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1606,6 +1606,10 @@ assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config) list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head) #define drm_for_each_fb(fb, dev) \ - list_for_each_entry(fb, &(dev)->mode_config.fb_list, head) + for (WARN_ON(!mutex_is_locked(&(dev)->mode_config.fb_lock)), \ + fb = list_first_entry(&(dev)->mode_config.fb_list, \ + struct drm_framebuffer, head); \ + &fb->head != (&(dev)->mode_config.fb_list); \ + fb = list_next_entry(fb, head)) #endif /* __DRM_CRTC_H__ */ -- cgit v1.2.3 From cff20ba2758d6b82978be5b1f40536bfc121af88 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:33 +0200 Subject: drm: Amend connector list locking rules Now that dp mst hotplug takes all locks we can amend the locking rules for the iterators. This is needed before we can roll these out in the atomic code to avoid getting burried in WARNINGs. v2: Rebase onto the extracted list locking assert and add a comment to explain the rules. v3: Fixup German->English translation fail in the comment. Cc: Chris Wilson Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 10547be5684a..fe3100115a41 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1592,7 +1592,15 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev, static inline void assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config) { - WARN_ON(!mutex_is_locked(&mode_config->mutex)); + /* + * The connector hotadd/remove code currently grabs both locks when + * updating lists. Hence readers need only hold either of them to be + * safe and the check amounts to + * + * WARN_ON(not_holding(A) && not_holding(B)). + */ + WARN_ON(!mutex_is_locked(&mode_config->mutex) && + !drm_modeset_is_locked(&mode_config->connection_mutex)); } #define drm_for_each_connector(connector, dev) \ -- cgit v1.2.3 From 3fdefa399e4644399ce3e74e65a75122d52dba6a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 9 Jul 2015 23:44:37 +0200 Subject: drm: gc now dead mode_group code Two nice things here: - drm_dev_register will truly register everything in the right order if the driver doesn't have a ->load callback. Before this we had to init the primary mode_group after the device nodes where already registered. - Less things to keep track of when reworking the connector locking, yay! Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 64 ---------------------------------- drivers/gpu/drm/drm_drv.c | 12 ------- drivers/gpu/drm/i915/intel_dp_mst.c | 3 -- drivers/gpu/drm/radeon/radeon_dp_mst.c | 3 -- include/drm/drmP.h | 1 - include/drm/drm_crtc.h | 26 -------------- 6 files changed, 109 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 805ef2f408a7..e385014ed616 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1679,70 +1679,6 @@ int drm_mode_create_suggested_offset_properties(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); -static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) -{ - uint32_t total_objects = 0; - - total_objects += dev->mode_config.num_crtc; - total_objects += dev->mode_config.num_connector; - total_objects += dev->mode_config.num_encoder; - - group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); - if (!group->id_list) - return -ENOMEM; - - group->num_crtcs = 0; - group->num_connectors = 0; - group->num_encoders = 0; - return 0; -} - -void drm_mode_group_destroy(struct drm_mode_group *group) -{ - kfree(group->id_list); - group->id_list = NULL; -} - -/* - * NOTE: Driver's shouldn't ever call drm_mode_group_init_legacy_group - it is - * the drm core's responsibility to set up mode control groups. - */ -int drm_mode_group_init_legacy_group(struct drm_device *dev, - struct drm_mode_group *group) -{ - struct drm_crtc *crtc; - struct drm_encoder *encoder; - struct drm_connector *connector; - int ret; - - ret = drm_mode_group_init(dev, group); - if (ret) - return ret; - - drm_for_each_crtc(crtc, dev) - group->id_list[group->num_crtcs++] = crtc->base.id; - - drm_for_each_encoder(encoder, dev) - group->id_list[group->num_crtcs + group->num_encoders++] = - encoder->base.id; - - drm_for_each_connector(connector, dev) - group->id_list[group->num_crtcs + group->num_encoders + - group->num_connectors++] = connector->base.id; - - return 0; -} -EXPORT_SYMBOL(drm_mode_group_init_legacy_group); - -void drm_reinit_primary_mode_group(struct drm_device *dev) -{ - drm_modeset_lock_all(dev); - drm_mode_group_destroy(&dev->primary->mode_group); - drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); - drm_modeset_unlock_all(dev); -} -EXPORT_SYMBOL(drm_reinit_primary_mode_group); - /** * drm_mode_getresources - get graphics configuration * @dev: drm device for the ioctl diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b7bf4ce8c012..f7798c3b543e 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -285,7 +285,6 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type) if (!minor) return; - drm_mode_group_destroy(&minor->mode_group); put_device(minor->kdev); spin_lock_irqsave(&drm_minor_lock, flags); @@ -705,20 +704,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) goto err_minors; } - /* setup grouping for legacy outputs */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = drm_mode_group_init_legacy_group(dev, - &dev->primary->mode_group); - if (ret) - goto err_unload; - } - ret = 0; goto out_unlock; -err_unload: - if (dev->driver->unload) - dev->driver->unload(dev); err_minors: drm_minor_unregister(dev, DRM_MINOR_LEGACY); drm_minor_unregister(dev, DRM_MINOR_RENDER); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index d0b2569c6241..585f0a45b3f1 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -441,7 +441,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0); drm_mode_connector_set_path_property(connector, pathprop); - drm_reinit_primary_mode_group(dev); drm_modeset_lock_all(dev); intel_connector_add_to_fbdev(intel_connector); drm_modeset_unlock_all(dev); @@ -466,8 +465,6 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_connector_cleanup(connector); drm_modeset_unlock_all(dev); - drm_reinit_primary_mode_group(dev); - kfree(intel_connector); DRM_DEBUG_KMS("\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index e649c8ff20a0..e4fc8f3bf58b 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -284,7 +284,6 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); drm_mode_connector_set_path_property(connector, pathprop); - drm_reinit_primary_mode_group(dev); drm_modeset_lock_all(dev); radeon_fb_add_connector(rdev, connector); @@ -309,8 +308,6 @@ static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_connector_cleanup(connector); drm_modeset_unlock_all(dev); - drm_reinit_primary_mode_group(dev); - kfree(connector); DRM_DEBUG_KMS("\n"); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 48db6a56975f..c89351ede92c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -675,7 +675,6 @@ struct drm_minor { /* currently active master for this node. Protected by master_mutex */ struct drm_master *master; - struct drm_mode_group mode_group; }; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index fe3100115a41..3071319ea194 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1017,29 +1017,6 @@ struct drm_mode_config_funcs { void (*atomic_state_free)(struct drm_atomic_state *state); }; -/** - * struct drm_mode_group - group of mode setting resources for potential sub-grouping - * @num_crtcs: CRTC count - * @num_encoders: encoder count - * @num_connectors: connector count - * @num_bridges: bridge count - * @id_list: list of KMS object IDs in this group - * - * Currently this simply tracks the global mode setting state. But in the - * future it could allow groups of objects to be set aside into independent - * control groups for use by different user level processes (e.g. two X servers - * running simultaneously on different heads, each with their own mode - * configuration and freedom of mode setting). - */ -struct drm_mode_group { - uint32_t num_crtcs; - uint32_t num_encoders; - uint32_t num_connectors; - - /* list of object IDs for this group */ - uint32_t *id_list; -}; - /** * struct drm_mode_config - Mode configuration control structure * @mutex: mutex protecting KMS related lists and structures @@ -1324,9 +1301,6 @@ extern const char *drm_get_tv_select_name(int val); extern void drm_fb_release(struct drm_file *file_priv); extern void drm_property_destroy_user_blobs(struct drm_device *dev, struct drm_file *file_priv); -extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); -extern void drm_mode_group_destroy(struct drm_mode_group *group); -extern void drm_reinit_primary_mode_group(struct drm_device *dev); extern bool drm_probe_ddc(struct i2c_adapter *adapter); extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); -- cgit v1.2.3 From 90a21700ed9635070fb04fe92fb50c5e3bc16605 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 23 Jul 2015 16:34:58 -0700 Subject: drm: Fix DP_TEST_COUNT_MASK By Vesa's DP 1.2 Spec this counter has 4 bits [3:0]. This mask is wrong since when the counter was introduced by myself on commit ad9dc91b6e21266bfc6f466db4b95e10211f31ee Author: Rodrigo Vivi Date: Tue Sep 16 19:18:12 2014 -0400 drm/i915: Fix Sink CRC Signed-off-by: Rodrigo Vivi Reviewed-by: Sivakumar Thulasimani Signed-off-by: Daniel Vetter --- include/drm/drm_dp_helper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2e86f642fc33..94898f6ea02a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -420,7 +420,7 @@ #define DP_TEST_SINK_MISC 0x246 # define DP_TEST_CRC_SUPPORTED (1 << 5) -# define DP_TEST_COUNT_MASK 0x7 +# define DP_TEST_COUNT_MASK 0xf #define DP_TEST_RESPONSE 0x260 # define DP_TEST_ACK (1 << 0) -- cgit v1.2.3 From fc596660dd4e83f7f84e3cd7b25dc5e8e83000ef Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jul 2015 13:28:57 +0200 Subject: drm/atomic: add connectors_changed to separate it from mode_changed, v2 This can be a separate case from mode_changed, when connectors stay the same but only the mode is different. Drivers may choose to implement specific optimizations to prevent a full modeset for this case. Changes since v1: - Update kerneldocs slightly. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Maarten Lankhorst Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 39 +++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_display.c | 2 +- include/drm/drm_atomic.h | 3 ++- include/drm/drm_crtc.h | 8 +++++--- 4 files changed, 38 insertions(+), 14 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 99656815641d..10bcdd554501 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -124,7 +124,7 @@ steal_encoder(struct drm_atomic_state *state, if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); - crtc_state->mode_changed = true; + crtc_state->connectors_changed = true; list_for_each_entry(connector, &config->connector_list, head) { if (connector->state->best_encoder != encoder) @@ -174,14 +174,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) idx = drm_crtc_index(connector->state->crtc); crtc_state = state->crtc_states[idx]; - crtc_state->mode_changed = true; + crtc_state->connectors_changed = true; } if (connector_state->crtc) { idx = drm_crtc_index(connector_state->crtc); crtc_state = state->crtc_states[idx]; - crtc_state->mode_changed = true; + crtc_state->connectors_changed = true; } } @@ -233,7 +233,7 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) idx = drm_crtc_index(connector_state->crtc); crtc_state = state->crtc_states[idx]; - crtc_state->mode_changed = true; + crtc_state->connectors_changed = true; DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n", connector->base.id, @@ -256,7 +256,8 @@ mode_fixup(struct drm_atomic_state *state) bool ret; for_each_crtc_in_state(state, crtc, crtc_state, i) { - if (!crtc_state->mode_changed) + if (!crtc_state->mode_changed && + !crtc_state->connectors_changed) continue; drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode); @@ -312,7 +313,8 @@ mode_fixup(struct drm_atomic_state *state) for_each_crtc_in_state(state, crtc, crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; - if (!crtc_state->mode_changed) + if (!crtc_state->mode_changed && + !crtc_state->connectors_changed) continue; funcs = crtc->helper_private; @@ -338,9 +340,14 @@ mode_fixup(struct drm_atomic_state *state) * * Check the state object to see if the requested state is physically possible. * This does all the crtc and connector related computations for an atomic - * update. It computes and updates crtc_state->mode_changed, adds any additional - * connectors needed for full modesets and calls down into ->mode_fixup - * functions of the driver backend. + * update and adds any additional connectors needed for full modesets and calls + * down into ->mode_fixup functions of the driver backend. + * + * crtc_state->mode_changed is set when the input mode is changed. + * crtc_state->connectors_changed is set when a connector is added or + * removed from the crtc. + * crtc_state->active_changed is set when crtc_state->active changes, + * which is used for dpms. * * IMPORTANT: * @@ -373,7 +380,17 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, if (crtc->state->enable != crtc_state->enable) { DRM_DEBUG_ATOMIC("[CRTC:%d] enable changed\n", crtc->base.id); + + /* + * For clarity this assignment is done here, but + * enable == 0 is only true when there are no + * connectors and a NULL mode. + * + * The other way around is true as well. enable != 0 + * iff connectors are attached and a mode is set. + */ crtc_state->mode_changed = true; + crtc_state->connectors_changed = true; } } @@ -448,6 +465,9 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset); * This does all the plane update related checks using by calling into the * ->atomic_check hooks provided by the driver. * + * It also sets crtc_state->planes_changed to indicate that a crtc has + * updated planes. + * * RETURNS * Zero for success or -errno */ @@ -2074,6 +2094,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, state->mode_changed = false; state->active_changed = false; state->planes_changed = false; + state->connectors_changed = false; state->event = NULL; } EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af0bcfee4771..07cee59edece 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -413,7 +413,7 @@ static const intel_limit_t intel_limits_bxt = { static bool needs_modeset(struct drm_crtc_state *state) { - return state->mode_changed || state->active_changed; + return drm_atomic_crtc_needs_modeset(state); } /** diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 8a3a913320eb..e67aeac2aee0 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -166,7 +166,8 @@ int __must_check drm_atomic_async_commit(struct drm_atomic_state *state); static inline bool drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) { - return state->mode_changed || state->active_changed; + return state->mode_changed || state->active_changed || + state->connectors_changed; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 3071319ea194..90a0ff70384a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -255,12 +255,13 @@ struct drm_atomic_state; * @crtc: backpointer to the CRTC * @enable: whether the CRTC should be enabled, gates all other state * @active: whether the CRTC is actively displaying (used for DPMS) - * @mode_changed: for use by helpers and drivers when computing state updates - * @active_changed: for use by helpers and drivers when computing state updates + * @planes_changed: planes on this crtc are updated + * @mode_changed: crtc_state->mode or crtc_state->enable has been changed + * @active_changed: crtc_state->active has been toggled. + * @connectors_changed: connectors to this crtc have been updated * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes * @last_vblank_count: for helpers and drivers to capture the vblank of the * update to ensure framebuffer cleanup isn't done too early - * @planes_changed: for use by helpers and drivers when computing state updates * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings * @mode: current mode timings * @event: optional pointer to a DRM event to signal upon completion of the @@ -283,6 +284,7 @@ struct drm_crtc_state { bool planes_changed : 1; bool mode_changed : 1; bool active_changed : 1; + bool connectors_changed : 1; /* attached planes bitmask: * WARNING: transitional helpers do not maintain plane_mask so -- cgit v1.2.3 From 613d2b272177c61c7cdb83be75a6e4c378d50ff9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jul 2015 13:28:58 +0200 Subject: drm/atomic: pass old crtc state to atomic_begin/flush. In intel it's useful to keep track of some state changes with old crtc state vs new state, for example to disable initial planes or when a modeset's prevented during fastboot. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Maarten Lankhorst Reviewed-by: Ander Conselvan de Oliveira [danvet: squash in fixup for exynos provided by Maarten.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 6 ++++-- drivers/gpu/drm/drm_atomic_helper.c | 8 ++++---- drivers/gpu/drm/drm_plane_helper.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 6 ++++-- drivers/gpu/drm/i915/intel_display.c | 10 ++++++---- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 ++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 ++++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 6 ++++-- drivers/gpu/drm/sti/sti_drm_crtc.c | 6 ++++-- drivers/gpu/drm/tegra/dc.c | 6 ++++-- include/drm/drm_crtc_helper.h | 6 ++++-- 11 files changed, 44 insertions(+), 26 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index f69b92535505..8b8fe3762ca9 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -239,7 +239,8 @@ static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, return atmel_hlcdc_plane_prepare_disc_area(s); } -static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c) +static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c, + struct drm_crtc_state *old_s) { struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); @@ -253,7 +254,8 @@ static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c) } } -static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc) +static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_s) { /* TODO: write common plane control register if available */ } diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 10bcdd554501..5ec13c7cc832 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1164,7 +1164,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_begin) continue; - funcs->atomic_begin(crtc); + funcs->atomic_begin(crtc, old_crtc_state); } for_each_plane_in_state(old_state, plane, old_plane_state, i) { @@ -1194,7 +1194,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (!funcs || !funcs->atomic_flush) continue; - funcs->atomic_flush(crtc); + funcs->atomic_flush(crtc, old_crtc_state); } } EXPORT_SYMBOL(drm_atomic_helper_commit_planes); @@ -1230,7 +1230,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) crtc_funcs = crtc->helper_private; if (crtc_funcs && crtc_funcs->atomic_begin) - crtc_funcs->atomic_begin(crtc); + crtc_funcs->atomic_begin(crtc, old_crtc_state); drm_for_each_plane_mask(plane, crtc->dev, plane_mask) { struct drm_plane_state *old_plane_state = @@ -1253,7 +1253,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state) } if (crtc_funcs && crtc_funcs->atomic_flush) - crtc_funcs->atomic_flush(crtc); + crtc_funcs->atomic_flush(crtc, old_crtc_state); } EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 46c704573306..5e5a07af02c8 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -437,7 +437,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, for (i = 0; i < 2; i++) { if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin) - crtc_funcs[i]->atomic_begin(crtc[i]); + crtc_funcs[i]->atomic_begin(crtc[i], crtc[i]->state); } /* @@ -452,7 +452,7 @@ int drm_plane_helper_commit(struct drm_plane *plane, for (i = 0; i < 2; i++) { if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) - crtc_funcs[i]->atomic_flush(crtc[i]); + crtc_funcs[i]->atomic_flush(crtc[i], crtc[i]->state); } /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 644b4b76e071..1610757230a5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -80,7 +80,8 @@ exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) exynos_crtc->ops->commit(exynos_crtc); } -static void exynos_crtc_atomic_begin(struct drm_crtc *crtc) +static void exynos_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); @@ -90,7 +91,8 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc) } } -static void exynos_crtc_atomic_flush(struct drm_crtc *crtc) +static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 07cee59edece..40c73da2abcf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -102,8 +102,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); -static void intel_begin_crtc_commit(struct drm_crtc *crtc); -static void intel_finish_crtc_commit(struct drm_crtc *crtc); +static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); +static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, @@ -13628,7 +13628,8 @@ intel_disable_primary_plane(struct drm_plane *plane, dev_priv->display.update_primary_plane(crtc, NULL, 0, 0); } -static void intel_begin_crtc_commit(struct drm_crtc *crtc) +static void intel_begin_crtc_commit(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -13644,7 +13645,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc) skl_detach_scalers(intel_crtc); } -static void intel_finish_crtc_commit(struct drm_crtc *crtc) +static void intel_finish_crtc_commit(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index c4bb9d9c7667..4dc158ed2e95 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -334,13 +334,15 @@ static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, return 0; } -static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc) +static void mdp4_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); DBG("%s: begin", mdp4_crtc->name); } -static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc) +static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index dea3d2e559b1..4c1df4e6e5bc 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -388,13 +388,15 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, return 0; } -static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc) +static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); DBG("%s: begin", mdp5_crtc->name); } -static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc) +static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct drm_device *dev = crtc->dev; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 65d6ba6621ac..48cb19949ca3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -496,7 +496,8 @@ static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc, return true; } -static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc) +static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct drm_pending_vblank_event *event = crtc->state->event; struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); @@ -512,7 +513,8 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc) } } -static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc) +static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 6b641c5a2ec7..26e63bf14efe 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -164,7 +164,8 @@ sti_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) sti_drm_crtc_mode_set(crtc, &crtc->state->adjusted_mode); } -static void sti_drm_atomic_begin(struct drm_crtc *crtc) +static void sti_drm_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct sti_mixer *mixer = to_sti_mixer(crtc); @@ -178,7 +179,8 @@ static void sti_drm_atomic_begin(struct drm_crtc *crtc) } } -static void sti_drm_atomic_flush(struct drm_crtc *crtc) +static void sti_drm_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { } diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index a287e4fec865..bf8ef3133e5b 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1277,7 +1277,8 @@ static int tegra_crtc_atomic_check(struct drm_crtc *crtc, return 0; } -static void tegra_crtc_atomic_begin(struct drm_crtc *crtc) +static void tegra_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct tegra_dc *dc = to_tegra_dc(crtc); @@ -1291,7 +1292,8 @@ static void tegra_crtc_atomic_begin(struct drm_crtc *crtc) } } -static void tegra_crtc_atomic_flush(struct drm_crtc *crtc) +static void tegra_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct tegra_dc_state *state = to_dc_state(crtc->state); struct tegra_dc *dc = to_tegra_dc(crtc); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index c8fc187061de..01cafcbe7deb 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -108,8 +108,10 @@ struct drm_crtc_helper_funcs { /* atomic helpers */ int (*atomic_check)(struct drm_crtc *crtc, struct drm_crtc_state *state); - void (*atomic_begin)(struct drm_crtc *crtc); - void (*atomic_flush)(struct drm_crtc *crtc); + void (*atomic_begin)(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state); + void (*atomic_flush)(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state); }; /** -- cgit v1.2.3 From 9a69a9ac20f7f3435dd18019f902351c61a9ad1d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 21 Jul 2015 11:34:55 +0200 Subject: drm: Make the connector dpms callback return a value, v2. This is required to properly handle failing dpms calls. When making a wait in i915 interruptible, I've noticed that the dpms sequence could fail with -ERESTARTSYS because it was waiting interruptibly for flips. So from now on allow drivers to fail in their connector dpms callback. Encoder and crtc dpms callbacks are unaffected. Changes since v1: - Update kerneldoc for the drm helper functions. Signed-off-by: Maarten Lankhorst [danvet: Resolve conflicts due to different merge order.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++------------ drivers/gpu/drm/drm_crtc.c | 4 ++-- drivers/gpu/drm/drm_crtc_helper.c | 9 ++++++--- drivers/gpu/drm/i915/intel_crt.c | 8 +++++--- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 8 +++++--- drivers/gpu/drm/i915/intel_sdvo.c | 8 +++++--- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 ++-- drivers/gpu/drm/radeon/radeon_dp_mst.c | 3 ++- drivers/gpu/drm/tegra/dsi.c | 3 ++- drivers/gpu/drm/tegra/hdmi.c | 5 +++-- drivers/gpu/drm/tegra/rgb.c | 5 +++-- drivers/gpu/drm/tegra/sor.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 3 ++- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 2 +- include/drm/drm_atomic_helper.h | 4 ++-- include/drm/drm_crtc.h | 2 +- include/drm/drm_crtc_helper.h | 2 +- 19 files changed, 65 insertions(+), 44 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5ec13c7cc832..57847ae8ce8c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1974,9 +1974,12 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); * implementing the legacy DPMS connector interface. It computes the new desired * ->active state for the corresponding CRTC (if the connector is enabled) and * updates it. + * + * Returns: + * Returns 0 on success, negative errno numbers on failure. */ -void drm_atomic_helper_connector_dpms(struct drm_connector *connector, - int mode) +int drm_atomic_helper_connector_dpms(struct drm_connector *connector, + int mode) { struct drm_mode_config *config = &connector->dev->mode_config; struct drm_atomic_state *state; @@ -1985,6 +1988,7 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, struct drm_connector *tmp_connector; int ret; bool active = false; + int old_mode = connector->dpms; if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; @@ -1993,18 +1997,19 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, crtc = connector->state->crtc; if (!crtc) - return; + return 0; - /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */ state = drm_atomic_state_alloc(connector->dev); if (!state) - return; + return -ENOMEM; state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); retry: crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return; + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto fail; + } WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); @@ -2023,17 +2028,16 @@ retry: if (ret != 0) goto fail; - /* Driver takes ownership of state on successful async commit. */ - return; + /* Driver takes ownership of state on successful commit. */ + return 0; fail: if (ret == -EDEADLK) goto backoff; + connector->dpms = old_mode; drm_atomic_state_free(state); - WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret); - - return; + return ret; backoff: drm_atomic_state_clear(state); drm_atomic_legacy_backoff(state); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 1f0da41ae2a1..dfac394d0602 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4753,9 +4753,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, /* Do DPMS ourselves */ if (property == connector->dev->mode_config.dpms_property) { - if (connector->funcs->dpms) - (*connector->funcs->dpms)(connector, (int)value); ret = 0; + if (connector->funcs->dpms) + ret = (*connector->funcs->dpms)(connector, (int)value); } else if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, value); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d3d038f05bf7..ef534758a02c 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -762,15 +762,18 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) * implementing the DPMS connector attribute. It computes the new desired DPMS * state for all encoders and crtcs in the output mesh and calls the ->dpms() * callback provided by the driver appropriately. + * + * Returns: + * Always returns 0. */ -void drm_helper_connector_dpms(struct drm_connector *connector, int mode) +int drm_helper_connector_dpms(struct drm_connector *connector, int mode) { struct drm_encoder *encoder = connector->encoder; struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; old_dpms = connector->dpms; connector->dpms = mode; @@ -802,7 +805,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) } } - return; + return 0; } EXPORT_SYMBOL(drm_helper_connector_dpms); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 521af2c069cb..5d78c1feec81 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -237,7 +237,7 @@ static void intel_enable_crt(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_crt_dpms(struct drm_connector *connector, int mode) +static int intel_crt_dpms(struct drm_connector *connector, int mode) { struct drm_device *dev = connector->dev; struct intel_encoder *encoder = intel_attached_encoder(connector); @@ -249,7 +249,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; old_dpms = connector->dpms; connector->dpms = mode; @@ -258,7 +258,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) crtc = encoder->base.crtc; if (!crtc) { encoder->connectors_active = false; - return; + return 0; } /* We need the pipe to run for anything but OFF. */ @@ -281,6 +281,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40c73da2abcf..13a6608be689 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6429,14 +6429,14 @@ struct intel_connector *intel_connector_alloc(void) /* Even simpler default implementation, if there's really no special case to * consider. */ -void intel_connector_dpms(struct drm_connector *connector, int mode) +int intel_connector_dpms(struct drm_connector *connector, int mode) { /* All the simple cases only support two dpms states. */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -6445,6 +6445,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); intel_modeset_check_state(connector->dev); + + return 0; } /* Simple connector->get_hw_state implementation for encoders that support only diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 47cef0e6c79c..320c9e6bd848 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -997,7 +997,7 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc); void intel_encoder_destroy(struct drm_encoder *encoder); int intel_connector_init(struct intel_connector *); struct intel_connector *intel_connector_alloc(void); -void intel_connector_dpms(struct drm_connector *, int mode); +int intel_connector_dpms(struct drm_connector *, int mode); bool intel_connector_get_hw_state(struct intel_connector *connector); void intel_modeset_check_state(struct drm_device *dev); bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index ece5bd754f85..fd5e522abebb 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -197,7 +197,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_dvo_dpms(struct drm_connector *connector, int mode) +static int intel_dvo_dpms(struct drm_connector *connector, int mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); struct drm_crtc *crtc; @@ -208,7 +208,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -216,7 +216,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) crtc = intel_dvo->base.base.crtc; if (!crtc) { intel_dvo->base.connectors_active = false; - return; + return 0; } /* We call connector dpms manually below in case pipe dpms doesn't @@ -238,6 +238,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index aa2fd751609c..2c435a79d4da 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1509,7 +1509,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder) } /* Special dpms function to support cloning between dvo/sdvo/crt. */ -static void intel_sdvo_dpms(struct drm_connector *connector, int mode) +static int intel_sdvo_dpms(struct drm_connector *connector, int mode) { struct drm_crtc *crtc; struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); @@ -1519,7 +1519,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) - return; + return 0; connector->dpms = mode; @@ -1527,7 +1527,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) crtc = intel_sdvo->base.base.crtc; if (!crtc) { intel_sdvo->base.connectors_active = false; - return; + return 0; } /* We set active outputs manually below in case pipe dpms doesn't change @@ -1551,6 +1551,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode) } intel_modeset_check_state(connector->dev); + + return 0; } static enum drm_mode_status diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 3162040bc314..1f26eba245d1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -919,7 +919,7 @@ nouveau_connector_funcs_lvds = { .force = nouveau_connector_force }; -static void +static int nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) { struct nouveau_encoder *nv_encoder = NULL; @@ -938,7 +938,7 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) } } - drm_helper_connector_dpms(connector, mode); + return drm_helper_connector_dpms(connector, mode); } static const struct drm_connector_funcs diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index e4fc8f3bf58b..5e09c061847f 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -246,9 +246,10 @@ radeon_dp_mst_connector_destroy(struct drm_connector *connector) kfree(radeon_connector); } -static void radeon_connector_dpms(struct drm_connector *connector, int mode) +static int radeon_connector_dpms(struct drm_connector *connector, int mode) { DRM_DEBUG_KMS("\n"); + return 0; } static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index ed970f622903..dc97c0b3681d 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -726,8 +726,9 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi) tegra_dsi_soft_reset(dsi->slave); } -static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) +static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } static void tegra_dsi_connector_reset(struct drm_connector *connector) diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 06ab1783bba1..fe4008a7ddba 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -772,9 +772,10 @@ static bool tegra_output_is_hdmi(struct tegra_output *output) return drm_detect_hdmi_monitor(edid); } -static void tegra_hdmi_connector_dpms(struct drm_connector *connector, - int mode) +static int tegra_hdmi_connector_dpms(struct drm_connector *connector, + int mode) { + return 0; } static const struct drm_connector_funcs tegra_hdmi_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 7cd833f5b5b5..9a99d213e1b1 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -88,9 +88,10 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, tegra_dc_writel(dc, table[i].value, table[i].offset); } -static void tegra_rgb_connector_dpms(struct drm_connector *connector, - int mode) +static int tegra_rgb_connector_dpms(struct drm_connector *connector, + int mode) { + return 0; } static const struct drm_connector_funcs tegra_rgb_connector_funcs = { diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 7591d8901f9a..ee8ad0d4a0f2 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -866,8 +866,9 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor) sor->debugfs_files = NULL; } -static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode) +static int tegra_sor_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } static enum drm_connector_status diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 07cda8cbbddb..2adc11bc0920 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1808,8 +1808,9 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, } } -void vmw_du_connector_dpms(struct drm_connector *connector, int mode) +int vmw_du_connector_dpms(struct drm_connector *connector, int mode) { + return 0; } void vmw_du_connector_save(struct drm_connector *connector) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 8d038c36bd57..f1a324cfb4c3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -133,7 +133,7 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height); int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); -void vmw_du_connector_dpms(struct drm_connector *connector, int mode); +int vmw_du_connector_dpms(struct drm_connector *connector, int mode); void vmw_du_connector_save(struct drm_connector *connector); void vmw_du_connector_restore(struct drm_connector *connector); enum drm_connector_status diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index cc1fee8a12d0..11266d147a29 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -87,8 +87,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t flags); -void drm_atomic_helper_connector_dpms(struct drm_connector *connector, - int mode); +int drm_atomic_helper_connector_dpms(struct drm_connector *connector, + int mode); /* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 90a0ff70384a..574656965126 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -527,7 +527,7 @@ struct drm_connector_state { * etc. */ struct drm_connector_funcs { - void (*dpms)(struct drm_connector *connector, int mode); + int (*dpms)(struct drm_connector *connector, int mode); void (*save)(struct drm_connector *connector); void (*restore)(struct drm_connector *connector); void (*reset)(struct drm_connector *connector); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 01cafcbe7deb..800e0d1cf32c 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -189,7 +189,7 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); -extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode); +extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode); extern void drm_helper_move_panel_connectors_to_head(struct drm_device *); -- cgit v1.2.3 From b8017d6c33be9862505a9154e302c4b00cbfca43 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 22 Jul 2015 14:57:56 +0530 Subject: drm/fb_helper: Add drm_fb_helper functions to manage fb_info creation Every drm driver calls framebuffer_alloc, fb_alloc_cmap, unregister_framebuffer, fb_dealloc_cmap and framebuffer_release in order to emulate fbdev support. Create drm_fb_helper functions that perform the above operations. This is part of an effort to prevent drm drivers from calling fbdev functions directly. It also removes repetitive code from drivers. There are some drivers that call alloc_apertures after framebuffer_alloc and some that don't. Make the helper always call alloc_apertures. This would make certain drivers allocate memory for apertures but not use them. Since it's a small amount of memory, it shouldn't be an issue. v2: - Added kerneldocs - Added a check for non-NULL fb_helper before proceeding. This will make the helpers work when we have a module param for fbdev emulation Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 80 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 4 +++ 2 files changed, 84 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 73f90f7e2f74..714c8af80180 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -654,6 +654,86 @@ out_free: } EXPORT_SYMBOL(drm_fb_helper_init); +/** + * drm_fb_helper_alloc_fbi - allocate fb_info and some of its members + * @fb_helper: driver-allocated fbdev helper + * + * A helper to alloc fb_info and the members cmap and apertures. Called + * by the driver within the fb_probe fb_helper callback function. + * + * RETURNS: + * fb_info pointer if things went okay, pointer containing error code + * otherwise + */ +struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper) +{ + struct device *dev = fb_helper->dev->dev; + struct fb_info *info; + int ret; + + info = framebuffer_alloc(0, dev); + if (!info) + return ERR_PTR(-ENOMEM); + + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret) + goto err_release; + + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto err_free_cmap; + } + + fb_helper->fbdev = info; + + return info; + +err_free_cmap: + fb_dealloc_cmap(&info->cmap); +err_release: + framebuffer_release(info); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_fb_helper_alloc_fbi); + +/** + * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device + * @fb_helper: driver-allocated fbdev helper + * + * A wrapper around unregister_framebuffer, to release the fb_info + * framebuffer device + */ +void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper) +{ + if (fb_helper && fb_helper->fbdev) + unregister_framebuffer(fb_helper->fbdev); +} +EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); + +/** + * drm_fb_helper_release_fbi - dealloc fb_info and its members + * @fb_helper: driver-allocated fbdev helper + * + * A helper to free memory taken by fb_info and the members cmap and + * apertures + */ +void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper) +{ + if (fb_helper) { + struct fb_info *info = fb_helper->fbdev; + + if (info) { + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } + + fb_helper->fbdev = NULL; + } +} +EXPORT_SYMBOL(drm_fb_helper_release_fbi); + void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { if (!list_empty(&fb_helper->kernel_fb_list)) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 0dfd94def593..2ee4ec53efc1 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -136,6 +136,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info); bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); + +struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper); +void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper); +void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper); void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, uint32_t fb_width, uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, -- cgit v1.2.3 From 47074ab7951c1fcfc3ff637eb8401c3a71272057 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 22 Jul 2015 14:57:57 +0530 Subject: drm/fb_helper: Create a wrapper for unlink_framebuffer Some drm drivers call unlink_framebuffer. Create a drm_fb_helper function that wraps around these calls. This is part of an effort to prevent drm drivers from calling fbdev functions directly, in order to make fbdev emulation a top level drm option. v2: - Added kerneldocs - Added a check for non-NULL fb_helper before proceeding. This will make the helpers work when we have a module param for fbdev emulation Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 13 +++++++++++++ include/drm/drm_fb_helper.h | 2 ++ 2 files changed, 15 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 714c8af80180..5383c3f7d0ec 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -748,6 +748,19 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) } EXPORT_SYMBOL(drm_fb_helper_fini); +/** + * drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer + * @fb_helper: driver-allocated fbdev helper + * + * A wrapper around unlink_framebuffer implemented by fbdev core + */ +void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) +{ + if (fb_helper && fb_helper->fbdev) + unlink_framebuffer(fb_helper->fbdev); +} +EXPORT_SYMBOL(drm_fb_helper_unlink_fbi); + static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 2ee4ec53efc1..4c908370a61e 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -145,6 +145,8 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, uint32_t depth); +void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper); + int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -- cgit v1.2.3 From cbb1a82e5608fd6511940d27c231f0f4e2495b04 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 31 Jul 2015 16:21:41 +0530 Subject: drm/fb_helper: Create wrappers for fb_sys_read/write funcs Some drm drivers populate their fb_ops with fb_sys_read/write fb sysfs ops. Create a drm_fb_helper function that wraps around these calls. This is part of an effort to prevent drm drivers from calling fbdev functions directly, in order to make fbdev emulation a top level drm option. v3: - Fix kerneldoc errors v2: - Added kerneldocs - Follow the drm way of aligning of arguments in func definitions - Remove unnecessary checks for non NULL fb_info Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/drm_fb_helper.c | 32 ++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 5 +++++ 3 files changed, 38 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c46ca311d8c3..6ab503b387db 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -37,6 +37,7 @@ config DRM_KMS_FB_HELPER select FB select FRAMEBUFFER_CONSOLE if !EXPERT select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE + select FB_SYS_FOPS help FBDEV helpers for KMS drivers. diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5383c3f7d0ec..39f3be2f37a2 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -761,6 +761,38 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) } EXPORT_SYMBOL(drm_fb_helper_unlink_fbi); +/** + * drm_fb_helper_sys_read - wrapper around fb_sys_read + * @info: fb_info struct pointer + * @buf: userspace buffer to read from framebuffer memory + * @count: number of bytes to read from framebuffer memory + * @ppos: read offset within framebuffer memory + * + * A wrapper around fb_sys_read implemented by fbdev core + */ +ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, + size_t count, loff_t *ppos) +{ + return fb_sys_read(info, buf, count, ppos); +} +EXPORT_SYMBOL(drm_fb_helper_sys_read); + +/** + * drm_fb_helper_sys_write - wrapper around fb_sys_write + * @info: fb_info struct pointer + * @buf: userspace buffer to write to framebuffer memory + * @count: number of bytes to write to framebuffer memory + * @ppos: write offset within framebuffer memory + * + * A wrapper around fb_sys_write implemented by fbdev core + */ +ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) +{ + return fb_sys_write(info, buf, count, ppos); +} +EXPORT_SYMBOL(drm_fb_helper_sys_write); + static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 4c908370a61e..fc123685baf4 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -147,6 +147,11 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper); +ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, + size_t count, loff_t *ppos); +ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos); + int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -- cgit v1.2.3 From 742547b73d27e7bce2d0dd0f1b95692436f30950 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 31 Jul 2015 16:21:42 +0530 Subject: drm/fb_helper: Create wrappers for blit, copyarea and fillrect funcs drm drivers that emulate fbdev populate their fb_fillrect, fb_copyarea and fb_imageblit fb_ops with the help of cfb_* or sys_* fbdev core helper functions. Create drm_fb_helper functions that wrap around these calls. This is part of an effort to prevent drm drivers from calling fbdev functions directly, in order to make fbdev emulation a top level drm option. v3: - Fixed kerneldoc errors v2: - Added kerneldocs - Follow the drm way of aligning of arguments in func definitions - Remove unnecessary checks for non NULL fb_info Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/Kconfig | 6 +++ drivers/gpu/drm/drm_fb_helper.c | 84 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fb_helper.h | 14 +++++++ 3 files changed, 104 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 6ab503b387db..35a8c0bf360f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -38,6 +38,12 @@ config DRM_KMS_FB_HELPER select FRAMEBUFFER_CONSOLE if !EXPERT select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE select FB_SYS_FOPS + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT help FBDEV helpers for KMS drivers. diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 39f3be2f37a2..e63350114c06 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -793,6 +793,90 @@ ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, } EXPORT_SYMBOL(drm_fb_helper_sys_write); +/** + * drm_fb_helper_sys_fillrect - wrapper around sys_fillrect + * @info: fbdev registered by the helper + * @rect: info about rectangle to fill + * + * A wrapper around sys_fillrect implemented by fbdev core + */ +void drm_fb_helper_sys_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + sys_fillrect(info, rect); +} +EXPORT_SYMBOL(drm_fb_helper_sys_fillrect); + +/** + * drm_fb_helper_sys_copyarea - wrapper around sys_copyarea + * @info: fbdev registered by the helper + * @area: info about area to copy + * + * A wrapper around sys_copyarea implemented by fbdev core + */ +void drm_fb_helper_sys_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + sys_copyarea(info, area); +} +EXPORT_SYMBOL(drm_fb_helper_sys_copyarea); + +/** + * drm_fb_helper_sys_imageblit - wrapper around sys_imageblit + * @info: fbdev registered by the helper + * @image: info about image to blit + * + * A wrapper around sys_imageblit implemented by fbdev core + */ +void drm_fb_helper_sys_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + sys_imageblit(info, image); +} +EXPORT_SYMBOL(drm_fb_helper_sys_imageblit); + +/** + * drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect + * @info: fbdev registered by the helper + * @rect: info about rectangle to fill + * + * A wrapper around cfb_imageblit implemented by fbdev core + */ +void drm_fb_helper_cfb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + cfb_fillrect(info, rect); +} +EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect); + +/** + * drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea + * @info: fbdev registered by the helper + * @area: info about area to copy + * + * A wrapper around cfb_copyarea implemented by fbdev core + */ +void drm_fb_helper_cfb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + cfb_copyarea(info, area); +} +EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea); + +/** + * drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit + * @info: fbdev registered by the helper + * @image: info about image to blit + * + * A wrapper around cfb_imageblit implemented by fbdev core + */ +void drm_fb_helper_cfb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ + cfb_imageblit(info, image); +} +EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); + static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index fc123685baf4..180290e62918 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -152,6 +152,20 @@ ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos); +void drm_fb_helper_sys_fillrect(struct fb_info *info, + const struct fb_fillrect *rect); +void drm_fb_helper_sys_copyarea(struct fb_info *info, + const struct fb_copyarea *area); +void drm_fb_helper_sys_imageblit(struct fb_info *info, + const struct fb_image *image); + +void drm_fb_helper_cfb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect); +void drm_fb_helper_cfb_copyarea(struct fb_info *info, + const struct fb_copyarea *area); +void drm_fb_helper_cfb_imageblit(struct fb_info *info, + const struct fb_image *image); + int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -- cgit v1.2.3 From fdefa58a5097b397ce2d3f6b6f8caa14aacfb70d Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 31 Jul 2015 16:21:43 +0530 Subject: drm/fb_helper: Create a wrapper for fb_set_suspend Some drm drivers call fb_set_suspend. Create a drm_fb_helper function that wraps around these calls. This is part of an effort to prevent drm drivers from calling fbdev functions directly, in order to make fbdev emulation a top level drm option. v3: - Fixed kerneldoc errors v2: - Added kerneldocs - Added a check for non-NULL fb_helper before proceeding. This will make the helpers work when we have a module param for fbdev emulation - Follow the drm way of aligning of arguments in func definitions Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 14 ++++++++++++++ include/drm/drm_fb_helper.h | 2 ++ 2 files changed, 16 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e63350114c06..c1cb7537a18f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -877,6 +877,20 @@ void drm_fb_helper_cfb_imageblit(struct fb_info *info, } EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); +/** + * drm_fb_helper_set_suspend - wrapper around fb_set_suspend + * @fb_helper: driver-allocated fbdev helper + * @state: desired state, zero to resume, non-zero to suspend + * + * A wrapper around fb_set_suspend implemented by fbdev core + */ +void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state) +{ + if (fb_helper && fb_helper->fbdev) + fb_set_suspend(fb_helper->fbdev, state); +} +EXPORT_SYMBOL(drm_fb_helper_set_suspend); + static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 180290e62918..ef32500e07fc 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -166,6 +166,8 @@ void drm_fb_helper_cfb_copyarea(struct fb_info *info, void drm_fb_helper_cfb_imageblit(struct fb_info *info, const struct fb_image *image); +void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state); + int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); -- cgit v1.2.3 From bf9e37baac6db7318862447973bd68b5acae4bef Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 Jul 2015 13:18:42 +0200 Subject: drm: Remove __drm_modeset_lock_all The last user is gone, no need for trylocking any more in this legacy helper. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_modeset_lock.c | 52 ++++++++------------------------------ include/drm/drm_modeset_lock.h | 1 - 2 files changed, 11 insertions(+), 42 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 744dfbc6a329..fba321ca4344 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -55,41 +55,27 @@ * drm_modeset_acquire_fini(&ctx); */ - /** - * __drm_modeset_lock_all - internal helper to grab all modeset locks - * @dev: DRM device - * @trylock: trylock mode for atomic contexts - * - * This is a special version of drm_modeset_lock_all() which can also be used in - * atomic contexts. Then @trylock must be set to true. + * drm_modeset_lock_all - take all modeset locks + * @dev: drm device * - * Returns: - * 0 on success or negative error code on failure. + * This function takes all modeset locks, suitable where a more fine-grained + * scheme isn't (yet) implemented. Locks must be dropped with + * drm_modeset_unlock_all. */ -int __drm_modeset_lock_all(struct drm_device *dev, - bool trylock) +void drm_modeset_lock_all(struct drm_device *dev) { struct drm_mode_config *config = &dev->mode_config; struct drm_modeset_acquire_ctx *ctx; int ret; - ctx = kzalloc(sizeof(*ctx), - trylock ? GFP_ATOMIC : GFP_KERNEL); - if (!ctx) - return -ENOMEM; + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (WARN_ON(!ctx)) + return; - if (trylock) { - if (!mutex_trylock(&config->mutex)) { - ret = -EBUSY; - goto out; - } - } else { - mutex_lock(&config->mutex); - } + mutex_lock(&config->mutex); drm_modeset_acquire_init(ctx, 0); - ctx->trylock_only = trylock; retry: ret = drm_modeset_lock(&config->connection_mutex, ctx); @@ -108,7 +94,7 @@ retry: drm_warn_on_modeset_not_all_locked(dev); - return 0; + return; fail: if (ret == -EDEADLK) { @@ -116,23 +102,7 @@ fail: goto retry; } -out: kfree(ctx); - return ret; -} -EXPORT_SYMBOL(__drm_modeset_lock_all); - -/** - * drm_modeset_lock_all - take all modeset locks - * @dev: drm device - * - * This function takes all modeset locks, suitable where a more fine-grained - * scheme isn't (yet) implemented. Locks must be dropped with - * drm_modeset_unlock_all. - */ -void drm_modeset_lock_all(struct drm_device *dev) -{ - WARN_ON(__drm_modeset_lock_all(dev, false) != 0); } EXPORT_SYMBOL(drm_modeset_lock_all); diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 70595ff565ba..5dd18bfdf601 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -130,7 +130,6 @@ struct drm_crtc; struct drm_plane; void drm_modeset_lock_all(struct drm_device *dev); -int __drm_modeset_lock_all(struct drm_device *dev, bool trylock); void drm_modeset_unlock_all(struct drm_device *dev); void drm_modeset_lock_crtc(struct drm_crtc *crtc, struct drm_plane *plane); -- cgit v1.2.3 From a03fdcb1863297481a4b817c2a759cafcbdfa0ae Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 5 Aug 2015 12:28:57 +0530 Subject: drm: Add top level Kconfig option for DRM fbdev emulation Legacy fbdev emulation support via DRM is achieved through KMS FB helpers. Most modesetting drivers enable provide fbdev emulation by default by selecting KMS FB helpers. A few provide a separate Kconfig option for the user to enable or disbale fbdev emulation. Enabling fbdev emulation is finally a distro-level decision. Having a top level Kconfig option for fbdev emulation helps by providing a uniform way to enable/disable fbdev emulation for any modesetting driver. It also lets us remove unnecessary driver specific Kconfig options that causes bloat. With a top level Kconfig in place, we can stub out the fb helper functions when not needed without breaking functionality. Having stub functions also prevents drivers to require wrapping fb helper function calls with #ifdefs. DRM_FBDEV_EMULATION defaults to y since many drivers enable fbdev emulation by default and majority of distributions expect the fbdev interface in the kernel. Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter --- drivers/gpu/drm/Kconfig | 13 ++++ drivers/gpu/drm/Makefile | 2 +- include/drm/drm_fb_helper.h | 185 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 35a8c0bf360f..06ae5008c5ed 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -47,6 +47,19 @@ config DRM_KMS_FB_HELPER help FBDEV helpers for KMS drivers. +config DRM_FBDEV_EMULATION + bool "Enable legacy fbdev support for your modesetting driver" + depends on DRM + select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER + default y + help + Choose this option if you have a need for the legacy fbdev + support. Note that this support also provides the linux console + support on top of your modesetting driver. + + If in doubt, say "Y". + config DRM_LOAD_EDID_FIRMWARE bool "Allow to specify an EDID data set instead of probing for it" depends on DRM_KMS_HELPER diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 5713d0534504..8858510437ea 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -23,7 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o -drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o +drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ef32500e07fc..dbab4622b58f 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -122,6 +122,7 @@ struct drm_fb_helper { bool delayed_hotplug; }; +#ifdef CONFIG_DRM_FBDEV_EMULATION void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, const struct drm_fb_helper_funcs *funcs); int drm_fb_helper_init(struct drm_device *dev, @@ -185,4 +186,188 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); +#else +static inline void drm_fb_helper_prepare(struct drm_device *dev, + struct drm_fb_helper *helper, + const struct drm_fb_helper_funcs *funcs) +{ +} + +static inline int drm_fb_helper_init(struct drm_device *dev, + struct drm_fb_helper *helper, int crtc_count, + int max_conn) +{ + return 0; +} + +static inline void drm_fb_helper_fini(struct drm_fb_helper *helper) +{ +} + +static inline int drm_fb_helper_blank(int blank, struct fb_info *info) +{ + return 0; +} + +static inline int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + return 0; +} + +static inline int drm_fb_helper_set_par(struct fb_info *info) +{ + return 0; +} + +static inline int drm_fb_helper_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + return 0; +} + +static inline bool +drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) +{ + return true; +} + +static inline struct fb_info * +drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper) +{ + return NULL; +} + +static inline void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper) +{ +} +static inline void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper) +{ +} + +static inline void drm_fb_helper_fill_var(struct fb_info *info, + struct drm_fb_helper *fb_helper, + uint32_t fb_width, uint32_t fb_height) +{ +} + +static inline void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, + uint32_t depth) +{ +} + +static inline int drm_fb_helper_setcmap(struct fb_cmap *cmap, + struct fb_info *info) +{ + return 0; +} + +static inline void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper) +{ +} + +static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info, + char __user *buf, size_t count, + loff_t *ppos) +{ + return -ENODEV; +} + +static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info, + const char __user *buf, + size_t count, loff_t *ppos) +{ + return -ENODEV; +} + +static inline void drm_fb_helper_sys_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ +} + +static inline void drm_fb_helper_sys_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ +} + +static inline void drm_fb_helper_sys_imageblit(struct fb_info *info, + const struct fb_image *image) +{ +} + +static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ +} + +static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ +} + +static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info, + const struct fb_image *image) +{ +} + +static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, + int state) +{ +} + +static inline int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) +{ + return 0; +} + +static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, + int bpp_sel) +{ + return 0; +} + +static inline int +drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) +{ + return 0; +} + +static inline int drm_fb_helper_debug_enter(struct fb_info *info) +{ + return 0; +} + +static inline int drm_fb_helper_debug_leave(struct fb_info *info) +{ + return 0; +} + +static inline struct drm_display_mode * +drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, + int width, int height) +{ + return NULL; +} + +static inline struct drm_display_mode * +drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, + int width, int height) +{ + return NULL; +} + +static inline int +drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + return 0; +} + +static inline int +drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, + struct drm_connector *connector) +{ + return 0; +} +#endif #endif -- cgit v1.2.3 From 45e3743aff6f3fbe3f08d43d443dc2d7b5396a31 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 12 Aug 2015 16:54:28 +0200 Subject: drm/plane: Use consistent data types for format count Rather than a mix of the the sized uint32_t and signed integer, use an unsized unsigned int to specify the format count. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 2 +- include/drm/drm_crtc.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7d02e32b4e94..21f1f5ce2d60 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1151,7 +1151,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, enum drm_plane_type type) { struct drm_mode_config *config = &dev->mode_config; @@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(drm_universal_plane_init); int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, bool is_primary) { enum drm_plane_type type; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 97ec61c842ed..0a1d4a5d152d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13681,7 +13681,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, struct intel_plane *primary; struct intel_plane_state *state; const uint32_t *intel_primary_formats; - int num_formats; + unsigned int num_formats; primary = kzalloc(sizeof(*primary), GFP_KERNEL); if (primary == NULL) diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 9f2498571d09..5f6ea1873f51 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -261,7 +261,7 @@ nv10_overlay_init(struct drm_device *device) { struct nouveau_drm *drm = nouveau_drm(device); struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); - int num_formats = ARRAY_SIZE(formats); + unsigned int num_formats = ARRAY_SIZE(formats); int ret; if (!plane) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 574656965126..6e5afc30b596 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -865,7 +865,7 @@ struct drm_plane { uint32_t possible_crtcs; uint32_t *format_types; - uint32_t format_count; + unsigned int format_count; bool format_default; struct drm_crtc *crtc; @@ -1270,13 +1270,13 @@ extern int drm_universal_plane_init(struct drm_device *dev, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, - uint32_t format_count, + unsigned int format_count, enum drm_plane_type type); extern int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, bool is_primary); extern void drm_plane_cleanup(struct drm_plane *plane); extern unsigned int drm_plane_index(struct drm_plane *plane); -- cgit v1.2.3 From b54a0935b03888c8412aa5acbf873af9d753fbdd Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 12 Aug 2015 16:54:29 +0200 Subject: drm/plane: Remove redundant extern Use of the extern keyword for function prototypes is unnecessary, so it can be removed. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- include/drm/drm_plane_helper.h | 45 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'include/drm') diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 96e16283afb9..dda401bf910e 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -43,9 +43,8 @@ * planes. */ -extern int drm_crtc_init(struct drm_device *dev, - struct drm_crtc *crtc, - const struct drm_crtc_funcs *funcs); +int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, + const struct drm_crtc_funcs *funcs); /** * drm_plane_helper_funcs - helper operations for CRTCs @@ -79,26 +78,26 @@ static inline void drm_plane_helper_add(struct drm_plane *plane, plane->helper_private = funcs; } -extern int drm_plane_helper_check_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_rect *src, - struct drm_rect *dest, - const struct drm_rect *clip, - int min_scale, - int max_scale, - bool can_position, - bool can_update_disabled, - bool *visible); -extern int drm_primary_helper_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); -extern int drm_primary_helper_disable(struct drm_plane *plane); -extern void drm_primary_helper_destroy(struct drm_plane *plane); +int drm_plane_helper_check_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_rect *src, + struct drm_rect *dest, + const struct drm_rect *clip, + int min_scale, + int max_scale, + bool can_position, + bool can_update_disabled, + bool *visible); +int drm_primary_helper_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); +int drm_primary_helper_disable(struct drm_plane *plane); +void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs; int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, -- cgit v1.2.3 From cc1ef118fc099295ae6aabbacc8af94d8d8885eb Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 12 Aug 2015 17:00:31 +0200 Subject: drm/irq: Make pipe unsigned and name consistent Name all references to the pipe number (CRTC index) consistently to make it easier to distinguish which is a pipe number and which is a pointer to struct drm_crtc. While at it also make all references to the pipe number unsigned because there is no longer any reason why it should ever be negative. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_irq.c | 316 +++++++++++++++++++++++----------------------- include/drm/drmP.h | 32 ++--- 2 files changed, 175 insertions(+), 173 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f7c8b758059f..c393f0c0ad3b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -43,8 +43,8 @@ #include /* Access macro for slots in vblank timestamp ringbuffer. */ -#define vblanktimestamp(dev, crtc, count) \ - ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) +#define vblanktimestamp(dev, pipe, count) \ + ((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE]) /* Retry timestamp calculation up to 3 times to satisfy * drm_timestamp_precision before giving up. @@ -57,7 +57,7 @@ #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 static bool -drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, +drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, struct timeval *tvblank, unsigned flags); static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ @@ -107,7 +107,7 @@ static void store_vblank(struct drm_device *dev, int crtc, /** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device - * @crtc: counter to update + * @pipe: counter to update * * Call back into the driver to update the appropriate vblank counter * (specified by @crtc). Deal with wraparound, if it occurred, and @@ -120,9 +120,9 @@ static void store_vblank(struct drm_device *dev, int crtc, * Note: caller must hold dev->vbl_lock since this reads & writes * device vblank fields. */ -static void drm_update_vblank_count(struct drm_device *dev, int crtc) +static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank, diff; bool rc; struct timeval t_vblank; @@ -140,21 +140,21 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) * corresponding vblank timestamp. */ do { - cur_vblank = dev->driver->get_vblank_counter(dev, crtc); - rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0); - } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); + cur_vblank = dev->driver->get_vblank_counter(dev, pipe); + rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); + } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe)); /* Deal with counter wrap */ diff = cur_vblank - vblank->last; if (cur_vblank < vblank->last) { diff += dev->max_vblank_count + 1; - DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", - crtc, vblank->last, cur_vblank, diff); + DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n", + pipe, vblank->last, cur_vblank, diff); } - DRM_DEBUG("updating vblank count on crtc %d, missed %d\n", - crtc, diff); + DRM_DEBUG("updating vblank count on crtc %u, missed %d\n", + pipe, diff); if (diff == 0) return; @@ -167,7 +167,7 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) if (!rc) t_vblank = (struct timeval) {0, 0}; - store_vblank(dev, crtc, diff, &t_vblank); + store_vblank(dev, pipe, diff, &t_vblank); } /* @@ -176,9 +176,9 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) * are preserved, even if there are any spurious vblank irq's after * disable. */ -static void vblank_disable_and_save(struct drm_device *dev, int crtc) +static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; unsigned long irqflags; u32 vblcount; s64 diff_ns; @@ -206,8 +206,8 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * vblank interrupt is disabled. */ if (!vblank->enabled && - drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0)) { - drm_update_vblank_count(dev, crtc); + drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) { + drm_update_vblank_count(dev, pipe); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); return; } @@ -218,7 +218,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * hardware potentially runtime suspended. */ if (vblank->enabled) { - dev->driver->disable_vblank(dev, crtc); + dev->driver->disable_vblank(dev, pipe); vblank->enabled = false; } @@ -235,9 +235,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * delayed gpu counter increment. */ do { - vblank->last = dev->driver->get_vblank_counter(dev, crtc); - vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); - } while (vblank->last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); + vblank->last = dev->driver->get_vblank_counter(dev, pipe); + vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0); + } while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc); if (!count) vblrc = 0; @@ -247,7 +247,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) */ vblcount = vblank->count; diff_ns = timeval_to_ns(&tvblank) - - timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); + timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); /* If there is at least 1 msec difference between the last stored * timestamp and tvblank, then we are currently executing our @@ -262,7 +262,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * hope for the best. */ if (vblrc && (abs64(diff_ns) > 1000000)) - store_vblank(dev, crtc, 1, &tvblank); + store_vblank(dev, pipe, 1, &tvblank); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } @@ -271,16 +271,16 @@ static void vblank_disable_fn(unsigned long arg) { struct drm_vblank_crtc *vblank = (void *)arg; struct drm_device *dev = vblank->dev; + unsigned int pipe = vblank->pipe; unsigned long irqflags; - int crtc = vblank->crtc; if (!dev->vblank_disable_allowed) return; spin_lock_irqsave(&dev->vbl_lock, irqflags); if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) { - DRM_DEBUG("disabling vblank on crtc %d\n", crtc); - vblank_disable_and_save(dev, crtc); + DRM_DEBUG("disabling vblank on crtc %u\n", pipe); + vblank_disable_and_save(dev, pipe); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } @@ -293,14 +293,14 @@ static void vblank_disable_fn(unsigned long arg) */ void drm_vblank_cleanup(struct drm_device *dev) { - int crtc; + unsigned int pipe; /* Bail if the driver didn't call drm_vblank_init() */ if (dev->num_crtcs == 0) return; - for (crtc = 0; crtc < dev->num_crtcs; crtc++) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + for (pipe = 0; pipe < dev->num_crtcs; pipe++) { + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; WARN_ON(vblank->enabled && drm_core_check_feature(dev, DRIVER_MODESET)); @@ -316,17 +316,18 @@ EXPORT_SYMBOL(drm_vblank_cleanup); /** * drm_vblank_init - initialize vblank support - * @dev: drm_device - * @num_crtcs: number of crtcs supported by @dev + * @dev: DRM device + * @num_crtcs: number of CRTCs supported by @dev * * This function initializes vblank support for @num_crtcs display pipelines. * * Returns: * Zero on success or a negative error code on failure. */ -int drm_vblank_init(struct drm_device *dev, int num_crtcs) +int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) { - int i, ret = -ENOMEM; + int ret = -ENOMEM; + unsigned int i; spin_lock_init(&dev->vbl_lock); spin_lock_init(&dev->vblank_time_lock); @@ -341,7 +342,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) struct drm_vblank_crtc *vblank = &dev->vblank[i]; vblank->dev = dev; - vblank->crtc = i; + vblank->pipe = i; init_waitqueue_head(&vblank->queue); setup_timer(&vblank->disable_timer, vblank_disable_fn, (unsigned long)vblank); @@ -624,17 +625,17 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, if (mode->flags & DRM_MODE_FLAG_INTERLACE) framedur_ns /= 2; } else - DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", + DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", crtc->base.id); crtc->pixeldur_ns = pixeldur_ns; crtc->linedur_ns = linedur_ns; crtc->framedur_ns = framedur_ns; - DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", + DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", crtc->base.id, mode->crtc_htotal, mode->crtc_vtotal, mode->crtc_vdisplay); - DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", + DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n", crtc->base.id, dotclock, framedur_ns, linedur_ns, pixeldur_ns); } @@ -643,7 +644,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); /** * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper * @dev: DRM device - * @crtc: Which CRTC's vblank timestamp to retrieve + * @pipe: index of CRTC whose vblank timestamp to retrieve * @max_error: Desired maximum allowable error in timestamps (nanosecs) * On return contains true maximum error of timestamp * @vblank_time: Pointer to struct timeval which should receive the timestamp @@ -686,7 +687,8 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. * */ -int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, +int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, + unsigned int pipe, int *max_error, struct timeval *vblank_time, unsigned flags, @@ -700,8 +702,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; bool invbl; - if (crtc < 0 || crtc >= dev->num_crtcs) { - DRM_ERROR("Invalid crtc %d\n", crtc); + if (pipe >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %u\n", pipe); return -EINVAL; } @@ -720,7 +722,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, * Happens during initial modesetting of a crtc. */ if (framedur_ns == 0) { - DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); + DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); return -EAGAIN; } @@ -736,13 +738,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */ - vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos, + vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos, &hpos, &stime, &etime); /* Return as no-op if scanout query unsupported or failed. */ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { - DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", - crtc, vbl_status); + DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n", + pipe, vbl_status); return -EIO; } @@ -756,8 +758,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, /* Noisy system timing? */ if (i == DRM_TIMESTAMP_MAXRETRIES) { - DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n", - crtc, duration_ns/1000, *max_error/1000, i); + DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n", + pipe, duration_ns/1000, *max_error/1000, i); } /* Return upper bound of timestamp precision error. */ @@ -790,8 +792,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_to_timeval(etime); - DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", - crtc, (int)vbl_status, hpos, vpos, + DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", + pipe, (int)vbl_status, hpos, vpos, (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, duration_ns/1000, i); @@ -816,7 +818,7 @@ static struct timeval get_drm_timestamp(void) * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent * vblank interval * @dev: DRM device - * @crtc: which CRTC's vblank timestamp to retrieve + * @pipe: index of CRTC whose vblank timestamp to retrieve * @tvblank: Pointer to target struct timeval which should receive the timestamp * @flags: Flags to pass to driver: * 0 = Default, @@ -833,7 +835,7 @@ static struct timeval get_drm_timestamp(void) * True if timestamp is considered to be very precise, false otherwise. */ static bool -drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, +drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, struct timeval *tvblank, unsigned flags) { int ret; @@ -843,7 +845,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, /* Query driver if possible and precision timestamping enabled. */ if (dev->driver->get_vblank_timestamp && (max_error > 0)) { - ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error, + ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, tvblank, flags); if (ret > 0) return true; @@ -860,7 +862,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, /** * drm_vblank_count - retrieve "cooked" vblank counter value * @dev: DRM device - * @crtc: which counter to retrieve + * @pipe: index of CRTC for which to retrieve the counter * * Fetches the "cooked" vblank count value that represents the number of * vblank events since the system was booted, including lost events due to @@ -871,11 +873,11 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, * Returns: * The software vblank counter. */ -u32 drm_vblank_count(struct drm_device *dev, int crtc) +u32 drm_vblank_count(struct drm_device *dev, int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return 0; return vblank->count; @@ -902,11 +904,10 @@ u32 drm_crtc_vblank_count(struct drm_crtc *crtc) EXPORT_SYMBOL(drm_crtc_vblank_count); /** - * drm_vblank_count_and_time - retrieve "cooked" vblank counter value - * and the system timestamp corresponding to that vblank counter value. - * + * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the + * system timestamp corresponding to that vblank counter value. * @dev: DRM device - * @crtc: which counter to retrieve + * @pipe: index of CRTC whose counter to retrieve * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. * * Fetches the "cooked" vblank count value that represents the number of @@ -914,13 +915,13 @@ EXPORT_SYMBOL(drm_crtc_vblank_count); * modesetting activity. Returns corresponding system timestamp of the time * of the vblank interval that corresponds to the current vblank counter value. */ -u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, +u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return 0; /* @@ -931,7 +932,7 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, do { cur_vblank = vblank->count; smp_rmb(); - *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); + *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); smp_rmb(); } while (cur_vblank != vblank->count); @@ -958,7 +959,7 @@ static void send_vblank_event(struct drm_device *dev, /** * drm_send_vblank_event - helper to send vblank event after pageflip * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index * @e: the event to send * * Updates sequence # and timestamp on event, and sends it to userspace. @@ -966,20 +967,20 @@ static void send_vblank_event(struct drm_device *dev, * * This is the legacy version of drm_crtc_send_vblank_event(). */ -void drm_send_vblank_event(struct drm_device *dev, int crtc, - struct drm_pending_vblank_event *e) +void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe, + struct drm_pending_vblank_event *e) { struct timeval now; unsigned int seq; if (dev->num_crtcs > 0) { - seq = drm_vblank_count_and_time(dev, crtc, &now); + seq = drm_vblank_count_and_time(dev, pipe, &now); } else { seq = 0; now = get_drm_timestamp(); } - e->pipe = crtc; + e->pipe = pipe; send_vblank_event(dev, e, seq, &now); } EXPORT_SYMBOL(drm_send_vblank_event); @@ -1004,11 +1005,11 @@ EXPORT_SYMBOL(drm_crtc_send_vblank_event); /** * drm_vblank_enable - enable the vblank interrupt on a CRTC * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index */ -static int drm_vblank_enable(struct drm_device *dev, int crtc) +static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; int ret = 0; assert_spin_locked(&dev->vbl_lock); @@ -1023,13 +1024,13 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc) * timestamps. Filtercode in drm_handle_vblank() will * prevent double-accounting of same vblank interval. */ - ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + ret = dev->driver->enable_vblank(dev, pipe); + DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); if (ret) atomic_dec(&vblank->refcount); else { vblank->enabled = true; - drm_update_vblank_count(dev, crtc); + drm_update_vblank_count(dev, pipe); } } @@ -1041,7 +1042,7 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc) /** * drm_vblank_get - get a reference count on vblank events * @dev: DRM device - * @crtc: which CRTC to own + * @pipe: index of CRTC to own * * Acquire a reference count on vblank events to avoid having them disabled * while in use. @@ -1051,22 +1052,22 @@ static int drm_vblank_enable(struct drm_device *dev, int crtc) * Returns: * Zero on success, nonzero on failure. */ -int drm_vblank_get(struct drm_device *dev, int crtc) +int drm_vblank_get(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; unsigned long irqflags; int ret = 0; if (!dev->num_crtcs) return -EINVAL; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return -EINVAL; spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ if (atomic_add_return(1, &vblank->refcount) == 1) { - ret = drm_vblank_enable(dev, crtc); + ret = drm_vblank_enable(dev, pipe); } else { if (!vblank->enabled) { atomic_dec(&vblank->refcount); @@ -1098,20 +1099,20 @@ int drm_crtc_vblank_get(struct drm_crtc *crtc) EXPORT_SYMBOL(drm_crtc_vblank_get); /** - * drm_vblank_put - give up ownership of vblank events + * drm_vblank_put - release ownership of vblank events * @dev: DRM device - * @crtc: which counter to give up + * @pipe: index of CRTC to release * * Release ownership of a given vblank counter, turning off interrupts * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. * * This is the legacy version of drm_crtc_vblank_put(). */ -void drm_vblank_put(struct drm_device *dev, int crtc) +void drm_vblank_put(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; if (WARN_ON(atomic_read(&vblank->refcount) == 0)) @@ -1148,33 +1149,34 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); /** * drm_wait_one_vblank - wait for one vblank * @dev: DRM device - * @crtc: crtc index + * @pipe: CRTC index * * This waits for one vblank to pass on @crtc, using the irq driver interfaces. * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. * due to lack of driver support or because the crtc is off. */ -void drm_wait_one_vblank(struct drm_device *dev, int crtc) +void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; int ret; u32 last; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; - ret = drm_vblank_get(dev, crtc); - if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", crtc, ret)) + ret = drm_vblank_get(dev, pipe); + if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret)) return; - last = drm_vblank_count(dev, crtc); + last = drm_vblank_count(dev, pipe); - ret = wait_event_timeout(dev->vblank[crtc].queue, - last != drm_vblank_count(dev, crtc), + ret = wait_event_timeout(vblank->queue, + last != drm_vblank_count(dev, pipe), msecs_to_jiffies(100)); - WARN(ret == 0, "vblank wait timed out on crtc %i\n", crtc); + WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe); - drm_vblank_put(dev, crtc); + drm_vblank_put(dev, pipe); } EXPORT_SYMBOL(drm_wait_one_vblank); @@ -1195,7 +1197,7 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank); /** * drm_vblank_off - disable vblank events on a CRTC * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index * * Drivers can use this function to shut down the vblank interrupt handling when * disabling a crtc. This function ensures that the latest vblank frame count is @@ -1206,21 +1208,21 @@ EXPORT_SYMBOL(drm_crtc_wait_one_vblank); * * This is the legacy version of drm_crtc_vblank_off(). */ -void drm_vblank_off(struct drm_device *dev, int crtc) +void drm_vblank_off(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_pending_vblank_event *e, *t; struct timeval now; unsigned long irqflags; unsigned int seq; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; spin_lock_irqsave(&dev->event_lock, irqflags); spin_lock(&dev->vbl_lock); - vblank_disable_and_save(dev, crtc); + vblank_disable_and_save(dev, pipe); wake_up(&vblank->queue); /* @@ -1234,16 +1236,16 @@ void drm_vblank_off(struct drm_device *dev, int crtc) spin_unlock(&dev->vbl_lock); /* Send any queued vblank events, lest the natives grow disquiet */ - seq = drm_vblank_count_and_time(dev, crtc, &now); + seq = drm_vblank_count_and_time(dev, pipe, &now); list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { - if (e->pipe != crtc) + if (e->pipe != pipe) continue; DRM_DEBUG("Sending premature vblank event on disable: \ wanted %d, current %d\n", e->event.sequence, seq); list_del(&e->base.link); - drm_vblank_put(dev, e->pipe); + drm_vblank_put(dev, pipe); send_vblank_event(dev, e, seq, &now); } spin_unlock_irqrestore(&dev->event_lock, irqflags); @@ -1304,7 +1306,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset); /** * drm_vblank_on - enable vblank events on a CRTC * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index * * This functions restores the vblank interrupt state captured with * drm_vblank_off() again. Note that calls to drm_vblank_on() and @@ -1313,12 +1315,12 @@ EXPORT_SYMBOL(drm_crtc_vblank_reset); * * This is the legacy version of drm_crtc_vblank_on(). */ -void drm_vblank_on(struct drm_device *dev, int crtc) +void drm_vblank_on(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; unsigned long irqflags; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; spin_lock_irqsave(&dev->vbl_lock, irqflags); @@ -1336,7 +1338,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc) * vblank counter value before and after a modeset */ vblank->last = - (dev->driver->get_vblank_counter(dev, crtc) - 1) & + (dev->driver->get_vblank_counter(dev, pipe) - 1) & dev->max_vblank_count; /* * re-enable interrupts if there are users left, or the @@ -1344,7 +1346,7 @@ void drm_vblank_on(struct drm_device *dev, int crtc) */ if (atomic_read(&vblank->refcount) != 0 || (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0)) - WARN_ON(drm_vblank_enable(dev, crtc)); + WARN_ON(drm_vblank_enable(dev, pipe)); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } EXPORT_SYMBOL(drm_vblank_on); @@ -1369,7 +1371,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_on); /** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index * * Account for vblank events across mode setting events, which will likely * reset the hardware frame counter. @@ -1389,15 +1391,15 @@ EXPORT_SYMBOL(drm_crtc_vblank_on); * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc * again. */ -void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) +void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; /* vblank is not initialized (IRQ not installed ?), or has been freed */ if (!dev->num_crtcs) return; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; /* @@ -1409,7 +1411,7 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) */ if (!vblank->inmodeset) { vblank->inmodeset = 0x1; - if (drm_vblank_get(dev, crtc) == 0) + if (drm_vblank_get(dev, pipe) == 0) vblank->inmodeset |= 0x2; } } @@ -1418,21 +1420,21 @@ EXPORT_SYMBOL(drm_vblank_pre_modeset); /** * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes * @dev: DRM device - * @crtc: CRTC in question + * @pipe: CRTC index * * This function again drops the temporary vblank reference acquired in * drm_vblank_pre_modeset. */ -void drm_vblank_post_modeset(struct drm_device *dev, int crtc) +void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; unsigned long irqflags; /* vblank is not initialized (IRQ not installed ?), or has been freed */ if (!dev->num_crtcs) return; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return; if (vblank->inmodeset) { @@ -1441,7 +1443,7 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) spin_unlock_irqrestore(&dev->vbl_lock, irqflags); if (vblank->inmodeset & 0x2) - drm_vblank_put(dev, crtc); + drm_vblank_put(dev, pipe); vblank->inmodeset = 0; } @@ -1463,7 +1465,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; - unsigned int crtc; + unsigned int pipe; /* If drm_vblank_init() hasn't been called yet, just no-op */ if (!dev->num_crtcs) @@ -1473,16 +1475,16 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; - crtc = modeset->crtc; - if (crtc >= dev->num_crtcs) + pipe = modeset->crtc; + if (pipe >= dev->num_crtcs) return -EINVAL; switch (modeset->cmd) { case _DRM_PRE_MODESET: - drm_vblank_pre_modeset(dev, crtc); + drm_vblank_pre_modeset(dev, pipe); break; case _DRM_POST_MODESET: - drm_vblank_post_modeset(dev, crtc); + drm_vblank_post_modeset(dev, pipe); break; default: return -EINVAL; @@ -1491,7 +1493,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, return 0; } -static int drm_queue_vblank_event(struct drm_device *dev, int pipe, +static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, union drm_wait_vblank *vblwait, struct drm_file *file_priv) { @@ -1545,7 +1547,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, vblwait->reply.sequence = vblwait->request.sequence; } - DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", + DRM_DEBUG("event on vblank count %d, current %d, crtc %u\n", vblwait->request.sequence, seq, pipe); trace_drm_vblank_event_queued(current->pid, pipe, @@ -1594,7 +1596,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_vblank_crtc *vblank; union drm_wait_vblank *vblwait = data; int ret; - unsigned int flags, seq, crtc, high_crtc; + unsigned int flags, seq, pipe, high_pipe; if (!dev->irq_enabled) return -EINVAL; @@ -1613,22 +1615,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data, } flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; - high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK); - if (high_crtc) - crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT; + high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK); + if (high_pipe) + pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT; else - crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; - if (crtc >= dev->num_crtcs) + pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; + if (pipe >= dev->num_crtcs) return -EINVAL; - vblank = &dev->vblank[crtc]; + vblank = &dev->vblank[pipe]; - ret = drm_vblank_get(dev, crtc); + ret = drm_vblank_get(dev, pipe); if (ret) { DRM_DEBUG("failed to acquire vblank counter, %d\n", ret); return ret; } - seq = drm_vblank_count(dev, crtc); + seq = drm_vblank_count(dev, pipe); switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { case _DRM_VBLANK_RELATIVE: @@ -1645,7 +1647,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, /* must hold on to the vblank ref until the event fires * drm_vblank_put will be called asynchronously */ - return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); + return drm_queue_vblank_event(dev, pipe, vblwait, file_priv); } if ((flags & _DRM_VBLANK_NEXTONMISS) && @@ -1653,11 +1655,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, vblwait->request.sequence = seq + 1; } - DRM_DEBUG("waiting on vblank count %d, crtc %d\n", - vblwait->request.sequence, crtc); + DRM_DEBUG("waiting on vblank count %d, crtc %u\n", + vblwait->request.sequence, pipe); vblank->last_wait = vblwait->request.sequence; DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, - (((drm_vblank_count(dev, crtc) - + (((drm_vblank_count(dev, pipe) - vblwait->request.sequence) <= (1 << 23)) || !vblank->enabled || !dev->irq_enabled)); @@ -1665,7 +1667,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data, if (ret != -EINTR) { struct timeval now; - vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now); + vblwait->reply.sequence = drm_vblank_count_and_time(dev, pipe, &now); vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; @@ -1676,11 +1678,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, } done: - drm_vblank_put(dev, crtc); + drm_vblank_put(dev, pipe); return ret; } -static void drm_handle_vblank_events(struct drm_device *dev, int crtc) +static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) { struct drm_pending_vblank_event *e, *t; struct timeval now; @@ -1688,10 +1690,10 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) assert_spin_locked(&dev->event_lock); - seq = drm_vblank_count_and_time(dev, crtc, &now); + seq = drm_vblank_count_and_time(dev, pipe, &now); list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { - if (e->pipe != crtc) + if (e->pipe != pipe) continue; if ((seq - e->event.sequence) > (1<<23)) continue; @@ -1700,26 +1702,26 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) e->event.sequence, seq); list_del(&e->base.link); - drm_vblank_put(dev, e->pipe); + drm_vblank_put(dev, pipe); send_vblank_event(dev, e, seq, &now); } - trace_drm_vblank_event(crtc, seq); + trace_drm_vblank_event(pipe, seq); } /** * drm_handle_vblank - handle a vblank event * @dev: DRM device - * @crtc: where this event occurred + * @pipe: index of CRTC where this event occurred * * Drivers should call this routine in their vblank interrupt handlers to * update the vblank counter and send any signals that may be pending. * * This is the legacy version of drm_crtc_handle_vblank(). */ -bool drm_handle_vblank(struct drm_device *dev, int crtc) +bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 vblcount; s64 diff_ns; struct timeval tvblank; @@ -1728,7 +1730,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) if (WARN_ON_ONCE(!dev->num_crtcs)) return false; - if (WARN_ON(crtc >= dev->num_crtcs)) + if (WARN_ON(pipe >= dev->num_crtcs)) return false; spin_lock_irqsave(&dev->event_lock, irqflags); @@ -1752,11 +1754,11 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) /* Get current timestamp and count. */ vblcount = vblank->count; - drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); + drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ); /* Compute time difference to timestamp of last vblank */ diff_ns = timeval_to_ns(&tvblank) - - timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); + timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); /* Update vblank timestamp and count if at least * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds @@ -1768,15 +1770,15 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) * ignore those for accounting. */ if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) - store_vblank(dev, crtc, 1, &tvblank); + store_vblank(dev, pipe, 1, &tvblank); else - DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", - crtc, (int) diff_ns); + DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n", + pipe, (int) diff_ns); spin_unlock(&dev->vblank_time_lock); wake_up(&vblank->queue); - drm_handle_vblank_events(dev, crtc); + drm_handle_vblank_events(dev, pipe); spin_unlock_irqrestore(&dev->event_lock, irqflags); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4717449d6aa9..1a9791ea1cf0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -681,7 +681,7 @@ struct drm_minor { struct drm_pending_vblank_event { struct drm_pending_event base; - int pipe; + unsigned int pipe; struct drm_event_vblank event; }; @@ -700,7 +700,7 @@ struct drm_vblank_crtc { /* for wraparound handling */ u32 last_wait; /* Last vblank seqno waited per CRTC */ unsigned int inmodeset; /* Display driver is setting mode */ - int crtc; /* crtc index */ + unsigned int pipe; /* crtc index */ bool enabled; /* so we don't call enable more than once per disable */ }; @@ -920,34 +920,34 @@ void drm_clflush_virt_range(void *addr, unsigned long length); extern int drm_irq_install(struct drm_device *dev, int irq); extern int drm_irq_uninstall(struct drm_device *dev); -extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); +extern int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp); -extern u32 drm_vblank_count(struct drm_device *dev, int crtc); +extern u32 drm_vblank_count(struct drm_device *dev, int pipe); extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc); -extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, +extern u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, struct timeval *vblanktime); -extern void drm_send_vblank_event(struct drm_device *dev, int crtc, - struct drm_pending_vblank_event *e); +extern void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe, + struct drm_pending_vblank_event *e); extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e); -extern bool drm_handle_vblank(struct drm_device *dev, int crtc); +extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc); -extern int drm_vblank_get(struct drm_device *dev, int crtc); -extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern int drm_vblank_get(struct drm_device *dev, unsigned int pipe); +extern void drm_vblank_put(struct drm_device *dev, unsigned int pipe); extern int drm_crtc_vblank_get(struct drm_crtc *crtc); extern void drm_crtc_vblank_put(struct drm_crtc *crtc); -extern void drm_wait_one_vblank(struct drm_device *dev, int crtc); +extern void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); -extern void drm_vblank_off(struct drm_device *dev, int crtc); -extern void drm_vblank_on(struct drm_device *dev, int crtc); +extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe); +extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe); extern void drm_crtc_vblank_off(struct drm_crtc *crtc); extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); extern void drm_crtc_vblank_on(struct drm_crtc *crtc); extern void drm_vblank_cleanup(struct drm_device *dev); extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - int crtc, int *max_error, + unsigned int pipe, int *max_error, struct timeval *vblank_time, unsigned flags, const struct drm_crtc *refcrtc, @@ -968,8 +968,8 @@ static inline wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc } /* Modesetting support */ -extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); -extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); +extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe); +extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe); /* Stub support (drm_stub.h) */ extern struct drm_master *drm_master_get(struct drm_master *master); -- cgit v1.2.3 From 5101020c78c9f242fe77bd7986bc24f7b800172a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 10 Jul 2015 22:31:08 -0700 Subject: drm: export the DRM permission check code This way drm_ioctl_permit() can be used by drivers Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/drm_ioctl.c | 3 ++- include/drm/drmP.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index b1d303fa2327..9a860ca1e9d7 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -480,7 +480,7 @@ static int drm_version(struct drm_device *dev, void *data, * indicated permissions. If so, returns zero. Otherwise returns an * error code suitable for ioctl return. */ -static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) +int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) { /* ROOT_ONLY is only for CAP_SYS_ADMIN */ if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN))) @@ -508,6 +508,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) return 0; } +EXPORT_SYMBOL(drm_ioctl_permit); #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ [DRM_IOCTL_NR(ioctl)] = { \ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4717449d6aa9..3b0c50f7412a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -887,6 +887,7 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv) /*@{*/ /* Driver support (drm_drv.h) */ +extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); extern long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern long drm_compat_ioctl(struct file *filp, -- cgit v1.2.3 From 627563d1696b8978b550ed192acc1bc8fc461da5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 28 Mar 2015 18:13:52 +0000 Subject: drm/edid: add function to help find SADs Add a function to find the start of the SADs in the ELD. This complements the helper to retrieve the SAD count. Signed-off-by: Russell King --- include/drm/drm_edid.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'include/drm') diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 799050198323..53c53c459b15 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -347,6 +347,25 @@ static inline int drm_eld_mnl(const uint8_t *eld) return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; } +/** + * drm_eld_sad - Get ELD SAD structures. + * @eld: pointer to an eld memory structure with sad_count set + */ +static inline const uint8_t *drm_eld_sad(const uint8_t *eld) +{ + unsigned int ver, mnl; + + ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT; + if (ver != 2 && ver != 31) + return NULL; + + mnl = drm_eld_mnl(eld); + if (mnl > 16) + return NULL; + + return eld + DRM_ELD_CEA_SAD(mnl, 0); +} + /** * drm_eld_sad_count - Get ELD SAD count. * @eld: pointer to an eld memory structure with sad_count set -- cgit v1.2.3 From b5814fff27c6d0212b86306bdd01fe3aea99cabb Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 27 Mar 2015 12:50:58 +0000 Subject: drm: bridge/dw_hdmi: introduce interface to setting sample rate Introduce dw_hdmi_set_sample_rate(), which allows us to configure the audio sample rate, setting the CTS/N values appropriately. Tested-by: Yakir Yang Signed-off-by: Russell King --- drivers/gpu/drm/bridge/dw_hdmi.c | 10 ++++++++++ include/drm/bridge/dw_hdmi.h | 5 +++++ 2 files changed, 15 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c index eeb01693812a..0ed8c49f1c6e 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.c +++ b/drivers/gpu/drm/bridge/dw_hdmi.c @@ -365,6 +365,16 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) mutex_unlock(&hdmi->audio_mutex); } +void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) +{ + mutex_lock(&hdmi->audio_mutex); + hdmi->sample_rate = rate; + hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, + hdmi->sample_rate, hdmi->ratio); + mutex_unlock(&hdmi->audio_mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); + /* * this submodule is responsible for the video data synchronization. * for example, for RGB 4:4:4 input, the data map is defined as diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index de13bfc35634..763af51e1d60 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -12,6 +12,8 @@ #include +struct dw_hdmi; + enum { DW_HDMI_RES_8, DW_HDMI_RES_10, @@ -59,4 +61,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, void *data, struct drm_encoder *encoder, struct resource *iores, int irq, const struct dw_hdmi_plat_data *plat_data); + +void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); + #endif /* __IMX_HDMI_H__ */ -- cgit v1.2.3 From b90120a9660884b8f11bbb9904fbaa4c12d17e0a Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 27 Mar 2015 12:59:58 +0000 Subject: drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio iMX6 devices suffer from an errata (ERR005174) where the audio FIFO can be emptied while it is partially full, resulting in misalignment of the audio samples. To prevent this, the errata workaround recommends writing N as zero until the audio FIFO has been loaded by DMA. Writing N=0 prevents the HDMI bridge from reading from the audio FIFO, effectively disabling audio. This means we need to provide the audio driver with a pair of functions to enable/disable audio. These are dw_hdmi_audio_enable() and dw_hdmi_audio_disable(). A spinlock is introduced to ensure that setting the CTS/N values can't race, ensuring that the audio driver calling the enable/disable functions (which are called in an atomic context) can't race with a modeset. Tested-by: Yakir Yang Signed-off-by: Russell King --- drivers/gpu/drm/bridge/dw_hdmi.c | 34 +++++++++++++++++++++++++++++++++- include/drm/bridge/dw_hdmi.h | 2 ++ 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c index 0ed8c49f1c6e..f070ee07b8c9 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.c +++ b/drivers/gpu/drm/bridge/dw_hdmi.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -123,8 +124,12 @@ struct dw_hdmi { struct i2c_adapter *ddc; void __iomem *regs; + spinlock_t audio_lock; struct mutex audio_mutex; unsigned int sample_rate; + unsigned int audio_cts; + unsigned int audio_n; + bool audio_enable; int ratio; void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); @@ -346,7 +351,11 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n", __func__, sample_rate, ratio, pixel_clk, n, cts); - hdmi_set_cts_n(hdmi, cts, n); + spin_lock_irq(&hdmi->audio_lock); + hdmi->audio_n = n; + hdmi->audio_cts = cts; + hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0); + spin_unlock_irq(&hdmi->audio_lock); } static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) @@ -375,6 +384,28 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) } EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); +void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) +{ + unsigned long flags; + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = true; + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); +} +EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); + +void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) +{ + unsigned long flags; + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = false; + hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); +} +EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); + /* * this submodule is responsible for the video data synchronization. * for example, for RGB 4:4:4 input, the data map is defined as @@ -1577,6 +1608,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, hdmi->encoder = encoder; mutex_init(&hdmi->audio_mutex); + spin_lock_init(&hdmi->audio_lock); of_property_read_u32(np, "reg-io-width", &val); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 763af51e1d60..bae79f3c4d28 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -63,5 +63,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, const struct dw_hdmi_plat_data *plat_data); void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); +void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); +void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); #endif /* __IMX_HDMI_H__ */ -- cgit v1.2.3 From 44790462d041d3037d60b3bf88f30837a72006ff Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 14 Jul 2015 11:33:31 +1000 Subject: drm/dp/mst: dump branch OUI in debugfs (v2) It appears some MST docks are worse than other, but the only way to know is to see the sw revisions in here, so dump the branch OUI so we can look at the sw revision. v2: Thierry made me feel guilty, so I parsed the branch OUI. Reviewed-by: Thierry Reding Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_mst_topology.c | 10 ++++++++++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 11 insertions(+) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b0487c9f018c..86bc9ade5fc4 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2631,6 +2631,16 @@ void drm_dp_mst_dump_topology(struct seq_file *m, seq_printf(m, "%02x ", buf[i]); seq_printf(m, "\n"); + /* dump the standard OUI branch header */ + ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE); + seq_printf(m, "branch oui: "); + for (i = 0; i < 0x3; i++) + seq_printf(m, "%02x", buf[i]); + seq_printf(m, " devid: "); + for (i = 0x3; i < 0x8; i++) + seq_printf(m, "%c", buf[i]); + seq_printf(m, " revision: hw: %x.%x sw: %x.%x", buf[0x9] >> 4, buf[0x9] & 0xf, buf[0xa], buf[0xb]); + seq_printf(m, "\n"); bret = dump_dp_payload_table(mgr, buf); if (bret == true) { seq_printf(m, "payload table: "); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 94898f6ea02a..499e9f625aef 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -578,6 +578,7 @@ u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE], u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE], int lane); +#define DP_BRANCH_OUI_HEADER_SIZE 0xc #define DP_RECEIVER_CAP_SIZE 0xf #define EDP_PSR_RECEIVER_CAP_SIZE 2 -- cgit v1.2.3