brintos

brintos / linux-shallow public Read only

0
0
Text · 23.4 KiB · 70d8ad0 Raw
1011 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * R-Car Display Unit Mode Setting4 *5 * Copyright (C) 2013-2015 Renesas Electronics Corporation6 *7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)8 */9 10#include <drm/drm_atomic.h>11#include <drm/drm_atomic_helper.h>12#include <drm/drm_crtc.h>13#include <drm/drm_device.h>14#include <drm/drm_framebuffer.h>15#include <drm/drm_gem_dma_helper.h>16#include <drm/drm_gem_framebuffer_helper.h>17#include <drm/drm_managed.h>18#include <drm/drm_probe_helper.h>19#include <drm/drm_vblank.h>20 21#include <linux/device.h>22#include <linux/dma-buf.h>23#include <linux/of.h>24#include <linux/of_graph.h>25#include <linux/of_platform.h>26#include <linux/platform_device.h>27#include <linux/wait.h>28 29#include "rcar_du_crtc.h"30#include "rcar_du_drv.h"31#include "rcar_du_encoder.h"32#include "rcar_du_kms.h"33#include "rcar_du_regs.h"34#include "rcar_du_vsp.h"35#include "rcar_du_writeback.h"36 37/* -----------------------------------------------------------------------------38 * Format helpers39 */40 41static const struct rcar_du_format_info rcar_du_format_infos[] = {42	{43		.fourcc = DRM_FORMAT_RGB565,44		.v4l2 = V4L2_PIX_FMT_RGB565,45		.bpp = 16,46		.planes = 1,47		.hsub = 1,48		.pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP,49		.edf = PnDDCR4_EDF_NONE,50	}, {51		.fourcc = DRM_FORMAT_ARGB1555,52		.v4l2 = V4L2_PIX_FMT_ARGB555,53		.bpp = 16,54		.planes = 1,55		.hsub = 1,56		.pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB,57		.edf = PnDDCR4_EDF_NONE,58	}, {59		.fourcc = DRM_FORMAT_XRGB1555,60		.v4l2 = V4L2_PIX_FMT_XRGB555,61		.bpp = 16,62		.planes = 1,63		.pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB,64		.edf = PnDDCR4_EDF_NONE,65	}, {66		.fourcc = DRM_FORMAT_XRGB8888,67		.v4l2 = V4L2_PIX_FMT_XBGR32,68		.bpp = 32,69		.planes = 1,70		.hsub = 1,71		.pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP,72		.edf = PnDDCR4_EDF_RGB888,73	}, {74		.fourcc = DRM_FORMAT_ARGB8888,75		.v4l2 = V4L2_PIX_FMT_ABGR32,76		.bpp = 32,77		.planes = 1,78		.hsub = 1,79		.pnmr = PnMR_SPIM_ALP | PnMR_DDDF_16BPP,80		.edf = PnDDCR4_EDF_ARGB8888,81	}, {82		.fourcc = DRM_FORMAT_UYVY,83		.v4l2 = V4L2_PIX_FMT_UYVY,84		.bpp = 16,85		.planes = 1,86		.hsub = 2,87		.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,88		.edf = PnDDCR4_EDF_NONE,89	}, {90		.fourcc = DRM_FORMAT_YUYV,91		.v4l2 = V4L2_PIX_FMT_YUYV,92		.bpp = 16,93		.planes = 1,94		.hsub = 2,95		.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,96		.edf = PnDDCR4_EDF_NONE,97	}, {98		.fourcc = DRM_FORMAT_NV12,99		.v4l2 = V4L2_PIX_FMT_NV12M,100		.bpp = 12,101		.planes = 2,102		.hsub = 2,103		.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,104		.edf = PnDDCR4_EDF_NONE,105	}, {106		.fourcc = DRM_FORMAT_NV21,107		.v4l2 = V4L2_PIX_FMT_NV21M,108		.bpp = 12,109		.planes = 2,110		.hsub = 2,111		.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,112		.edf = PnDDCR4_EDF_NONE,113	}, {114		.fourcc = DRM_FORMAT_NV16,115		.v4l2 = V4L2_PIX_FMT_NV16M,116		.bpp = 16,117		.planes = 2,118		.hsub = 2,119		.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,120		.edf = PnDDCR4_EDF_NONE,121	},122	/*123	 * The following formats are not supported on Gen2 and thus have no124	 * associated .pnmr or .edf settings.125	 */126	{127		.fourcc = DRM_FORMAT_RGB332,128		.v4l2 = V4L2_PIX_FMT_RGB332,129		.bpp = 8,130		.planes = 1,131		.hsub = 1,132	}, {133		.fourcc = DRM_FORMAT_ARGB4444,134		.v4l2 = V4L2_PIX_FMT_ARGB444,135		.bpp = 16,136		.planes = 1,137		.hsub = 1,138	}, {139		.fourcc = DRM_FORMAT_XRGB4444,140		.v4l2 = V4L2_PIX_FMT_XRGB444,141		.bpp = 16,142		.planes = 1,143		.hsub = 1,144	}, {145		.fourcc = DRM_FORMAT_RGBA4444,146		.v4l2 = V4L2_PIX_FMT_RGBA444,147		.bpp = 16,148		.planes = 1,149		.hsub = 1,150	}, {151		.fourcc = DRM_FORMAT_RGBX4444,152		.v4l2 = V4L2_PIX_FMT_RGBX444,153		.bpp = 16,154		.planes = 1,155		.hsub = 1,156	}, {157		.fourcc = DRM_FORMAT_ABGR4444,158		.v4l2 = V4L2_PIX_FMT_ABGR444,159		.bpp = 16,160		.planes = 1,161		.hsub = 1,162	}, {163		.fourcc = DRM_FORMAT_XBGR4444,164		.v4l2 = V4L2_PIX_FMT_XBGR444,165		.bpp = 16,166		.planes = 1,167		.hsub = 1,168	}, {169		.fourcc = DRM_FORMAT_BGRA4444,170		.v4l2 = V4L2_PIX_FMT_BGRA444,171		.bpp = 16,172		.planes = 1,173		.hsub = 1,174	}, {175		.fourcc = DRM_FORMAT_BGRX4444,176		.v4l2 = V4L2_PIX_FMT_BGRX444,177		.bpp = 16,178		.planes = 1,179		.hsub = 1,180	}, {181		.fourcc = DRM_FORMAT_RGBA5551,182		.v4l2 = V4L2_PIX_FMT_RGBA555,183		.bpp = 16,184		.planes = 1,185		.hsub = 1,186	}, {187		.fourcc = DRM_FORMAT_RGBX5551,188		.v4l2 = V4L2_PIX_FMT_RGBX555,189		.bpp = 16,190		.planes = 1,191		.hsub = 1,192	}, {193		.fourcc = DRM_FORMAT_ABGR1555,194		.v4l2 = V4L2_PIX_FMT_ABGR555,195		.bpp = 16,196		.planes = 1,197		.hsub = 1,198	}, {199		.fourcc = DRM_FORMAT_XBGR1555,200		.v4l2 = V4L2_PIX_FMT_XBGR555,201		.bpp = 16,202		.planes = 1,203		.hsub = 1,204	}, {205		.fourcc = DRM_FORMAT_BGRA5551,206		.v4l2 = V4L2_PIX_FMT_BGRA555,207		.bpp = 16,208		.planes = 1,209		.hsub = 1,210	}, {211		.fourcc = DRM_FORMAT_BGRX5551,212		.v4l2 = V4L2_PIX_FMT_BGRX555,213		.bpp = 16,214		.planes = 1,215		.hsub = 1,216	}, {217		.fourcc = DRM_FORMAT_BGR888,218		.v4l2 = V4L2_PIX_FMT_RGB24,219		.bpp = 24,220		.planes = 1,221		.hsub = 1,222	}, {223		.fourcc = DRM_FORMAT_RGB888,224		.v4l2 = V4L2_PIX_FMT_BGR24,225		.bpp = 24,226		.planes = 1,227		.hsub = 1,228	}, {229		.fourcc = DRM_FORMAT_RGBA8888,230		.v4l2 = V4L2_PIX_FMT_BGRA32,231		.bpp = 32,232		.planes = 1,233		.hsub = 1,234	}, {235		.fourcc = DRM_FORMAT_RGBX8888,236		.v4l2 = V4L2_PIX_FMT_BGRX32,237		.bpp = 32,238		.planes = 1,239		.hsub = 1,240	}, {241		.fourcc = DRM_FORMAT_ABGR8888,242		.v4l2 = V4L2_PIX_FMT_RGBA32,243		.bpp = 32,244		.planes = 1,245		.hsub = 1,246	}, {247		.fourcc = DRM_FORMAT_XBGR8888,248		.v4l2 = V4L2_PIX_FMT_RGBX32,249		.bpp = 32,250		.planes = 1,251		.hsub = 1,252	}, {253		.fourcc = DRM_FORMAT_BGRA8888,254		.v4l2 = V4L2_PIX_FMT_ARGB32,255		.bpp = 32,256		.planes = 1,257		.hsub = 1,258	}, {259		.fourcc = DRM_FORMAT_BGRX8888,260		.v4l2 = V4L2_PIX_FMT_XRGB32,261		.bpp = 32,262		.planes = 1,263		.hsub = 1,264	}, {265		.fourcc = DRM_FORMAT_RGBX1010102,266		.v4l2 = V4L2_PIX_FMT_RGBX1010102,267		.bpp = 32,268		.planes = 1,269		.hsub = 1,270	}, {271		.fourcc = DRM_FORMAT_RGBA1010102,272		.v4l2 = V4L2_PIX_FMT_RGBA1010102,273		.bpp = 32,274		.planes = 1,275		.hsub = 1,276	}, {277		.fourcc = DRM_FORMAT_ARGB2101010,278		.v4l2 = V4L2_PIX_FMT_ARGB2101010,279		.bpp = 32,280		.planes = 1,281		.hsub = 1,282	}, {283		.fourcc = DRM_FORMAT_YVYU,284		.v4l2 = V4L2_PIX_FMT_YVYU,285		.bpp = 16,286		.planes = 1,287		.hsub = 2,288	}, {289		.fourcc = DRM_FORMAT_NV61,290		.v4l2 = V4L2_PIX_FMT_NV61M,291		.bpp = 16,292		.planes = 2,293		.hsub = 2,294	}, {295		.fourcc = DRM_FORMAT_YUV420,296		.v4l2 = V4L2_PIX_FMT_YUV420M,297		.bpp = 12,298		.planes = 3,299		.hsub = 2,300	}, {301		.fourcc = DRM_FORMAT_YVU420,302		.v4l2 = V4L2_PIX_FMT_YVU420M,303		.bpp = 12,304		.planes = 3,305		.hsub = 2,306	}, {307		.fourcc = DRM_FORMAT_YUV422,308		.v4l2 = V4L2_PIX_FMT_YUV422M,309		.bpp = 16,310		.planes = 3,311		.hsub = 2,312	}, {313		.fourcc = DRM_FORMAT_YVU422,314		.v4l2 = V4L2_PIX_FMT_YVU422M,315		.bpp = 16,316		.planes = 3,317		.hsub = 2,318	}, {319		.fourcc = DRM_FORMAT_YUV444,320		.v4l2 = V4L2_PIX_FMT_YUV444M,321		.bpp = 24,322		.planes = 3,323		.hsub = 1,324	}, {325		.fourcc = DRM_FORMAT_YVU444,326		.v4l2 = V4L2_PIX_FMT_YVU444M,327		.bpp = 24,328		.planes = 3,329		.hsub = 1,330	}, {331		.fourcc = DRM_FORMAT_Y210,332		.v4l2 = V4L2_PIX_FMT_Y210,333		.bpp = 32,334		.planes = 1,335		.hsub = 2,336	}, {337		.fourcc = DRM_FORMAT_Y212,338		.v4l2 = V4L2_PIX_FMT_Y212,339		.bpp = 32,340		.planes = 1,341		.hsub = 2,342	},343};344 345const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)346{347	unsigned int i;348 349	for (i = 0; i < ARRAY_SIZE(rcar_du_format_infos); ++i) {350		if (rcar_du_format_infos[i].fourcc == fourcc)351			return &rcar_du_format_infos[i];352	}353 354	return NULL;355}356 357/* -----------------------------------------------------------------------------358 * Frame buffer359 */360 361static const struct drm_gem_object_funcs rcar_du_gem_funcs = {362	.free = drm_gem_dma_object_free,363	.print_info = drm_gem_dma_object_print_info,364	.get_sg_table = drm_gem_dma_object_get_sg_table,365	.vmap = drm_gem_dma_object_vmap,366	.mmap = drm_gem_dma_object_mmap,367	.vm_ops = &drm_gem_dma_vm_ops,368};369 370struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev,371				struct dma_buf_attachment *attach,372				struct sg_table *sgt)373{374	struct rcar_du_device *rcdu = to_rcar_du_device(dev);375	struct drm_gem_dma_object *dma_obj;376	struct drm_gem_object *gem_obj;377	int ret;378 379	if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))380		return drm_gem_dma_prime_import_sg_table(dev, attach, sgt);381 382	/* Create a DMA GEM buffer. */383	dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);384	if (!dma_obj)385		return ERR_PTR(-ENOMEM);386 387	gem_obj = &dma_obj->base;388	gem_obj->funcs = &rcar_du_gem_funcs;389 390	drm_gem_private_object_init(dev, gem_obj, attach->dmabuf->size);391	dma_obj->map_noncoherent = false;392 393	ret = drm_gem_create_mmap_offset(gem_obj);394	if (ret) {395		drm_gem_object_release(gem_obj);396		kfree(dma_obj);397		return ERR_PTR(ret);398	}399 400	dma_obj->dma_addr = 0;401	dma_obj->sgt = sgt;402 403	return gem_obj;404}405 406int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,407			struct drm_mode_create_dumb *args)408{409	struct rcar_du_device *rcdu = to_rcar_du_device(dev);410	unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);411	unsigned int align;412 413	/*414	 * The R8A7779 DU requires a 16 pixels pitch alignment as documented,415	 * but the R8A7790 DU seems to require a 128 bytes pitch alignment.416	 */417	if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))418		align = 128;419	else420		align = 16 * args->bpp / 8;421 422	args->pitch = roundup(min_pitch, align);423 424	return drm_gem_dma_dumb_create_internal(file, dev, args);425}426 427static struct drm_framebuffer *428rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,429		  const struct drm_mode_fb_cmd2 *mode_cmd)430{431	struct rcar_du_device *rcdu = to_rcar_du_device(dev);432	const struct rcar_du_format_info *format;433	unsigned int chroma_pitch;434	unsigned int max_pitch;435	unsigned int align;436	unsigned int i;437 438	format = rcar_du_format_info(mode_cmd->pixel_format);439	if (format == NULL) {440		dev_dbg(dev->dev, "unsupported pixel format %p4cc\n",441			&mode_cmd->pixel_format);442		return ERR_PTR(-EINVAL);443	}444 445	if (rcdu->info->gen < 3) {446		/*447		 * On Gen2 the DU limits the pitch to 4095 pixels and requires448		 * buffers to be aligned to a 16 pixels boundary (or 128 bytes449		 * on some platforms).450		 */451		unsigned int bpp = format->planes == 1 ? format->bpp / 8 : 1;452 453		max_pitch = 4095 * bpp;454 455		if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))456			align = 128;457		else458			align = 16 * bpp;459	} else {460		/*461		 * On Gen3 the memory interface is handled by the VSP that462		 * limits the pitch to 65535 bytes and has no alignment463		 * constraint.464		 */465		max_pitch = 65535;466		align = 1;467	}468 469	if (mode_cmd->pitches[0] & (align - 1) ||470	    mode_cmd->pitches[0] > max_pitch) {471		dev_dbg(dev->dev, "invalid pitch value %u\n",472			mode_cmd->pitches[0]);473		return ERR_PTR(-EINVAL);474	}475 476	/*477	 * Calculate the chroma plane(s) pitch using the horizontal subsampling478	 * factor. For semi-planar formats, the U and V planes are combined, the479	 * pitch must thus be doubled.480	 */481	chroma_pitch = mode_cmd->pitches[0] / format->hsub;482	if (format->planes == 2)483		chroma_pitch *= 2;484 485	for (i = 1; i < format->planes; ++i) {486		if (mode_cmd->pitches[i] != chroma_pitch) {487			dev_dbg(dev->dev,488				"luma and chroma pitches are not compatible\n");489			return ERR_PTR(-EINVAL);490		}491	}492 493	return drm_gem_fb_create(dev, file_priv, mode_cmd);494}495 496/* -----------------------------------------------------------------------------497 * Atomic Check and Update498 */499 500static int rcar_du_atomic_check(struct drm_device *dev,501				struct drm_atomic_state *state)502{503	struct rcar_du_device *rcdu = to_rcar_du_device(dev);504	int ret;505 506	ret = drm_atomic_helper_check(dev, state);507	if (ret)508		return ret;509 510	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))511		return 0;512 513	return rcar_du_atomic_check_planes(dev, state);514}515 516static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)517{518	struct drm_device *dev = old_state->dev;519	struct rcar_du_device *rcdu = to_rcar_du_device(dev);520	struct drm_crtc_state *crtc_state;521	struct drm_crtc *crtc;522	unsigned int i;523 524	/*525	 * Store RGB routing to DPAD0 and DPAD1, the hardware will be configured526	 * when starting the CRTCs.527	 */528	rcdu->dpad1_source = -1;529 530	for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) {531		struct rcar_du_crtc_state *rcrtc_state =532			to_rcar_crtc_state(crtc_state);533		struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);534 535		if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD0))536			rcdu->dpad0_source = rcrtc->index;537 538		if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))539			rcdu->dpad1_source = rcrtc->index;540	}541 542	/* Apply the atomic update. */543	drm_atomic_helper_commit_modeset_disables(dev, old_state);544	drm_atomic_helper_commit_planes(dev, old_state,545					DRM_PLANE_COMMIT_ACTIVE_ONLY);546	drm_atomic_helper_commit_modeset_enables(dev, old_state);547 548	drm_atomic_helper_commit_hw_done(old_state);549	drm_atomic_helper_wait_for_flip_done(dev, old_state);550 551	drm_atomic_helper_cleanup_planes(dev, old_state);552}553 554/* -----------------------------------------------------------------------------555 * Initialization556 */557 558static const struct drm_mode_config_helper_funcs rcar_du_mode_config_helper = {559	.atomic_commit_tail = rcar_du_atomic_commit_tail,560};561 562static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {563	.fb_create = rcar_du_fb_create,564	.atomic_check = rcar_du_atomic_check,565	.atomic_commit = drm_atomic_helper_commit,566};567 568static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,569				     enum rcar_du_output output,570				     struct of_endpoint *ep)571{572	struct device_node *entity;573	int ret;574 575	/* Locate the connected entity and initialize the encoder. */576	entity = of_graph_get_remote_port_parent(ep->local_node);577	if (!entity) {578		dev_dbg(rcdu->dev, "unconnected endpoint %pOF, skipping\n",579			ep->local_node);580		return -ENODEV;581	}582 583	if (!of_device_is_available(entity)) {584		dev_dbg(rcdu->dev,585			"connected entity %pOF is disabled, skipping\n",586			entity);587		of_node_put(entity);588		return -ENODEV;589	}590 591	ret = rcar_du_encoder_init(rcdu, output, entity);592	if (ret && ret != -EPROBE_DEFER && ret != -ENOLINK)593		dev_warn(rcdu->dev,594			 "failed to initialize encoder %pOF on output %s (%d), skipping\n",595			 entity, rcar_du_output_name(output), ret);596 597	of_node_put(entity);598 599	return ret;600}601 602static int rcar_du_encoders_init(struct rcar_du_device *rcdu)603{604	struct device_node *np = rcdu->dev->of_node;605	struct device_node *ep_node;606	unsigned int num_encoders = 0;607 608	/*609	 * Iterate over the endpoints and create one encoder for each output610	 * pipeline.611	 */612	for_each_endpoint_of_node(np, ep_node) {613		enum rcar_du_output output;614		struct of_endpoint ep;615		unsigned int i;616		int ret;617 618		ret = of_graph_parse_endpoint(ep_node, &ep);619		if (ret < 0) {620			of_node_put(ep_node);621			return ret;622		}623 624		/* Find the output route corresponding to the port number. */625		for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) {626			if (rcdu->info->routes[i].possible_crtcs &&627			    rcdu->info->routes[i].port == ep.port) {628				output = i;629				break;630			}631		}632 633		if (i == RCAR_DU_OUTPUT_MAX) {634			dev_warn(rcdu->dev,635				 "port %u references unexisting output, skipping\n",636				 ep.port);637			continue;638		}639 640		/* Process the output pipeline. */641		ret = rcar_du_encoders_init_one(rcdu, output, &ep);642		if (ret < 0) {643			if (ret == -EPROBE_DEFER) {644				of_node_put(ep_node);645				return ret;646			}647 648			continue;649		}650 651		num_encoders++;652	}653 654	return num_encoders;655}656 657static int rcar_du_properties_init(struct rcar_du_device *rcdu)658{659	/*660	 * The color key is expressed as an RGB888 triplet stored in a 32-bit661	 * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0)662	 * or enable source color keying (1).663	 */664	rcdu->props.colorkey =665		drm_property_create_range(&rcdu->ddev, 0, "colorkey",666					  0, 0x01ffffff);667	if (rcdu->props.colorkey == NULL)668		return -ENOMEM;669 670	return 0;671}672 673static int rcar_du_vsps_init(struct rcar_du_device *rcdu)674{675	const struct device_node *np = rcdu->dev->of_node;676	const char *vsps_prop_name = "renesas,vsps";677	struct of_phandle_args args;678	struct {679		struct device_node *np;680		unsigned int crtcs_mask;681	} vsps[RCAR_DU_MAX_VSPS] = { { NULL, }, };682	unsigned int vsps_count = 0;683	unsigned int cells;684	unsigned int i;685	int ret;686 687	/*688	 * First parse the DT vsps property to populate the list of VSPs. Each689	 * entry contains a pointer to the VSP DT node and a bitmask of the690	 * connected DU CRTCs.691	 */692	ret = of_property_count_u32_elems(np, vsps_prop_name);693	if (ret < 0) {694		/* Backward compatibility with old DTBs. */695		vsps_prop_name = "vsps";696		ret = of_property_count_u32_elems(np, vsps_prop_name);697	}698	cells = ret / rcdu->num_crtcs - 1;699	if (cells > 1)700		return -EINVAL;701 702	for (i = 0; i < rcdu->num_crtcs; ++i) {703		unsigned int j;704 705		ret = of_parse_phandle_with_fixed_args(np, vsps_prop_name,706						       cells, i, &args);707		if (ret < 0)708			goto error;709 710		/*711		 * Add the VSP to the list or update the corresponding existing712		 * entry if the VSP has already been added.713		 */714		for (j = 0; j < vsps_count; ++j) {715			if (vsps[j].np == args.np)716				break;717		}718 719		if (j < vsps_count)720			of_node_put(args.np);721		else722			vsps[vsps_count++].np = args.np;723 724		vsps[j].crtcs_mask |= BIT(i);725 726		/*727		 * Store the VSP pointer and pipe index in the CRTC. If the728		 * second cell of the 'renesas,vsps' specifier isn't present,729		 * default to 0 to remain compatible with older DT bindings.730		 */731		rcdu->crtcs[i].vsp = &rcdu->vsps[j];732		rcdu->crtcs[i].vsp_pipe = cells >= 1 ? args.args[0] : 0;733	}734 735	/*736	 * Then initialize all the VSPs from the node pointers and CRTCs bitmask737	 * computed previously.738	 */739	for (i = 0; i < vsps_count; ++i) {740		struct rcar_du_vsp *vsp = &rcdu->vsps[i];741 742		vsp->index = i;743		vsp->dev = rcdu;744 745		ret = rcar_du_vsp_init(vsp, vsps[i].np, vsps[i].crtcs_mask);746		if (ret < 0)747			goto error;748	}749 750	return 0;751 752error:753	for (i = 0; i < ARRAY_SIZE(vsps); ++i)754		of_node_put(vsps[i].np);755 756	return ret;757}758 759static int rcar_du_cmm_init(struct rcar_du_device *rcdu)760{761	const struct device_node *np = rcdu->dev->of_node;762	unsigned int i;763	int cells;764 765	cells = of_property_count_u32_elems(np, "renesas,cmms");766	if (cells == -EINVAL)767		return 0;768 769	if (cells > rcdu->num_crtcs) {770		dev_err(rcdu->dev,771			"Invalid number of entries in 'renesas,cmms'\n");772		return -EINVAL;773	}774 775	for (i = 0; i < cells; ++i) {776		struct platform_device *pdev;777		struct device_link *link;778		struct device_node *cmm;779		int ret;780 781		cmm = of_parse_phandle(np, "renesas,cmms", i);782		if (!cmm) {783			dev_err(rcdu->dev,784				"Failed to parse 'renesas,cmms' property\n");785			return -EINVAL;786		}787 788		if (!of_device_is_available(cmm)) {789			/* It's fine to have a phandle to a non-enabled CMM. */790			of_node_put(cmm);791			continue;792		}793 794		pdev = of_find_device_by_node(cmm);795		if (!pdev) {796			dev_err(rcdu->dev, "No device found for CMM%u\n", i);797			of_node_put(cmm);798			return -EINVAL;799		}800 801		of_node_put(cmm);802 803		/*804		 * -ENODEV is used to report that the CMM config option is805		 * disabled: return 0 and let the DU continue probing.806		 */807		ret = rcar_cmm_init(pdev);808		if (ret) {809			platform_device_put(pdev);810			return ret == -ENODEV ? 0 : ret;811		}812 813		rcdu->cmms[i] = pdev;814 815		/*816		 * Enforce suspend/resume ordering by making the CMM a provider817		 * of the DU: CMM is suspended after and resumed before the DU.818		 */819		link = device_link_add(rcdu->dev, &pdev->dev, DL_FLAG_STATELESS);820		if (!link) {821			dev_err(rcdu->dev,822				"Failed to create device link to CMM%u\n", i);823			return -EINVAL;824		}825	}826 827	return 0;828}829 830static void rcar_du_modeset_cleanup(struct drm_device *dev, void *res)831{832	struct rcar_du_device *rcdu = to_rcar_du_device(dev);833	unsigned int i;834 835	for (i = 0; i < ARRAY_SIZE(rcdu->cmms); ++i)836		platform_device_put(rcdu->cmms[i]);837}838 839int rcar_du_modeset_init(struct rcar_du_device *rcdu)840{841	static const unsigned int mmio_offsets[] = {842		DU0_REG_OFFSET, DU2_REG_OFFSET843	};844 845	struct drm_device *dev = &rcdu->ddev;846	struct drm_encoder *encoder;847	unsigned int dpad0_sources;848	unsigned int num_encoders;849	unsigned int num_groups;850	unsigned int swindex;851	unsigned int hwindex;852	unsigned int i;853	int ret;854 855	ret = drmm_mode_config_init(dev);856	if (ret)857		return ret;858 859	ret = drmm_add_action(&rcdu->ddev, rcar_du_modeset_cleanup, NULL);860	if (ret)861		return ret;862 863	dev->mode_config.min_width = 0;864	dev->mode_config.min_height = 0;865	dev->mode_config.normalize_zpos = true;866	dev->mode_config.funcs = &rcar_du_mode_config_funcs;867	dev->mode_config.helper_private = &rcar_du_mode_config_helper;868 869	if (rcdu->info->gen < 3) {870		dev->mode_config.max_width = 4095;871		dev->mode_config.max_height = 2047;872	} else {873		/*874		 * The Gen3 DU uses the VSP1 for memory access, and is limited875		 * to frame sizes of 8190x8190.876		 */877		dev->mode_config.max_width = 8190;878		dev->mode_config.max_height = 8190;879	}880 881	rcdu->num_crtcs = hweight8(rcdu->info->channels_mask);882 883	ret = rcar_du_properties_init(rcdu);884	if (ret < 0)885		return ret;886 887	/*888	 * Initialize vertical blanking interrupts handling. Start with vblank889	 * disabled for all CRTCs.890	 */891	ret = drm_vblank_init(dev, rcdu->num_crtcs);892	if (ret < 0)893		return ret;894 895	/* Initialize the groups. */896	num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);897 898	for (i = 0; i < num_groups; ++i) {899		struct rcar_du_group *rgrp = &rcdu->groups[i];900 901		mutex_init(&rgrp->lock);902 903		rgrp->dev = rcdu;904		rgrp->mmio_offset = mmio_offsets[i];905		rgrp->index = i;906		/* Extract the channel mask for this group only. */907		rgrp->channels_mask = (rcdu->info->channels_mask >> (2 * i))908				   & GENMASK(1, 0);909		rgrp->num_crtcs = hweight8(rgrp->channels_mask);910 911		/*912		 * If we have more than one CRTCs in this group pre-associate913		 * the low-order planes with CRTC 0 and the high-order planes914		 * with CRTC 1 to minimize flicker occurring when the915		 * association is changed.916		 */917		rgrp->dptsr_planes = rgrp->num_crtcs > 1918				   ? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)919				   : 0;920 921		if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {922			ret = rcar_du_planes_init(rgrp);923			if (ret < 0)924				return ret;925		}926	}927 928	/* Initialize the compositors. */929	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {930		ret = rcar_du_vsps_init(rcdu);931		if (ret < 0)932			return ret;933	}934 935	/* Initialize the Color Management Modules. */936	ret = rcar_du_cmm_init(rcdu);937	if (ret)938		return dev_err_probe(rcdu->dev, ret,939				     "failed to initialize CMM\n");940 941	/* Create the CRTCs. */942	for (swindex = 0, hwindex = 0; swindex < rcdu->num_crtcs; ++hwindex) {943		struct rcar_du_group *rgrp;944 945		/* Skip unpopulated DU channels. */946		if (!(rcdu->info->channels_mask & BIT(hwindex)))947			continue;948 949		rgrp = &rcdu->groups[hwindex / 2];950 951		ret = rcar_du_crtc_create(rgrp, swindex++, hwindex);952		if (ret < 0)953			return ret;954	}955 956	/* Initialize the encoders. */957	ret = rcar_du_encoders_init(rcdu);958	if (ret < 0)959		return dev_err_probe(rcdu->dev, ret,960				     "failed to initialize encoders\n");961 962	if (ret == 0) {963		dev_err(rcdu->dev, "error: no encoder could be initialized\n");964		return -EINVAL;965	}966 967	num_encoders = ret;968 969	/*970	 * Set the possible CRTCs and possible clones. There's always at least971	 * one way for all encoders to clone each other, set all bits in the972	 * possible clones field.973	 */974	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {975		struct rcar_du_encoder *renc = to_rcar_encoder(encoder);976		const struct rcar_du_output_routing *route =977			&rcdu->info->routes[renc->output];978 979		encoder->possible_crtcs = route->possible_crtcs;980		encoder->possible_clones = (1 << num_encoders) - 1;981	}982 983	/* Create the writeback connectors. */984	if (rcdu->info->gen >= 3) {985		for (i = 0; i < rcdu->num_crtcs; ++i) {986			struct rcar_du_crtc *rcrtc = &rcdu->crtcs[i];987 988			ret = rcar_du_writeback_init(rcdu, rcrtc);989			if (ret < 0)990				return ret;991		}992	}993 994	/*995	 * Initialize the default DPAD0 source to the index of the first DU996	 * channel that can be connected to DPAD0. The exact value doesn't997	 * matter as it should be overwritten by mode setting for the RGB998	 * output, but it is nonetheless required to ensure a valid initial999	 * hardware configuration on Gen3 where DU0 can't always be connected to1000	 * DPAD0.1001	 */1002	dpad0_sources = rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;1003	rcdu->dpad0_source = ffs(dpad0_sources) - 1;1004 1005	drm_mode_config_reset(dev);1006 1007	drm_kms_helper_poll_init(dev);1008 1009	return 0;1010}1011