File Index
Files and directories
Sign in
FILE

rcar_du_kms.c

File preview with syntax highlighting.

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