Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 202dfa08 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/media into drm-next

The series interleaves DRM and V4L2 patches due to dependencies between the R-
Car DU and VSP drivers. Mauro has acked all the V4L2 patches to go through
your tree, and they don't conflict with anything queued for v4.13 in his tree.
If I need to send any conflicting patches through Mauro's tree for v4.13, I'll
make sure to base them on this branch.

* 'drm/next/du' of git://linuxtv.org/pinchartl/media:
  drm: rcar-du: Map memory through the VSP device
  v4l: vsp1: Add API to map and unmap DRM buffers through the VSP
  v4l: vsp1: Map the DL and video buffers through the proper bus master
  v4l: rcar-fcp: Add an API to retrieve the FCP device
  v4l: rcar-fcp: Don't get/put module reference
  drm: rcar-du: Register a completion callback with VSP1
  v4l: vsp1: Extend VSP1 module API to allow DRM callbacks
  v4l: vsp1: Postpone frame end handling in event of display list race
  drm: rcar-du: Arm the page flip event after queuing the page flip
parents 7249e3d6 fa5b4114
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -378,7 +378,7 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 * Page Flip
 */

static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
{
	struct drm_pending_vblank_event *event;
	struct drm_device *dev = rcrtc->crtc.dev;
@@ -581,17 +581,6 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
{
	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;

	if (crtc->state->event) {
		WARN_ON(drm_crtc_vblank_get(crtc) != 0);

		spin_lock_irqsave(&dev->event_lock, flags);
		rcrtc->event = crtc->state->event;
		crtc->state->event = NULL;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_begin(rcrtc);
@@ -601,9 +590,20 @@ 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);
	struct drm_device *dev = rcrtc->crtc.dev;
	unsigned long flags;

	rcar_du_crtc_update_planes(rcrtc);

	if (crtc->state->event) {
		WARN_ON(drm_crtc_vblank_get(crtc) != 0);

		spin_lock_irqsave(&dev->event_lock, flags);
		rcrtc->event = crtc->state->event;
		crtc->state->event = NULL;
		spin_unlock_irqrestore(&dev->event_lock, flags);
	}

	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
		rcar_du_vsp_atomic_flush(rcrtc);
}
@@ -650,6 +650,7 @@ static const struct drm_crtc_funcs crtc_funcs = {
static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
{
	struct rcar_du_crtc *rcrtc = arg;
	struct rcar_du_device *rcdu = rcrtc->group->dev;
	irqreturn_t ret = IRQ_NONE;
	u32 status;

@@ -658,7 +659,10 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)

	if (status & DSSR_FRM) {
		drm_crtc_handle_vblank(&rcrtc->crtc);

		if (rcdu->info->gen < 3)
			rcar_du_crtc_finish_page_flip(rcrtc);

		ret = IRQ_HANDLED;
	}

+1 −0
Original line number Diff line number Diff line
@@ -73,5 +73,6 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);

void rcar_du_crtc_route_output(struct drm_crtc *crtc,
			       enum rcar_du_output output);
void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);

#endif /* __RCAR_DU_CRTC_H__ */
+77 −6
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>

#include <linux/dma-mapping.h>
#include <linux/of_platform.h>
#include <linux/scatterlist.h>
#include <linux/videodev2.h>

#include <media/vsp1.h>
@@ -28,6 +30,13 @@
#include "rcar_du_kms.h"
#include "rcar_du_vsp.h"

static void rcar_du_vsp_complete(void *private)
{
	struct rcar_du_crtc *crtc = private;

	rcar_du_crtc_finish_page_flip(crtc);
}

