module_param(encode_video_nr, int, 0644);
MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
+static int isp_video_nr = 12;
+module_param(isp_video_nr, int, 0644);
+MODULE_PARM_DESC(isp_video_nr, "isp video device number");
+
static unsigned int debug;
module_param(debug, uint, 0644);
MODULE_PARM_DESC(debug, "activates debug info (0-3)");
+enum bcm2835_codec_role {
+ DECODE,
+ ENCODE,
+ ISP,
+};
+
+static const char * const components[] = {
+ "ril.video_decode",
+ "ril.video_encode",
+ "ril.isp",
+};
+
#define MIN_W 32
#define MIN_H 32
#define MAX_W 1920
atomic_t num_inst;
/* allocated mmal instance and components */
- bool decode; /* Is this instance a decoder? */
+ enum bcm2835_codec_role role;
/* The list of formats supported on input and output queues. */
struct bcm2835_codec_fmt_list supported_fmts[2];
port->es.video.frame_rate.den = 1;
} else {
/* Compressed format - leave resolution as 0 for decode */
- if (ctx->dev->decode) {
+ if (ctx->dev->role == DECODE) {
port->es.video.width = 0;
port->es.video.height = 0;
port->es.video.crop.width = 0;
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
q_data->bytesperline, q_data->sizeimage);
- if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
+ if (ctx->dev->role == DECODE &&
+ q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
f->fmt.pix.width && f->fmt.pix.height) {
/*
* On the decoder, if provided with a resolution on the input
bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
true : false;
- if (capture_queue ^ ctx->dev->decode)
+ if ((ctx->dev->role == DECODE && !capture_queue) ||
+ (ctx->dev->role == ENCODE && capture_queue))
/* OUTPUT on decoder and CAPTURE on encoder are not valid. */
return -EINVAL;
if (!q_data)
return -EINVAL;
- if (ctx->dev->decode) {
+ switch (ctx->dev->role) {
+ case DECODE:
switch (s->target) {
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
case V4L2_SEL_TGT_COMPOSE:
default:
return -EINVAL;
}
- } else {
+ break;
+ case ENCODE:
switch (s->target) {
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP_BOUNDS:
default:
return -EINVAL;
}
+ break;
+ case ISP:
+ break;
}
return 0;
__func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
s->r.width, s->r.height);
- if (capture_queue ^ ctx->dev->decode)
+ if ((ctx->dev->role == DECODE && !capture_queue) ||
+ (ctx->dev->role == ENCODE && capture_queue))
/* OUTPUT on decoder and CAPTURE on encoder are not valid. */
return -EINVAL;
if (!q_data)
return -EINVAL;
- if (ctx->dev->decode) {
+ switch (ctx->dev->role) {
+ case DECODE:
switch (s->target) {
case V4L2_SEL_TGT_COMPOSE:
/* Accept cropped image */
default:
return -EINVAL;
}
- } else {
+ break;
+ case ENCODE:
switch (s->target) {
case V4L2_SEL_TGT_CROP:
/* Only support crop from (0,0) */
default:
return -EINVAL;
}
+ break;
+ case ISP:
+ break;
}
return 0;
{
struct bcm2835_codec_ctx *ctx = file2ctx(file);
- if (!ctx->dev->decode)
+ if (ctx->dev->role != DECODE)
return -EINVAL;
switch (cmd->cmd) {
{
struct bcm2835_codec_ctx *ctx = file2ctx(file);
- if (ctx->dev->decode)
+ if (ctx->dev->role != ENCODE)
return -EINVAL;
switch (cmd->cmd) {
unsigned int enable = 1;
int ret;
- ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
- "ril.video_decode" : "ril.video_encode",
+ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
&ctx->component);
if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
- __func__, dev->decode ? "decode" : "encode");
+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
+ __func__, components[dev->role]);
return -ENOMEM;
}
if (ret < 0)
goto destroy_component;
- if (dev->decode) {
- if (ctx->q_data[V4L2_M2M_DST].sizeimage <
- ctx->component->output[0].minimum_buffer.size)
- v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
- ctx->q_data[V4L2_M2M_DST].sizeimage,
- ctx->component->output[0].minimum_buffer.size);
- } else {
+ if (dev->role == ENCODE) {
if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
ctx->component->output[0].minimum_buffer.size)
v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
/* Now we have a component we can set all the ctrls */
bcm2835_codec_set_ctrls(ctx);
+ } else {
+ if (ctx->q_data[V4L2_M2M_DST].sizeimage <
+ ctx->component->output[0].minimum_buffer.size)
+ v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
+ ctx->q_data[V4L2_M2M_DST].sizeimage,
+ ctx->component->output[0].minimum_buffer.size);
}
return 0;
struct v4l2_ctrl_handler *hdl;
int rc = 0;
- v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
- dev->decode ? "decode" : "encode");
if (mutex_lock_interruptible(&dev->dev_mutex)) {
v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
return -ERESTARTSYS;
ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
- if (dev->decode) {
+ switch (dev->role) {
+ case DECODE:
/*
* Input width and height are irrelevant as they will be defined
* by the bitstream not the format. Required by V4L2 though.
get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
ctx->q_data[V4L2_M2M_DST].height,
ctx->q_data[V4L2_M2M_DST].fmt);
- } else {
+ break;
+ case ENCODE:
ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
ctx->q_data[V4L2_M2M_DST].sizeimage =
DEF_COMP_BUF_SIZE_720P_OR_LESS;
+ break;
+ case ISP:
+ break;
}
ctx->colorspace = V4L2_COLORSPACE_REC709;
file->private_data = &ctx->fh;
ctx->dev = dev;
hdl = &ctx->hdl;
- if (!dev->decode) {
+ if (dev->role == ENCODE) {
/* Encode controls */
v4l2_ctrl_handler_init(hdl, 6);
unsigned int i, j, num_encodings;
int ret;
- ret = vchiq_mmal_component_init(dev->instance,
- dev->decode ?
- "ril.video_decode" :
- "ril.video_encode",
+ ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
&component);
if (ret < 0) {
- v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
- __func__);
+ v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
+ __func__, components[dev->role]);
return -ENOMEM;
}
static int bcm2835_codec_create(struct platform_device *pdev,
struct bcm2835_codec_dev **new_dev,
- bool decode)
+ enum bcm2835_codec_role role)
{
struct bcm2835_codec_dev *dev;
struct video_device *vfd;
int video_nr;
int ret;
+ const static char *roles[] = {"decode", "encode", "isp"};
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
dev->pdev = pdev;
- dev->decode = decode;
+ dev->role = role;
ret = vchiq_mmal_init(&dev->instance);
if (ret)
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
- if (dev->decode) {
+ switch (role) {
+ case DECODE:
v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
video_nr = decode_video_nr;
- } else {
+ break;
+ case ENCODE:
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
video_nr = encode_video_nr;
+ break;
+ case ISP:
+ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
+ video_nr = isp_video_nr;
+ break;
+ default:
+ ret = -EINVAL;
+ goto unreg_dev;
}
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
}
v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
- dev->decode ? "decode" : "encode");
+ roles[role]);
return 0;
err_m2m:
if (!drv)
return -ENOMEM;
- ret = bcm2835_codec_create(pdev, &drv->encode, false);
+ ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
if (ret)
goto out;
- ret = bcm2835_codec_create(pdev, &drv->decode, true);
+ ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
+ if (ret)
+ goto out;
+
+ ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
if (ret)
goto out;
bcm2835_codec_destroy(drv->encode);
drv->encode = NULL;
}
+ if (drv->decode) {
+ bcm2835_codec_destroy(drv->decode);
+ drv->decode = NULL;
+ }
return ret;
}
{
struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
+ bcm2835_codec_destroy(drv->isp);
+
bcm2835_codec_destroy(drv->encode);
bcm2835_codec_destroy(drv->decode);