static int bru_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { struct vsp1_bru *bru = to_bru(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *compose; if (sel->pad == bru->entity.source_pad) return -EINVAL; if (sel->target != V4L2_SEL_TGT_COMPOSE) return -EINVAL; /* The compose rectangle top left corner must be inside the output * frame. */ format = vsp1_entity_get_pad_format(&bru->entity, cfg, bru->entity.source_pad, sel->which); sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); /* Scaling isn't supported, the compose rectangle size must be identical * to the sink format size. */ format = vsp1_entity_get_pad_format(&bru->entity, cfg, sel->pad, sel->which); sel->r.width = format->width; sel->r.height = format->height; compose = bru_get_compose(bru, cfg, sel->pad, sel->which); *compose = sel->r; return 0; }
static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; int ret = 0; mutex_lock(&lut->entity.lock); config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which); if (!config) { ret = -EINVAL; goto done; } /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad); if (fmt->pad == LUT_PAD_SOURCE) { /* The LUT output format can't be modified. */ fmt->format = *format; goto done; } format->code = fmt->format.code; format->width = clamp_t(unsigned int, fmt->format.width, LUT_MIN_SIZE, LUT_MAX_SIZE); format->height = clamp_t(unsigned int, fmt->format.height, LUT_MIN_SIZE, LUT_MAX_SIZE); format->field = V4L2_FIELD_NONE; format->colorspace = V4L2_COLORSPACE_SRGB; fmt->format = *format; /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&lut->entity, config, LUT_PAD_SOURCE); *format = fmt->format; done: mutex_unlock(&lut->entity.lock); return ret; }
int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, fmt->which); if (fmt->pad == RWPF_PAD_SOURCE) { /* The RWPF performs format conversion but can't scale, only the * format code can be changed on the source pad. */ format->code = fmt->format.code; fmt->format = *format; return 0; } format->code = fmt->format.code; format->width = clamp_t(unsigned int, fmt->format.width, RWPF_MIN_WIDTH, rwpf->max_width); format->height = clamp_t(unsigned int, fmt->format.height, RWPF_MIN_HEIGHT, rwpf->max_height); format->field = V4L2_FIELD_NONE; format->colorspace = V4L2_COLORSPACE_SRGB; fmt->format = *format; /* Update the sink crop rectangle. */ crop = vsp1_rwpf_get_crop(rwpf, cfg, fmt->which); crop->left = 0; crop->top = 0; crop->width = fmt->format.width; crop->height = fmt->format.height; /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE, fmt->which); *format = fmt->format; return 0; }
static int brx_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { struct vsp1_brx *brx = to_brx(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; struct v4l2_rect *compose; int ret = 0; if (sel->pad == brx->entity.source_pad) return -EINVAL; if (sel->target != V4L2_SEL_TGT_COMPOSE) return -EINVAL; mutex_lock(&brx->entity.lock); config = vsp1_entity_get_pad_config(&brx->entity, cfg, sel->which); if (!config) { ret = -EINVAL; goto done; } /* * The compose rectangle top left corner must be inside the output * frame. */ format = vsp1_entity_get_pad_format(&brx->entity, config, brx->entity.source_pad); sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); /* * Scaling isn't supported, the compose rectangle size must be identical * to the sink format size. */ format = vsp1_entity_get_pad_format(&brx->entity, config, sel->pad); sel->r.width = format->width; sel->r.height = format->height; compose = brx_get_compose(brx, config, sel->pad); *compose = sel->r; done: mutex_unlock(&brx->entity.lock); return ret; }
static int brx_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_brx *brx = to_brx(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; int ret = 0; mutex_lock(&brx->entity.lock); config = vsp1_entity_get_pad_config(&brx->entity, cfg, fmt->which); if (!config) { ret = -EINVAL; goto done; } brx_try_format(brx, config, fmt->pad, &fmt->format); format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad); *format = fmt->format; /* Reset the compose rectangle */ if (fmt->pad != brx->entity.source_pad) { struct v4l2_rect *compose; compose = brx_get_compose(brx, config, fmt->pad); compose->left = 0; compose->top = 0; compose->width = format->width; compose->height = format->height; } /* Propagate the format code to all pads */ if (fmt->pad == BRX_PAD_SINK(0)) { unsigned int i; for (i = 0; i <= brx->entity.source_pad; ++i) { format = vsp1_entity_get_pad_format(&brx->entity, config, i); format->code = fmt->format.code; } } done: mutex_unlock(&brx->entity.lock); return ret; }
int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; /* Cropping is implemented on the sink pad. */ if (sel->pad != RWPF_PAD_SINK) return -EINVAL; if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; /* Make sure the crop rectangle is entirely contained in the image. The * WPF top and left offsets are limited to 255. */ format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SINK, sel->which); sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2); sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2); if (rwpf->entity.type == VSP1_ENTITY_WPF) { sel->r.left = min_t(unsigned int, sel->r.left, 255); sel->r.top = min_t(unsigned int, sel->r.top, 255); }
static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { struct v4l2_mbus_framefmt *format; unsigned int minimum; unsigned int maximum; switch (pad) { case UDS_PAD_SINK: /* Default to YUV if the requested format is not supported. */ if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->code = MEDIA_BUS_FMT_AYUV8_1X32; fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE); fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE); break; case UDS_PAD_SOURCE: /* The UDS scales but can't perform format conversion. */ format = vsp1_entity_get_pad_format(&uds->entity, cfg, UDS_PAD_SINK, which); fmt->code = format->code; uds_output_limits(format->width, &minimum, &maximum); fmt->width = clamp(fmt->width, minimum, maximum); uds_output_limits(format->height, &minimum, &maximum); fmt->height = clamp(fmt->height, minimum, maximum); break; } fmt->field = V4L2_FIELD_NONE; fmt->colorspace = V4L2_COLORSPACE_SRGB; }
static int uds_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_uds *uds = to_uds(subdev); struct v4l2_mbus_framefmt *format; format = vsp1_entity_get_pad_format(&uds->entity, cfg, UDS_PAD_SINK, fse->which); if (fse->index || fse->code != format->code) return -EINVAL; if (fse->pad == UDS_PAD_SINK) { fse->min_width = UDS_MIN_SIZE; fse->max_width = UDS_MAX_SIZE; fse->min_height = UDS_MIN_SIZE; fse->max_height = UDS_MAX_SIZE; } else { uds_output_limits(format->width, &fse->min_width, &fse->max_width); uds_output_limits(format->height, &fse->min_height, &fse->max_height); } return 0; }
static int histo_set_crop(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *config, struct v4l2_subdev_selection *sel) { struct vsp1_histogram *histo = subdev_to_histo(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *selection; /* The crop rectangle must be inside the input frame. */ format = vsp1_entity_get_pad_format(&histo->entity, config, HISTO_PAD_SINK); sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); sel->r.width = clamp_t(unsigned int, sel->r.width, HISTO_MIN_SIZE, format->width - sel->r.left); sel->r.height = clamp_t(unsigned int, sel->r.height, HISTO_MIN_SIZE, format->height - sel->r.top); /* Set the crop rectangle and reset the compose rectangle. */ selection = vsp1_entity_get_pad_selection(&histo->entity, config, sel->pad, V4L2_SEL_TGT_CROP); *selection = sel->r; selection = vsp1_entity_get_pad_selection(&histo->entity, config, sel->pad, V4L2_SEL_TGT_COMPOSE); *selection = sel->r; return 0; }
int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; /* Cropping is implemented on the sink pad. */ if (sel->pad != RWPF_PAD_SINK) return -EINVAL; switch (sel->target) { case V4L2_SEL_TGT_CROP: sel->r = *vsp1_rwpf_get_crop(rwpf, cfg, sel->which); break; case V4L2_SEL_TGT_CROP_BOUNDS: format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SINK, sel->which); sel->r.left = 0; sel->r.top = 0; sel->r.width = format->width; sel->r.height = format->height; break; default: return -EINVAL; } return 0; }
static void lif_configure(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_list *dl, bool full) { const struct v4l2_mbus_framefmt *format; struct vsp1_lif *lif = to_lif(&entity->subdev); unsigned int hbth = 1300; unsigned int obth = 400; unsigned int lbth = 200; if (!full) return; format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, LIF_PAD_SOURCE); obth = min(obth, (format->width + 1) / 2 * format->height - 4); vsp1_lif_write(lif, dl, VI6_LIF_CSBTH, (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); vsp1_lif_write(lif, dl, VI6_LIF_CTRL, (obth << VI6_LIF_CTRL_OBTH_SHIFT) | (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); }
int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fse->pad, fse->which); if (fse->index || fse->code != format->code) return -EINVAL; if (fse->pad == RWPF_PAD_SINK) { fse->min_width = RWPF_MIN_WIDTH; fse->max_width = rwpf->max_width; fse->min_height = RWPF_MIN_HEIGHT; fse->max_height = rwpf->max_height; } else { /* The size on the source pad are fixed and always identical to * the size on the sink pad. */ fse->min_width = format->width; fse->max_width = format->width; fse->min_height = format->height; fse->max_height = format->height; } return 0; }
static int lut_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { static const unsigned int codes[] = { MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AHSV8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; struct vsp1_lut *lut = to_lut(subdev); struct v4l2_mbus_framefmt *format; if (code->pad == LUT_PAD_SINK) { if (code->index >= ARRAY_SIZE(codes)) return -EINVAL; code->code = codes[code->index]; } else { /* The LUT can't perform format conversion, the sink format is * always identical to the source format. */ if (code->index) return -EINVAL; format = vsp1_entity_get_pad_format(&lut->entity, cfg, LUT_PAD_SINK, code->which); code->code = format->code; } return 0; }
static int lut_enum_frame_size(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { struct vsp1_lut *lut = to_lut(subdev); struct v4l2_mbus_framefmt *format; format = vsp1_entity_get_pad_format(&lut->entity, cfg, fse->pad, fse->which); if (fse->index || fse->code != format->code) return -EINVAL; if (fse->pad == LUT_PAD_SINK) { fse->min_width = LUT_MIN_SIZE; fse->max_width = LUT_MAX_SIZE; fse->min_height = LUT_MIN_SIZE; fse->max_height = LUT_MAX_SIZE; } else { /* The size on the source pad are fixed and always identical to * the size on the sink pad. */ fse->min_width = format->width; fse->max_width = format->width; fse->min_height = format->height; fse->max_height = format->height; } return 0; }
static int bru_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { static const unsigned int codes[] = { MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_AYUV8_1X32, }; struct vsp1_bru *bru = to_bru(subdev); struct v4l2_mbus_framefmt *format; if (code->pad == BRU_PAD_SINK(0)) { if (code->index >= ARRAY_SIZE(codes)) return -EINVAL; code->code = codes[code->index]; } else { if (code->index) return -EINVAL; format = vsp1_entity_get_pad_format(&bru->entity, cfg, BRU_PAD_SINK(0), code->which); code->code = format->code; } return 0; }
static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { struct v4l2_mbus_framefmt *format; switch (pad) { case BRU_PAD_SINK(0): /* Default to YUV if the requested format is not supported. */ if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->code = MEDIA_BUS_FMT_AYUV8_1X32; break; default: /* The BRU can't perform format conversion. */ format = vsp1_entity_get_pad_format(&bru->entity, cfg, BRU_PAD_SINK(0), which); fmt->code = format->code; break; } fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE); fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE); fmt->field = V4L2_FIELD_NONE; fmt->colorspace = V4L2_COLORSPACE_SRGB; }
static int histo_get_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { struct vsp1_histogram *histo = subdev_to_histo(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; int ret = 0; if (sel->pad != HISTO_PAD_SINK) return -EINVAL; mutex_lock(&histo->entity.lock); config = vsp1_entity_get_pad_config(&histo->entity, cfg, sel->which); if (!config) { ret = -EINVAL; goto done; } switch (sel->target) { case V4L2_SEL_TGT_COMPOSE_BOUNDS: case V4L2_SEL_TGT_COMPOSE_DEFAULT: crop = vsp1_entity_get_pad_selection(&histo->entity, config, HISTO_PAD_SINK, V4L2_SEL_TGT_CROP); sel->r.left = 0; sel->r.top = 0; sel->r.width = crop->width; sel->r.height = crop->height; break; case V4L2_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_DEFAULT: format = vsp1_entity_get_pad_format(&histo->entity, config, HISTO_PAD_SINK); sel->r.left = 0; sel->r.top = 0; sel->r.width = format->width; sel->r.height = format->height; break; case V4L2_SEL_TGT_COMPOSE: case V4L2_SEL_TGT_CROP: sel->r = *vsp1_entity_get_pad_selection(&histo->entity, config, sel->pad, sel->target); break; default: ret = -EINVAL; break; } done: mutex_unlock(&histo->entity.lock); return ret; }
static void lif_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_body *dlb) { const struct v4l2_mbus_framefmt *format; struct vsp1_lif *lif = to_lif(&entity->subdev); unsigned int hbth; unsigned int obth; unsigned int lbth; format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, LIF_PAD_SOURCE); switch (entity->vsp1->version & VI6_IP_VERSION_SOC_MASK) { case VI6_IP_VERSION_MODEL_VSPD_GEN2: case VI6_IP_VERSION_MODEL_VSPD_V2H: hbth = 1536; obth = min(128U, (format->width + 1) / 2 * format->height - 4); lbth = 1520; break; case VI6_IP_VERSION_MODEL_VSPDL_GEN3: case VI6_IP_VERSION_MODEL_VSPD_V3: hbth = 0; obth = 1500; lbth = 0; break; case VI6_IP_VERSION_MODEL_VSPD_GEN3: default: hbth = 0; obth = 3000; lbth = 0; break; } vsp1_lif_write(lif, dlb, VI6_LIF_CSBTH, (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | (lbth << VI6_LIF_CSBTH_LBTH_SHIFT)); vsp1_lif_write(lif, dlb, VI6_LIF_CTRL, (obth << VI6_LIF_CTRL_OBTH_SHIFT) | (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); /* * On R-Car V3M the LIF0 buffer attribute register has to be set to a * non-default value to guarantee proper operation (otherwise artifacts * may appear on the output). The value required by the manual is not * explained but is likely a buffer size or threshold. */ if ((entity->vsp1->version & VI6_IP_VERSION_MASK) == (VI6_IP_VERSION_MODEL_VSPD_V3 | VI6_IP_VERSION_SOC_V3M)) vsp1_lif_write(lif, dlb, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 | (1536 << VI6_LIF_LBA_LBA1_SHIFT)); }
static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lif *lif = to_lif(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which); if (!config) return -EINVAL; /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad); if (fmt->pad == LIF_PAD_SOURCE) { /* The LIF source format is always identical to its sink * format. */ fmt->format = *format; return 0; } format->code = fmt->format.code; format->width = clamp_t(unsigned int, fmt->format.width, LIF_MIN_SIZE, LIF_MAX_SIZE); format->height = clamp_t(unsigned int, fmt->format.height, LIF_MIN_SIZE, LIF_MAX_SIZE); format->field = V4L2_FIELD_NONE; format->colorspace = V4L2_COLORSPACE_SRGB; fmt->format = *format; /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&lif->entity, config, LIF_PAD_SOURCE); *format = fmt->format; return 0; }
static int clu_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_clu *clu = to_clu(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which); if (!config) return -EINVAL; /* Default to YUV if the requested format is not supported. */ if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad); if (fmt->pad == CLU_PAD_SOURCE) { /* The CLU output format can't be modified. */ fmt->format = *format; return 0; } format->code = fmt->format.code; format->width = clamp_t(unsigned int, fmt->format.width, CLU_MIN_SIZE, CLU_MAX_SIZE); format->height = clamp_t(unsigned int, fmt->format.height, CLU_MIN_SIZE, CLU_MAX_SIZE); format->field = V4L2_FIELD_NONE; format->colorspace = V4L2_COLORSPACE_SRGB; fmt->format = *format; /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&clu->entity, config, CLU_PAD_SOURCE); *format = fmt->format; return 0; }
int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad, fmt->which); return 0; }
static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_lut *lut = to_lut(subdev); fmt->format = *vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad, fmt->which); return 0; }
static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad, fmt->which); return 0; }
static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); fmt->format = *vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad, fmt->which); return 0; }
static int hsit_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_hsit *hsit = to_hsit(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; config = vsp1_entity_get_pad_config(&hsit->entity, cfg, fmt->which); if (!config) return -EINVAL; format = vsp1_entity_get_pad_format(&hsit->entity, config, fmt->pad); if (fmt->pad == HSIT_PAD_SOURCE) { /* The HST and HSI output format code and resolution can't be * modified. */ fmt->format = *format; return 0; } format->code = hsit->inverse ? MEDIA_BUS_FMT_AHSV8888_1X32 : MEDIA_BUS_FMT_ARGB8888_1X32; format->width = clamp_t(unsigned int, fmt->format.width, HSIT_MIN_SIZE, HSIT_MAX_SIZE); format->height = clamp_t(unsigned int, fmt->format.height, HSIT_MIN_SIZE, HSIT_MAX_SIZE); format->field = V4L2_FIELD_NONE; format->colorspace = V4L2_COLORSPACE_SRGB; fmt->format = *format; /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&hsit->entity, config, HSIT_PAD_SOURCE); *format = fmt->format; format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32 : MEDIA_BUS_FMT_AHSV8888_1X32; return 0; }
static int hsit_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) { struct vsp1_hsit *hsit = to_hsit(subdev); fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad, fmt->which); return 0; }
static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_uds *uds = to_uds(subdev); struct v4l2_mbus_framefmt *format; uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which); format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad, fmt->which); *format = fmt->format; if (fmt->pad == UDS_PAD_SINK) { /* Propagate the format to the source pad. */ format = vsp1_entity_get_pad_format(&uds->entity, cfg, UDS_PAD_SOURCE, fmt->which); *format = fmt->format; uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which); } return 0; }
static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct vsp1_bru *bru = to_bru(subdev); struct v4l2_mbus_framefmt *format; bru_try_format(bru, cfg, fmt->pad, &fmt->format, fmt->which); format = vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad, fmt->which); *format = fmt->format; /* Reset the compose rectangle */ if (fmt->pad != bru->entity.source_pad) { struct v4l2_rect *compose; compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which); compose->left = 0; compose->top = 0; compose->width = format->width; compose->height = format->height; } /* Propagate the format code to all pads */ if (fmt->pad == BRU_PAD_SINK(0)) { unsigned int i; for (i = 0; i <= bru->entity.source_pad; ++i) { format = vsp1_entity_get_pad_format(&bru->entity, cfg, i, fmt->which); format->code = fmt->format.code; } } return 0; }
static void clu_configure(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_list *dl, bool full) { struct vsp1_clu *clu = to_clu(&entity->subdev); struct vsp1_dl_body *dlb; unsigned long flags; u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN; /* The format can't be changed during streaming, only verify it at * stream start and store the information internally for future partial * reconfiguration calls. */ if (full) { struct v4l2_mbus_framefmt *format; format = vsp1_entity_get_pad_format(&clu->entity, clu->entity.config, CLU_PAD_SINK); clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32; return; } /* 2D mode can only be used with the YCbCr pixel encoding. */ if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode) ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D; vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl); spin_lock_irqsave(&clu->lock, flags); dlb = clu->clu; clu->clu = NULL; spin_unlock_irqrestore(&clu->lock, flags); if (dlb) vsp1_dl_list_add_fragment(dl, dlb); }
int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { struct vsp1_rwpf *rwpf = to_rwpf(subdev); struct v4l2_mbus_framefmt *format; struct v4l2_rect *crop; /* Cropping is implemented on the sink pad. */ if (sel->pad != RWPF_PAD_SINK) return -EINVAL; if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; /* Make sure the crop rectangle is entirely contained in the image. The * WPF top and left offsets are limited to 255. */ format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SINK, sel->which); /* Restrict the crop rectangle coordinates to multiples of 2 to avoid * shifting the color plane. */ if (format->code == MEDIA_BUS_FMT_AYUV8_1X32) { sel->r.left = ALIGN(sel->r.left, 2); sel->r.top = ALIGN(sel->r.top, 2); sel->r.width = round_down(sel->r.width, 2); sel->r.height = round_down(sel->r.height, 2); } sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2); sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2); if (rwpf->entity.type == VSP1_ENTITY_WPF) { sel->r.left = min_t(unsigned int, sel->r.left, 255); sel->r.top = min_t(unsigned int, sel->r.top, 255); }