Skip to content

Commit

Permalink
drm/imx: atomic phase 3 step 1: Use atomic configuration
Browse files Browse the repository at this point in the history
Replacing drm_crtc_helper_set_config() by drm_atomic_helper_set_config()
and converting the suspend/resume operations to atomic make us be able
to use atomic configurations.  All of these allow us to remove the
crtc_funcs->mode_set callback as it is no longer used.  Also, change
the plane_funcs->update/disable_plane callbacks from the transitional
version to the atomic version.  Furthermore, switching to the pure atomic
version of set_config callback means that we may implement CRTC/plane
atomic checks by using the new CRTC/plane states instead of the legacy
ones and we may remove the private ipu_crtc->enabled state which was left
there for the transitional atomic helpers in phase 1.  Page flip is also
switched to the atomic version.  Last, the legacy function
drm_helper_disable_unused_functions() is removed from ->load in order
not to confuse the atomic driver.

Signed-off-by: Liu Ying <gnuiyl@gmail.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
  • Loading branch information
Liu Ying authored and Philipp Zabel committed Jul 12, 2016
1 parent 032003c commit 5f2f911
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 308 deletions.
76 changes: 74 additions & 2 deletions drivers/gpu/drm/imx/imx-drm-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
*/
#include <linux/component.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reservation.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
Expand All @@ -41,6 +45,7 @@ struct imx_drm_device {
struct imx_drm_crtc *crtc[MAX_CRTC];
unsigned int pipes;
struct drm_fbdev_cma *fbhelper;
struct drm_atomic_state *state;
};

struct imx_drm_crtc {
Expand Down Expand Up @@ -169,6 +174,63 @@ static void imx_drm_output_poll_changed(struct drm_device *drm)
static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
.fb_create = drm_fb_cma_create,
.output_poll_changed = imx_drm_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};

static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
struct drm_plane_state *plane_state;
struct drm_gem_cma_object *cma_obj;
struct fence *excl;
unsigned shared_count;
struct fence **shared;
unsigned int i, j;
int ret;

/* Wait for fences. */
for_each_crtc_in_state(state, crtc, crtc_state, i) {
plane_state = crtc->primary->state;
if (plane_state->fb) {
cma_obj = drm_fb_cma_get_gem_obj(plane_state->fb, 0);
if (cma_obj->base.dma_buf) {
ret = reservation_object_get_fences_rcu(
cma_obj->base.dma_buf->resv, &excl,
&shared_count, &shared);
if (unlikely(ret))
DRM_ERROR("failed to get fences "
"for buffer\n");

if (excl) {
fence_wait(excl, false);
fence_put(excl);
}
for (j = 0; j < shared_count; i++) {
fence_wait(shared[j], false);
fence_put(shared[j]);
}
}
}
}

drm_atomic_helper_commit_modeset_disables(dev, state);

drm_atomic_helper_commit_planes(dev, state, true);

drm_atomic_helper_commit_modeset_enables(dev, state);

drm_atomic_helper_commit_hw_done(state);

drm_atomic_helper_wait_for_vblanks(dev, state);

drm_atomic_helper_cleanup_planes(dev, state);
}

static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
.atomic_commit_tail = imx_drm_atomic_commit_tail,
};

/*
Expand Down Expand Up @@ -210,6 +272,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
drm->mode_config.max_width = 4096;
drm->mode_config.max_height = 4096;
drm->mode_config.funcs = &imx_drm_mode_config_funcs;
drm->mode_config.helper_private = &imx_drm_mode_config_helpers;

drm_mode_config_init(drm);

Expand Down Expand Up @@ -252,7 +315,6 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
legacyfb_depth = 16;
}
drm_helper_disable_unused_functions(drm);
imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
drm->mode_config.num_crtc, MAX_CRTC);
if (IS_ERR(imxdrm->fbhelper)) {
Expand Down Expand Up @@ -454,24 +516,34 @@ static int imx_drm_platform_remove(struct platform_device *pdev)
static int imx_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct imx_drm_device *imxdrm;

/* The drm_dev is NULL before .load hook is called */
if (drm_dev == NULL)
return 0;

drm_kms_helper_poll_disable(drm_dev);

imxdrm = drm_dev->dev_private;
imxdrm->state = drm_atomic_helper_suspend(drm_dev);
if (IS_ERR(imxdrm->state)) {
drm_kms_helper_poll_enable(drm_dev);
return PTR_ERR(imxdrm->state);
}

return 0;
}

static int imx_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct imx_drm_device *imx_drm;

if (drm_dev == NULL)
return 0;

drm_helper_resume_force_mode(drm_dev);
imx_drm = drm_dev->dev_private;
drm_atomic_helper_resume(drm_dev, imx_drm->state);
drm_kms_helper_poll_enable(drm_dev);

return 0;
Expand Down
Loading

0 comments on commit 5f2f911

Please sign in to comment.