root/drivers/media/platform/vsp1/vsp1_drv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vsp1_irq_handler
  2. vsp1_create_sink_links
  3. vsp1_uapi_create_links
  4. vsp1_destroy_entities
  5. vsp1_create_entities
  6. vsp1_reset_wpf
  7. vsp1_device_init
  8. vsp1_device_get
  9. vsp1_device_put
  10. vsp1_pm_suspend
  11. vsp1_pm_resume
  12. vsp1_pm_runtime_suspend
  13. vsp1_pm_runtime_resume
  14. vsp1_probe
  15. vsp1_remove

   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_WFP_IRQ_STA_DFE | VI6_WFP_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_WFP_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 /*
 554  * vsp1_device_get - Acquire the VSP1 device
 555  *
 556  * Make sure the device is not suspended and initialize it if needed.
 557  *
 558  * Return 0 on success or a negative error code otherwise.
 559  */
 560 int vsp1_device_get(struct vsp1_device *vsp1)
 561 {
 562         int ret;
 563 
 564         ret = pm_runtime_get_sync(vsp1->dev);
 565         return ret < 0 ? ret : 0;
 566 }
 567 
 568 /*
 569  * vsp1_device_put - Release the VSP1 device
 570  *
 571  * Decrement the VSP1 reference count and cleanup the device if the last
 572  * reference is released.
 573  */
 574 void vsp1_device_put(struct vsp1_device *vsp1)
 575 {
 576         pm_runtime_put_sync(vsp1->dev);
 577 }
 578 
 579 /* -----------------------------------------------------------------------------
 580  * Power Management
 581  */
 582 
 583 static int __maybe_unused vsp1_pm_suspend(struct device *dev)
 584 {
 585         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 586 
 587         /*
 588          * When used as part of a display pipeline, the VSP is stopped and
 589          * restarted explicitly by the DU.
 590          */
 591         if (!vsp1->drm)
 592                 vsp1_video_suspend(vsp1);
 593 
 594         pm_runtime_force_suspend(vsp1->dev);
 595 
 596         return 0;
 597 }
 598 
 599 static int __maybe_unused vsp1_pm_resume(struct device *dev)
 600 {
 601         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 602 
 603         pm_runtime_force_resume(vsp1->dev);
 604 
 605         /*
 606          * When used as part of a display pipeline, the VSP is stopped and
 607          * restarted explicitly by the DU.
 608          */
 609         if (!vsp1->drm)
 610                 vsp1_video_resume(vsp1);
 611 
 612         return 0;
 613 }
 614 
 615 static int __maybe_unused vsp1_pm_runtime_suspend(struct device *dev)
 616 {
 617         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 618 
 619         rcar_fcp_disable(vsp1->fcp);
 620 
 621         return 0;
 622 }
 623 
 624 static int __maybe_unused vsp1_pm_runtime_resume(struct device *dev)
 625 {
 626         struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 627         int ret;
 628 
 629         if (vsp1->info) {
 630                 ret = vsp1_device_init(vsp1);
 631                 if (ret < 0)
 632                         return ret;
 633         }
 634 
 635         return rcar_fcp_enable(vsp1->fcp);
 636 }
 637 
 638 static const struct dev_pm_ops vsp1_pm_ops = {
 639         SET_SYSTEM_SLEEP_PM_OPS(vsp1_pm_suspend, vsp1_pm_resume)
 640         SET_RUNTIME_PM_OPS(vsp1_pm_runtime_suspend, vsp1_pm_runtime_resume, NULL)
 641 };
 642 
 643 /* -----------------------------------------------------------------------------
 644  * Platform Driver
 645  */
 646 
 647 static const struct vsp1_device_info vsp1_device_infos[] = {
 648         {
 649                 .version = VI6_IP_VERSION_MODEL_VSPS_H2,
 650                 .model = "VSP1-S",
 651                 .gen = 2,
 652                 .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
 653                           | VSP1_HAS_HGT | VSP1_HAS_LUT | VSP1_HAS_SRU
 654                           | VSP1_HAS_WPF_VFLIP,
 655                 .rpf_count = 5,
 656                 .uds_count = 3,
 657                 .wpf_count = 4,
 658                 .num_bru_inputs = 4,
 659                 .uapi = true,
 660         }, {
 661                 .version = VI6_IP_VERSION_MODEL_VSPR_H2,
 662                 .model = "VSP1-R",
 663                 .gen = 2,
 664                 .features = VSP1_HAS_BRU | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
 665                 .rpf_count = 5,
 666                 .uds_count = 3,
 667                 .wpf_count = 4,
 668                 .num_bru_inputs = 4,
 669                 .uapi = true,
 670         }, {
 671                 .version = VI6_IP_VERSION_MODEL_VSPD_GEN2,
 672                 .model = "VSP1-D",
 673                 .gen = 2,
 674                 .features = VSP1_HAS_BRU | VSP1_HAS_HGO | VSP1_HAS_LUT,
 675                 .lif_count = 1,
 676                 .rpf_count = 4,
 677                 .uds_count = 1,
 678                 .wpf_count = 1,
 679                 .num_bru_inputs = 4,
 680                 .uapi = true,
 681         }, {
 682                 .version = VI6_IP_VERSION_MODEL_VSPS_M2,
 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 = 1,
 690                 .wpf_count = 4,
 691                 .num_bru_inputs = 4,
 692                 .uapi = true,
 693         }, {
 694                 .version = VI6_IP_VERSION_MODEL_VSPS_V2H,
 695                 .model = "VSP1V-S",
 696                 .gen = 2,
 697                 .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT
 698                           | VSP1_HAS_SRU | VSP1_HAS_WPF_VFLIP,
 699                 .rpf_count = 4,
 700                 .uds_count = 1,
 701                 .wpf_count = 4,
 702                 .num_bru_inputs = 4,
 703                 .uapi = true,
 704         }, {
 705                 .version = VI6_IP_VERSION_MODEL_VSPD_V2H,
 706                 .model = "VSP1V-D",
 707                 .gen = 2,
 708                 .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_LUT,
 709                 .lif_count = 1,
 710                 .rpf_count = 4,
 711                 .uds_count = 1,
 712                 .wpf_count = 1,
 713                 .num_bru_inputs = 4,
 714                 .uapi = true,
 715         }, {
 716                 .version = VI6_IP_VERSION_MODEL_VSPI_GEN3,
 717                 .model = "VSP2-I",
 718                 .gen = 3,
 719                 .features = VSP1_HAS_CLU | VSP1_HAS_HGO | VSP1_HAS_HGT
 720                           | VSP1_HAS_LUT | VSP1_HAS_SRU | VSP1_HAS_WPF_HFLIP
 721                           | VSP1_HAS_WPF_VFLIP,
 722                 .rpf_count = 1,
 723                 .uds_count = 1,
 724                 .wpf_count = 1,
 725                 .uapi = true,
 726         }, {
 727                 .version = VI6_IP_VERSION_MODEL_VSPBD_GEN3,
 728                 .model = "VSP2-BD",
 729                 .gen = 3,
 730                 .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
 731                 .rpf_count = 5,
 732                 .wpf_count = 1,
 733                 .num_bru_inputs = 5,
 734                 .uapi = true,
 735         }, {
 736                 .version = VI6_IP_VERSION_MODEL_VSPBC_GEN3,
 737                 .model = "VSP2-BC",
 738                 .gen = 3,
 739                 .features = VSP1_HAS_BRU | VSP1_HAS_CLU | VSP1_HAS_HGO
 740                           | VSP1_HAS_LUT | VSP1_HAS_WPF_VFLIP,
 741                 .rpf_count = 5,
 742                 .wpf_count = 1,
 743                 .num_bru_inputs = 5,
 744                 .uapi = true,
 745         }, {
 746                 .version = VI6_IP_VERSION_MODEL_VSPBS_GEN3,
 747                 .model = "VSP2-BS",
 748                 .gen = 3,
 749                 .features = VSP1_HAS_BRS | VSP1_HAS_WPF_VFLIP,
 750                 .rpf_count = 2,
 751                 .wpf_count = 1,
 752                 .uapi = true,
 753         }, {
 754                 .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
 755                 .model = "VSP2-D",
 756                 .gen = 3,
 757                 .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP | VSP1_HAS_EXT_DL,
 758                 .lif_count = 1,
 759                 .rpf_count = 5,
 760                 .uif_count = 1,
 761                 .wpf_count = 2,
 762                 .num_bru_inputs = 5,
 763         }, {
 764                 .version = VI6_IP_VERSION_MODEL_VSPD_V3,
 765                 .model = "VSP2-D",
 766                 .gen = 3,
 767                 .features = VSP1_HAS_BRS | VSP1_HAS_BRU,
 768                 .lif_count = 1,
 769                 .rpf_count = 5,
 770                 .uif_count = 1,
 771                 .wpf_count = 1,
 772                 .num_bru_inputs = 5,
 773         }, {
 774                 .version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
 775                 .model = "VSP2-DL",
 776                 .gen = 3,
 777                 .features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
 778                 .lif_count = 2,
 779                 .rpf_count = 5,
 780                 .uif_count = 2,
 781                 .wpf_count = 2,
 782                 .num_bru_inputs = 5,
 783         },
 784 };
 785 
 786 static int vsp1_probe(struct platform_device *pdev)
 787 {
 788         struct vsp1_device *vsp1;
 789         struct device_node *fcp_node;
 790         struct resource *irq;
 791         struct resource *io;
 792         unsigned int i;
 793         int ret;
 794 
 795         vsp1 = devm_kzalloc(&pdev->dev, sizeof(*vsp1), GFP_KERNEL);
 796         if (vsp1 == NULL)
 797                 return -ENOMEM;
 798 
 799         vsp1->dev = &pdev->dev;
 800         INIT_LIST_HEAD(&vsp1->entities);
 801         INIT_LIST_HEAD(&vsp1->videos);
 802 
 803         platform_set_drvdata(pdev, vsp1);
 804 
 805         /* I/O and IRQ resources (clock managed by the clock PM domain). */
 806         io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 807         vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
 808         if (IS_ERR(vsp1->mmio))
 809                 return PTR_ERR(vsp1->mmio);
 810 
 811         irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 812         if (!irq) {
 813                 dev_err(&pdev->dev, "missing IRQ\n");
 814                 return -EINVAL;
 815         }
 816 
 817         ret = devm_request_irq(&pdev->dev, irq->start, vsp1_irq_handler,
 818                               IRQF_SHARED, dev_name(&pdev->dev), vsp1);
 819         if (ret < 0) {
 820                 dev_err(&pdev->dev, "failed to request IRQ\n");
 821                 return ret;
 822         }
 823 
 824         /* FCP (optional). */
 825         fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0);
 826         if (fcp_node) {
 827                 vsp1->fcp = rcar_fcp_get(fcp_node);
 828                 of_node_put(fcp_node);
 829                 if (IS_ERR(vsp1->fcp)) {
 830                         dev_dbg(&pdev->dev, "FCP not found (%ld)\n",
 831                                 PTR_ERR(vsp1->fcp));
 832                         return PTR_ERR(vsp1->fcp);
 833                 }
 834 
 835                 /*
 836                  * When the FCP is present, it handles all bus master accesses
 837                  * for the VSP and must thus be used in place of the VSP device
 838                  * to map DMA buffers.
 839                  */
 840                 vsp1->bus_master = rcar_fcp_get_device(vsp1->fcp);
 841         } else {
 842                 vsp1->bus_master = vsp1->dev;
 843         }
 844 
 845         /* Configure device parameters based on the version register. */
 846         pm_runtime_enable(&pdev->dev);
 847 
 848         ret = pm_runtime_get_sync(&pdev->dev);
 849         if (ret < 0)
 850                 goto done;
 851 
 852         vsp1->version = vsp1_read(vsp1, VI6_IP_VERSION);
 853         pm_runtime_put_sync(&pdev->dev);
 854 
 855         for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
 856                 if ((vsp1->version & VI6_IP_VERSION_MODEL_MASK) ==
 857                     vsp1_device_infos[i].version) {
 858                         vsp1->info = &vsp1_device_infos[i];
 859                         break;
 860                 }
 861         }
 862 
 863         if (!vsp1->info) {
 864                 dev_err(&pdev->dev, "unsupported IP version 0x%08x\n",
 865                         vsp1->version);
 866                 ret = -ENXIO;
 867                 goto done;
 868         }
 869 
 870         dev_dbg(&pdev->dev, "IP version 0x%08x\n", vsp1->version);
 871 
 872         /* Instantiate entities. */
 873         ret = vsp1_create_entities(vsp1);
 874         if (ret < 0) {
 875                 dev_err(&pdev->dev, "failed to create entities\n");
 876                 goto done;
 877         }
 878 
 879 done:
 880         if (ret)
 881                 pm_runtime_disable(&pdev->dev);
 882 
 883         return ret;
 884 }
 885 
 886 static int vsp1_remove(struct platform_device *pdev)
 887 {
 888         struct vsp1_device *vsp1 = platform_get_drvdata(pdev);
 889 
 890         vsp1_destroy_entities(vsp1);
 891         rcar_fcp_put(vsp1->fcp);
 892 
 893         pm_runtime_disable(&pdev->dev);
 894 
 895         return 0;
 896 }
 897 
 898 static const struct of_device_id vsp1_of_match[] = {
 899         { .compatible = "renesas,vsp1" },
 900         { .compatible = "renesas,vsp2" },
 901         { },
 902 };
 903 MODULE_DEVICE_TABLE(of, vsp1_of_match);
 904 
 905 static struct platform_driver vsp1_platform_driver = {
 906         .probe          = vsp1_probe,
 907         .remove         = vsp1_remove,
 908         .driver         = {
 909                 .name   = "vsp1",
 910                 .pm     = &vsp1_pm_ops,
 911                 .of_match_table = vsp1_of_match,
 912         },
 913 };
 914 
 915 module_platform_driver(vsp1_platform_driver);
 916 
 917 MODULE_ALIAS("vsp1");
 918 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
 919 MODULE_DESCRIPTION("Renesas VSP1 Driver");
 920 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */