1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * vsp1_drv.c  --  R-Car VSP1 Driver
4 *
5 * Copyright (C) 2013-2015 Renesas Electronics Corporation
6 *
7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */
9
10#include <linux/clk.h>
11#include <linux/delay.h>
12#include <linux/device.h>
13#include <linux/interrupt.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/reset.h>
19#include <linux/videodev2.h>
20
21#include <media/rcar-fcp.h>
22#include <media/v4l2-subdev.h>
23
24#include "vsp1.h"
25#include "vsp1_brx.h"
26#include "vsp1_clu.h"
27#include "vsp1_dl.h"
28#include "vsp1_drm.h"
29#include "vsp1_hgo.h"
30#include "vsp1_hgt.h"
31#include "vsp1_hsit.h"
32#include "vsp1_lif.h"
33#include "vsp1_lut.h"
34#include "vsp1_pipe.h"
35#include "vsp1_rwpf.h"
36#include "vsp1_sru.h"
37#include "vsp1_uds.h"
38#include "vsp1_uif.h"
39#include "vsp1_video.h"
40
41/* -----------------------------------------------------------------------------
42 * Interrupt Handling
43 */
44
45static irqreturn_t vsp1_irq_handler(int irq, void *data)
46{
47	u32 mask = VI6_WPF_IRQ_STA_DFE | VI6_WPF_IRQ_STA_FRE |
48		   VI6_WPF_IRQ_STA_UND;
49	struct vsp1_device *vsp1 = data;
50	irqreturn_t ret = IRQ_NONE;
51	unsigned int i;
52	u32 status;
53
54	for (i = 0; i < vsp1->info->wpf_count; ++i) {
55		struct vsp1_rwpf *wpf = vsp1->wpf[i];
56
57		if (wpf == NULL)
58			continue;
59
60		status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i));
61		vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
62
63		if ((status & VI6_WPF_IRQ_STA_UND) && wpf->entity.pipe) {
64			wpf->entity.pipe->underrun_count++;
65
66			dev_warn_ratelimited(vsp1->dev,
67				"Underrun occurred at WPF%u (total underruns %u)\n",
68				i, wpf->entity.pipe->underrun_count);
69		}
70
71		if (status & VI6_WPF_IRQ_STA_DFE) {
72			vsp1_pipeline_frame_end(wpf->entity.pipe);
73			ret = IRQ_HANDLED;
74		}
75	}
76
77	return ret;
78}
79
80/* -----------------------------------------------------------------------------
81 * Entities
82 */
83
84/*
85 * vsp1_create_sink_links - Create links from all sources to the given sink
86 *
87 * This function creates media links from all valid sources to the given sink
88 * pad. Links that would be invalid according to the VSP1 hardware capabilities
89 * are skipped. Those include all links
90 *
91 * - from a UDS to a UDS (UDS entities can't be chained)
92 * - from an entity to itself (no loops are allowed)
93 *
94 * Furthermore, the BRS can't be connected to histogram generators, but no
95 * special check is currently needed as all VSP instances that include a BRS
96 * have no histogram generator.
97 */
98static int vsp1_create_sink_links(struct vsp1_device *vsp1,
99				  struct vsp1_entity *sink)
100{
101	struct media_entity *entity = &sink->subdev.entity;
102	struct vsp1_entity *source;
103	unsigned int pad;
104	int ret;
105
106	list_for_each_entry(source, &vsp1->entities, list_dev) {
107		u32 flags;
108
109		if (source->type == sink->type)
110			continue;
111
112		if (source->type == VSP1_ENTITY_HGO ||
113		    source->type == VSP1_ENTITY_HGT ||
114		    source->type == VSP1_ENTITY_LIF ||
115		    source->type == VSP1_ENTITY_WPF)
116			continue;
117
118		flags = source->type == VSP1_ENTITY_RPF &&
119			sink->type == VSP1_ENTITY_WPF &&
120			source->index == sink->index
121		      ? MEDIA_LNK_FL_ENABLED : 0;
122
123		for (pad = 0; pad < entity->num_pads; ++pad) {
124			if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK))
125				continue;
126
127			ret = media_create_pad_link(&source->subdev.entity,
128						       source->source_pad,
129						       entity, pad, flags);
130			if (ret < 0)
131				return ret;
132
133			if (flags & MEDIA_LNK_FL_ENABLED)
134				source->sink = sink;
135		}
136	}
137
138	return 0;
139}
140
141static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
142{
143	struct vsp1_entity *entity;
144	unsigned int i;
145	int ret;
146
147	list_for_each_entry(entity, &vsp1->entities, list_dev) {
148		if (entity->type == VSP1_ENTITY_LIF ||
149		    entity->type == VSP1_ENTITY_RPF)
150			continue;
151
152		ret = vsp1_create_sink_links(vsp1, entity);
153		if (ret < 0)
154			return ret;
155	}
156
157	if (vsp1->hgo) {
158		ret = media_create_pad_link(&vsp1->hgo->histo.entity.subdev.entity,
159					    HISTO_PAD_SOURCE,
160					    &vsp1->hgo->histo.video.entity, 0,
161					    MEDIA_LNK_FL_ENABLED |
162					    MEDIA_LNK_FL_IMMUTABLE);
163		if (ret < 0)
164			return ret;
165	}
166
167	if (vsp1->hgt) {
168		ret = media_create_pad_link(&vsp1->hgt->histo.entity.subdev.entity,
169					    HISTO_PAD_SOURCE,
170					    &vsp1->hgt->histo.video.entity, 0,
171					    MEDIA_LNK_FL_ENABLED |
172					    MEDIA_LNK_FL_IMMUTABLE);
173		if (ret < 0)
174			return ret;
175	}
176
177	for (i = 0; i < vsp1->info->lif_count; ++i) {
178		if (!vsp1->lif[i])
179			continue;
180
181		ret = media_create_pad_link(&vsp1->wpf[i]->entity.subdev.entity,
182					    RWPF_PAD_SOURCE,
183					    &vsp1->lif[i]->entity.subdev.entity,
184					    LIF_PAD_SINK, 0);
185		if (ret < 0)
186			return ret;
187	}
188
189	for (i = 0; i < vsp1->info->rpf_count; ++i) {
190		struct vsp1_rwpf *rpf = vsp1->rpf[i];
191
192		ret = media_create_pad_link(&rpf->video->video.entity, 0,
193					    &rpf->entity.subdev.entity,
194					    RWPF_PAD_SINK,
195					    MEDIA_LNK_FL_ENABLED |
196					    MEDIA_LNK_FL_IMMUTABLE);
197		if (ret < 0)
198			return ret;
199	}
200
201	for (i = 0; i < vsp1->info->wpf_count; ++i) {
202		/*
203		 * Connect the video device to the WPF. All connections are
204		 * immutable.
205		 */
206		struct vsp1_rwpf *wpf = vsp1->wpf[i];
207
208		ret = media_create_pad_link(&wpf->entity.subdev.entity,
209					    RWPF_PAD_SOURCE,
210					    &wpf->video->video.entity, 0,
211					    MEDIA_LNK_FL_IMMUTABLE |
212					    MEDIA_LNK_FL_ENABLED);
213		if (ret < 0)
214			return ret;
215	}
216
217	return 0;
218}
219
220static void vsp1_destroy_entities(struct vsp1_device *vsp1)
221{
222	struct vsp1_entity *entity, *_entity;
223	struct vsp1_video *video, *_video;
224
225	list_for_each_entry_safe(entity, _entity, &vsp1->entities, list_dev) {
226		list_del(&entity->list_dev);
227		vsp1_entity_destroy(entity);
228	}
229
230	list_for_each_entry_safe(video, _video, &vsp1->videos, list) {
231		list_del(&video->list);
232		vsp1_video_cleanup(video);
233	}
234
235	v4l2_device_unregister(&vsp1->v4l2_dev);
236	if (vsp1->info->uapi)
237		media_device_unregister(&vsp1->media_dev);
238	media_device_cleanup(&vsp1->media_dev);
239
240	if (!vsp1->info->uapi)
241		vsp1_drm_cleanup(vsp1);
242}
243
244static int vsp1_create_entities(struct vsp1_device *vsp1)
245{
246	struct media_device *mdev = &vsp1->media_dev;
247	struct v4l2_device *vdev = &vsp1->v4l2_dev;
248	struct vsp1_entity *entity;
249	unsigned int i;
250	int ret;
251
252	mdev->dev = vsp1->dev;
253	mdev->hw_revision = vsp1->version;
254	strscpy(mdev->model, vsp1->info->model, sizeof(mdev->model));
255	media_device_init(mdev);
256
257	vsp1->media_ops.link_setup = vsp1_entity_link_setup;
258	/*
259	 * Don't perform link validation when the userspace API is disabled as
260	 * the pipeline is configured internally by the driver in that case, and
261	 * its configuration can thus be trusted.
262	 */
263	if (vsp1->info->uapi)
264		vsp1->media_ops.link_validate = v4l2_subdev_link_validate;
265
266	vdev->mdev = mdev;
267	ret = v4l2_device_register(vsp1->dev, vdev);
268	if (ret < 0) {
269		dev_err(vsp1->dev, "V4L2 device registration failed (%d)\n",
270			ret);
271		goto done;
272	}
273
274	/* Instantiate all the entities. */
275	if (vsp1_feature(vsp1, VSP1_HAS_BRS)) {
276		vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS);
277		if (IS_ERR(vsp1->brs)) {
278			ret = PTR_ERR(vsp1->brs);
279			goto done;
280		}
281
282		list_add_tail(&vsp1->brs->entity.list_dev, &vsp1->entities);
283	}
284
285	if (vsp1_feature(vsp1, VSP1_HAS_BRU)) {
286		vsp1->bru = vsp1_brx_create(vsp1, VSP1_ENTITY_BRU);
287		if (IS_ERR(vsp1->bru)) {
288			ret = PTR_ERR(vsp1->bru);
289			goto done;
290		}
291
292		list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities);
293	}
294
295	if (vsp1_feature(vsp1, VSP1_HAS_CLU)) {
296		vsp1->clu = vsp1_clu_create(vsp1);
297		if (IS_ERR(vsp1->clu)) {
298			ret = PTR_ERR(vsp1->clu);
299			goto done;
300		}
301
302		list_add_tail(&vsp1->clu->entity.list_dev, &vsp1->entities);
303	}
304
305	vsp1->hsi = vsp1_hsit_create(vsp1, true);
306	if (IS_ERR(vsp1->hsi)) {
307		ret = PTR_ERR(vsp1->hsi);
308		goto done;
309	}
310
311	list_add_tail(&vsp1->hsi->entity.list_dev, &vsp1->entities);
312
313	vsp1->hst = vsp1_hsit_create(vsp1, false);
314	if (IS_ERR(vsp1->hst)) {
315		ret = PTR_ERR(vsp1->hst);
316		goto done;
317	}
318
319	list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
320
321	if (vsp1_feature(vsp1, VSP1_HAS_HGO) && vsp1->info->uapi) {
322		vsp1->hgo = vsp1_hgo_create(vsp1);
323		if (IS_ERR(vsp1->hgo)) {
324			ret = PTR_ERR(vsp1->hgo);
325			goto done;
326		}
327
328		list_add_tail(&vsp1->hgo->histo.entity.list_dev,
329			      &vsp1->entities);
330	}
331
332	if (vsp1_feature(vsp1, VSP1_HAS_HGT) && vsp1->info->uapi) {
333		vsp1->hgt = vsp1_hgt_create(vsp1);
334		if (IS_ERR(vsp1->hgt)) {
335			ret = PTR_ERR(vsp1->hgt);
336			goto done;
337		}
338
339		list_add_tail(&vsp1->hgt->histo.entity.list_dev,
340			      &vsp1->entities);
341	}
342
343	/*
344	 * The LIFs are only supported when used in conjunction with the DU, in
345	 * which case the userspace API is disabled. If the userspace API is
346	 * enabled skip the LIFs, even when present.
347	 */
348	if (!vsp1->info->uapi) {
349		for (i = 0; i < vsp1->info->lif_count; ++i) {
350			struct vsp1_lif *lif;
351
352			lif = vsp1_lif_create(vsp1, i);
353			if (IS_ERR(lif)) {
354				ret = PTR_ERR(lif);
355				goto done;
356			}
357
358			vsp1->lif[i] = lif;
359			list_add_tail(&lif->entity.list_dev, &vsp1->entities);
360		}
361	}
362
363	if (vsp1_feature(vsp1, VSP1_HAS_LUT)) {
364		vsp1->lut = vsp1_lut_create(vsp1);
365		if (IS_ERR(vsp1->lut)) {
366			ret = PTR_ERR(vsp1->lut);
367			goto done;
368		}
369
370		list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities);
371	}
372
373	for (i = 0; i < vsp1->info->rpf_count; ++i) {
374		struct vsp1_rwpf *rpf;
375
376		rpf = vsp1_rpf_create(vsp1, i);
377		if (IS_ERR(rpf)) {
378			ret = PTR_ERR(rpf);
379			goto done;
380		}
381
382		vsp1->rpf[i] = rpf;
383		list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
384
385		if (vsp1->info->uapi) {
386			struct vsp1_video *video = vsp1_video_create(vsp1, rpf);
387
388			if (IS_ERR(video)) {
389				ret = PTR_ERR(video);
390				goto done;
391			}
392
393			list_add_tail(&video->list, &vsp1->videos);
394		}
395	}
396
397	if (vsp1_feature(vsp1, VSP1_HAS_SRU)) {
398		vsp1->sru = vsp1_sru_create(vsp1);
399		if (IS_ERR(vsp1->sru)) {
400			ret = PTR_ERR(vsp1->sru);
401			goto done;
402		}
403
404		list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities);
405	}
406
407	for (i = 0; i < vsp1->info->uds_count; ++i) {
408		struct vsp1_uds *uds;
409
410		uds = vsp1_uds_create(vsp1, i);
411		if (IS_ERR(uds)) {
412			ret = PTR_ERR(uds);
413			goto done;
414		}
415
416		vsp1->uds[i] = uds;
417		list_add_tail(&uds->entity.list_dev, &vsp1->entities);
418	}
419
420	for (i = 0; i < vsp1->info->uif_count; ++i) {
421		struct vsp1_uif *uif;
422
423		uif = vsp1_uif_create(vsp1, i);
424		if (IS_ERR(uif)) {
425			ret = PTR_ERR(uif);
426			goto done;
427		}
428
429		vsp1->uif[i] = uif;
430		list_add_tail(&uif->entity.list_dev, &vsp1->entities);
431	}
432
433	for (i = 0; i < vsp1->info->wpf_count; ++i) {
434		struct vsp1_rwpf *wpf;
435
436		wpf = vsp1_wpf_create(vsp1, i);
437		if (IS_ERR(wpf)) {
438			ret = PTR_ERR(wpf);
439			goto done;
440		}
441
442		vsp1->wpf[i] = wpf;
443		list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
444
445		if (vsp1->info->uapi) {
446			struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
447
448			if (IS_ERR(video)) {
449				ret = PTR_ERR(video);
450				goto done;
451			}
452
453			list_add_tail(&video->list, &vsp1->videos);
454		}
455	}
456
457	/* Register all subdevs. */
458	list_for_each_entry(entity, &vsp1->entities, list_dev) {
459		ret = v4l2_device_register_subdev(&vsp1->v4l2_dev,
460						  &entity->subdev);
461		if (ret < 0)
462			goto done;
463	}
464
465	/*
466	 * Create links and register subdev nodes if the userspace API is
467	 * enabled or initialize the DRM pipeline otherwise.
468	 */
469	if (vsp1->info->uapi) {
470		ret = vsp1_uapi_create_links(vsp1);
471		if (ret < 0)
472			goto done;
473
474		ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
475		if (ret < 0)
476			goto done;
477
478		ret = media_device_register(mdev);
479	} else {
480		ret = vsp1_drm_init(vsp1);
481	}
482
483done:
484	if (ret < 0)
485		vsp1_destroy_entities(vsp1);
486
487	return ret;
488}
489
490int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index)
491{
492	unsigned int timeout;
493	u32 status;
494
495	status = vsp1_read(vsp1, VI6_STATUS);
496	if (!(status & VI6_STATUS_SYS_ACT(index)))
497		return 0;
498
499	vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(index));
500	for (timeout = 10; timeout > 0; --timeout) {
501		status = vsp1_read(vsp1, VI6_STATUS);
502		if (!(status & VI6_STATUS_SYS_ACT(index)))
503			break;
504
505		usleep_range(1000, 2000);
506	}
507
508	if (!timeout) {
509		dev_err(vsp1->dev, "failed to reset wpf.%u\n", index);
510		return -ETIMEDOUT;
511	}
512
513	return 0;
514}
515
516static int vsp1_device_init(struct vsp1_device *vsp1)
517{
518	unsigned int i;
519	int ret;
520
521	/* Reset any channel that might be running. */
522	for (i = 0; i < vsp1->info->wpf_count; ++i) {
523		ret = vsp1_reset_wpf(vsp1, i);
524		if (ret < 0)
525			return ret;
526	}
527
528	vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) |
529		   (8 << VI6_CLK_DCSWT_CSTRW_SHIFT));
530
531	for (i = 0; i < vsp1->info->rpf_count; ++i)
532		vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED);
533
534	for (i = 0; i < vsp1->info->uds_count; ++i)
535		vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
536
537	for (i = 0; i < vsp1->info->uif_count; ++i)
538		vsp1_write(vsp1, VI6_DPR_UIF_ROUTE(i), VI6_DPR_NODE_UNUSED);
539
540	vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED);
541	vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED);
542	vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED);
543	vsp1_write(vsp1, VI6_DPR_HST_ROUTE, VI6_DPR_NODE_UNUSED);
544	vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED);
545	vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED);
546
547	if (vsp1_feature(vsp1, VSP1_HAS_BRS))
548		vsp1_write(vsp1, VI6_DPR_ILV_BRS_ROUTE, VI6_DPR_NODE_UNUSED);
549
550	vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
551		   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
552	vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
553		   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
554
555	vsp1_dlm_setup(vsp1);
556
557	return 0;
558}
559
560static void vsp1_mask_all_interrupts(struct vsp1_device *vsp1)
561{
562	unsigned int i;
563
564	for (i = 0; i < vsp1->info->lif_count; ++i)
565		vsp1_write(vsp1, VI6_DISP_IRQ_ENB(i), 0);
566	for (i = 0; i < vsp1->info->wpf_count; ++i)
567		vsp1_write(vsp1, VI6_WPF_IRQ_ENB(i), 0);
568}
569
570/*
571 * vsp1_device_get - Acquire the VSP1 device
572 *
573 * Make sure the device is not suspended and initialize it if needed.
574 *
575 * Return 0 on success or a negative error code otherwise.
576 */
577int vsp1_device_get(struct vsp1_device *vsp1)
578{
579	return pm_runtime_resume_and_get(vsp1->dev);
580}
581
582/*
583 * vsp1_device_put - Release the VSP1 device
584 *
585 * Decrement the VSP1 reference count and cleanup the device if the last
586 * reference is released.
587 */
588void vsp1_device_put(struct vsp1_device *vsp1)
589{
590	pm_runtime_put_sync(vsp1->dev);
591}
592
593/* -----------------------------------------------------------------------------
594 * Power Management
595 */
596
597static int __maybe_unused vsp1_pm_suspend(struct device *dev)
598{
599	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
600
601	/*
602	 * When used as part of a display pipeline, the VSP is stopped and
603	 * restarted explicitly by the DU.
604	 */
605	if (!vsp1->drm)
606		vsp1_video_suspend(vsp1);
607
608	pm_runtime_force_suspend(vsp1->dev);
609
610	return 0;
611}
612
613static int __maybe_unused vsp1_pm_resume(struct device *dev)
614{
615	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
616
617	pm_runtime_force_resume(vsp1->dev);
618
619	/*
620	 * When used as part of a display pipeline, the VSP is stopped and
621	 * restarted explicitly by the DU.
622	 */
623	if (!vsp1->drm)
624		vsp1_video_resume(vsp1);
625
626	return 0;
627}
628
629static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev)
630{
631	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
632
633	rcar_fcp_disable(vsp1->fcp);
634	reset_control_assert(vsp1->rstc);
635
636	return 0;
637}
638
639static int __maybe_unused vsp1_pm_runtime_resume(struct device *dev)
640{
641	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
642	int ret;
643
644	ret = reset_control_deassert(vsp1->rstc);
645	if (ret < 0)
646		return ret;
647
648	if (vsp1->info) {
649		/*
650		 * On R-Car Gen2 and RZ/G1, vsp1 register access after deassert
651		 * can cause lock-up. It is a special case and needs some delay
652		 * to avoid this lock-up.
653		 */
654		if (vsp1->info->gen == 2)
655			udelay(1);
656
657		ret = vsp1_device_init(vsp1);
658		if (ret < 0)
659			goto done;
660	}
661
662	ret = rcar_fcp_enable(vsp1->fcp);
663
664done:
665	if (ret < 0)
666		reset_control_assert(vsp1->rstc);
667
668	return ret;
669}
670
671static const struct dev_pm_ops vsp1_pm_ops = {
672	SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume)
673	SET_RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL)
674};
675
676/* -----------------------------------------------------------------------------
677 * Platform Driver
678 */
679
680static const struct vsp1_device_info vsp1_device_infos[] = {
681	{
682		.version = VI6_IP_VERSION_MODEL_VSPS_H2,
683		.model = "VSP1-S",
684		.gen = 2,
685		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
686			  | VSP1_HAS_HGT | VSP1_HAS_LUT | VSP1_HAS_SRU
687			  | VSP1_HAS_WPF_VFLIP,
688		.rpf_count = 5,
689		.uds_count = 3,
690		.wpf_count = 4,
691		.num_bru_inputs = 4,
692		.uapi = true,
693	}, {
694		.version = VI6_IP_VERSION_MODEL_VSPR_H2,
695		.model = "VSP1-R",
696		.gen = 2,
697		.features = VSP1_HAS_BRU | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
698		.rpf_count = 5,
699		.uds_count = 3,
700		.wpf_count = 4,
701		.num_bru_inputs = 4,
702		.uapi = true,
703	}, {
704		.version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
705		.model = "VSP1-D",
706		.gen = 2,
707		.features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LUT,
708		.lif_count = 1,
709		.rpf_count = 4,
710		.uds_count = 1,
711		.wpf_count = 1,
712		.num_bru_inputs = 4,
713		.uapi = true,
714	}, {
715		.version = VI6_IP_VERSION_MODEL_VSPS_M2,
716		.model = "VSP1-S",
717		.gen = 2,
718		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
719			  | VSP1_HAS_HGT | VSP1_HAS_LUT | VSP1_HAS_SRU
720			  | VSP1_HAS_WPF_VFLIP,
721		.rpf_count = 5,
722		.uds_count = 1,
723		.wpf_count = 4,
724		.num_bru_inputs = 4,
725		.uapi = true,
726	}, {
727		.version = VI6_IP_VERSION_MODEL_VSPS_V2H,
728		.model = "VSP1V-S",
729		.gen = 2,
730		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
731			  | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
732		.rpf_count = 4,
733		.uds_count = 1,
734		.wpf_count = 4,
735		.num_bru_inputs = 4,
736		.uapi = true,
737	}, {
738		.version = VI6_IP_VERSION_MODEL_VSPD_V2H,
739		.model = "VSP1V-D",
740		.gen = 2,
741		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT,
742		.lif_count = 1,
743		.rpf_count = 4,
744		.uds_count = 1,
745		.wpf_count = 1,
746		.num_bru_inputs = 4,
747		.uapi = true,
748	}, {
749		.version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
750		.model = "VSP2-I",
751		.gen = 3,
752		.features = VSP1_HAS_CLU | VSP1_HAS_HGO | VSP1_HAS_HGT
753			  | VSP1_HAS_LUT | VSP1_HAS_SRU | VSP1_HAS_WPF_HFLIP
754			  | VSP1_HAS_WPF_VFLIP,
755		.rpf_count = 1,
756		.uds_count = 1,
757		.wpf_count = 1,
758		.uapi = true,
759	}, {
760		.version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
761		.model = "VSP2-BD",
762		.gen = 3,
763		.features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
764		.rpf_count = 5,
765		.wpf_count = 1,
766		.num_bru_inputs = 5,
767		.uapi = true,
768	}, {
769		.version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
770		.model = "VSP2-BC",
771		.gen = 3,
772		.features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
773			  | VSP1_HAS_LUT | VSP1_HAS_WPF_VFLIP,
774		.rpf_count = 5,
775		.wpf_count = 1,
776		.num_bru_inputs = 5,
777		.uapi = true,
778	}, {
779		.version = VI6_IP_VERSION_MODEL_VSPBS_GEN3,
780		.model = "VSP2-BS",
781		.gen = 3,
782		.features = VSP1_HAS_BRS | VSP1_HAS_WPF_VFLIP,
783		.rpf_count = 2,
784		.wpf_count = 1,
785		.uapi = true,
786	}, {
787		.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
788		.model = "VSP2-D",
789		.gen = 3,
790		.features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP | VSP1_HAS_EXT_DL,
791		.lif_count = 1,
792		.rpf_count = 5,
793		.uif_count = 1,
794		.wpf_count = 2,
795		.num_bru_inputs = 5,
796	}, {
797		.version = VI6_IP_VERSION_MODEL_VSPD_V3,
798		.model = "VSP2-D",
799		.soc = VI6_IP_VERSION_SOC_V3H,
800		.gen = 3,
801		.features = VSP1_HAS_BRS | VSP1_HAS_BRU,
802		.lif_count = 1,
803		.rpf_count = 5,
804		.uif_count = 1,
805		.wpf_count = 1,
806		.num_bru_inputs = 5,
807	}, {
808		.version = VI6_IP_VERSION_MODEL_VSPD_V3,
809		.model = "VSP2-D",
810		.soc = VI6_IP_VERSION_SOC_V3M,
811		.gen = 3,
812		.features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_NON_ZERO_LBA,
813		.lif_count = 1,
814		.rpf_count = 5,
815		.uif_count = 1,
816		.wpf_count = 1,
817		.num_bru_inputs = 5,
818	}, {
819		.version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
820		.model = "VSP2-DL",
821		.gen = 3,
822		.features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
823		.lif_count = 2,
824		.rpf_count = 5,
825		.uif_count = 2,
826		.wpf_count = 2,
827		.num_bru_inputs = 5,
828	}, {
829		.version = VI6_IP_VERSION_MODEL_VSPD_GEN4,
830		.model = "VSP2-D",
831		.gen = 4,
832		.features = VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
833		.lif_count = 1,
834		.rpf_count = 5,
835		.uif_count = 2,
836		.wpf_count = 1,
837		.num_bru_inputs = 5,
838	},
839};
840
841static const struct vsp1_device_info rzg2l_vsp2_device_info = {
842	.version = VI6_IP_VERSION_MODEL_VSPD_RZG2L,
843	.model = "VSP2-D",
844	.soc = VI6_IP_VERSION_SOC_RZG2L,
845	.gen = 3,
846	.features = VSP1_HAS_BRS | VSP1_HAS_WPF_VFLIP | VSP1_HAS_EXT_DL
847		  | VSP1_HAS_NON_ZERO_LBA,
848	.lif_count = 1,
849	.rpf_count = 2,
850	.wpf_count = 1,
851};
852
853static const struct vsp1_device_info *vsp1_lookup_info(struct vsp1_device *vsp1)
854{
855	const struct vsp1_device_info *info;
856	unsigned int i;
857	u32 model;
858	u32 soc;
859
860	/*
861	 * Try the info stored in match data first for devices that don't have
862	 * a version register.
863	 */
864	info = of_device_get_match_data(vsp1->dev);
865	if (info) {
866		vsp1->version = VI6_IP_VERSION_VSP_SW | info->version | info->soc;
867		return info;
868	}
869
870	vsp1->version = vsp1_read(vsp1, VI6_IP_VERSION);
871	model = vsp1->version & VI6_IP_VERSION_MODEL_MASK;
872	soc = vsp1->version & VI6_IP_VERSION_SOC_MASK;
873
874	for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
875		info = &vsp1_device_infos[i];
876
877		if (model == info->version && (!info->soc || soc == info->soc))
878			return info;
879	}
880
881	dev_err(vsp1->dev, "unsupported IP version 0x%08x\n", vsp1->version);
882
883	return NULL;
884}
885
886static int vsp1_probe(struct platform_device *pdev)
887{
888	struct vsp1_device *vsp1;
889	struct device_node *fcp_node;
890	int ret;
891	int irq;
892
893	vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL);
894	if (vsp1 == NULL)
895		return -ENOMEM;
896
897	vsp1->dev = &pdev->dev;
898	INIT_LIST_HEAD(&vsp1->entities);
899	INIT_LIST_HEAD(&vsp1->videos);
900
901	platform_set_drvdata(pdev, vsp1);
902
903	/* I/O and IRQ resources (clock managed by the clock PM domain). */
904	vsp1->mmio = devm_platform_ioremap_resource(pdev, 0);
905	if (IS_ERR(vsp1->mmio))
906		return PTR_ERR(vsp1->mmio);
907
908	irq = platform_get_irq(pdev, 0);
909	if (irq < 0)
910		return irq;
911
912	vsp1->rstc = devm_reset_control_get_shared(&pdev->dev, NULL);
913	if (IS_ERR(vsp1->rstc))
914		return dev_err_probe(&pdev->dev, PTR_ERR(vsp1->rstc),
915				     "failed to get reset control\n");
916
917	/* FCP (optional). */
918	fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0);
919	if (fcp_node) {
920		vsp1->fcp = rcar_fcp_get(fcp_node);
921		of_node_put(fcp_node);
922		if (IS_ERR(vsp1->fcp)) {
923			dev_dbg(&pdev->dev, "FCP not found (%ld)\n",
924				PTR_ERR(vsp1->fcp));
925			return PTR_ERR(vsp1->fcp);
926		}
927
928		/*
929		 * When the FCP is present, it handles all bus master accesses
930		 * for the VSP and must thus be used in place of the VSP device
931		 * to map DMA buffers.
932		 */
933		vsp1->bus_master = rcar_fcp_get_device(vsp1->fcp);
934	} else {
935		vsp1->bus_master = vsp1->dev;
936	}
937
938	/* Configure device parameters based on the version register. */
939	pm_runtime_enable(&pdev->dev);
940
941	ret = vsp1_device_get(vsp1);
942	if (ret < 0)
943		goto done;
944
945	vsp1->info = vsp1_lookup_info(vsp1);
946	if (!vsp1->info) {
947		vsp1_device_put(vsp1);
948		ret = -ENXIO;
949		goto done;
950	}
951
952	dev_dbg(&pdev->dev, "IP version 0x%08x\n", vsp1->version);
953
954	/*
955	 * Previous use of the hardware (e.g. by the bootloader) could leave
956	 * some interrupts enabled and pending.
957	 *
958	 * TODO: Investigate if this shouldn't be better handled by using the
959	 * device reset provided by the CPG.
960	 */
961	vsp1_mask_all_interrupts(vsp1);
962
963	vsp1_device_put(vsp1);
964
965	ret = devm_request_irq(&pdev->dev, irq, vsp1_irq_handler,
966			       IRQF_SHARED, dev_name(&pdev->dev), vsp1);
967	if (ret < 0) {
968		dev_err(&pdev->dev, "failed to request IRQ\n");
969		goto done;
970	}
971
972	/* Instantiate entities. */
973	ret = vsp1_create_entities(vsp1);
974	if (ret < 0) {
975		dev_err(&pdev->dev, "failed to create entities\n");
976		goto done;
977	}
978
979done:
980	if (ret) {
981		pm_runtime_disable(&pdev->dev);
982		rcar_fcp_put(vsp1->fcp);
983	}
984
985	return ret;
986}
987
988static void vsp1_remove(struct platform_device *pdev)
989{
990	struct vsp1_device *vsp1 = platform_get_drvdata(pdev);
991
992	vsp1_destroy_entities(vsp1);
993	rcar_fcp_put(vsp1->fcp);
994
995	pm_runtime_disable(&pdev->dev);
996}
997
998static const struct of_device_id vsp1_of_match[] = {
999	{ .compatible = "renesas,vsp1" },
1000	{ .compatible = "renesas,vsp2" },
1001	{ .compatible = "renesas,r9a07g044-vsp2", .data = &rzg2l_vsp2_device_info },
1002	{ },
1003};
1004MODULE_DEVICE_TABLE(of, vsp1_of_match);
1005
1006static struct platform_driver vsp1_platform_driver = {
1007	.probe		= vsp1_probe,
1008	.remove_new	= vsp1_remove,
1009	.driver		= {
1010		.name	= "vsp1",
1011		.pm	= &vsp1_pm_ops,
1012		.of_match_table = vsp1_of_match,
1013	},
1014};
1015
1016module_platform_driver(vsp1_platform_driver);
1017
1018MODULE_ALIAS("vsp1");
1019MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
1020MODULE_DESCRIPTION("Renesas VSP1 Driver");
1021MODULE_LICENSE("GPL");
1022