static void rpf_configure_frame(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb) { struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); vsp1_rpf_write(rpf, dlb, VI6_RPF_VRTCOL_SET, rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); vsp1_rpf_write(rpf, dlb, VI6_RPF_MULT_ALPHA, rpf->mult_alpha | (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT)); vsp1_pipeline_propagate_alpha(pipe, dlb, rpf->alpha); }
static int rpf_s_ctrl(struct v4l2_ctrl *ctrl) { struct vsp1_rwpf *rpf = container_of(ctrl->handler, struct vsp1_rwpf, ctrls); struct vsp1_pipeline *pipe; if (!vsp1_entity_is_streaming(&rpf->entity)) return 0; switch (ctrl->id) { case V4L2_CID_ALPHA_COMPONENT: vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity); vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val); break; } return 0; }
static int rpf_s_stream(struct v4l2_subdev *subdev, int enable) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_rwpf *rpf = to_rwpf(subdev); struct vsp1_device *vsp1 = rpf->entity.vsp1; const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; const struct v4l2_pix_format_mplane *format = &rpf->format; const struct v4l2_rect *crop = &rpf->crop; u32 pstride; u32 infmt; int ret; ret = vsp1_entity_set_streaming(&rpf->entity, enable); if (ret < 0) return ret; if (!enable) return 0; /* Source size, stride and crop offsets. * * The crop offsets correspond to the location of the crop rectangle top * left corner in the plane buffer. Only two offsets are needed, as * planes 2 and 3 always have identical strides. */ vsp1_rpf_write(rpf, VI6_RPF_SRC_BSIZE, (crop->width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | (crop->height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); vsp1_rpf_write(rpf, VI6_RPF_SRC_ESIZE, (crop->width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | (crop->height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); rpf->offsets[0] = crop->top * format->plane_fmt[0].bytesperline + crop->left * fmtinfo->bpp[0] / 8; pstride = format->plane_fmt[0].bytesperline << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y, rpf->buf_addr[0] + rpf->offsets[0]); if (format->num_planes > 1) { rpf->offsets[1] = crop->top * format->plane_fmt[1].bytesperline + crop->left * fmtinfo->bpp[1] / 8; pstride |= format->plane_fmt[1].bytesperline << VI6_RPF_SRCM_PSTRIDE_C_SHIFT; vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0, rpf->buf_addr[1] + rpf->offsets[1]); if (format->num_planes > 2) vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1, rpf->buf_addr[2] + rpf->offsets[1]); } vsp1_rpf_write(rpf, VI6_RPF_SRCM_PSTRIDE, pstride); /* Format */ infmt = VI6_RPF_INFMT_CIPM | (fmtinfo->hwfmt << VI6_RPF_INFMT_RDFMT_SHIFT); if (fmtinfo->swap_yc) infmt |= VI6_RPF_INFMT_SPYCS; if (fmtinfo->swap_uv) infmt |= VI6_RPF_INFMT_SPUVS; if (rpf->entity.formats[RWPF_PAD_SINK].code != rpf->entity.formats[RWPF_PAD_SOURCE].code) infmt |= VI6_RPF_INFMT_CSC; vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt); vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap); /* Output location */ vsp1_rpf_write(rpf, VI6_RPF_LOC, (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) | (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT)); /* Use the alpha channel (extended to 8 bits) when available or an * alpha value set through the V4L2_CID_ALPHA_COMPONENT control * otherwise. Disable color keying. */ vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT | (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED : VI6_RPF_ALPH_SEL_ASEL_FIXED)); if (vsp1->info->uapi) mutex_lock(rpf->ctrls.lock); vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET, rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val); if (vsp1->info->uapi) mutex_unlock(rpf->ctrls.lock); vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0); vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0); return 0; }