This source file includes following definitions.
- vsp1_entity_route_setup
 
- vsp1_entity_configure_stream
 
- vsp1_entity_configure_frame
 
- vsp1_entity_configure_partition
 
- vsp1_entity_get_pad_config
 
- vsp1_entity_get_pad_format
 
- vsp1_entity_get_pad_selection
 
- vsp1_entity_init_cfg
 
- vsp1_subdev_get_pad_format
 
- vsp1_subdev_enum_mbus_code
 
- vsp1_subdev_enum_frame_size
 
- vsp1_subdev_set_pad_format
 
- media_entity_to_vsp1_entity
 
- vsp1_entity_link_setup_source
 
- vsp1_entity_link_setup_sink
 
- vsp1_entity_link_setup
 
- vsp1_entity_remote_pad
 
- vsp1_entity_init
 
- vsp1_entity_destroy
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   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 
  35 
  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 
  48 
  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 
  65 
  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 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 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 
 133 
 134 
 135 
 136 
 137 
 138 
 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 
 150 
 151 
 152 
 153 
 154 
 155 
 156 
 157 
 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 
 176 
 177 
 178 
 179 
 180 
 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 
 203 
 204 
 205 
 206 
 207 
 208 
 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 
 230 
 231 
 232 
 233 
 234 
 235 
 236 
 237 
 238 
 239 
 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 
 259 
 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 
 279 
 280 
 281 
 282 
 283 
 284 
 285 
 286 
 287 
 288 
 289 
 290 
 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 
 324 
 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 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 
 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                 
 381                 fmt->format = *format;
 382                 goto done;
 383         }
 384 
 385         
 386 
 387 
 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         
 405         format = vsp1_entity_get_pad_format(entity, config, entity->source_pad);
 406         *format = fmt->format;
 407 
 408         
 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 
 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 
 455 
 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                 
 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 
 507 
 508 
 509 
 510 
 511 
 512 
 513 
 514 
 515 
 516 
 517 
 518 
 519 
 520 
 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                 
 533                 if (link->sink == pad)
 534                         return link->source;
 535 
 536                 if (link->source != pad)
 537                         continue;
 538 
 539                 
 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 
 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),       
 602         VSP1_ENTITY_ROUTE_UIF(1),       
 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         
 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         
 649         entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
 650                                          : MEDIA_PAD_FL_SINK;
 651 
 652         
 653         ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
 654                                      entity->pads);
 655         if (ret < 0)
 656                 return ret;
 657 
 658         
 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 
 673 
 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 }