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