]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/vsp1/vsp1_drv.c
Merge tag 'pstore-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
[linux.git] / drivers / media / platform / vsp1 / vsp1_drv.c
1 /*
2  * vsp1_drv.c  --  R-Car VSP1 Driver
3  *
4  * Copyright (C) 2013-2015 Renesas Electronics Corporation
5  *
6  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/device.h>
17 #include <linux/interrupt.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/of_device.h>
21 #include <linux/platform_device.h>
22 #include <linux/videodev2.h>
23
24 #include <media/v4l2-subdev.h>
25
26 #include "vsp1.h"
27 #include "vsp1_bru.h"
28 #include "vsp1_dl.h"
29 #include "vsp1_drm.h"
30 #include "vsp1_hsit.h"
31 #include "vsp1_lif.h"
32 #include "vsp1_lut.h"
33 #include "vsp1_pipe.h"
34 #include "vsp1_rwpf.h"
35 #include "vsp1_sru.h"
36 #include "vsp1_uds.h"
37 #include "vsp1_video.h"
38
39 /* -----------------------------------------------------------------------------
40  * Interrupt Handling
41  */
42
43 static irqreturn_t vsp1_irq_handler(int irq, void *data)
44 {
45         u32 mask = VI6_WFP_IRQ_STA_DFE | VI6_WFP_IRQ_STA_FRE;
46         struct vsp1_device *vsp1 = data;
47         irqreturn_t ret = IRQ_NONE;
48         unsigned int i;
49         u32 status;
50
51         for (i = 0; i < vsp1->info->wpf_count; ++i) {
52                 struct vsp1_rwpf *wpf = vsp1->wpf[i];
53
54                 if (wpf == NULL)
55                         continue;
56
57                 status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i));
58                 vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
59
60                 if (status & VI6_WFP_IRQ_STA_FRE) {
61                         vsp1_pipeline_frame_end(wpf->pipe);
62                         ret = IRQ_HANDLED;
63                 }
64         }
65
66         status = vsp1_read(vsp1, VI6_DISP_IRQ_STA);
67         vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST);
68
69         if (status & VI6_DISP_IRQ_STA_DST) {
70                 vsp1_drm_display_start(vsp1);
71                 ret = IRQ_HANDLED;
72         }
73
74         return ret;
75 }
76
77 /* -----------------------------------------------------------------------------
78  * Entities
79  */
80
81 /*
82  * vsp1_create_sink_links - Create links from all sources to the given sink
83  *
84  * This function creates media links from all valid sources to the given sink
85  * pad. Links that would be invalid according to the VSP1 hardware capabilities
86  * are skipped. Those include all links
87  *
88  * - from a UDS to a UDS (UDS entities can't be chained)
89  * - from an entity to itself (no loops are allowed)
90  */
91 static int vsp1_create_sink_links(struct vsp1_device *vsp1,
92                                   struct vsp1_entity *sink)
93 {
94         struct media_entity *entity = &sink->subdev.entity;
95         struct vsp1_entity *source;
96         unsigned int pad;
97         int ret;
98
99         list_for_each_entry(source, &vsp1->entities, list_dev) {
100                 u32 flags;
101
102                 if (source->type == sink->type)
103                         continue;
104
105                 if (source->type == VSP1_ENTITY_LIF ||
106                     source->type == VSP1_ENTITY_WPF)
107                         continue;
108
109                 flags = source->type == VSP1_ENTITY_RPF &&
110                         sink->type == VSP1_ENTITY_WPF &&
111                         source->index == sink->index
112                       ? MEDIA_LNK_FL_ENABLED : 0;
113
114                 for (pad = 0; pad < entity->num_pads; ++pad) {
115                         if (!(entity->pads[pad].flags & MEDIA_PAD_FL_SINK))
116                                 continue;
117
118                         ret = media_create_pad_link(&source->subdev.entity,
119                                                        source->source_pad,
120                                                        entity, pad, flags);
121                         if (ret < 0)
122                                 return ret;
123
124                         if (flags & MEDIA_LNK_FL_ENABLED)
125                                 source->sink = entity;
126                 }
127         }
128
129         return 0;
130 }
131
132 static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
133 {
134         struct vsp1_entity *entity;
135         unsigned int i;
136         int ret;
137
138         list_for_each_entry(entity, &vsp1->entities, list_dev) {
139                 if (entity->type == VSP1_ENTITY_LIF ||
140                     entity->type == VSP1_ENTITY_RPF)
141                         continue;
142
143                 ret = vsp1_create_sink_links(vsp1, entity);
144                 if (ret < 0)
145                         return ret;
146         }
147
148         if (vsp1->info->features & VSP1_HAS_LIF) {
149                 ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
150                                             RWPF_PAD_SOURCE,
151                                             &vsp1->lif->entity.subdev.entity,
152                                             LIF_PAD_SINK, 0);
153                 if (ret < 0)
154                         return ret;
155         }
156
157         for (i = 0; i < vsp1->info->rpf_count; ++i) {
158                 struct vsp1_rwpf *rpf = vsp1->rpf[i];
159
160                 ret = media_create_pad_link(&rpf->video->video.entity, 0,
161                                             &rpf->entity.subdev.entity,
162                                             RWPF_PAD_SINK,
163                                             MEDIA_LNK_FL_ENABLED |
164                                             MEDIA_LNK_FL_IMMUTABLE);
165                 if (ret < 0)
166                         return ret;
167         }
168
169         for (i = 0; i < vsp1->info->wpf_count; ++i) {
170                 /* Connect the video device to the WPF. All connections are
171                  * immutable except for the WPF0 source link if a LIF is
172                  * present.
173                  */
174                 struct vsp1_rwpf *wpf = vsp1->wpf[i];
175                 unsigned int flags = MEDIA_LNK_FL_ENABLED;
176
177                 if (!(vsp1->info->features & VSP1_HAS_LIF) || i != 0)
178                         flags |= MEDIA_LNK_FL_IMMUTABLE;
179
180                 ret = media_create_pad_link(&wpf->entity.subdev.entity,
181                                             RWPF_PAD_SOURCE,
182                                             &wpf->video->video.entity, 0,
183                                             flags);
184                 if (ret < 0)
185                         return ret;
186         }
187
188         return 0;
189 }
190
191 static void vsp1_destroy_entities(struct vsp1_device *vsp1)
192 {
193         struct vsp1_entity *entity, *_entity;
194         struct vsp1_video *video, *_video;
195
196         list_for_each_entry_safe(entity, _entity, &vsp1->entities, list_dev) {
197                 list_del(&entity->list_dev);
198                 vsp1_entity_destroy(entity);
199         }
200
201         list_for_each_entry_safe(video, _video, &vsp1->videos, list) {
202                 list_del(&video->list);
203                 vsp1_video_cleanup(video);
204         }
205
206         v4l2_device_unregister(&vsp1->v4l2_dev);
207         media_device_unregister(&vsp1->media_dev);
208         media_device_cleanup(&vsp1->media_dev);
209
210         if (!vsp1->info->uapi)
211                 vsp1_drm_cleanup(vsp1);
212 }
213
214 static int vsp1_create_entities(struct vsp1_device *vsp1)
215 {
216         struct media_device *mdev = &vsp1->media_dev;
217         struct v4l2_device *vdev = &vsp1->v4l2_dev;
218         struct vsp1_entity *entity;
219         unsigned int i;
220         int ret;
221
222         mdev->dev = vsp1->dev;
223         strlcpy(mdev->model, "VSP1", sizeof(mdev->model));
224         snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
225                  dev_name(mdev->dev));
226         media_device_init(mdev);
227
228         vsp1->media_ops.link_setup = vsp1_entity_link_setup;
229         /* Don't perform link validation when the userspace API is disabled as
230          * the pipeline is configured internally by the driver in that case, and
231          * its configuration can thus be trusted.
232          */
233         if (vsp1->info->uapi)
234                 vsp1->media_ops.link_validate = v4l2_subdev_link_validate;
235
236         vdev->mdev = mdev;
237         ret = v4l2_device_register(vsp1->dev, vdev);
238         if (ret < 0) {
239                 dev_err(vsp1->dev, "V4L2 device registration failed (%d)\n",
240                         ret);
241                 goto done;
242         }
243
244         /* Instantiate all the entities. */
245         if (vsp1->info->features & VSP1_HAS_BRU) {
246                 vsp1->bru = vsp1_bru_create(vsp1);
247                 if (IS_ERR(vsp1->bru)) {
248                         ret = PTR_ERR(vsp1->bru);
249                         goto done;
250                 }
251
252                 list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities);
253         }
254
255         vsp1->hsi = vsp1_hsit_create(vsp1, true);
256         if (IS_ERR(vsp1->hsi)) {
257                 ret = PTR_ERR(vsp1->hsi);
258                 goto done;
259         }
260
261         list_add_tail(&vsp1->hsi->entity.list_dev, &vsp1->entities);
262
263         vsp1->hst = vsp1_hsit_create(vsp1, false);
264         if (IS_ERR(vsp1->hst)) {
265                 ret = PTR_ERR(vsp1->hst);
266                 goto done;
267         }
268
269         list_add_tail(&vsp1->hst->entity.list_dev, &vsp1->entities);
270
271         if (vsp1->info->features & VSP1_HAS_LIF) {
272                 vsp1->lif = vsp1_lif_create(vsp1);
273                 if (IS_ERR(vsp1->lif)) {
274                         ret = PTR_ERR(vsp1->lif);
275                         goto done;
276                 }
277
278                 list_add_tail(&vsp1->lif->entity.list_dev, &vsp1->entities);
279         }
280
281         if (vsp1->info->features & VSP1_HAS_LUT) {
282                 vsp1->lut = vsp1_lut_create(vsp1);
283                 if (IS_ERR(vsp1->lut)) {
284                         ret = PTR_ERR(vsp1->lut);
285                         goto done;
286                 }
287
288                 list_add_tail(&vsp1->lut->entity.list_dev, &vsp1->entities);
289         }
290
291         for (i = 0; i < vsp1->info->rpf_count; ++i) {
292                 struct vsp1_rwpf *rpf;
293
294                 rpf = vsp1_rpf_create(vsp1, i);
295                 if (IS_ERR(rpf)) {
296                         ret = PTR_ERR(rpf);
297                         goto done;
298                 }
299
300                 vsp1->rpf[i] = rpf;
301                 list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
302
303                 if (vsp1->info->uapi) {
304                         struct vsp1_video *video = vsp1_video_create(vsp1, rpf);
305
306                         if (IS_ERR(video)) {
307                                 ret = PTR_ERR(video);
308                                 goto done;
309                         }
310
311                         list_add_tail(&video->list, &vsp1->videos);
312                 }
313         }
314
315         if (vsp1->info->features & VSP1_HAS_SRU) {
316                 vsp1->sru = vsp1_sru_create(vsp1);
317                 if (IS_ERR(vsp1->sru)) {
318                         ret = PTR_ERR(vsp1->sru);
319                         goto done;
320                 }
321
322                 list_add_tail(&vsp1->sru->entity.list_dev, &vsp1->entities);
323         }
324
325         for (i = 0; i < vsp1->info->uds_count; ++i) {
326                 struct vsp1_uds *uds;
327
328                 uds = vsp1_uds_create(vsp1, i);
329                 if (IS_ERR(uds)) {
330                         ret = PTR_ERR(uds);
331                         goto done;
332                 }
333
334                 vsp1->uds[i] = uds;
335                 list_add_tail(&uds->entity.list_dev, &vsp1->entities);
336         }
337
338         for (i = 0; i < vsp1->info->wpf_count; ++i) {
339                 struct vsp1_rwpf *wpf;
340
341                 wpf = vsp1_wpf_create(vsp1, i);
342                 if (IS_ERR(wpf)) {
343                         ret = PTR_ERR(wpf);
344                         goto done;
345                 }
346
347                 vsp1->wpf[i] = wpf;
348                 list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
349
350                 if (vsp1->info->uapi) {
351                         struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
352
353                         if (IS_ERR(video)) {
354                                 ret = PTR_ERR(video);
355                                 goto done;
356                         }
357
358                         list_add_tail(&video->list, &vsp1->videos);
359                         wpf->entity.sink = &video->video.entity;
360                 }
361         }
362
363         /* Register all subdevs. */
364         list_for_each_entry(entity, &vsp1->entities, list_dev) {
365                 ret = v4l2_device_register_subdev(&vsp1->v4l2_dev,
366                                                   &entity->subdev);
367                 if (ret < 0)
368                         goto done;
369         }
370
371         /* Create links. */
372         if (vsp1->info->uapi)
373                 ret = vsp1_uapi_create_links(vsp1);
374         else
375                 ret = vsp1_drm_create_links(vsp1);
376         if (ret < 0)
377                 goto done;
378
379         /* Register subdev nodes if the userspace API is enabled or initialize
380          * the DRM pipeline otherwise.
381          */
382         if (vsp1->info->uapi)
383                 ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
384         else
385                 ret = vsp1_drm_init(vsp1);
386         if (ret < 0)
387                 goto done;
388
389         ret = media_device_register(mdev);
390
391 done:
392         if (ret < 0)
393                 vsp1_destroy_entities(vsp1);
394
395         return ret;
396 }
397
398 int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index)
399 {
400         unsigned int timeout;
401         u32 status;
402
403         status = vsp1_read(vsp1, VI6_STATUS);
404         if (!(status & VI6_STATUS_SYS_ACT(index)))
405                 return 0;
406
407         vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(index));
408         for (timeout = 10; timeout > 0; --timeout) {
409                 status = vsp1_read(vsp1, VI6_STATUS);
410                 if (!(status & VI6_STATUS_SYS_ACT(index)))
411                         break;
412
413                 usleep_range(1000, 2000);
414         }
415
416         if (!timeout) {
417                 dev_err(vsp1->dev, "failed to reset wpf.%u\n", index);
418                 return -ETIMEDOUT;
419         }
420
421         return 0;
422 }
423
424 static int vsp1_device_init(struct vsp1_device *vsp1)
425 {
426         unsigned int i;
427         int ret;
428
429         /* Reset any channel that might be running. */
430         for (i = 0; i < vsp1->info->wpf_count; ++i) {
431                 ret = vsp1_reset_wpf(vsp1, i);
432                 if (ret < 0)
433                         return ret;
434         }
435
436         vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) |
437                    (8 << VI6_CLK_DCSWT_CSTRW_SHIFT));
438
439         for (i = 0; i < vsp1->info->rpf_count; ++i)
440                 vsp1_write(vsp1, VI6_DPR_RPF_ROUTE(i), VI6_DPR_NODE_UNUSED);
441
442         for (i = 0; i < vsp1->info->uds_count; ++i)
443                 vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
444
445         vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED);
446         vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED);
447         vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED);
448         vsp1_write(vsp1, VI6_DPR_HST_ROUTE, VI6_DPR_NODE_UNUSED);
449         vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED);
450         vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED);
451
452         vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
453                    (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
454         vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
455                    (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
456
457         vsp1_dlm_setup(vsp1);
458
459         return 0;
460 }
461
462 /*
463  * vsp1_device_get - Acquire the VSP1 device
464  *
465  * Increment the VSP1 reference count and initialize the device if the first
466  * reference is taken.
467  *
468  * Return 0 on success or a negative error code otherwise.
469  */
470 int vsp1_device_get(struct vsp1_device *vsp1)
471 {
472         int ret = 0;
473
474         mutex_lock(&vsp1->lock);
475         if (vsp1->ref_count > 0)
476                 goto done;
477
478         ret = clk_prepare_enable(vsp1->clock);
479         if (ret < 0)
480                 goto done;
481
482         ret = vsp1_device_init(vsp1);
483         if (ret < 0) {
484                 clk_disable_unprepare(vsp1->clock);
485                 goto done;
486         }
487
488 done:
489         if (!ret)
490                 vsp1->ref_count++;
491
492         mutex_unlock(&vsp1->lock);
493         return ret;
494 }
495
496 /*
497  * vsp1_device_put - Release the VSP1 device
498  *
499  * Decrement the VSP1 reference count and cleanup the device if the last
500  * reference is released.
501  */
502 void vsp1_device_put(struct vsp1_device *vsp1)
503 {
504         mutex_lock(&vsp1->lock);
505
506         if (--vsp1->ref_count == 0)
507                 clk_disable_unprepare(vsp1->clock);
508
509         mutex_unlock(&vsp1->lock);
510 }
511
512 /* -----------------------------------------------------------------------------
513  * Power Management
514  */
515
516 #ifdef CONFIG_PM_SLEEP
517 static int vsp1_pm_suspend(struct device *dev)
518 {
519         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
520
521         WARN_ON(mutex_is_locked(&vsp1->lock));
522
523         if (vsp1->ref_count == 0)
524                 return 0;
525
526         vsp1_pipelines_suspend(vsp1);
527
528         clk_disable_unprepare(vsp1->clock);
529
530         return 0;
531 }
532
533 static int vsp1_pm_resume(struct device *dev)
534 {
535         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
536
537         WARN_ON(mutex_is_locked(&vsp1->lock));
538
539         if (vsp1->ref_count == 0)
540                 return 0;
541
542         clk_prepare_enable(vsp1->clock);
543
544         vsp1_pipelines_resume(vsp1);
545
546         return 0;
547 }
548 #endif
549
550 static const struct dev_pm_ops vsp1_pm_ops = {
551         SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume)
552 };
553
554 /* -----------------------------------------------------------------------------
555  * Platform Driver
556  */
557
558 static const struct vsp1_device_info vsp1_device_infos[] = {
559         {
560                 .version = VI6_IP_VERSION_MODEL_VSPS_H2,
561                 .gen = 2,
562                 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
563                 .rpf_count = 5,
564                 .uds_count = 3,
565                 .wpf_count = 4,
566                 .num_bru_inputs = 4,
567                 .uapi = true,
568         }, {
569                 .version = VI6_IP_VERSION_MODEL_VSPR_H2,
570                 .gen = 2,
571                 .features = VSP1_HAS_BRU | VSP1_HAS_SRU,
572                 .rpf_count = 5,
573                 .uds_count = 1,
574                 .wpf_count = 4,
575                 .num_bru_inputs = 4,
576                 .uapi = true,
577         }, {
578                 .version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
579                 .gen = 2,
580                 .features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_LUT,
581                 .rpf_count = 4,
582                 .uds_count = 1,
583                 .wpf_count = 4,
584                 .num_bru_inputs = 4,
585                 .uapi = true,
586         }, {
587                 .version = VI6_IP_VERSION_MODEL_VSPS_M2,
588                 .gen = 2,
589                 .features = VSP1_HAS_BRU | VSP1_HAS_LUT | VSP1_HAS_SRU,
590                 .rpf_count = 5,
591                 .uds_count = 3,
592                 .wpf_count = 4,
593                 .num_bru_inputs = 4,
594                 .uapi = true,
595         }, {
596                 .version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
597                 .gen = 3,
598                 .features = VSP1_HAS_LUT | VSP1_HAS_SRU,
599                 .rpf_count = 1,
600                 .uds_count = 1,
601                 .wpf_count = 1,
602                 .uapi = true,
603         }, {
604                 .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
605                 .gen = 3,
606                 .features = VSP1_HAS_BRU,
607                 .rpf_count = 5,
608                 .wpf_count = 1,
609                 .num_bru_inputs = 5,
610                 .uapi = true,
611         }, {
612                 .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
613                 .gen = 3,
614                 .features = VSP1_HAS_BRU | VSP1_HAS_LUT,
615                 .rpf_count = 5,
616                 .wpf_count = 1,
617                 .num_bru_inputs = 5,
618                 .uapi = true,
619         }, {
620                 .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
621                 .gen = 3,
622                 .features = VSP1_HAS_BRU | VSP1_HAS_LIF,
623                 .rpf_count = 5,
624                 .wpf_count = 2,
625                 .num_bru_inputs = 5,
626         },
627 };
628
629 static int vsp1_probe(struct platform_device *pdev)
630 {
631         struct vsp1_device *vsp1;
632         struct resource *irq;
633         struct resource *io;
634         unsigned int i;
635         u32 version;
636         int ret;
637
638         vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL);
639         if (vsp1 == NULL)
640                 return -ENOMEM;
641
642         vsp1->dev = &pdev->dev;
643         mutex_init(&vsp1->lock);
644         INIT_LIST_HEAD(&vsp1->entities);
645         INIT_LIST_HEAD(&vsp1->videos);
646
647         /* I/O, IRQ and clock resources */
648         io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
649         vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
650         if (IS_ERR(vsp1->mmio))
651                 return PTR_ERR(vsp1->mmio);
652
653         vsp1->clock = devm_clk_get(&pdev->dev, NULL);
654         if (IS_ERR(vsp1->clock)) {
655                 dev_err(&pdev->dev, "failed to get clock\n");
656                 return PTR_ERR(vsp1->clock);
657         }
658
659         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
660         if (!irq) {
661                 dev_err(&pdev->dev, "missing IRQ\n");
662                 return -EINVAL;
663         }
664
665         ret = devm_request_irq(&pdev->dev, irq->start, vsp1_irq_handler,
666                               IRQF_SHARED, dev_name(&pdev->dev), vsp1);
667         if (ret < 0) {
668                 dev_err(&pdev->dev, "failed to request IRQ\n");
669                 return ret;
670         }
671
672         /* Configure device parameters based on the version register. */
673         ret = clk_prepare_enable(vsp1->clock);
674         if (ret < 0)
675                 return ret;
676
677         version = vsp1_read(vsp1, VI6_IP_VERSION);
678         clk_disable_unprepare(vsp1->clock);
679
680         for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
681                 if ((version & VI6_IP_VERSION_MODEL_MASK) ==
682                     vsp1_device_infos[i].version) {
683                         vsp1->info = &vsp1_device_infos[i];
684                         break;
685                 }
686         }
687
688         if (!vsp1->info) {
689                 dev_err(&pdev->dev, "unsupported IP version 0x%08x\n", version);
690                 return -ENXIO;
691         }
692
693         dev_dbg(&pdev->dev, "IP version 0x%08x\n", version);
694
695         /* Instanciate entities */
696         ret = vsp1_create_entities(vsp1);
697         if (ret < 0) {
698                 dev_err(&pdev->dev, "failed to create entities\n");
699                 return ret;
700         }
701
702         platform_set_drvdata(pdev, vsp1);
703
704         return 0;
705 }
706
707 static int vsp1_remove(struct platform_device *pdev)
708 {
709         struct vsp1_device *vsp1 = platform_get_drvdata(pdev);
710
711         vsp1_destroy_entities(vsp1);
712
713         return 0;
714 }
715
716 static const struct of_device_id vsp1_of_match[] = {
717         { .compatible = "renesas,vsp1" },
718         { .compatible = "renesas,vsp2" },
719         { },
720 };
721
722 static struct platform_driver vsp1_platform_driver = {
723         .probe          = vsp1_probe,
724         .remove         = vsp1_remove,
725         .driver         = {
726                 .name   = "vsp1",
727                 .pm     = &vsp1_pm_ops,
728                 .of_match_table = vsp1_of_match,
729         },
730 };
731
732 module_platform_driver(vsp1_platform_driver);
733
734 MODULE_ALIAS("vsp1");
735 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
736 MODULE_DESCRIPTION("Renesas VSP1 Driver");
737 MODULE_LICENSE("GPL");