Merge tag 'media/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:
 - new DVB frontend drivers: ascot2e, cxd2841er, horus3a, lnbh25
 - new HDMI capture driver: tc358743
 - new driver for NetUP DVB new boards (netup_unidvb)
 - IR support for DVBSky cards (smipcie-ir)
 - Coda driver has gain macroblock tiling support
 - Renesas R-Car gains JPEG codec driver
 - new DVB platform driver for STi boards: c8sectpfe
 - added documentation for the media core kABI to device-drivers DocBook
 - lots of driver fixups, cleanups and improvements

* tag 'media/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (297 commits)
  [media] c8sectpfe: Remove select on undefined LIBELF_32
  [media] i2c: fix platform_no_drv_owner.cocci warnings
  [media] cx231xx: Use wake_up_interruptible() instead of wake_up_interruptible_nr()
  [media] tc358743: only queue subdev notifications if devnode is set
  [media] tc358743: add missing Kconfig dependency/select
  [media] c8sectpfe: Use %pad to print 'dma_addr_t'
  [media] DocBook media: Fix typo "the the" in xml files
  [media] tc358743: make reset gpio optional
  [media] tc358743: set direction of reset gpio using devm_gpiod_get
  [media] dvbdev: document most of the functions/data structs
  [media] dvb_frontend.h: document the struct dvb_frontend
  [media] dvb-frontend.h: document struct dtv_frontend_properties
  [media] dvb-frontend.h: document struct dvb_frontend_ops
  [media] dvb: Use DVBFE_ALGO_HW where applicable
  [media] dvb_frontend.h: document struct analog_demod_ops
  [media] dvb_frontend.h: Document struct dvb_tuner_ops
  [media] Docbook: Document struct analog_parameters
  [media] dvb_frontend.h: get rid of dvbfe_modcod
  [media] add documentation for struct dvb_tuner_info
  [media] dvb_frontend: document dvb_frontend_tune_settings
  ...
This commit is contained in:
Linus Torvalds
2015-09-05 18:21:14 -07:00
277 changed files with 18659 additions and 4356 deletions

View File

