cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vsp1_drm.c (27987B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * vsp1_drm.c  --  R-Car VSP1 DRM/KMS Interface
      4 *
      5 * Copyright (C) 2015 Renesas Electronics Corporation
      6 *
      7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
      8 */
      9
     10#include <linux/device.h>
     11#include <linux/dma-mapping.h>
     12#include <linux/slab.h>
     13
     14#include <media/media-entity.h>
     15#include <media/v4l2-subdev.h>
     16#include <media/vsp1.h>
     17
     18#include "vsp1.h"
     19#include "vsp1_brx.h"
     20#include "vsp1_dl.h"
     21#include "vsp1_drm.h"
     22#include "vsp1_lif.h"
     23#include "vsp1_pipe.h"
     24#include "vsp1_rwpf.h"
     25#include "vsp1_uif.h"
     26
     27#define BRX_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
     28
     29/* -----------------------------------------------------------------------------
     30 * Interrupt Handling
     31 */
     32
     33static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
     34				       unsigned int completion)
     35{
     36	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
     37
     38	if (drm_pipe->du_complete) {
     39		struct vsp1_entity *uif = drm_pipe->uif;
     40		unsigned int status = completion
     41				    & (VSP1_DU_STATUS_COMPLETE |
     42				       VSP1_DU_STATUS_WRITEBACK);
     43		u32 crc;
     44
     45		crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0;
     46		drm_pipe->du_complete(drm_pipe->du_private, status, crc);
     47	}
     48
     49	if (completion & VSP1_DL_FRAME_END_INTERNAL) {
     50		drm_pipe->force_brx_release = false;
     51		wake_up(&drm_pipe->wait_queue);
     52	}
     53}
     54
     55/* -----------------------------------------------------------------------------
     56 * Pipeline Configuration
     57 */
     58
     59/*
     60 * Insert the UIF in the pipeline between the prev and next entities. If no UIF
     61 * is available connect the two entities directly.
     62 */
     63static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
     64			      struct vsp1_pipeline *pipe,
     65			      struct vsp1_entity *uif,
     66			      struct vsp1_entity *prev, unsigned int prev_pad,
     67			      struct vsp1_entity *next, unsigned int next_pad)
     68{
     69	struct v4l2_subdev_format format;
     70	int ret;
     71
     72	if (!uif) {
     73		/*
     74		 * If there's no UIF to be inserted, connect the previous and
     75		 * next entities directly.
     76		 */
     77		prev->sink = next;
     78		prev->sink_pad = next_pad;
     79		return 0;
     80	}
     81
     82	prev->sink = uif;
     83	prev->sink_pad = UIF_PAD_SINK;
     84
     85	memset(&format, 0, sizeof(format));
     86	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
     87	format.pad = prev_pad;
     88
     89	ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL, &format);
     90	if (ret < 0)
     91		return ret;
     92
     93	format.pad = UIF_PAD_SINK;
     94
     95	ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL, &format);
     96	if (ret < 0)
     97		return ret;
     98
     99	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
    100		__func__, format.format.width, format.format.height,
    101		format.format.code);
    102
    103	/*
    104	 * The UIF doesn't mangle the format between its sink and source pads,
    105	 * so there is no need to retrieve the format on its source pad.
    106	 */
    107
    108	uif->sink = next;
    109	uif->sink_pad = next_pad;
    110
    111	return 0;
    112}
    113
    114/* Setup one RPF and the connected BRx sink pad. */
    115static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
    116				      struct vsp1_pipeline *pipe,
    117				      struct vsp1_rwpf *rpf,
    118				      struct vsp1_entity *uif,
    119				      unsigned int brx_input)
    120{
    121	struct v4l2_subdev_selection sel;
    122	struct v4l2_subdev_format format;
    123	const struct v4l2_rect *crop;
    124	int ret;
    125
    126	/*
    127	 * Configure the format on the RPF sink pad and propagate it up to the
    128	 * BRx sink pad.
    129	 */
    130	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
    131
    132	memset(&format, 0, sizeof(format));
    133	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
    134	format.pad = RWPF_PAD_SINK;
    135	format.format.width = crop->width + crop->left;
    136	format.format.height = crop->height + crop->top;
    137	format.format.code = rpf->fmtinfo->mbus;
    138	format.format.field = V4L2_FIELD_NONE;
    139
    140	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
    141			       &format);
    142	if (ret < 0)
    143		return ret;
    144
    145	dev_dbg(vsp1->dev,
    146		"%s: set format %ux%u (%x) on RPF%u sink\n",
    147		__func__, format.format.width, format.format.height,
    148		format.format.code, rpf->entity.index);
    149
    150	memset(&sel, 0, sizeof(sel));
    151	sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
    152	sel.pad = RWPF_PAD_SINK;
    153	sel.target = V4L2_SEL_TGT_CROP;
    154	sel.r = *crop;
    155
    156	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL,
    157			       &sel);
    158	if (ret < 0)
    159		return ret;
    160
    161	dev_dbg(vsp1->dev,
    162		"%s: set selection (%u,%u)/%ux%u on RPF%u sink\n",
    163		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
    164		rpf->entity.index);
    165
    166	/*
    167	 * RPF source, hardcode the format to ARGB8888 to turn on format
    168	 * conversion if needed.
    169	 */
    170	format.pad = RWPF_PAD_SOURCE;
    171
    172	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL,
    173			       &format);
    174	if (ret < 0)
    175		return ret;
    176
    177	dev_dbg(vsp1->dev,
    178		"%s: got format %ux%u (%x) on RPF%u source\n",
    179		__func__, format.format.width, format.format.height,
    180		format.format.code, rpf->entity.index);
    181
    182	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
    183
    184	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
    185			       &format);
    186	if (ret < 0)
    187		return ret;
    188
    189	/* Insert and configure the UIF if available. */
    190	ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE,
    191				 pipe->brx, brx_input);
    192	if (ret < 0)
    193		return ret;
    194
    195	/* BRx sink, propagate the format from the RPF source. */
    196	format.pad = brx_input;
    197
    198	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
    199			       &format);
    200	if (ret < 0)
    201		return ret;
    202
    203	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
    204		__func__, format.format.width, format.format.height,
    205		format.format.code, BRX_NAME(pipe->brx), format.pad);
    206
    207	sel.pad = brx_input;
    208	sel.target = V4L2_SEL_TGT_COMPOSE;
    209	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
    210
    211	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
    212			       &sel);
    213	if (ret < 0)
    214		return ret;
    215
    216	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
    217		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
    218		BRX_NAME(pipe->brx), sel.pad);
    219
    220	return 0;
    221}
    222
    223/* Setup the BRx source pad. */
    224static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1,
    225					 struct vsp1_pipeline *pipe);
    226static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
    227
    228static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
    229				      struct vsp1_pipeline *pipe)
    230{
    231	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
    232	struct v4l2_subdev_format format = {
    233		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
    234	};
    235	struct vsp1_entity *brx;
    236	int ret;
    237
    238	/*
    239	 * Pick a BRx:
    240	 * - If we need more than two inputs, use the BRU.
    241	 * - Otherwise, if we are not forced to release our BRx, keep it.
    242	 * - Else, use any free BRx (randomly starting with the BRU).
    243	 */
    244	if (pipe->num_inputs > 2)
    245		brx = &vsp1->bru->entity;
    246	else if (pipe->brx && !drm_pipe->force_brx_release)
    247		brx = pipe->brx;
    248	else if (vsp1_feature(vsp1, VSP1_HAS_BRU) && !vsp1->bru->entity.pipe)
    249		brx = &vsp1->bru->entity;
    250	else
    251		brx = &vsp1->brs->entity;
    252
    253	/* Switch BRx if needed. */
    254	if (brx != pipe->brx) {
    255		struct vsp1_entity *released_brx = NULL;
    256
    257		/* Release our BRx if we have one. */
    258		if (pipe->brx) {
    259			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
    260				__func__, pipe->lif->index,
    261				BRX_NAME(pipe->brx));
    262
    263			/*
    264			 * The BRx might be acquired by the other pipeline in
    265			 * the next step. We must thus remove it from the list
    266			 * of entities for this pipeline. The other pipeline's
    267			 * hardware configuration will reconfigure the BRx
    268			 * routing.
    269			 *
    270			 * However, if the other pipeline doesn't acquire our
    271			 * BRx, we need to keep it in the list, otherwise the
    272			 * hardware configuration step won't disconnect it from
    273			 * the pipeline. To solve this, store the released BRx
    274			 * pointer to add it back to the list of entities later
    275			 * if it isn't acquired by the other pipeline.
    276			 */
    277			released_brx = pipe->brx;
    278
    279			list_del(&pipe->brx->list_pipe);
    280			pipe->brx->sink = NULL;
    281			pipe->brx->pipe = NULL;
    282			pipe->brx = NULL;
    283		}
    284
    285		/*
    286		 * If the BRx we need is in use, force the owner pipeline to
    287		 * switch to the other BRx and wait until the switch completes.
    288		 */
    289		if (brx->pipe) {
    290			struct vsp1_drm_pipeline *owner_pipe;
    291
    292			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
    293				__func__, pipe->lif->index, BRX_NAME(brx));
    294
    295			owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
    296			owner_pipe->force_brx_release = true;
    297
    298			vsp1_du_pipeline_setup_inputs(vsp1, &owner_pipe->pipe);
    299			vsp1_du_pipeline_configure(&owner_pipe->pipe);
    300
    301			ret = wait_event_timeout(owner_pipe->wait_queue,
    302						 !owner_pipe->force_brx_release,
    303						 msecs_to_jiffies(500));
    304			if (ret == 0)
    305				dev_warn(vsp1->dev,
    306					 "DRM pipeline %u reconfiguration timeout\n",
    307					 owner_pipe->pipe.lif->index);
    308		}
    309
    310		/*
    311		 * If the BRx we have released previously hasn't been acquired
    312		 * by the other pipeline, add it back to the entities list (with
    313		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
    314		 * disconnect it from the hardware pipeline.
    315		 */
    316		if (released_brx && !released_brx->pipe)
    317			list_add_tail(&released_brx->list_pipe,
    318				      &pipe->entities);
    319
    320		/* Add the BRx to the pipeline. */
    321		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
    322			__func__, pipe->lif->index, BRX_NAME(brx));
    323
    324		pipe->brx = brx;
    325		pipe->brx->pipe = pipe;
    326		pipe->brx->sink = &pipe->output->entity;
    327		pipe->brx->sink_pad = 0;
    328
    329		list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
    330	}
    331
    332	/*
    333	 * Configure the format on the BRx source and verify that it matches the
    334	 * requested format. We don't set the media bus code as it is configured
    335	 * on the BRx sink pad 0 and propagated inside the entity, not on the
    336	 * source pad.
    337	 */
    338	format.pad = brx->source_pad;
    339	format.format.width = drm_pipe->width;
    340	format.format.height = drm_pipe->height;
    341	format.format.field = V4L2_FIELD_NONE;
    342
    343	ret = v4l2_subdev_call(&brx->subdev, pad, set_fmt, NULL,
    344			       &format);
    345	if (ret < 0)
    346		return ret;
    347
    348	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
    349		__func__, format.format.width, format.format.height,
    350		format.format.code, BRX_NAME(brx), brx->source_pad);
    351
    352	if (format.format.width != drm_pipe->width ||
    353	    format.format.height != drm_pipe->height) {
    354		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
    355		return -EPIPE;
    356	}
    357
    358	return 0;
    359}
    360
    361static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
    362{
    363	return vsp1->drm->inputs[rpf->entity.index].zpos;
    364}
    365
    366/* Setup the input side of the pipeline (RPFs and BRx). */
    367static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1,
    368					struct vsp1_pipeline *pipe)
    369{
    370	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
    371	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
    372	struct vsp1_entity *uif;
    373	bool use_uif = false;
    374	struct vsp1_brx *brx;
    375	unsigned int i;
    376	int ret;
    377
    378	/* Count the number of enabled inputs and sort them by Z-order. */
    379	pipe->num_inputs = 0;
    380
    381	for (i = 0; i < vsp1->info->rpf_count; ++i) {
    382		struct vsp1_rwpf *rpf = vsp1->rpf[i];
    383		unsigned int j;
    384
    385		if (!pipe->inputs[i])
    386			continue;
    387
    388		/* Insert the RPF in the sorted RPFs array. */
    389		for (j = pipe->num_inputs++; j > 0; --j) {
    390			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
    391				break;
    392			inputs[j] = inputs[j-1];
    393		}
    394
    395		inputs[j] = rpf;
    396	}
    397
    398	/*
    399	 * Setup the BRx. This must be done before setting up the RPF input
    400	 * pipelines as the BRx sink compose rectangles depend on the BRx source
    401	 * format.
    402	 */
    403	ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
    404	if (ret < 0) {
    405		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
    406			BRX_NAME(pipe->brx));
    407		return ret;
    408	}
    409
    410	brx = to_brx(&pipe->brx->subdev);
    411
    412	/* Setup the RPF input pipeline for every enabled input. */
    413	for (i = 0; i < pipe->brx->source_pad; ++i) {
    414		struct vsp1_rwpf *rpf = inputs[i];
    415
    416		if (!rpf) {
    417			brx->inputs[i].rpf = NULL;
    418			continue;
    419		}
    420
    421		if (!rpf->entity.pipe) {
    422			rpf->entity.pipe = pipe;
    423			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
    424		}
    425
    426		brx->inputs[i].rpf = rpf;
    427		rpf->brx_input = i;
    428		rpf->entity.sink = pipe->brx;
    429		rpf->entity.sink_pad = i;
    430
    431		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
    432			__func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
    433
    434		uif = drm_pipe->crc.source == VSP1_DU_CRC_PLANE &&
    435		      drm_pipe->crc.index == i ? drm_pipe->uif : NULL;
    436		if (uif)
    437			use_uif = true;
    438		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, uif, i);
    439		if (ret < 0) {
    440			dev_err(vsp1->dev,
    441				"%s: failed to setup RPF.%u\n",
    442				__func__, rpf->entity.index);
    443			return ret;
    444		}
    445	}
    446
    447	/* Insert and configure the UIF at the BRx output if available. */
    448	uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL;
    449	if (uif)
    450		use_uif = true;
    451	ret = vsp1_du_insert_uif(vsp1, pipe, uif,
    452				 pipe->brx, pipe->brx->source_pad,
    453				 &pipe->output->entity, 0);
    454	if (ret < 0)
    455		dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n",
    456			__func__, BRX_NAME(pipe->brx));
    457
    458	/* If the DRM pipe does not have a UIF there is nothing we can update. */
    459	if (!drm_pipe->uif)
    460		return 0;
    461
    462	/*
    463	 * If the UIF is not in use schedule it for removal by setting its pipe
    464	 * pointer to NULL, vsp1_du_pipeline_configure() will remove it from the
    465	 * hardware pipeline and from the pipeline's list of entities. Otherwise
    466	 * make sure it is present in the pipeline's list of entities if it
    467	 * wasn't already.
    468	 */
    469	if (!use_uif) {
    470		drm_pipe->uif->pipe = NULL;
    471	} else if (!drm_pipe->uif->pipe) {
    472		drm_pipe->uif->pipe = pipe;
    473		list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
    474	}
    475
    476	return 0;
    477}
    478
    479/* Setup the output side of the pipeline (WPF and LIF). */
    480static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
    481					 struct vsp1_pipeline *pipe)
    482{
    483	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
    484	struct v4l2_subdev_format format = { 0, };
    485	int ret;
    486
    487	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
    488	format.pad = RWPF_PAD_SINK;
    489	format.format.width = drm_pipe->width;
    490	format.format.height = drm_pipe->height;
    491	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
    492	format.format.field = V4L2_FIELD_NONE;
    493
    494	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
    495			       &format);
    496	if (ret < 0)
    497		return ret;
    498
    499	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
    500		__func__, format.format.width, format.format.height,
    501		format.format.code, pipe->output->entity.index);
    502
    503	format.pad = RWPF_PAD_SOURCE;
    504	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
    505			       &format);
    506	if (ret < 0)
    507		return ret;
    508
    509	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
    510		__func__, format.format.width, format.format.height,
    511		format.format.code, pipe->output->entity.index);
    512
    513	format.pad = LIF_PAD_SINK;
    514	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
    515			       &format);
    516	if (ret < 0)
    517		return ret;
    518
    519	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
    520		__func__, format.format.width, format.format.height,
    521		format.format.code, pipe->lif->index);
    522
    523	/*
    524	 * Verify that the format at the output of the pipeline matches the
    525	 * requested frame size and media bus code.
    526	 */
    527	if (format.format.width != drm_pipe->width ||
    528	    format.format.height != drm_pipe->height ||
    529	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
    530		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
    531			pipe->lif->index);
    532		return -EPIPE;
    533	}
    534
    535	return 0;
    536}
    537
    538/* Configure all entities in the pipeline. */
    539static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
    540{
    541	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
    542	struct vsp1_entity *entity;
    543	struct vsp1_entity *next;
    544	struct vsp1_dl_list *dl;
    545	struct vsp1_dl_body *dlb;
    546	unsigned int dl_flags = 0;
    547
    548	if (drm_pipe->force_brx_release)
    549		dl_flags |= VSP1_DL_FRAME_END_INTERNAL;
    550	if (pipe->output->writeback)
    551		dl_flags |= VSP1_DL_FRAME_END_WRITEBACK;
    552
    553	dl = vsp1_dl_list_get(pipe->output->dlm);
    554	dlb = vsp1_dl_list_get_body0(dl);
    555
    556	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
    557		/* Disconnect unused entities from the pipeline. */
    558		if (!entity->pipe) {
    559			vsp1_dl_body_write(dlb, entity->route->reg,
    560					   VI6_DPR_NODE_UNUSED);
    561
    562			entity->sink = NULL;
    563			list_del(&entity->list_pipe);
    564
    565			continue;
    566		}
    567
    568		vsp1_entity_route_setup(entity, pipe, dlb);
    569		vsp1_entity_configure_stream(entity, pipe, dl, dlb);
    570		vsp1_entity_configure_frame(entity, pipe, dl, dlb);
    571		vsp1_entity_configure_partition(entity, pipe, dl, dlb);
    572	}
    573
    574	vsp1_dl_list_commit(dl, dl_flags);
    575}
    576
    577static int vsp1_du_pipeline_set_rwpf_format(struct vsp1_device *vsp1,
    578					    struct vsp1_rwpf *rwpf,
    579					    u32 pixelformat, unsigned int pitch)
    580{
    581	const struct vsp1_format_info *fmtinfo;
    582	unsigned int chroma_hsub;
    583
    584	fmtinfo = vsp1_get_format_info(vsp1, pixelformat);
    585	if (!fmtinfo) {
    586		dev_dbg(vsp1->dev, "Unsupported pixel format %08x\n",
    587			pixelformat);
    588		return -EINVAL;
    589	}
    590
    591	/*
    592	 * Only formats with three planes can affect the chroma planes pitch.
    593	 * All formats with two planes have a horizontal subsampling value of 2,
    594	 * but combine U and V in a single chroma plane, which thus results in
    595	 * the luma plane and chroma plane having the same pitch.
    596	 */
    597	chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1;
    598
    599	rwpf->fmtinfo = fmtinfo;
    600	rwpf->format.num_planes = fmtinfo->planes;
    601	rwpf->format.plane_fmt[0].bytesperline = pitch;
    602	rwpf->format.plane_fmt[1].bytesperline = pitch / chroma_hsub;
    603
    604	return 0;
    605}
    606
    607/* -----------------------------------------------------------------------------
    608 * DU Driver API
    609 */
    610
    611int vsp1_du_init(struct device *dev)
    612{
    613	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    614
    615	if (!vsp1)
    616		return -EPROBE_DEFER;
    617
    618	return 0;
    619}
    620EXPORT_SYMBOL_GPL(vsp1_du_init);
    621
    622/**
    623 * vsp1_du_setup_lif - Setup the output part of the VSP pipeline
    624 * @dev: the VSP device
    625 * @pipe_index: the DRM pipeline index
    626 * @cfg: the LIF configuration
    627 *
    628 * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
    629 * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
    630 * source pads, and the LIF sink pad.
    631 *
    632 * The @pipe_index argument selects which DRM pipeline to setup. The number of
    633 * available pipelines depend on the VSP instance.
    634 *
    635 * As the media bus code on the blend unit source pad is conditioned by the
    636 * configuration of its sink 0 pad, we also set up the formats on all blend unit
    637 * sinks, even if the configuration will be overwritten later by
    638 * vsp1_du_setup_rpf(). This ensures that the blend unit configuration is set to
    639 * a well defined state.
    640 *
    641 * Return 0 on success or a negative error code on failure.
    642 */
    643int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
    644		      const struct vsp1_du_lif_config *cfg)
    645{
    646	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    647	struct vsp1_drm_pipeline *drm_pipe;
    648	struct vsp1_pipeline *pipe;
    649	unsigned long flags;
    650	unsigned int i;
    651	int ret;
    652
    653	if (pipe_index >= vsp1->info->lif_count)
    654		return -EINVAL;
    655
    656	drm_pipe = &vsp1->drm->pipe[pipe_index];
    657	pipe = &drm_pipe->pipe;
    658
    659	if (!cfg) {
    660		struct vsp1_brx *brx;
    661
    662		mutex_lock(&vsp1->drm->lock);
    663
    664		brx = to_brx(&pipe->brx->subdev);
    665
    666		/*
    667		 * NULL configuration means the CRTC is being disabled, stop
    668		 * the pipeline and turn the light off.
    669		 */
    670		ret = vsp1_pipeline_stop(pipe);
    671		if (ret == -ETIMEDOUT)
    672			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
    673
    674		for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
    675			struct vsp1_rwpf *rpf = pipe->inputs[i];
    676
    677			if (!rpf)
    678				continue;
    679
    680			/*
    681			 * Remove the RPF from the pipe and the list of BRx
    682			 * inputs.
    683			 */
    684			WARN_ON(!rpf->entity.pipe);
    685			rpf->entity.pipe = NULL;
    686			list_del(&rpf->entity.list_pipe);
    687			pipe->inputs[i] = NULL;
    688
    689			brx->inputs[rpf->brx_input].rpf = NULL;
    690		}
    691
    692		drm_pipe->du_complete = NULL;
    693		pipe->num_inputs = 0;
    694
    695		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
    696			__func__, pipe->lif->index,
    697			BRX_NAME(pipe->brx));
    698
    699		list_del(&pipe->brx->list_pipe);
    700		pipe->brx->pipe = NULL;
    701		pipe->brx = NULL;
    702
    703		mutex_unlock(&vsp1->drm->lock);
    704
    705		vsp1_dlm_reset(pipe->output->dlm);
    706		vsp1_device_put(vsp1);
    707
    708		dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__);
    709
    710		return 0;
    711	}
    712
    713	drm_pipe->width = cfg->width;
    714	drm_pipe->height = cfg->height;
    715	pipe->interlaced = cfg->interlaced;
    716
    717	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u%s\n",
    718		__func__, pipe_index, cfg->width, cfg->height,
    719		pipe->interlaced ? "i" : "");
    720
    721	mutex_lock(&vsp1->drm->lock);
    722
    723	/* Setup formats through the pipeline. */
    724	ret = vsp1_du_pipeline_setup_inputs(vsp1, pipe);
    725	if (ret < 0)
    726		goto unlock;
    727
    728	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
    729	if (ret < 0)
    730		goto unlock;
    731
    732	/* Enable the VSP1. */
    733	ret = vsp1_device_get(vsp1);
    734	if (ret < 0)
    735		goto unlock;
    736
    737	/*
    738	 * Register a callback to allow us to notify the DRM driver of frame
    739	 * completion events.
    740	 */
    741	drm_pipe->du_complete = cfg->callback;
    742	drm_pipe->du_private = cfg->callback_data;
    743
    744	/* Disable the display interrupts. */
    745	vsp1_write(vsp1, VI6_DISP_IRQ_STA(pipe_index), 0);
    746	vsp1_write(vsp1, VI6_DISP_IRQ_ENB(pipe_index), 0);
    747
    748	/* Configure all entities in the pipeline. */
    749	vsp1_du_pipeline_configure(pipe);
    750
    751unlock:
    752	mutex_unlock(&vsp1->drm->lock);
    753
    754	if (ret < 0)
    755		return ret;
    756
    757	/* Start the pipeline. */
    758	spin_lock_irqsave(&pipe->irqlock, flags);
    759	vsp1_pipeline_run(pipe);
    760	spin_unlock_irqrestore(&pipe->irqlock, flags);
    761
    762	dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__);
    763
    764	return 0;
    765}
    766EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
    767
    768/**
    769 * vsp1_du_atomic_begin - Prepare for an atomic update
    770 * @dev: the VSP device
    771 * @pipe_index: the DRM pipeline index
    772 */
    773void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
    774{
    775}
    776EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
    777
    778/**
    779 * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
    780 * @dev: the VSP device
    781 * @pipe_index: the DRM pipeline index
    782 * @rpf_index: index of the RPF to setup (0-based)
    783 * @cfg: the RPF configuration
    784 *
    785 * Configure the VSP to perform image composition through RPF @rpf_index as
    786 * described by the @cfg configuration. The image to compose is referenced by
    787 * @cfg.mem and composed using the @cfg.src crop rectangle and the @cfg.dst
    788 * composition rectangle. The Z-order is configurable with higher @zpos values
    789 * displayed on top.
    790 *
    791 * If the @cfg configuration is NULL, the RPF will be disabled. Calling the
    792 * function on a disabled RPF is allowed.
    793 *
    794 * Image format as stored in memory is expressed as a V4L2 @cfg.pixelformat
    795 * value. The memory pitch is configurable to allow for padding at end of lines,
    796 * or simply for images that extend beyond the crop rectangle boundaries. The
    797 * @cfg.pitch value is expressed in bytes and applies to all planes for
    798 * multiplanar formats.
    799 *
    800 * The source memory buffer is referenced by the DMA address of its planes in
    801 * the @cfg.mem array. Up to two planes are supported. The second plane DMA
    802 * address is ignored for formats using a single plane.
    803 *
    804 * This function isn't reentrant, the caller needs to serialize calls.
    805 *
    806 * Return 0 on success or a negative error code on failure.
    807 */
    808int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
    809			  unsigned int rpf_index,
    810			  const struct vsp1_du_atomic_config *cfg)
    811{
    812	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    813	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
    814	struct vsp1_rwpf *rpf;
    815	int ret;
    816
    817	if (rpf_index >= vsp1->info->rpf_count)
    818		return -EINVAL;
    819
    820	rpf = vsp1->rpf[rpf_index];
    821
    822	if (!cfg) {
    823		dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__,
    824			rpf_index);
    825
    826		/*
    827		 * Remove the RPF from the pipeline's inputs. Keep it in the
    828		 * pipeline's entity list to let vsp1_du_pipeline_configure()
    829		 * remove it from the hardware pipeline.
    830		 */
    831		rpf->entity.pipe = NULL;
    832		drm_pipe->pipe.inputs[rpf_index] = NULL;
    833		return 0;
    834	}
    835
    836	dev_dbg(vsp1->dev,
    837		"%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n",
    838		__func__, rpf_index,
    839		cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height,
    840		cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height,
    841		cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1],
    842		&cfg->mem[2], cfg->zpos);
    843
    844	/*
    845	 * Store the format, stride, memory buffer address, crop and compose
    846	 * rectangles and Z-order position and for the input.
    847	 */
    848	ret = vsp1_du_pipeline_set_rwpf_format(vsp1, rpf, cfg->pixelformat,
    849					       cfg->pitch);
    850	if (ret < 0)
    851		return ret;
    852
    853	rpf->alpha = cfg->alpha;
    854
    855	rpf->mem.addr[0] = cfg->mem[0];
    856	rpf->mem.addr[1] = cfg->mem[1];
    857	rpf->mem.addr[2] = cfg->mem[2];
    858
    859	vsp1->drm->inputs[rpf_index].crop = cfg->src;
    860	vsp1->drm->inputs[rpf_index].compose = cfg->dst;
    861	vsp1->drm->inputs[rpf_index].zpos = cfg->zpos;
    862
    863	drm_pipe->pipe.inputs[rpf_index] = rpf;
    864
    865	return 0;
    866}
    867EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
    868
    869/**
    870 * vsp1_du_atomic_flush - Commit an atomic update
    871 * @dev: the VSP device
    872 * @pipe_index: the DRM pipeline index
    873 * @cfg: atomic pipe configuration
    874 */
    875void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
    876			  const struct vsp1_du_atomic_pipe_config *cfg)
    877{
    878	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    879	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
    880	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
    881	int ret;
    882
    883	drm_pipe->crc = cfg->crc;
    884
    885	mutex_lock(&vsp1->drm->lock);
    886
    887	if (cfg->writeback.pixelformat) {
    888		const struct vsp1_du_writeback_config *wb_cfg = &cfg->writeback;
    889
    890		ret = vsp1_du_pipeline_set_rwpf_format(vsp1, pipe->output,
    891						       wb_cfg->pixelformat,
    892						       wb_cfg->pitch);
    893		if (WARN_ON(ret < 0))
    894			goto done;
    895
    896		pipe->output->mem.addr[0] = wb_cfg->mem[0];
    897		pipe->output->mem.addr[1] = wb_cfg->mem[1];
    898		pipe->output->mem.addr[2] = wb_cfg->mem[2];
    899		pipe->output->writeback = true;
    900	}
    901
    902	vsp1_du_pipeline_setup_inputs(vsp1, pipe);
    903	vsp1_du_pipeline_configure(pipe);
    904
    905done:
    906	mutex_unlock(&vsp1->drm->lock);
    907}
    908EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
    909
    910int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt)
    911{
    912	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    913
    914	/*
    915	 * As all the buffers allocated by the DU driver are coherent, we can
    916	 * skip cache sync. This will need to be revisited when support for
    917	 * non-coherent buffers will be added to the DU driver.
    918	 */
    919	return dma_map_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE,
    920			       DMA_ATTR_SKIP_CPU_SYNC);
    921}
    922EXPORT_SYMBOL_GPL(vsp1_du_map_sg);
    923
    924void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt)
    925{
    926	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
    927
    928	dma_unmap_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE,
    929			  DMA_ATTR_SKIP_CPU_SYNC);
    930}
    931EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg);
    932
    933/* -----------------------------------------------------------------------------
    934 * Initialization
    935 */
    936
    937int vsp1_drm_init(struct vsp1_device *vsp1)
    938{
    939	unsigned int i;
    940
    941	vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL);
    942	if (!vsp1->drm)
    943		return -ENOMEM;
    944
    945	mutex_init(&vsp1->drm->lock);
    946
    947	/* Create one DRM pipeline per LIF. */
    948	for (i = 0; i < vsp1->info->lif_count; ++i) {
    949		struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
    950		struct vsp1_pipeline *pipe = &drm_pipe->pipe;
    951
    952		init_waitqueue_head(&drm_pipe->wait_queue);
    953
    954		vsp1_pipeline_init(pipe);
    955
    956		pipe->frame_end = vsp1_du_pipeline_frame_end;
    957
    958		/*
    959		 * The output side of the DRM pipeline is static, add the
    960		 * corresponding entities manually.
    961		 */
    962		pipe->output = vsp1->wpf[i];
    963		pipe->lif = &vsp1->lif[i]->entity;
    964
    965		pipe->output->entity.pipe = pipe;
    966		pipe->output->entity.sink = pipe->lif;
    967		pipe->output->entity.sink_pad = 0;
    968		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
    969
    970		pipe->lif->pipe = pipe;
    971		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
    972
    973		/*
    974		 * CRC computation is initially disabled, don't add the UIF to
    975		 * the pipeline.
    976		 */
    977		if (i < vsp1->info->uif_count)
    978			drm_pipe->uif = &vsp1->uif[i]->entity;
    979	}
    980
    981	/* Disable all RPFs initially. */
    982	for (i = 0; i < vsp1->info->rpf_count; ++i) {
    983		struct vsp1_rwpf *input = vsp1->rpf[i];
    984
    985		INIT_LIST_HEAD(&input->entity.list_pipe);
    986	}
    987
    988	return 0;
    989}
    990
    991void vsp1_drm_cleanup(struct vsp1_device *vsp1)
    992{
    993	mutex_destroy(&vsp1->drm->lock);
    994}