linux/drivers/media/platform/vsp1/vsp1_entity.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * vsp1_entity.c  --  R-Car VSP1 Base Entity
   4 *
   5 * Copyright (C) 2013-2014 Renesas Electronics Corporation
   6 *
   7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   8 */
   9
  10#include <linux/device.h>
  11#include <linux/gfp.h>
  12
  13#include <media/media-entity.h>
  14#include <media/v4l2-ctrls.h>
  15#include <media/v4l2-subdev.h>
  16
  17#include "vsp1.h"
  18#include "vsp1_dl.h"
  19#include "vsp1_entity.h"
  20#include "vsp1_pipe.h"
  21#include "vsp1_rwpf.h"
  22
  23void vsp1_entity_route_setup(struct vsp1_entity *entity,
  24                             struct vsp1_pipeline *pipe,
  25                             struct vsp1_dl_body *dlb)
  26{
  27        struct vsp1_entity *source;
  28        u32 route;
  29
  30        if (entity->type == VSP1_ENTITY_HGO) {
  31                u32 smppt;
  32
  33                /*
  34                 * The HGO is a special case, its routing is configured on the
  35                 * sink pad.
  36                 */
  37                source = entity->sources[0];
  38                smppt = (pipe->output->entity.index << VI6_DPR_SMPPT_TGW_SHIFT)
  39                      | (source->route->output << VI6_DPR_SMPPT_PT_SHIFT);
  40
  41                vsp1_dl_body_write(dlb, VI6_DPR_HGO_SMPPT, smppt);
  42                return;
  43        } else if (entity->type == VSP1_ENTITY_HGT) {
  44                u32 smppt;
  45
  46                /*
  47                 * The HGT is a special case, its routing is configured on the
  48                 * sink pad.
  49                 */
  50                source = entity->sources[0];
  51                smppt = (pipe->output->entity.index << VI6_DPR_SMPPT_TGW_SHIFT)
  52                      | (source->route->output << VI6_DPR_SMPPT_PT_SHIFT);
  53
  54                vsp1_dl_body_write(dlb, VI6_DPR_HGT_SMPPT, smppt);
  55                return;
  56        }
  57
  58        source = entity;
  59        if (source->route->reg == 0)
  60                return;
  61
  62        route = source->sink->route->inputs[source->sink_pad];
  63        /*
  64         * The ILV and BRS share the same data path route. The extra BRSSEL bit
  65         * selects between the ILV and BRS.
  66         */
  67        if (source->type == VSP1_ENTITY_BRS)
  68                route |= VI6_DPR_ROUTE_BRSSEL;
  69        vsp1_dl_body_write(dlb, source->route->reg, route);
  70}
  71
  72void vsp1_entity_configure_stream(struct vsp1_entity *entity,
  73                                  struct vsp1_pipeline *pipe,
  74                                  struct vsp1_dl_list *dl,
  75                                  struct vsp1_dl_body *dlb)
  76{
  77        if (entity->ops->configure_stream)
  78                entity->ops->configure_stream(entity, pipe, dl, dlb);
  79}
  80
  81void vsp1_entity_configure_frame(struct vsp1_entity *entity,
  82                                 struct vsp1_pipeline *pipe,
  83                                 struct vsp1_dl_list *dl,
  84                                 struct vsp1_dl_body *dlb)
  85{
  86        if (entity->ops->configure_frame)
  87                entity->ops->configure_frame(entity, pipe, dl, dlb);
  88}
  89
  90void vsp1_entity_configure_partition(struct vsp1_entity *entity,
  91                                     struct vsp1_pipeline *pipe,
  92                                     struct vsp1_dl_list *dl,
  93                                     struct vsp1_dl_body *dlb)
  94{
  95        if (entity->ops->configure_partition)
  96                entity->ops->configure_partition(entity, pipe, dl, dlb);
  97}
  98
  99/* -----------------------------------------------------------------------------
 100 * V4L2 Subdevice Operations
 101 */
 102
 103/**
 104 * vsp1_entity_get_pad_config - Get the pad configuration for an entity
 105 * @entity: the entity
 106 * @cfg: the TRY pad configuration
 107 * @which: configuration selector (ACTIVE or TRY)
 108 *
 109 * When called with which set to V4L2_SUBDEV_FORMAT_ACTIVE the caller must hold
 110 * the entity lock to access the returned configuration.
 111 *
 112 * Return the pad configuration requested by the which argument. The TRY
 113 * configuration is passed explicitly to the function through the cfg argument
 114 * and simply returned when requested. The ACTIVE configuration comes from the
 115 * entity structure.
 116 */
 117struct v4l2_subdev_pad_config *
 118vsp1_entity_get_pad_config(struct vsp1_entity *entity,
 119                           struct v4l2_subdev_pad_config *cfg,
 120                           enum v4l2_subdev_format_whence which)
 121{
 122        switch (which) {
 123        case V4L2_SUBDEV_FORMAT_ACTIVE:
 124                return entity->config;
 125        case V4L2_SUBDEV_FORMAT_TRY:
 126        default:
 127                return cfg;
 128        }
 129}
 130
 131/**
 132 * vsp1_entity_get_pad_format - Get a pad format from storage for an entity
 133 * @entity: the entity
 134 * @cfg: the configuration storage
 135 * @pad: the pad number
 136 *
 137 * Return the format stored in the given configuration for an entity's pad. The
 138 * configuration can be an ACTIVE or TRY configuration.
 139 */
 140struct v4l2_mbus_framefmt *
 141vsp1_entity_get_pad_format(struct vsp1_entity *entity,
 142                           struct v4l2_subdev_pad_config *cfg,
 143                           unsigned int pad)
 144{
 145        return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad);
 146}
 147
 148/**
 149 * vsp1_entity_get_pad_selection - Get a pad selection from storage for entity
 150 * @entity: the entity
 151 * @cfg: the configuration storage
 152 * @pad: the pad number
 153 * @target: the selection target
 154 *
 155 * Return the selection rectangle stored in the given configuration for an
 156 * entity's pad. The configuration can be an ACTIVE or TRY configuration. The
 157 * selection target can be COMPOSE or CROP.
 158 */
 159struct v4l2_rect *
 160vsp1_entity_get_pad_selection(struct vsp1_entity *entity,
 161                              struct v4l2_subdev_pad_config *cfg,
 162                              unsigned int pad, unsigned int target)
 163{
 164        switch (target) {
 165        case V4L2_SEL_TGT_COMPOSE:
 166                return v4l2_subdev_get_try_compose(&entity->subdev, cfg, pad);
 167        case V4L2_SEL_TGT_CROP:
 168                return v4l2_subdev_get_try_crop(&entity->subdev, cfg, pad);
 169        default:
 170                return NULL;
 171        }
 172}
 173
 174/*
 175 * vsp1_entity_init_cfg - Initialize formats on all pads
 176 * @subdev: V4L2 subdevice
 177 * @cfg: V4L2 subdev pad configuration
 178 *
 179 * Initialize all pad formats with default values in the given pad config. This
 180 * function can be used as a handler for the subdev pad::init_cfg operation.
 181 */
 182int vsp1_entity_init_cfg(struct v4l2_subdev *subdev,
 183                         struct v4l2_subdev_pad_config *cfg)
 184{
 185        struct v4l2_subdev_format format;
 186        unsigned int pad;
 187
 188        for (pad = 0; pad < subdev->entity.num_pads - 1; ++pad) {
 189                memset(&format, 0, sizeof(format));
 190
 191                format.pad = pad;
 192                format.which = cfg ? V4L2_SUBDEV_FORMAT_TRY
 193                             : V4L2_SUBDEV_FORMAT_ACTIVE;
 194
 195                v4l2_subdev_call(subdev, pad, set_fmt, cfg, &format);
 196        }
 197
 198        return 0;
 199}
 200
 201/*
 202 * vsp1_subdev_get_pad_format - Subdev pad get_fmt handler
 203 * @subdev: V4L2 subdevice
 204 * @cfg: V4L2 subdev pad configuration
 205 * @fmt: V4L2 subdev format
 206 *
 207 * This function implements the subdev get_fmt pad operation. It can be used as
 208 * a direct drop-in for the operation handler.
 209 */
 210int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
 211                               struct v4l2_subdev_pad_config *cfg,
 212                               struct v4l2_subdev_format *fmt)
 213{
 214        struct vsp1_entity *entity = to_vsp1_entity(subdev);
 215        struct v4l2_subdev_pad_config *config;
 216
 217        config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
 218        if (!config)
 219                return -EINVAL;
 220
 221        mutex_lock(&entity->lock);
 222        fmt->format = *vsp1_entity_get_pad_format(entity, config, fmt->pad);
 223        mutex_unlock(&entity->lock);
 224
 225        return 0;
 226}
 227
 228/*
 229 * vsp1_subdev_enum_mbus_code - Subdev pad enum_mbus_code handler
 230 * @subdev: V4L2 subdevice
 231 * @cfg: V4L2 subdev pad configuration
 232 * @code: Media bus code enumeration
 233 * @codes: Array of supported media bus codes
 234 * @ncodes: Number of supported media bus codes
 235 *
 236 * This function implements the subdev enum_mbus_code pad operation for entities
 237 * that do not support format conversion. It enumerates the given supported
 238 * media bus codes on the sink pad and reports a source pad format identical to
 239 * the sink pad.
 240 */
 241int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
 242                               struct v4l2_subdev_pad_config *cfg,
 243                               struct v4l2_subdev_mbus_code_enum *code,
 244                               const unsigned int *codes, unsigned int ncodes)
 245{
 246        struct vsp1_entity *entity = to_vsp1_entity(subdev);
 247
 248        if (code->pad == 0) {
 249                if (code->index >= ncodes)
 250                        return -EINVAL;
 251
 252                code->code = codes[code->index];
 253        } else {
 254                struct v4l2_subdev_pad_config *config;
 255                struct v4l2_mbus_framefmt *format;
 256
 257                /*
 258                 * The entity can't perform format conversion, the sink format
 259                 * is always identical to the source format.
 260                 */
 261                if (code->index)
 262                        return -EINVAL;
 263
 264                config = vsp1_entity_get_pad_config(entity, cfg, code->which);
 265                if (!config)
 266                        return -EINVAL;
 267
 268                mutex_lock(&entity->lock);
 269                format = vsp1_entity_get_pad_format(entity, config, 0);
 270                code->code = format->code;
 271                mutex_unlock(&entity->lock);
 272        }
 273
 274        return 0;
 275}
 276
 277/*
 278 * vsp1_subdev_enum_frame_size - Subdev pad enum_frame_size handler
 279 * @subdev: V4L2 subdevice
 280 * @cfg: V4L2 subdev pad configuration
 281 * @fse: Frame size enumeration
 282 * @min_width: Minimum image width
 283 * @min_height: Minimum image height
 284 * @max_width: Maximum image width
 285 * @max_height: Maximum image height
 286 *
 287 * This function implements the subdev enum_frame_size pad operation for
 288 * entities that do not support scaling or cropping. It reports the given
 289 * minimum and maximum frame width and height on the sink pad, and a fixed
 290 * source pad size identical to the sink pad.
 291 */
 292int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
 293                                struct v4l2_subdev_pad_config *cfg,
 294                                struct v4l2_subdev_frame_size_enum *fse,
 295                                unsigned int min_width, unsigned int min_height,
 296                                unsigned int max_width, unsigned int max_height)
 297{
 298        struct vsp1_entity *entity = to_vsp1_entity(subdev);
 299        struct v4l2_subdev_pad_config *config;
 300        struct v4l2_mbus_framefmt *format;
 301        int ret = 0;
 302
 303        config = vsp1_entity_get_pad_config(entity, cfg, fse->which);
 304        if (!config)
 305                return -EINVAL;
 306
 307        format = vsp1_entity_get_pad_format(entity, config, fse->pad);
 308
 309        mutex_lock(&entity->lock);
 310
 311        if (fse->index || fse->code != format->code) {
 312                ret = -EINVAL;
 313                goto done;
 314        }
 315
 316        if (fse->pad == 0) {
 317                fse->min_width = min_width;
 318                fse->max_width = max_width;
 319                fse->min_height = min_height;
 320                fse->max_height = max_height;
 321        } else {
 322                /*
 323                 * The size on the source pad are fixed and always identical to
 324                 * the size on the sink pad.
 325                 */
 326                fse->min_width = format->width;
 327                fse->max_width = format->width;
 328                fse->min_height = format->height;
 329                fse->max_height = format->height;
 330        }
 331
 332done:
 333        mutex_unlock(&entity->lock);
 334        return ret;
 335}
 336
 337/*
 338 * vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
 339 * @subdev: V4L2 subdevice
 340 * @cfg: V4L2 subdev pad configuration
 341 * @fmt: V4L2 subdev format
 342 * @codes: Array of supported media bus codes
 343 * @ncodes: Number of supported media bus codes
 344 * @min_width: Minimum image width
 345 * @min_height: Minimum image height
 346 * @max_width: Maximum image width
 347 * @max_height: Maximum image height
 348 *
 349 * This function implements the subdev set_fmt pad operation for entities that
 350 * do not support scaling or cropping. It defaults to the first supplied media
 351 * bus code if the requested code isn't supported, clamps the size to the
 352 * supplied minimum and maximum, and propagates the sink pad format to the
 353 * source pad.
 354 */
 355int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
 356                               struct v4l2_subdev_pad_config *cfg,
 357                               struct v4l2_subdev_format *fmt,
 358                               const unsigned int *codes, unsigned int ncodes,
 359                               unsigned int min_width, unsigned int min_height,
 360                               unsigned int max_width, unsigned int max_height)
 361{
 362        struct vsp1_entity *entity = to_vsp1_entity(subdev);
 363        struct v4l2_subdev_pad_config *config;
 364        struct v4l2_mbus_framefmt *format;
 365        struct v4l2_rect *selection;
 366        unsigned int i;
 367        int ret = 0;
 368
 369        mutex_lock(&entity->lock);
 370
 371        config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
 372        if (!config) {
 373                ret = -EINVAL;
 374                goto done;
 375        }
 376
 377        format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
 378
 379        if (fmt->pad == entity->source_pad) {
 380                /* The output format can't be modified. */
 381                fmt->format = *format;
 382                goto done;
 383        }
 384
 385        /*
 386         * Default to the first media bus code if the requested format is not
 387         * supported.
 388         */
 389        for (i = 0; i < ncodes; ++i) {
 390                if (fmt->format.code == codes[i])
 391                        break;
 392        }
 393
 394        format->code = i < ncodes ? codes[i] : codes[0];
 395        format->width = clamp_t(unsigned int, fmt->format.width,
 396                                min_width, max_width);
 397        format->height = clamp_t(unsigned int, fmt->format.height,
 398                                 min_height, max_height);
 399        format->field = V4L2_FIELD_NONE;
 400        format->colorspace = V4L2_COLORSPACE_SRGB;
 401
 402        fmt->format = *format;
 403
 404        /* Propagate the format to the source pad. */
 405        format = vsp1_entity_get_pad_format(entity, config, entity->source_pad);
 406        *format = fmt->format;
 407
 408        /* Reset the crop and compose rectangles. */
 409        selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
 410                                                  V4L2_SEL_TGT_CROP);
 411        selection->left = 0;
 412        selection->top = 0;
 413        selection->width = format->width;
 414        selection->height = format->height;
 415
 416        selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
 417                                                  V4L2_SEL_TGT_COMPOSE);
 418        selection->left = 0;
 419        selection->top = 0;
 420        selection->width = format->width;
 421        selection->height = format->height;
 422
 423done:
 424        mutex_unlock(&entity->lock);
 425        return ret;
 426}
 427
 428/* -----------------------------------------------------------------------------
 429 * Media Operations
 430 */
 431
 432static inline struct vsp1_entity *
 433media_entity_to_vsp1_entity(struct media_entity *entity)
 434{
 435        return container_of(entity, struct vsp1_entity, subdev.entity);
 436}
 437
 438static int vsp1_entity_link_setup_source(const struct media_pad *source_pad,
 439                                         const struct media_pad *sink_pad,
 440                                         u32 flags)
 441{
 442        struct vsp1_entity *source;
 443
 444        source = media_entity_to_vsp1_entity(source_pad->entity);
 445
 446        if (!source->route)
 447                return 0;
 448
 449        if (flags & MEDIA_LNK_FL_ENABLED) {
 450                struct vsp1_entity *sink
 451                        = media_entity_to_vsp1_entity(sink_pad->entity);
 452
 453                /*
 454                 * Fan-out is limited to one for the normal data path plus
 455                 * optional HGO and HGT. We ignore the HGO and HGT here.
 456                 */
 457                if (sink->type != VSP1_ENTITY_HGO &&
 458                    sink->type != VSP1_ENTITY_HGT) {
 459                        if (source->sink)
 460                                return -EBUSY;
 461                        source->sink = sink;
 462                        source->sink_pad = sink_pad->index;
 463                }
 464        } else {
 465                source->sink = NULL;
 466                source->sink_pad = 0;
 467        }
 468
 469        return 0;
 470}
 471
 472static int vsp1_entity_link_setup_sink(const struct media_pad *source_pad,
 473                                       const struct media_pad *sink_pad,
 474                                       u32 flags)
 475{
 476        struct vsp1_entity *sink;
 477        struct vsp1_entity *source;
 478
 479        sink = media_entity_to_vsp1_entity(sink_pad->entity);
 480        source = media_entity_to_vsp1_entity(source_pad->entity);
 481
 482        if (flags & MEDIA_LNK_FL_ENABLED) {
 483                /* Fan-in is limited to one. */
 484                if (sink->sources[sink_pad->index])
 485                        return -EBUSY;
 486
 487                sink->sources[sink_pad->index] = source;
 488        } else {
 489                sink->sources[sink_pad->index] = NULL;
 490        }
 491
 492        return 0;
 493}
 494
 495int vsp1_entity_link_setup(struct media_entity *entity,
 496                           const struct media_pad *local,
 497                           const struct media_pad *remote, u32 flags)
 498{
 499        if (local->flags & MEDIA_PAD_FL_SOURCE)
 500                return vsp1_entity_link_setup_source(local, remote, flags);
 501        else
 502                return vsp1_entity_link_setup_sink(remote, local, flags);
 503}
 504
 505/**
 506 * vsp1_entity_remote_pad - Find the pad at the remote end of a link
 507 * @pad: Pad at the local end of the link
 508 *
 509 * Search for a remote pad connected to the given pad by iterating over all
 510 * links originating or terminating at that pad until an enabled link is found.
 511 *
 512 * Our link setup implementation guarantees that the output fan-out will not be
 513 * higher than one for the data pipelines, except for the links to the HGO and
 514 * HGT that can be enabled in addition to a regular data link. When traversing
 515 * outgoing links this function ignores HGO and HGT entities and should thus be
 516 * used in place of the generic media_entity_remote_pad() function to traverse
 517 * data pipelines.
 518 *
 519 * Return a pointer to the pad at the remote end of the first found enabled
 520 * link, or NULL if no enabled link has been found.
 521 */
 522struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad)
 523{
 524        struct media_link *link;
 525
 526        list_for_each_entry(link, &pad->entity->links, list) {
 527                struct vsp1_entity *entity;
 528
 529                if (!(link->flags & MEDIA_LNK_FL_ENABLED))
 530                        continue;
 531
 532                /* If we're the sink the source will never be an HGO or HGT. */
 533                if (link->sink == pad)
 534                        return link->source;
 535
 536                if (link->source != pad)
 537                        continue;
 538
 539                /* If the sink isn't a subdevice it can't be an HGO or HGT. */
 540                if (!is_media_entity_v4l2_subdev(link->sink->entity))
 541                        return link->sink;
 542
 543                entity = media_entity_to_vsp1_entity(link->sink->entity);
 544                if (entity->type != VSP1_ENTITY_HGO &&
 545                    entity->type != VSP1_ENTITY_HGT)
 546                        return link->sink;
 547        }
 548
 549        return NULL;
 550
 551}
 552
 553/* -----------------------------------------------------------------------------
 554 * Initialization
 555 */
 556
 557#define VSP1_ENTITY_ROUTE(ent)                                          \
 558        { VSP1_ENTITY_##ent, 0, VI6_DPR_##ent##_ROUTE,                  \
 559          { VI6_DPR_NODE_##ent }, VI6_DPR_NODE_##ent }
 560
 561#define VSP1_ENTITY_ROUTE_RPF(idx)                                      \
 562        { VSP1_ENTITY_RPF, idx, VI6_DPR_RPF_ROUTE(idx),                 \
 563          { 0, }, VI6_DPR_NODE_RPF(idx) }
 564
 565#define VSP1_ENTITY_ROUTE_UDS(idx)                                      \
 566        { VSP1_ENTITY_UDS, idx, VI6_DPR_UDS_ROUTE(idx),                 \
 567          { VI6_DPR_NODE_UDS(idx) }, VI6_DPR_NODE_UDS(idx) }
 568
 569#define VSP1_ENTITY_ROUTE_UIF(idx)                                      \
 570        { VSP1_ENTITY_UIF, idx, VI6_DPR_UIF_ROUTE(idx),                 \
 571          { VI6_DPR_NODE_UIF(idx) }, VI6_DPR_NODE_UIF(idx) }
 572
 573#define VSP1_ENTITY_ROUTE_WPF(idx)                                      \
 574        { VSP1_ENTITY_WPF, idx, 0,                                      \
 575          { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) }
 576
 577static const struct vsp1_route vsp1_routes[] = {
 578        { VSP1_ENTITY_BRS, 0, VI6_DPR_ILV_BRS_ROUTE,
 579          { VI6_DPR_NODE_BRS_IN(0), VI6_DPR_NODE_BRS_IN(1) }, 0 },
 580        { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE,
 581          { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1),
 582            VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3),
 583            VI6_DPR_NODE_BRU_IN(4) }, VI6_DPR_NODE_BRU_OUT },
 584        VSP1_ENTITY_ROUTE(CLU),
 585        { VSP1_ENTITY_HGO, 0, 0, { 0, }, 0 },
 586        { VSP1_ENTITY_HGT, 0, 0, { 0, }, 0 },
 587        VSP1_ENTITY_ROUTE(HSI),
 588        VSP1_ENTITY_ROUTE(HST),
 589        { VSP1_ENTITY_LIF, 0, 0, { 0, }, 0 },
 590        { VSP1_ENTITY_LIF, 1, 0, { 0, }, 0 },
 591        VSP1_ENTITY_ROUTE(LUT),
 592        VSP1_ENTITY_ROUTE_RPF(0),
 593        VSP1_ENTITY_ROUTE_RPF(1),
 594        VSP1_ENTITY_ROUTE_RPF(2),
 595        VSP1_ENTITY_ROUTE_RPF(3),
 596        VSP1_ENTITY_ROUTE_RPF(4),
 597        VSP1_ENTITY_ROUTE(SRU),
 598        VSP1_ENTITY_ROUTE_UDS(0),
 599        VSP1_ENTITY_ROUTE_UDS(1),
 600        VSP1_ENTITY_ROUTE_UDS(2),
 601        VSP1_ENTITY_ROUTE_UIF(0),       /* Named UIF4 in the documentation */
 602        VSP1_ENTITY_ROUTE_UIF(1),       /* Named UIF5 in the documentation */
 603        VSP1_ENTITY_ROUTE_WPF(0),
 604        VSP1_ENTITY_ROUTE_WPF(1),
 605        VSP1_ENTITY_ROUTE_WPF(2),
 606        VSP1_ENTITY_ROUTE_WPF(3),
 607};
 608
 609int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 610                     const char *name, unsigned int num_pads,
 611                     const struct v4l2_subdev_ops *ops, u32 function)
 612{
 613        struct v4l2_subdev *subdev;
 614        unsigned int i;
 615        int ret;
 616
 617        for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
 618                if (vsp1_routes[i].type == entity->type &&
 619                    vsp1_routes[i].index == entity->index) {
 620                        entity->route = &vsp1_routes[i];
 621                        break;
 622                }
 623        }
 624
 625        if (i == ARRAY_SIZE(vsp1_routes))
 626                return -EINVAL;
 627
 628        mutex_init(&entity->lock);
 629
 630        entity->vsp1 = vsp1;
 631        entity->source_pad = num_pads - 1;
 632
 633        /* Allocate and initialize pads. */
 634        entity->pads = devm_kcalloc(vsp1->dev,
 635                                    num_pads, sizeof(*entity->pads),
 636                                    GFP_KERNEL);
 637        if (entity->pads == NULL)
 638                return -ENOMEM;
 639
 640        for (i = 0; i < num_pads - 1; ++i)
 641                entity->pads[i].flags = MEDIA_PAD_FL_SINK;
 642
 643        entity->sources = devm_kcalloc(vsp1->dev, max(num_pads - 1, 1U),
 644                                       sizeof(*entity->sources), GFP_KERNEL);
 645        if (entity->sources == NULL)
 646                return -ENOMEM;
 647
 648        /* Single-pad entities only have a sink. */
 649        entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
 650                                         : MEDIA_PAD_FL_SINK;
 651
 652        /* Initialize the media entity. */
 653        ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
 654                                     entity->pads);
 655        if (ret < 0)
 656                return ret;
 657
 658        /* Initialize the V4L2 subdev. */
 659        subdev = &entity->subdev;
 660        v4l2_subdev_init(subdev, ops);
 661
 662        subdev->entity.function = function;
 663        subdev->entity.ops = &vsp1->media_ops;
 664        subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 665
 666        snprintf(subdev->name, sizeof(subdev->name), "%s %s",
 667                 dev_name(vsp1->dev), name);
 668
 669        vsp1_entity_init_cfg(subdev, NULL);
 670
 671        /*
 672         * Allocate the pad configuration to store formats and selection
 673         * rectangles.
 674         */
 675        entity->config = v4l2_subdev_alloc_pad_config(&entity->subdev);
 676        if (entity->config == NULL) {
 677                media_entity_cleanup(&entity->subdev.entity);
 678                return -ENOMEM;
 679        }
 680
 681        return 0;
 682}
 683
 684void vsp1_entity_destroy(struct vsp1_entity *entity)
 685{
 686        if (entity->ops && entity->ops->destroy)
 687                entity->ops->destroy(entity);
 688        if (entity->subdev.ctrl_handler)
 689                v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
 690        v4l2_subdev_free_pad_config(entity->config);
 691        media_entity_cleanup(&entity->subdev.entity);
 692}
 693