mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
staging: bcm2835_codec: Add support for the ISP as an M2M device
The MMAL ISP component can also use this same V4L2 wrapper to provide a M2M format conversion and resizer. Instantiate 3 V4L2 devices now, one for each of decode, encode, and isp. The ISP currently doesn't expose any controls via V4L2, but this can be extended in the future. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
This commit is contained in:
committed by
popcornmix
parent
5eb70b12e3
commit
f06f2971be
@@ -54,10 +54,26 @@ static int encode_video_nr = 11;
|
|||||||
module_param(encode_video_nr, int, 0644);
|
module_param(encode_video_nr, int, 0644);
|
||||||
MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
|
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;
|
static unsigned int debug;
|
||||||
module_param(debug, uint, 0644);
|
module_param(debug, uint, 0644);
|
||||||
MODULE_PARM_DESC(debug, "activates debug info (0-3)");
|
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_W 32
|
||||||
#define MIN_H 32
|
#define MIN_H 32
|
||||||
#define MAX_W 1920
|
#define MAX_W 1920
|
||||||
@@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
|
|||||||
atomic_t num_inst;
|
atomic_t num_inst;
|
||||||
|
|
||||||
/* allocated mmal instance and components */
|
/* 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. */
|
/* The list of formats supported on input and output queues. */
|
||||||
struct bcm2835_codec_fmt_list supported_fmts[2];
|
struct bcm2835_codec_fmt_list supported_fmts[2];
|
||||||
|
|
||||||
@@ -558,7 +574,7 @@ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
|
|||||||
port->es.video.frame_rate.den = 1;
|
port->es.video.frame_rate.den = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Compressed format - leave resolution as 0 for decode */
|
/* 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.width = 0;
|
||||||
port->es.video.height = 0;
|
port->es.video.height = 0;
|
||||||
port->es.video.crop.width = 0;
|
port->es.video.crop.width = 0;
|
||||||
@@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
|
|||||||
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
|
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
|
||||||
q_data->bytesperline, q_data->sizeimage);
|
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) {
|
f->fmt.pix.width && f->fmt.pix.height) {
|
||||||
/*
|
/*
|
||||||
* On the decoder, if provided with a resolution on the input
|
* On the decoder, if provided with a resolution on the input
|
||||||
@@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct file *file, void *priv,
|
|||||||
bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
|
bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
|
||||||
true : false;
|
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. */
|
/* OUTPUT on decoder and CAPTURE on encoder are not valid. */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct file *file, void *priv,
|
|||||||
if (!q_data)
|
if (!q_data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ctx->dev->decode) {
|
switch (ctx->dev->role) {
|
||||||
|
case DECODE:
|
||||||
switch (s->target) {
|
switch (s->target) {
|
||||||
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
|
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
|
||||||
case V4L2_SEL_TGT_COMPOSE:
|
case V4L2_SEL_TGT_COMPOSE:
|
||||||
@@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct file *file, void *priv,
|
|||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
case ENCODE:
|
||||||
switch (s->target) {
|
switch (s->target) {
|
||||||
case V4L2_SEL_TGT_CROP_DEFAULT:
|
case V4L2_SEL_TGT_CROP_DEFAULT:
|
||||||
case V4L2_SEL_TGT_CROP_BOUNDS:
|
case V4L2_SEL_TGT_CROP_BOUNDS:
|
||||||
@@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct file *file, void *priv,
|
|||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case ISP:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
|||||||
__func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
|
__func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
|
||||||
s->r.width, s->r.height);
|
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. */
|
/* OUTPUT on decoder and CAPTURE on encoder are not valid. */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
|||||||
if (!q_data)
|
if (!q_data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ctx->dev->decode) {
|
switch (ctx->dev->role) {
|
||||||
|
case DECODE:
|
||||||
switch (s->target) {
|
switch (s->target) {
|
||||||
case V4L2_SEL_TGT_COMPOSE:
|
case V4L2_SEL_TGT_COMPOSE:
|
||||||
/* Accept cropped image */
|
/* Accept cropped image */
|
||||||
@@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
|||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
case ENCODE:
|
||||||
switch (s->target) {
|
switch (s->target) {
|
||||||
case V4L2_SEL_TGT_CROP:
|
case V4L2_SEL_TGT_CROP:
|
||||||
/* Only support crop from (0,0) */
|
/* Only support crop from (0,0) */
|
||||||
@@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct file *file, void *priv,
|
|||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case ISP:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct file *file, void *priv,
|
|||||||
{
|
{
|
||||||
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||||
|
|
||||||
if (!ctx->dev->decode)
|
if (ctx->dev->role != DECODE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (cmd->cmd) {
|
switch (cmd->cmd) {
|
||||||
@@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct file *file, void *priv,
|
|||||||
{
|
{
|
||||||
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
struct bcm2835_codec_ctx *ctx = file2ctx(file);
|
||||||
|
|
||||||
if (ctx->dev->decode)
|
if (ctx->dev->role != ENCODE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (cmd->cmd) {
|
switch (cmd->cmd) {
|
||||||
@@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
|
|||||||
unsigned int enable = 1;
|
unsigned int enable = 1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
|
ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
|
||||||
"ril.video_decode" : "ril.video_encode",
|
|
||||||
&ctx->component);
|
&ctx->component);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
|
v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
|
||||||
__func__, dev->decode ? "decode" : "encode");
|
__func__, components[dev->role]);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto destroy_component;
|
goto destroy_component;
|
||||||
|
|
||||||
if (dev->decode) {
|
if (dev->role == ENCODE) {
|
||||||
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 (ctx->q_data[V4L2_M2M_SRC].sizeimage <
|
if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
|
||||||
ctx->component->output[0].minimum_buffer.size)
|
ctx->component->output[0].minimum_buffer.size)
|
||||||
v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
|
v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
|
||||||
@@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
|
|||||||
|
|
||||||
/* Now we have a component we can set all the ctrls */
|
/* Now we have a component we can set all the ctrls */
|
||||||
bcm2835_codec_set_ctrls(ctx);
|
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;
|
return 0;
|
||||||
@@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct file *file)
|
|||||||
struct v4l2_ctrl_handler *hdl;
|
struct v4l2_ctrl_handler *hdl;
|
||||||
int rc = 0;
|
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)) {
|
if (mutex_lock_interruptible(&dev->dev_mutex)) {
|
||||||
v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
|
v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
@@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct file *file)
|
|||||||
|
|
||||||
ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
|
ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
|
||||||
ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
|
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
|
* Input width and height are irrelevant as they will be defined
|
||||||
* by the bitstream not the format. Required by V4L2 though.
|
* by the bitstream not the format. Required by V4L2 though.
|
||||||
@@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct file *file)
|
|||||||
get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
|
get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
|
||||||
ctx->q_data[V4L2_M2M_DST].height,
|
ctx->q_data[V4L2_M2M_DST].height,
|
||||||
ctx->q_data[V4L2_M2M_DST].fmt);
|
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_width = DEFAULT_WIDTH;
|
||||||
ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
|
ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
|
||||||
ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
|
ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
|
||||||
@@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct file *file)
|
|||||||
ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
|
ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
|
||||||
ctx->q_data[V4L2_M2M_DST].sizeimage =
|
ctx->q_data[V4L2_M2M_DST].sizeimage =
|
||||||
DEF_COMP_BUF_SIZE_720P_OR_LESS;
|
DEF_COMP_BUF_SIZE_720P_OR_LESS;
|
||||||
|
break;
|
||||||
|
case ISP:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
||||||
@@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct file *file)
|
|||||||
file->private_data = &ctx->fh;
|
file->private_data = &ctx->fh;
|
||||||
ctx->dev = dev;
|
ctx->dev = dev;
|
||||||
hdl = &ctx->hdl;
|
hdl = &ctx->hdl;
|
||||||
if (!dev->decode) {
|
if (dev->role == ENCODE) {
|
||||||
/* Encode controls */
|
/* Encode controls */
|
||||||
v4l2_ctrl_handler_init(hdl, 6);
|
v4l2_ctrl_handler_init(hdl, 6);
|
||||||
|
|
||||||
@@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
|
|||||||
unsigned int i, j, num_encodings;
|
unsigned int i, j, num_encodings;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = vchiq_mmal_component_init(dev->instance,
|
ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
|
||||||
dev->decode ?
|
|
||||||
"ril.video_decode" :
|
|
||||||
"ril.video_encode",
|
|
||||||
&component);
|
&component);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
|
v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
|
||||||
__func__);
|
__func__, components[dev->role]);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2406,12 +2434,13 @@ destroy_component:
|
|||||||
|
|
||||||
static int bcm2835_codec_create(struct platform_device *pdev,
|
static int bcm2835_codec_create(struct platform_device *pdev,
|
||||||
struct bcm2835_codec_dev **new_dev,
|
struct bcm2835_codec_dev **new_dev,
|
||||||
bool decode)
|
enum bcm2835_codec_role role)
|
||||||
{
|
{
|
||||||
struct bcm2835_codec_dev *dev;
|
struct bcm2835_codec_dev *dev;
|
||||||
struct video_device *vfd;
|
struct video_device *vfd;
|
||||||
int video_nr;
|
int video_nr;
|
||||||
int ret;
|
int ret;
|
||||||
|
const static char *roles[] = {"decode", "encode", "isp"};
|
||||||
|
|
||||||
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
@@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
|||||||
|
|
||||||
dev->pdev = pdev;
|
dev->pdev = pdev;
|
||||||
|
|
||||||
dev->decode = decode;
|
dev->role = role;
|
||||||
|
|
||||||
ret = vchiq_mmal_init(&dev->instance);
|
ret = vchiq_mmal_init(&dev->instance);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
|||||||
vfd->lock = &dev->dev_mutex;
|
vfd->lock = &dev->dev_mutex;
|
||||||
vfd->v4l2_dev = &dev->v4l2_dev;
|
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_ENCODER_CMD);
|
||||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
||||||
video_nr = decode_video_nr;
|
video_nr = decode_video_nr;
|
||||||
} else {
|
break;
|
||||||
|
case ENCODE:
|
||||||
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
|
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
|
||||||
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
|
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
|
||||||
video_nr = encode_video_nr;
|
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);
|
ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
|
||||||
@@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct platform_device *pdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
|
v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
|
||||||
dev->decode ? "decode" : "encode");
|
roles[role]);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_m2m:
|
err_m2m:
|
||||||
@@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct platform_device *pdev)
|
|||||||
if (!drv)
|
if (!drv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = bcm2835_codec_create(pdev, &drv->encode, false);
|
ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -2526,6 +2572,10 @@ out:
|
|||||||
bcm2835_codec_destroy(drv->encode);
|
bcm2835_codec_destroy(drv->encode);
|
||||||
drv->encode = NULL;
|
drv->encode = NULL;
|
||||||
}
|
}
|
||||||
|
if (drv->decode) {
|
||||||
|
bcm2835_codec_destroy(drv->decode);
|
||||||
|
drv->decode = NULL;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
|
struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
bcm2835_codec_destroy(drv->isp);
|
||||||
|
|
||||||
bcm2835_codec_destroy(drv->encode);
|
bcm2835_codec_destroy(drv->encode);
|
||||||
|
|
||||||
bcm2835_codec_destroy(drv->decode);
|
bcm2835_codec_destroy(drv->decode);
|
||||||
|
|||||||
Reference in New Issue
Block a user