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

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

DEFINITIONS

This source file includes following definitions.
  1. vsp1_entity_route_setup
  2. vsp1_entity_configure_stream
  3. vsp1_entity_configure_frame
  4. vsp1_entity_configure_partition
  5. vsp1_entity_get_pad_config
  6. vsp1_entity_get_pad_format
  7. vsp1_entity_get_pad_selection
  8. vsp1_entity_init_cfg
  9. vsp1_subdev_get_pad_format
  10. vsp1_subdev_enum_mbus_code
  11. vsp1_subdev_enum_frame_size
  12. vsp1_subdev_set_pad_format
  13. media_entity_to_vsp1_entity
  14. vsp1_entity_link_setup_source
  15. vsp1_entity_link_setup_sink
  16. vsp1_entity_link_setup
  17. vsp1_entity_remote_pad
  18. vsp1_entity_init
  19. vsp1_entity_destroy

   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 
  23 void 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 
  72 void 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 
  81 void 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 
  90 void 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  */
 117 struct v4l2_subdev_pad_config *
 118 vsp1_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  */
 140 struct v4l2_mbus_framefmt *
 141 vsp1_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  */
 159 struct v4l2_rect *
 160 vsp1_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  */
 182 int 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  */
 210 int 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  */
 241 int 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  */
 292 int 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 
 332 done:
 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  */
 355 int 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 
 423 done:
 424         mutex_unlock(&entity->lock);
 425         return ret;
 426 }
 427 
 428 /* -----------------------------------------------------------------------------
 429  * Media Operations
 430  */
 431 
 432 static inline struct vsp1_entity *
 433 media_entity_to_vsp1_entity(struct media_entity *entity)
 434 {
 435         return container_of(entity, struct vsp1_entity, subdev.entity);
 436 }
 437 
 438 static 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 
 472 static 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 
 495 int 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  */
 522 struct 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 
 577 static 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 
 609 int 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 
 684 void 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 }

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