diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 9dd48f7490df..4a0c599b6a6d 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -1615,6 +1615,11 @@ void intel_crt_init(struct drm_device *dev) !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers !Edrivers/gpu/drm/drm_fb_helper.c !Iinclude/drm/drm_fb_helper.h + + + Framebuffer CMA Helper Functions Reference +!Pdrivers/gpu/drm/drm_fb_cma_helper.c framebuffer cma helper functions +!Edrivers/gpu/drm/drm_fb_cma_helper.c Display Port Helper Functions Reference diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 997fd21e5388..43a0b3dfa846 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -384,8 +384,6 @@ mode_fixup(struct drm_atomic_state *state) */ encoder = conn_state->best_encoder; funcs = encoder->helper_private; - if (!funcs) - continue; ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode, &crtc_state->adjusted_mode); @@ -394,7 +392,7 @@ mode_fixup(struct drm_atomic_state *state) return -EINVAL; } - if (funcs->atomic_check) { + if (funcs && funcs->atomic_check) { ret = funcs->atomic_check(encoder, crtc_state, conn_state); if (ret) { @@ -402,7 +400,7 @@ mode_fixup(struct drm_atomic_state *state) encoder->base.id, encoder->name); return ret; } - } else if (funcs->mode_fixup) { + } else if (funcs && funcs->mode_fixup) { ret = funcs->mode_fixup(encoder, &crtc_state->mode, &crtc_state->adjusted_mode); if (!ret) { @@ -707,12 +705,14 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) drm_bridge_disable(encoder->bridge); /* Right function depends upon target state. */ - if (connector->state->crtc && funcs->prepare) - funcs->prepare(encoder); - else if (funcs->disable) - funcs->disable(encoder); - else - funcs->dpms(encoder, DRM_MODE_DPMS_OFF); + if (funcs) { + if (connector->state->crtc && funcs->prepare) + funcs->prepare(encoder); + else if (funcs->disable) + funcs->disable(encoder); + else if (funcs->dpms) + funcs->dpms(encoder, DRM_MODE_DPMS_OFF); + } drm_bridge_post_disable(encoder->bridge); } @@ -873,7 +873,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) * Each encoder has at most one connector (since we always steal * it away), so we won't call mode_set hooks twice. */ - if (funcs->mode_set) + if (funcs && funcs->mode_set) funcs->mode_set(encoder, mode, adjusted_mode); drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode); @@ -974,10 +974,12 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, */ drm_bridge_pre_enable(encoder->bridge); - if (funcs->enable) - funcs->enable(encoder); - else - funcs->commit(encoder); + if (funcs) { + if (funcs->enable) + funcs->enable(encoder); + else if (funcs->commit) + funcs->commit(encoder); + } drm_bridge_enable(encoder->bridge); } @@ -2480,6 +2482,23 @@ backoff: } EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); +/** + * drm_atomic_helper_best_encoder - Helper for &drm_connector_helper_funcs + * ->best_encoder callback + * @connector: Connector control structure + * + * This is a &drm_connector_helper_funcs ->best_encoder callback helper for + * connectors that support exactly 1 encoder, statically determined at driver + * init time. + */ +struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector) +{ + WARN_ON(connector->encoder_ids[1]); + return drm_encoder_find(connector->dev, connector->encoder_ids[0]); +} +EXPORT_SYMBOL(drm_atomic_helper_best_encoder); + /** * DOC: atomic state reset and initialization * diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index f47a252ffa89..a6e42433ef0e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -170,11 +170,14 @@ drm_encoder_disable(struct drm_encoder *encoder) { const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + return; + drm_bridge_disable(encoder->bridge); if (encoder_funcs->disable) (*encoder_funcs->disable)(encoder); - else + else if (encoder_funcs->dpms) (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); drm_bridge_post_disable(encoder->bridge); @@ -248,6 +251,9 @@ drm_crtc_prepare_encoders(struct drm_device *dev) drm_for_each_encoder(encoder, dev) { encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + continue; + /* Disable unused encoders */ if (encoder->crtc == NULL) drm_encoder_disable(encoder); @@ -326,6 +332,10 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + continue; + ret = drm_bridge_mode_fixup(encoder->bridge, mode, adjusted_mode); if (!ret) { @@ -360,11 +370,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + continue; + drm_bridge_disable(encoder->bridge); - encoder_funcs = encoder->helper_private; /* Disable the encoders as the first thing we do. */ - encoder_funcs->prepare(encoder); + if (encoder_funcs->prepare) + encoder_funcs->prepare(encoder); drm_bridge_post_disable(encoder->bridge); } @@ -385,11 +399,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + continue; + DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", encoder->base.id, encoder->name, mode->base.id, mode->name); - encoder_funcs = encoder->helper_private; - encoder_funcs->mode_set(encoder, mode, adjusted_mode); + if (encoder_funcs->mode_set) + encoder_funcs->mode_set(encoder, mode, adjusted_mode); drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode); } @@ -402,10 +420,14 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; + encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + continue; + drm_bridge_pre_enable(encoder->bridge); - encoder_funcs = encoder->helper_private; - encoder_funcs->commit(encoder); + if (encoder_funcs->commit) + encoder_funcs->commit(encoder); drm_bridge_enable(encoder->bridge); } @@ -790,12 +812,15 @@ static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode) struct drm_bridge *bridge = encoder->bridge; const struct drm_encoder_helper_funcs *encoder_funcs; + encoder_funcs = encoder->helper_private; + if (!encoder_funcs) + return; + if (mode == DRM_MODE_DPMS_ON) drm_bridge_pre_enable(bridge); else drm_bridge_disable(bridge); - encoder_funcs = encoder->helper_private; if (encoder_funcs->dpms) encoder_funcs->dpms(encoder, mode); diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 086f600a975a..3165ac0e93e5 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -43,14 +43,12 @@ struct drm_fbdev_cma { * Provides helper functions for creating a cma (contiguous memory allocator) * backed framebuffer. * - * drm_fb_cma_create() is used in the - * (struct drm_mode_config_funcs *)->fb_create callback function to create the - * cma backed framebuffer. + * drm_fb_cma_create() is used in the &drm_mode_config_funcs ->fb_create + * callback function to create a cma backed framebuffer. * * An fbdev framebuffer backed by cma is also available by calling * drm_fbdev_cma_init(). drm_fbdev_cma_fini() tears it down. - * If CONFIG_FB_DEFERRED_IO is enabled and the callback - * (struct drm_framebuffer_funcs)->dirty is set, fb_deferred_io + * If the &drm_framebuffer_funcs ->dirty callback is set, fb_deferred_io * will be set up automatically. dirty() is called by * drm_fb_helper_deferred_io() in process context (struct delayed_work). * diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 385284bc773c..e03f8ad90b3a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -85,14 +85,14 @@ static LIST_HEAD(kernel_fb_helper_list); * should call drm_fb_helper_single_add_all_connectors() followed by * drm_fb_helper_initial_config(). * - * If CONFIG_FB_DEFERRED_IO is enabled and &drm_framebuffer_funcs ->dirty is - * set, the drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} - * functions will accumulate changes and schedule &fb_helper .dirty_work to run - * right away. This worker then calls the dirty() function ensuring that it - * will always run in process context since the fb_*() function could be - * running in atomic context. If drm_fb_helper_deferred_io() is used as the - * deferred_io callback it will also schedule dirty_work with the damage - * collected from the mmap page writes. + * If &drm_framebuffer_funcs ->dirty is set, the + * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will + * accumulate changes and schedule &drm_fb_helper ->dirty_work to run right + * away. This worker then calls the dirty() function ensuring that it will + * always run in process context since the fb_*() function could be running in + * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io + * callback it will also schedule dirty_work with the damage collected from the + * mmap page writes. */ /** diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 6c4dd49de993..21c719e8e02b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -418,7 +418,7 @@ static struct drm_driver exynos_drm_driver = { .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = exynos_drm_crtc_enable_vblank, .disable_vblank = exynos_drm_crtc_disable_vblank, - .gem_free_object = exynos_drm_gem_free_object, + .gem_free_object_unlocked = exynos_drm_gem_free_object, .gem_vm_ops = &exynos_drm_gem_vm_ops, .dumb_create = exynos_drm_gem_dumb_create, .dumb_map_offset = exynos_drm_gem_dumb_map_offset, diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c index 3abb400151ac..4e990299735c 100644 --- a/drivers/gpu/drm/sti/sti_cursor.c +++ b/drivers/gpu/drm/sti/sti_cursor.c @@ -6,6 +6,8 @@ * License terms: GNU General Public License (GPL), version 2 */ +#include + #include #include #include diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index ff3d3e7e7704..ff33c38da197 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -5,6 +5,7 @@ * for STMicroelectronics. * License terms: GNU General Public License (GPL), version 2 */ +#include #include #include diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index ec0d017eaf1a..f7d3464cdf09 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index e05b0dc523ff..1edec29b9e45 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c index e7425c38fc93..aed7801b51f7 100644 --- a/drivers/gpu/drm/sti/sti_mixer.c +++ b/drivers/gpu/drm/sti/sti_mixer.c @@ -5,6 +5,7 @@ * for STMicroelectronics. * License terms: GNU General Public License (GPL), version 2 */ +#include #include "sti_compositor.h" #include "sti_mixer.h" diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 2c99016443e5..f983db5a59da 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c index 5a2c5dc3687b..523ed19f5ac6 100644 --- a/drivers/gpu/drm/sti/sti_vid.c +++ b/drivers/gpu/drm/sti/sti_vid.c @@ -3,6 +3,7 @@ * Author: Fabien Dessenne for STMicroelectronics. * License terms: GNU General Public License (GPL), version 2 */ +#include #include diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 71a52f4e688b..45deb8fd8e7c 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -932,7 +932,7 @@ static struct drm_driver tegra_drm_driver = { .debugfs_cleanup = tegra_debugfs_cleanup, #endif - .gem_free_object = tegra_bo_free_object, + .gem_free_object_unlocked = tegra_bo_free_object, .gem_vm_ops = &tegra_bo_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 03642878bc51..ccca709a255b 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -110,6 +110,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, uint32_t flags); int drm_atomic_helper_connector_dpms(struct drm_connector *connector, int mode); +struct drm_encoder * +drm_atomic_helper_best_encoder(struct drm_connector *connector); /* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);