@@ -15,6 +15,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/gcd.h>
#include <linux/genalloc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -61,10 +62,9 @@ int coda_debug;
module_param(coda_debug, int, 0644);
MODULE_PARM_DESC(coda_debug, "Debug level (0-2)");
struct coda_fmt {
char *name;
u32 fourcc;
};
static int disable_tiling;
module_param(disable_tiling, int, 0644);
MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
void coda_write(struct coda_dev *dev, u32 data, u32 reg)
{
@@ -90,17 +90,17 @@ void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
u32 base_cb, base_cr;
switch (q_data->fourcc) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_YUV420:
default:
base_cb = base_y + q_data->bytesperline * q_data->height;
base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
break;
case V4L2_PIX_FMT_YVU420:
/* Switch Cb and Cr for YVU420 format */
base_cr = base_y + q_data->bytesperline * q_data->height;
base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_NV12:
default:
base_cb = base_y + q_data->bytesperline * q_data->height;
base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
break;
case V4L2_PIX_FMT_YUV422P:
base_cb = base_y + q_data->bytesperline * q_data->height;
base_cr = base_cb + q_data->bytesperline * q_data->height / 2;
@@ -111,40 +111,6 @@ void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
coda_write(ctx->dev, base_cr, reg_y + 8);
}
/*
* Array of all formats supported by any version of Coda:
*/
static const struct coda_fmt coda_formats[] = {
{
.name = "YUV 4:2:0 Planar, YCbCr",
.fourcc = V4L2_PIX_FMT_YUV420,
},
{
.name = "YUV 4:2:0 Planar, YCrCb",
.fourcc = V4L2_PIX_FMT_YVU420,
},
{
.name = "YUV 4:2:0 Partial interleaved Y/CbCr",
.fourcc = V4L2_PIX_FMT_NV12,
},
{
.name = "YUV 4:2:2 Planar, YCbCr",
.fourcc = V4L2_PIX_FMT_YUV422P,
},
{
.name = "H264 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H264,
},
{
.name = "MPEG4 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG4,
},
{
.name = "JPEG Encoded Images",
.fourcc = V4L2_PIX_FMT_JPEG,
},
};
#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \
{ mode, src_fourcc, dst_fourcc, max_w, max_h }
@@ -190,9 +156,9 @@ static const struct coda_video_device coda_bit_encoder = {
.type = CODA_INST_ENCODER,
.ops = &coda_bit_encode_ops,
.src_formats = {
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
},
.dst_formats = {
V4L2_PIX_FMT_H264,
@@ -205,9 +171,9 @@ static const struct coda_video_device coda_bit_jpeg_encoder = {
.type = CODA_INST_ENCODER,
.ops = &coda_bit_encode_ops,
.src_formats = {
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV422P,
},
.dst_formats = {
@@ -224,9 +190,9 @@ static const struct coda_video_device coda_bit_decoder = {
V4L2_PIX_FMT_MPEG4,
},
.dst_formats = {
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
},
};
@@ -238,9 +204,9 @@ static const struct coda_video_device coda_bit_jpeg_decoder = {
V4L2_PIX_FMT_JPEG,
},
.dst_formats = {
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
V4L2_PIX_FMT_YUV422P,
},
};
@@ -261,38 +227,21 @@ static const struct coda_video_device *coda9_video_devices[] = {
&coda_bit_decoder,
};
static bool coda_format_is_yuv(u32 fourcc)
{
switch (fourcc) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_YUV422P:
return true;
default:
return false;
}
}
static const char *coda_format_name(u32 fourcc)
{
int i;
for (i = 0; i < ARRAY_SIZE(coda_formats); i++) {
if (coda_formats[i].fourcc == fourcc)
return coda_formats[i].name;
}
return NULL;
}
/*
* Normalize all supported YUV 4:2:0 formats to the value used in the codec
* tables.
*/
static u32 coda_format_normalize_yuv(u32 fourcc)
{
return coda_format_is_yuv(fourcc) ? V4L2_PIX_FMT_YUV420 : fourcc;
switch (fourcc) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_YUV422P:
return V4L2_PIX_FMT_YUV420;
default:
return fourcc;
}
}
static const struct coda_codec *coda_find_codec(struct coda_dev *dev,
@@ -396,7 +345,6 @@ static int coda_enum_fmt(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
const struct coda_video_device *cvd = to_coda_video_device(vdev);
const u32 *formats;
const char *name;
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
formats = cvd->src_formats;
@@ -408,11 +356,7 @@ static int coda_enum_fmt(struct file *file, void *priv,
if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
return -EINVAL;
name = coda_format_name(formats[f->index]);
strlcpy(f->description, name, sizeof(f->description));
f->pixelformat = formats[f->index];
if (!coda_format_is_yuv(formats[f->index]))
f->flags |= V4L2_FMT_FLAG_COMPRESSED;
return 0;
}
@@ -504,9 +448,9 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
S_ALIGN);
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
/*
* Frame stride must be at least multiple of 8,
* but multiple of 16 for h.264 or JPEG 4:2:x
@@ -645,6 +589,22 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
q_data->rect.width = f->fmt.pix.width;
q_data->rect.height = f->fmt.pix.height;
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_NV12:
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
if (!disable_tiling)
break;
}
/* else fall through */
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
break;
default:
break;
}
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
f->type, q_data->width, q_data->height, q_data->fourcc);
@@ -831,6 +791,104 @@ static int coda_decoder_cmd(struct file *file, void *fh,
return 0;
}
static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
{
struct coda_ctx *ctx = fh_to_ctx(fh);
struct v4l2_fract *tpf;
if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return -EINVAL;
a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
tpf = &a->parm.output.timeperframe;
tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK;
tpf->numerator = 1 + (ctx->params.framerate >>
CODA_FRATE_DIV_OFFSET);
return 0;
}
/*
* Approximate timeperframe v4l2_fract with values that can be written
* into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields.
*/
static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe)
{
struct v4l2_fract s = *timeperframe;
struct v4l2_fract f0;
struct v4l2_fract f1 = { 1, 0 };
struct v4l2_fract f2 = { 0, 1 };
unsigned int i, div, s_denominator;
/* Lower bound is 1/65535 */
if (s.numerator == 0 || s.denominator / s.numerator > 65535) {
timeperframe->numerator = 1;
timeperframe->denominator = 65535;
return;
}
/* Upper bound is 65536/1, map everything above to infinity */
if (s.denominator == 0 || s.numerator / s.denominator > 65536) {
timeperframe->numerator = 1;
timeperframe->denominator = 0;
return;
}
/* Reduce fraction to lowest terms */
div = gcd(s.numerator, s.denominator);
if (div > 1) {
s.numerator /= div;
s.denominator /= div;
}
if (s.numerator <= 65536 && s.denominator < 65536) {
*timeperframe = s;
return;
}
/* Find successive convergents from continued fraction expansion */
while (f2.numerator <= 65536 && f2.denominator < 65536) {
f0 = f1;
f1 = f2;
/* Stop when f2 exactly equals timeperframe */
if (s.numerator == 0)
break;
i = s.denominator / s.numerator;
f2.numerator = f0.numerator + i * f1.numerator;
f2.denominator = f0.denominator + i * f2.denominator;
s_denominator = s.numerator;
s.numerator = s.denominator % s.numerator;
s.denominator = s_denominator;
}
*timeperframe = f1;
}
static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe)
{
return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) |
timeperframe->denominator;
}
static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
{
struct coda_ctx *ctx = fh_to_ctx(fh);
struct v4l2_fract *tpf;
if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return -EINVAL;
tpf = &a->parm.output.timeperframe;
coda_approximate_timeperframe(tpf);
ctx->params.framerate = coda_timeperframe_to_frate(tpf);
return 0;
}
static int coda_subscribe_event(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub)
{
@@ -871,31 +929,13 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
.vidioc_try_decoder_cmd = coda_try_decoder_cmd,
.vidioc_decoder_cmd = coda_decoder_cmd,
.vidioc_g_parm = coda_g_parm,
.vidioc_s_parm = coda_s_parm,
.vidioc_subscribe_event = coda_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
void coda_set_gdi_regs(struct coda_ctx *ctx)
{
struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
struct coda_dev *dev = ctx->dev;
int i;
for (i = 0; i < 16; i++)
coda_write(dev, tiled_map->xy2ca_map[i],
CODA9_GDI_XY2_CAS_0 + 4 * i);
for (i = 0; i < 4; i++)
coda_write(dev, tiled_map->xy2ba_map[i],
CODA9_GDI_XY2_BA_0 + 4 * i);
for (i = 0; i < 16; i++)
coda_write(dev, tiled_map->xy2ra_map[i],
CODA9_GDI_XY2_RAS_0 + 4 * i);
coda_write(dev, tiled_map->xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
for (i = 0; i < 32; i++)
coda_write(dev, tiled_map->rbc2axi_map[i],
CODA9_GDI_RBC2_AXI_0 + 4 * i);
}
/*
* Mem-to-mem operations.
*/
@@ -949,14 +989,14 @@ static void coda_pic_run_work(struct work_struct *work)
static int coda_job_ready(void *m2m_priv)
{
struct coda_ctx *ctx = m2m_priv;
int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
/*
* For both 'P' and 'key' frame cases 1 picture
* and 1 frame are needed. In the decoder case,
* the compressed frame can be in the bitstream.
*/
if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
ctx->inst_type != CODA_INST_DECODER) {
if (!src_bufs && ctx->inst_type != CODA_INST_DECODER) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"not ready: not enough video buffers.\n");
return 0;
@@ -969,27 +1009,17 @@ static int coda_job_ready(void *m2m_priv)
}
if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
struct list_head *meta;
bool stream_end;
int num_metas;
int src_bufs;
bool stream_end = ctx->bit_stream_param &
CODA_BIT_STREAM_END_FLAG;
int num_metas = ctx->num_metas;
if (ctx->hold && !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) {
if (ctx->hold && !src_bufs) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"%d: not ready: on hold for more buffers.\n",
ctx->idx);
return 0;
}
stream_end = ctx->bit_stream_param &
CODA_BIT_STREAM_END_FLAG;
num_metas = 0;
list_for_each(meta, &ctx->buffer_meta_list)
num_metas++;
src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
if (!stream_end && (num_metas + src_bufs) < 2) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"%d: not ready: need 2 buffers available (%d, %d)\n",
@@ -998,8 +1028,8 @@ static int coda_job_ready(void *m2m_priv)
}
if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
!stream_end && (coda_get_bitstream_payload(ctx) < 512)) {
if (!src_bufs && !stream_end &&
(coda_get_bitstream_payload(ctx) < 512)) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"%d: not ready: not enough bitstream data (%d).\n",
ctx->idx, coda_get_bitstream_payload(ctx));
@@ -1015,6 +1045,7 @@ static int coda_job_ready(void *m2m_priv)
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"job ready\n");
return 1;
}
@@ -1052,32 +1083,6 @@ static const struct v4l2_m2m_ops coda_m2m_ops = {
.unlock = coda_unlock,
};
static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
{
struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
int luma_map, chro_map, i;
memset(tiled_map, 0, sizeof(*tiled_map));
luma_map = 64;
chro_map = 64;
tiled_map->map_type = tiled_map_type;
for (i = 0; i < 16; i++)
tiled_map->xy2ca_map[i] = luma_map << 8 | chro_map;
for (i = 0; i < 4; i++)
tiled_map->xy2ba_map[i] = luma_map << 8 | chro_map;
for (i = 0; i < 16; i++)
tiled_map->xy2ra_map[i] = luma_map << 8 | chro_map;
if (tiled_map_type == GDI_LINEAR_FRAME_MAP) {
tiled_map->xy2rbc_config = 0;
} else {
dev_err(&ctx->dev->plat_dev->dev, "invalid map type: %d\n",
tiled_map_type);
return;
}
}
static void set_default_params(struct coda_ctx *ctx)
{
unsigned int max_w, max_h, usize, csize;
@@ -1094,8 +1099,8 @@ static void set_default_params(struct coda_ctx *ctx)
ctx->params.framerate = 30;
/* Default formats for output and input queues */
ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->codec->src_fourcc;
ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc;
ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->cvd->src_formats[0];
ctx->q_data[V4L2_M2M_DST].fourcc = ctx->cvd->dst_formats[0];
ctx->q_data[V4L2_M2M_SRC].width = max_w;
ctx->q_data[V4L2_M2M_SRC].height = max_h;
ctx->q_data[V4L2_M2M_DST].width = max_w;
@@ -1116,8 +1121,11 @@ static void set_default_params(struct coda_ctx *ctx)
ctx->q_data[V4L2_M2M_DST].rect.width = max_w;
ctx->q_data[V4L2_M2M_DST].rect.height = max_h;
if (ctx->dev->devtype->product == CODA_960)
coda_set_tiled_map_type(ctx, GDI_LINEAR_FRAME_MAP);
/*
* Since the RBC2AXI logic only supports a single chroma plane,
* macroblock tiling only works for to NV12 pixel format.
*/
ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
}
/*
@@ -1244,9 +1252,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
if (q_data_src->fourcc == V4L2_PIX_FMT_H264 ||
(q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
ctx->dev->devtype->product == CODA_7541)) {
if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
/* copy the buffers that were queued before streamon */
mutex_lock(&ctx->bitstream_mutex);
coda_fill_bitstream(ctx, false);
@@ -1315,7 +1321,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
goto err;
}
ctx->initialized = 1;
return ret;
err:
@@ -1334,6 +1339,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
struct coda_ctx *ctx = vb2_get_drv_priv(q);
struct coda_dev *dev = ctx->dev;
struct vb2_buffer *buf;
unsigned long flags;
bool stop;
stop = ctx->streamon_out && ctx->streamon_cap;
@@ -1368,20 +1374,23 @@ static void coda_stop_streaming(struct vb2_queue *q)
queue_work(dev->workqueue, &ctx->seq_end_work);
flush_work(&ctx->seq_end_work);
}
mutex_lock(&ctx->bitstream_mutex);
spin_lock_irqsave(&ctx->buffer_meta_lock, flags);
while (!list_empty(&ctx->buffer_meta_list)) {
meta = list_first_entry(&ctx->buffer_meta_list,
struct coda_buffer_meta, list);
list_del(&meta->list);
kfree(meta);
}
mutex_unlock(&ctx->bitstream_mutex);
ctx->num_metas = 0;
spin_unlock_irqrestore(&ctx->buffer_meta_lock, flags);
kfifo_init(&ctx->bitstream_fifo,
ctx->bitstream.vaddr, ctx->bitstream.size);
ctx->initialized = 0;
ctx->runcounter = 0;
ctx->aborting = 0;
}
if (!ctx->streamon_out && !ctx->streamon_cap)
ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
}
static const struct vb2_ops coda_qops = {
@@ -1469,6 +1478,12 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_JPEG_RESTART_INTERVAL:
ctx->params.jpeg_restart_interval = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_VBV_DELAY:
ctx->params.vbv_delay = ctrl->val;
break;
case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
ctx->params.vbv_size = min(ctrl->val * 8192, 0x7fffffff);
break;
default:
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"Invalid control, id=%d, val=%d\n",
@@ -1528,6 +1543,14 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0,
1920 * 1088 / 256, 1, 0);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_VBV_DELAY, 0, 0x7fff, 1, 0);
/*
* The maximum VBV size value is 0x7fffffff bits,
* one bit less than 262144 KiB
*/
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_VBV_SIZE, 0, 262144, 1, 0);
}
static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
@@ -1726,6 +1749,7 @@ static int coda_open(struct file *file)
mutex_init(&ctx->bitstream_mutex);
mutex_init(&ctx->buffer_mutex);
INIT_LIST_HEAD(&ctx->buffer_meta_list);
spin_lock_init(&ctx->buffer_meta_lock);
coda_lock(ctx);
list_add(&ctx->list, &dev->instances);
@@ -1769,7 +1793,7 @@ static int coda_release(struct file *file)
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
/* In case the instance was not running, we still need to call SEQ_END */
if (ctx->initialized && ctx->ops->seq_end_work) {
if (ctx->ops->seq_end_work) {
queue_work(dev->workqueue, &ctx->seq_end_work);
flush_work(&ctx->seq_end_work);
}