void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
{
	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
@@ -35,6 +44,8 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
	struct vsp1_du_lif_config cfg = {
		.width = mode->hdisplay,
		.height = mode->vdisplay,
		.callback = rcar_du_vsp_complete,
		.callback_data = crtc,
	};
	struct rcar_du_plane_state state = {
		.state = {
@@ -170,12 +181,9 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
	cfg.dst.width = state->state.crtc_w;
	cfg.dst.height = state->state.crtc_h;

	for (i = 0; i < state->format->planes; ++i) {
		struct drm_gem_cma_object *gem;

		gem = drm_fb_cma_get_gem_obj(fb, i);
		cfg.mem[i] = gem->paddr + fb->offsets[i];
	}
	for (i = 0; i < state->format->planes; ++i)
		cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
			   + fb->offsets[i];

	for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {
		if (formats_kms[i] == state->format->fourcc) {
@@ -187,6 +195,67 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
	vsp1_du_atomic_update(plane->vsp->vsp, plane->index, &cfg);
}

static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
					struct drm_plane_state *state)
{
	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
	struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
	struct rcar_du_device *rcdu = vsp->dev;
	unsigned int i;
	int ret;

	if (!state->fb)
		return 0;

	for (i = 0; i < rstate->format->planes; ++i) {
		struct drm_gem_cma_object *gem =
			drm_fb_cma_get_gem_obj(state->fb, i);
		struct sg_table *sgt = &rstate->sg_tables[i];

		ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr,
				      gem->base.size);
		if (ret)
			goto fail;

		ret = vsp1_du_map_sg(vsp->vsp, sgt);
		if (!ret) {
			sg_free_table(sgt);
			ret = -ENOMEM;
			goto fail;
		}
	}

	return 0;

fail:
	while (i--) {
		struct sg_table *sgt = &rstate->sg_tables[i];

		vsp1_du_unmap_sg(vsp->vsp, sgt);
		sg_free_table(sgt);
	}

	return ret;
}

static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
					 struct drm_plane_state *state)
{
	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
	struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
	unsigned int i;

	if (!state->fb)
		return;

	for (i = 0; i < rstate->format->planes; ++i) {
		struct sg_table *sgt = &rstate->sg_tables[i];

		vsp1_du_unmap_sg(vsp->vsp, sgt);
		sg_free_table(sgt);
	}
}

static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
					  struct drm_plane_state *state)
{
@@ -227,6 +296,8 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
}

static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
	.prepare_fb = rcar_du_vsp_plane_prepare_fb,
	.cleanup_fb = rcar_du_vsp_plane_cleanup_fb,
	.atomic_check = rcar_du_vsp_plane_atomic_check,
	.atomic_update = rcar_du_vsp_plane_atomic_update,
};
+2 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
 * struct rcar_du_vsp_plane_state - Driver-specific plane state
 * @state: base DRM plane state
 * @format: information about the pixel format used by the plane
 * @sg_tables: scatter-gather tables for the frame buffer memory
 * @alpha: value of the plane alpha property
 * @zpos: value of the plane zpos property
 */
@@ -50,6 +51,7 @@ struct rcar_du_vsp_plane_state {
	struct drm_plane_state state;

	const struct rcar_du_format_info *format;
	struct sg_table sg_tables[3];

	unsigned int alpha;
	unsigned int zpos;
+8 −9
Original line number Diff line number Diff line
@@ -53,14 +53,7 @@ struct rcar_fcp_device *rcar_fcp_get(const struct device_node *np)
		if (fcp->dev->of_node != np)
			continue;

		/*
		 * Make sure the module won't be unloaded behind our back. This
		 * is a poor man's safety net, the module should really not be
		 * unloaded while FCP users can be active.
		 */
		if (!try_module_get(fcp->dev->driver->owner))
			fcp = NULL;

		get_device(fcp->dev);
		goto done;
	}

@@ -81,10 +74,16 @@ EXPORT_SYMBOL_GPL(rcar_fcp_get);
void rcar_fcp_put(struct rcar_fcp_device *fcp)
{
	if (fcp)
		module_put(fcp->dev->driver->owner);
		put_device(fcp->dev);
}
EXPORT_SYMBOL_GPL(rcar_fcp_put);

struct device *rcar_fcp_get_device(struct rcar_fcp_device *fcp)
{
	return fcp->dev;
}
EXPORT_SYMBOL_GPL(rcar_fcp_get_device);

/**
 * rcar_fcp_enable - Enable an FCP
 * @fcp: The FCP instance
Loading