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 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 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 */ 98 static 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 141 static 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 220 static 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 244 static 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 483 done: 484 if (ret < 0) 485 vsp1_destroy_entities(vsp1); 486 487 return ret; 488 } 489 490 int 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 516 static 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 560 static 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 */ 577 int 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 */ 588 void vsp1_device_put(struct vsp1_device *vsp1) 589 { 590 pm_runtime_put_sync(vsp1->dev); 591 } 592 593 /* ----------------------------------------------------------------------------- 594 * Power Management 595 */ 596 597 static 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 613 static 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 629 static 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 639 static 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 664 done: 665 if (ret < 0) 666 reset_control_assert(vsp1->rstc); 667 668 return ret; 669 } 670 671 static 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 680 static 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 841 static 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 853 static 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 886 static 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 979 done: 980 if (ret) { 981 pm_runtime_disable(&pdev->dev); 982 rcar_fcp_put(vsp1->fcp); 983 } 984 985 return ret; 986 } 987 988 static 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 998 static 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 }; 1004 MODULE_DEVICE_TABLE(of, vsp1_of_match); 1005 1006 static 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 1016 module_platform_driver(vsp1_platform_driver); 1017 1018 MODULE_ALIAS("vsp1"); 1019 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 1020 MODULE_DESCRIPTION("Renesas VSP1 Driver"); 1021 MODULE_LICENSE("GPL"); 1022