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