static int bru_s_stream(struct v4l2_subdev *subdev, int enable) { struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity); struct vsp1_bru *bru = to_bru(subdev); struct v4l2_mbus_framefmt *format; unsigned int flags; unsigned int i; int ret; ret = vsp1_entity_set_streaming(&bru->entity, enable); if (ret < 0) return ret; if (!enable) return 0; format = &bru->entity.formats[bru->entity.source_pad]; /* The hardware is extremely flexible but we have no userspace API to * expose all the parameters, nor is it clear whether we would have use * cases for all the supported modes. Let's just harcode the parameters * to sane default values for now. */ /* Disable dithering and enable color data normalization unless the * format at the pipeline output is premultiplied. */ flags = pipe->output ? pipe->output->format.flags : 0; vsp1_bru_write(bru, VI6_BRU_INCTRL, flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? 0 : VI6_BRU_INCTRL_NRM); /* Set the background position to cover the whole output image. */ vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE, (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0); /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP * unit with a NOP operation to make BRU input 1 available as the * Blend/ROP unit B SRC input. */ vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | VI6_BRU_ROP_CROP(VI6_ROP_NOP) | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); for (i = 0; i < bru->entity.source_pad; ++i) { bool premultiplied = false; u32 ctrl = 0; /* Configure all Blend/ROP units corresponding to an enabled BRU * input for alpha blending. Blend/ROP units corresponding to * disabled BRU inputs are used in ROP NOP mode to ignore the * SRC input. */ if (bru->inputs[i].rpf) { ctrl |= VI6_BRU_CTRL_RBC; premultiplied = bru->inputs[i].rpf->format.flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; } else { ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); } /* Select the virtual RPF as the Blend/ROP unit A DST input to * serve as a background color. */ if (i == 0) ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF; /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to * D in that order. The Blend/ROP unit B SRC is hardwired to the * ROP unit output, the corresponding register bits must be set * to 0. */ if (i != 1) ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl); /* Harcode the blending formula to * * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa * DSTa = DSTa * (1 - SRCa) + SRCa * * when the SRC input isn't premultiplied, and to * * DSTc = DSTc * (1 - SRCa) + SRCc * DSTa = DSTa * (1 - SRCa) + SRCa * * otherwise. */ vsp1_bru_write(bru, VI6_BRU_BLD(i), VI6_BRU_BLD_CCMDX_255_SRC_A | (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : VI6_BRU_BLD_CCMDY_SRC_A) | VI6_BRU_BLD_ACMDX_255_SRC_A | VI6_BRU_BLD_ACMDY_COEFY | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); } return 0; }
static void brx_configure_stream(struct vsp1_entity *entity, struct vsp1_pipeline *pipe, struct vsp1_dl_body *dlb) { struct vsp1_brx *brx = to_brx(&entity->subdev); struct v4l2_mbus_framefmt *format; unsigned int flags; unsigned int i; format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config, brx->entity.source_pad); /* * The hardware is extremely flexible but we have no userspace API to * expose all the parameters, nor is it clear whether we would have use * cases for all the supported modes. Let's just harcode the parameters * to sane default values for now. */ /* * Disable dithering and enable color data normalization unless the * format at the pipeline output is premultiplied. */ flags = pipe->output ? pipe->output->format.flags : 0; vsp1_brx_write(brx, dlb, VI6_BRU_INCTRL, flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ? 0 : VI6_BRU_INCTRL_NRM); /* * Set the background position to cover the whole output image and * configure its color. */ vsp1_brx_write(brx, dlb, VI6_BRU_VIRRPF_SIZE, (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) | (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT)); vsp1_brx_write(brx, dlb, VI6_BRU_VIRRPF_LOC, 0); vsp1_brx_write(brx, dlb, VI6_BRU_VIRRPF_COL, brx->bgcolor | (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT)); /* * Route BRU input 1 as SRC input to the ROP unit and configure the ROP * unit with a NOP operation to make BRU input 1 available as the * Blend/ROP unit B SRC input. Only needed for BRU, the BRS has no ROP * unit. */ if (entity->type == VSP1_ENTITY_BRU) vsp1_brx_write(brx, dlb, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) | VI6_BRU_ROP_CROP(VI6_ROP_NOP) | VI6_BRU_ROP_AROP(VI6_ROP_NOP)); for (i = 0; i < brx->entity.source_pad; ++i) { bool premultiplied = false; u32 ctrl = 0; /* * Configure all Blend/ROP units corresponding to an enabled BRx * input for alpha blending. Blend/ROP units corresponding to * disabled BRx inputs are used in ROP NOP mode to ignore the * SRC input. */ if (brx->inputs[i].rpf) { ctrl |= VI6_BRU_CTRL_RBC; premultiplied = brx->inputs[i].rpf->format.flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; } else { ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); } /* * Select the virtual RPF as the Blend/ROP unit A DST input to * serve as a background color. */ if (i == 0) ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF; /* * Route inputs 0 to 3 as SRC inputs to Blend/ROP units A to D * in that order. In the BRU the Blend/ROP unit B SRC is * hardwired to the ROP unit output, the corresponding register * bits must be set to 0. The BRS has no ROP unit and doesn't * need any special processing. */ if (!(entity->type == VSP1_ENTITY_BRU && i == 1)) ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); vsp1_brx_write(brx, dlb, VI6_BRU_CTRL(i), ctrl); /* * Harcode the blending formula to * * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa * DSTa = DSTa * (1 - SRCa) + SRCa * * when the SRC input isn't premultiplied, and to * * DSTc = DSTc * (1 - SRCa) + SRCc * DSTa = DSTa * (1 - SRCa) + SRCa * * otherwise. */ vsp1_brx_write(brx, dlb, VI6_BRU_BLD(i), VI6_BRU_BLD_CCMDX_255_SRC_A | (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : VI6_BRU_BLD_CCMDY_SRC_A) | VI6_BRU_BLD_ACMDX_255_SRC_A | VI6_BRU_BLD_ACMDY_COEFY | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); } }