staticint disable_vdoa;
module_param(disable_vdoa, int, 0644);
MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion");
staticint enable_bwb = 0;
module_param(enable_bwb, int, 0644);
MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams");
/* * Normalize all supported YUV 4:2:0 formats to the value used in the codec * tables.
*/ static u32 coda_format_normalize_yuv(u32 fourcc)
{ switch (fourcc) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_YUYV: return V4L2_PIX_FMT_YUV420; default: return fourcc;
}
}
staticconststruct coda_codec *coda_find_codec(struct coda_dev *dev, int src_fourcc, int dst_fourcc)
{ conststruct coda_codec *codecs = dev->devtype->codecs; int num_codecs = dev->devtype->num_codecs; int k;
for (k = 0; k < num_codecs; k++) { if (codecs[k].src_fourcc == src_fourcc &&
codecs[k].dst_fourcc == dst_fourcc) break;
}
if (k == num_codecs) return NULL;
return &codecs[k];
}
staticvoid coda_get_max_dimensions(struct coda_dev *dev, conststruct coda_codec *codec, int *max_w, int *max_h)
{ conststruct coda_codec *codecs = dev->devtype->codecs; int num_codecs = dev->devtype->num_codecs; unsignedint w, h; int k;
if (codec) {
w = codec->max_w;
h = codec->max_h;
} else { for (k = 0, w = 0, h = 0; k < num_codecs; k++) {
w = max(w, codecs[k].max_w);
h = max(h, codecs[k].max_h);
}
}
/* * If the source format is already fixed, only allow the same * chroma subsampling.
*/
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT); if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
vb2_is_streaming(src_vq)) { if (ctx->params.jpeg_chroma_subsampling ==
V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
formats = coda_formats_420;
} elseif (ctx->params.jpeg_chroma_subsampling ==
V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
f->pixelformat = V4L2_PIX_FMT_YUV422P; return f->index ? -EINVAL : 0;
}
}
} else { return -EINVAL;
}
if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0) return -EINVAL;
/* Skip YUYV if the vdoa is not available */ if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
formats[f->index] == V4L2_PIX_FMT_YUYV) return -EINVAL;
for (i = 0; i < CODA_MAX_FORMATS; i++) { /* Skip YUYV if the vdoa is not available */ if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
formats[i] == V4L2_PIX_FMT_YUYV) continue;
staticunsignedint coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
u32 width, u32 height)
{ /* * This is a rough estimate for sensible compressed buffer * sizes (between 1 and 16 bits per pixel). This could be * improved by better format specific worst case estimates.
*/ return round_up(clamp(sizeimage, width * height / 8,
width * height * 2), PAGE_SIZE);
}
/* * If the source format is already fixed, only allow the same output * resolution. When decoding JPEG images, we also have to make sure to * use the same chroma subsampling.
*/
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (vb2_is_streaming(src_vq)) { if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
ctx->dev->devtype->product == CODA_960) {
hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
}
f->fmt.pix.width = q_data_src->width >> hscale;
f->fmt.pix.height = q_data_src->height >> vscale;
if (ctx->inst_type != CODA_INST_DECODER) return 0;
/* Setting the coded format determines the selected codec */
codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat,
V4L2_PIX_FMT_YUV420); if (!codec) {
v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); return -EINVAL;
}
ctx->codec = codec;
dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (!dst_vq) return -EINVAL;
/* * Setting the capture queue format is not possible while the capture * queue is still busy. This is not an error, but the user will have to * make sure themselves that the capture format is set correctly before * starting the output queue again.
*/ if (vb2_is_busy(dst_vq)) return 0;
ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb); if (ret) return ret;
/* * Allow to allocate instance specific per-context buffers, such as * bitstream ringbuffer, slice buffer, work buffer, etc. if needed.
*/ if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs) return ctx->ops->reqbufs(ctx, rb);
ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec); if (ret < 0) return ret;
mutex_lock(&ctx->wakeup_mutex);
buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); if (buf) { /* * If the last output buffer is still on the queue, make sure * that decoder finish_run will see the last flag and report it * to userspace.
*/
buf->flags |= V4L2_BUF_FLAG_LAST;
} else { /* Set the stream-end flag on this context */
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
/* * If the last output buffer has already been taken from the * queue, wake up the capture queue and signal end of stream * via the -EPIPE mechanism.
*/
coda_wake_up_capture_queue(ctx);
}
mutex_unlock(&ctx->wakeup_mutex);
/* * Approximate timeperframe v4l2_fract with values that can be written * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields.
*/ staticvoid 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 }; unsignedint i, div, s_denominator;
/* * 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 (!src_bufs && ctx->inst_type != CODA_INST_DECODER) {
coda_dbg(1, ctx, "not ready: not enough vid-out buffers.\n"); return 0;
}
if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
coda_dbg(1, ctx, "not ready: not enough vid-cap buffers.\n"); return 0;
}
/* * 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;
}
q_data = get_q_data(ctx, vb->vb2_queue->type); if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { if (vbuf->field == V4L2_FIELD_ANY)
vbuf->field = V4L2_FIELD_NONE; if (vbuf->field != V4L2_FIELD_NONE) {
v4l2_warn(&ctx->dev->v4l2_dev, "%s field isn't supported\n", __func__); return -EINVAL;
}
}
if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
v4l2_warn(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
__func__, vb2_plane_size(vb, 0),
(long)q_data->sizeimage); return -EINVAL;
}
return 0;
}
staticvoid coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value)
{ if (!ctrl) return;
v4l2_ctrl_lock(ctrl);
/* * Extend the control range if the parsed stream contains a known but * unsupported value or level.
*/ if (value > ctrl->maximum) {
__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value,
ctrl->menu_skip_mask & ~(1 << value),
ctrl->default_value);
} elseif (value < ctrl->minimum) {
__v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum,
ctrl->menu_skip_mask & ~(1 << value),
ctrl->default_value);
}
/* * In the decoder case, immediately try to copy the buffer into the * bitstream ringbuffer and mark it as ready to be dequeued.
*/ if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* * For backwards compatibility, queuing an empty buffer marks * the stream end
*/ if (vb2_get_plane_payload(vb, 0) == 0)
coda_bit_stream_end_flag(ctx);
if (q_data->fourcc == V4L2_PIX_FMT_H264) { /* * Unless already done, try to obtain profile_idc and * level_idc from the SPS header. This allows to decide * whether to enable reordering during sequence * initialization.
*/ if (!ctx->params.h264_profile_idc) {
coda_sps_parse_profile(ctx, vb);
coda_update_profile_level_ctrls(ctx,
ctx->params.h264_profile_idc,
ctx->params.h264_level_idc);
}
}
mutex_lock(&ctx->bitstream_mutex);
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); if (vb2_is_streaming(vb->vb2_queue)) /* This set buf->sequence = ctx->qsequence++ */
coda_fill_bitstream(ctx, NULL);
mutex_unlock(&ctx->bitstream_mutex);
if (!ctx->initialized) { /* * Run sequence initialization in case the queued * buffer contained headers.
*/ if (vb2_is_streaming(vb->vb2_queue) &&
ctx->ops->seq_init_work) {
queue_work(ctx->dev->workqueue,
&ctx->seq_init_work);
flush_work(&ctx->seq_init_work);
}
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 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, &list);
mutex_unlock(&ctx->bitstream_mutex);
if (ctx->dev->devtype->product != CODA_960 &&
coda_get_bitstream_payload(ctx) < 512) {
v4l2_err(v4l2_dev, "start payload < 512\n");
ret = -EINVAL; goto err;
}
if (!ctx->initialized) { /* Run sequence initialization */ if (ctx->ops->seq_init_work) {
queue_work(ctx->dev->workqueue,
&ctx->seq_init_work);
flush_work(&ctx->seq_init_work);
}
}
}
/* * Check the first input JPEG buffer to determine chroma * subsampling.
*/ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
coda_jpeg_decode_header(ctx, &buf->vb2_buf); /* * We have to start streaming even if the first buffer * does not contain a valid JPEG image. The error will * be caught during device run and will be signalled * via the capture buffer error flag.
*/
/* Allow BIT decoder device_run with no new buffers queued */ if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
ctx->gopcounter = ctx->params.gop_size - 1;
if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
ctx->params.gop_size = 1;
ctx->gopcounter = ctx->params.gop_size - 1; /* Only decoders have this control */ if (ctx->mb_err_cnt_ctrl)
v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0);
ret = ctx->ops->start_streaming(ctx); if (ctx->inst_type == CODA_INST_DECODER) { if (ret == -EAGAIN) goto out;
} if (ret < 0) goto err;
if (val_names)
coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d (\"%s\")\n",
ctrl->id, ctrl->name, ctrl->val, val_names[ctrl->val]); else
coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d\n",
ctrl->id, ctrl->name, ctrl->val);
switch (ctrl->id) { case V4L2_CID_HFLIP: if (ctrl->val)
ctx->params.rot_mode |= CODA_MIR_HOR; else
ctx->params.rot_mode &= ~CODA_MIR_HOR; break; case V4L2_CID_VFLIP: if (ctrl->val)
ctx->params.rot_mode |= CODA_MIR_VER; else
ctx->params.rot_mode &= ~CODA_MIR_VER; break; case V4L2_CID_MPEG_VIDEO_BITRATE:
ctx->params.bitrate = ctrl->val / 1000;
ctx->params.bitrate_changed = true; break; case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
ctx->params.gop_size = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
ctx->params.h264_intra_qp = ctrl->val;
ctx->params.h264_intra_qp_changed = true; break; case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
ctx->params.h264_inter_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
ctx->params.h264_min_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
ctx->params.h264_max_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
ctx->params.h264_slice_beta_offset_div2 = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
ctx->params.h264_disable_deblocking_filter_idc = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
ctx->params.h264_constrained_intra_pred_flag = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
ctx->params.frame_rc_enable = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
ctx->params.mb_rc_enable = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
ctx->params.h264_chroma_qp_index_offset = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_H264_PROFILE: /* TODO: switch between baseline and constrained baseline */ if (ctx->inst_type == CODA_INST_ENCODER)
ctx->params.h264_profile_idc = 66; break; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: /* nothing to do, this is set by the encoder */ break; case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
ctx->params.mpeg4_intra_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
ctx->params.mpeg4_inter_qp = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: /* nothing to do, these are fixed */ break; case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
ctx->params.slice_mode = ctrl->val;
ctx->params.slice_mode_changed = true; break; case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
ctx->params.slice_max_mb = ctrl->val;
ctx->params.slice_mode_changed = true; break; case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
ctx->params.slice_max_bits = ctrl->val * 8;
ctx->params.slice_mode_changed = true; break; case V4L2_CID_MPEG_VIDEO_HEADER_MODE: break; case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
ctx->params.intra_refresh = ctrl->val;
ctx->params.intra_refresh_changed = true; break; case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
ctx->params.force_ipicture = true; break; case V4L2_CID_JPEG_COMPRESSION_QUALITY:
coda_set_jpeg_compression_quality(ctx, ctrl->val); break; 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:
coda_dbg(1, ctx, "Invalid control, id=%d, val=%d\n",
ctrl->id, ctrl->val); return -EINVAL;
}
staticint coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq)
{
vq->drv_priv = ctx;
vq->ops = &coda_qops;
vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
vq->lock = &ctx->dev->dev_mutex; /* One way to indicate end-of-stream for coda is to set the * bytesused == 0. However by default videobuf2 handles bytesused * equal to 0 as a special case and changes its value to the size * of the buffer. Set the allow_zero_bytesused flag, so * that videobuf2 will keep the value of bytesused intact.
*/
vq->allow_zero_bytesused = 1; /* * We might be fine with no buffers on some of the queues, but that * would need to be reflected in job_ready(). Currently we expect all * queues to have at least one buffer queued.
*/
vq->min_queued_buffers = 1;
vq->dev = ctx->dev->dev;
return vb2_queue_init(vq);
}
int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
{ int ret;
switch (dev->devtype->product) { case CODA_960: /* * Enabling the BWB when decoding can hang the firmware with * certain streams. The issue was tracked as ENGR00293425 by * Freescale. As a workaround, disable BWB for all decoders. * The enable_bwb module parameter allows to override this.
*/ if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER)
ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB;
fallthrough; case CODA_HX4: case CODA_7541:
ctx->reg_idx = 0; break; default:
ctx->reg_idx = idx;
} if (ctx->dev->vdoa && !disable_vdoa) {
ctx->vdoa = vdoa_context_create(dev->vdoa); if (!ctx->vdoa)
v4l2_warn(&dev->v4l2_dev, "Failed to create vdoa context: not using vdoa");
}
ctx->use_vdoa = false;
/* Power up and upload firmware if necessary */
ret = pm_runtime_resume_and_get(dev->dev); if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret); goto err_pm_get;
}
ret = clk_prepare_enable(dev->clk_per); if (ret) goto err_clk_enable;
ret = clk_prepare_enable(dev->clk_ahb); if (ret) goto err_clk_ahb;
set_default_params(ctx);
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
ctx->ops->queue_init); if (IS_ERR(ctx->fh.m2m_ctx)) {
ret = PTR_ERR(ctx->fh.m2m_ctx);
if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
coda_bit_stream_end_flag(ctx);
/* If this instance is running, call .job_abort and wait for it to end */
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
if (ctx->vdoa)
vdoa_context_destroy(ctx->vdoa);
/* In case the instance was not running, we still need to call SEQ_END */ if (ctx->ops->seq_end_work) {
queue_work(dev->workqueue, &ctx->seq_end_work);
flush_work(&ctx->seq_end_work);
}
if (ctx->dev->devtype->product == CODA_DX6)
coda_free_aux_buf(dev, &ctx->workbuf);
staticint coda_hw_init(struct coda_dev *dev)
{
u32 data;
u16 *p; int i, ret;
ret = clk_prepare_enable(dev->clk_per); if (ret) goto err_clk_per;
ret = clk_prepare_enable(dev->clk_ahb); if (ret) goto err_clk_ahb;
reset_control_reset(dev->rstc);
/* * Copy the first CODA_ISRAM_SIZE in the internal SRAM. * The 16-bit chars in the code buffer are in memory access * order, re-sort them to CODA order for register download. * Data in this SRAM survives a reboot.
*/
p = (u16 *)dev->codebuf.vaddr; if (dev->devtype->product == CODA_DX6) { for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) {
data = CODA_DOWN_ADDRESS_SET(i) |
CODA_DOWN_DATA_SET(p[i ^ 1]);
coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
}
} else { for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) {
data = CODA_DOWN_ADDRESS_SET(i) |
CODA_DOWN_DATA_SET(p[round_down(i, 4) +
3 - (i % 4)]);
coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
}
}
/* Clear registers */ for (i = 0; i < 64; i++)
coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
/* Tell the BIT where to find everything it needs */ if (dev->devtype->product == CODA_960 ||
dev->devtype->product == CODA_7541 ||
dev->devtype->product == CODA_HX4) {
coda_write(dev, dev->tempbuf.paddr,
CODA_REG_BIT_TEMP_BUF_ADDR);
coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
} else {
coda_write(dev, dev->workbuf.paddr,
CODA_REG_BIT_WORK_BUF_ADDR);
}
coda_write(dev, dev->codebuf.paddr,
CODA_REG_BIT_CODE_BUF_ADDR);
coda_write(dev, 0, CODA_REG_BIT_CODE_RUN);
/* Set default values */ switch (dev->devtype->product) { case CODA_DX6:
coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH,
CODA_REG_BIT_STREAM_CTRL); break; default:
coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH,
CODA_REG_BIT_STREAM_CTRL);
} if (dev->devtype->product == CODA_960)
coda_write(dev, CODA9_FRAME_ENABLE_BWB,
CODA_REG_BIT_FRAME_MEM_CTRL); else
coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
if (dev->devtype->product != CODA_DX6)
coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
/* Not applicable, use the selection API instead */
v4l2_disable_ioctl(vfd, VIDIOC_CROPCAP);
v4l2_disable_ioctl(vfd, VIDIOC_G_CROP);
v4l2_disable_ioctl(vfd, VIDIOC_S_CROP);
/* Check if the firmware has a 16-byte Freescale header, skip it */ if (buf[0] == 'M' && buf[1] == 'X')
src += 4; /* * Check whether the firmware is in native order or pre-reordered for * memory access. The first instruction opcode always is 0xe40e.
*/ if (__le16_to_cpup((__le16 *)src) == 0xe40e) {
u32 *dst = dev->codebuf.vaddr; int i;
/* Firmware in native order, reorder while copying */ if (dev->devtype->product == CODA_DX6) { for (i = 0; i < (size - 16) / 4; i++)
dst[i] = (src[i] << 16) | (src[i] >> 16);
} else { for (i = 0; i < (size - 16) / 4; i += 2) {
dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16);
dst[i + 1] = (src[i] << 16) | (src[i] >> 16);
}
}
} else { /* Copy the already reordered firmware image */
memcpy(dev->codebuf.vaddr, src, size);
}
}
staticvoid coda_fw_callback(conststruct firmware *fw, void *context)
{ struct coda_dev *dev = context; int i, ret;
if (!fw) {
dev->firmware++;
ret = coda_firmware_request(dev); if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); goto put_pm;
} return;
} if (dev->firmware > 0) { /* * Since we can't suppress warnings for failed asynchronous * firmware requests, report that the fallback firmware was * found.
*/
dev_info(dev->dev, "Using fallback firmware %s\n",
dev->devtype->firmware[dev->firmware]);
}
/* allocate auxiliary per-device code buffer for the BIT processor */
ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
dev->debugfs_root); if (ret < 0) goto put_pm;
ret = coda_hw_init(dev); if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); goto put_pm;
}
ret = coda_check_firmware(dev); if (ret < 0) goto put_pm;
dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops); if (IS_ERR(dev->m2m_dev)) {
v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); goto put_pm;
}
for (i = 0; i < dev->devtype->num_vdevs; i++) {
ret = coda_register_device(dev, i); if (ret) {
v4l2_err(&dev->v4l2_dev, "Failed to register %s video device: %d\n",
dev->devtype->vdevs[i]->name, ret); goto rel_vfd;
}
}
pm_runtime_put_sync(dev->dev); return;
rel_vfd: while (--i >= 0)
video_unregister_device(&dev->vfd[i]);
v4l2_m2m_release(dev->m2m_dev);
put_pm:
pm_runtime_put_sync(dev->dev);
}
dev->dev = &pdev->dev;
dev->clk_per = devm_clk_get(&pdev->dev, "per"); if (IS_ERR(dev->clk_per)) {
dev_err(&pdev->dev, "Could not get per clock\n"); return PTR_ERR(dev->clk_per);
}
dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(dev->clk_ahb)) {
dev_err(&pdev->dev, "Could not get ahb clock\n"); return PTR_ERR(dev->clk_ahb);
}
/* Get memory for physical registers */
dev->regs_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->regs_base)) return PTR_ERR(dev->regs_base);
ret = devm_request_irq(&pdev->dev, irq, coda_irq_handler, 0,
CODA_NAME "-video", dev); if (ret < 0) {
dev_err(&pdev->dev, "failed to request irq: %d\n", ret); return ret;
}
/* JPEG IRQ */ if (dev->devtype->product == CODA_960) {
irq = platform_get_irq_byname(pdev, "jpeg"); if (irq < 0) return irq;
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
coda9_jpeg_irq_handler,
IRQF_ONESHOT, CODA_NAME "-jpeg",
dev); if (ret < 0) {
dev_err(&pdev->dev, "failed to request jpeg irq\n"); return ret;
}
}
dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev,
NULL); if (IS_ERR(dev->rstc)) {
ret = PTR_ERR(dev->rstc);
dev_err(&pdev->dev, "failed get reset control: %d\n", ret); return ret;
}
/* Get IRAM pool from device tree */
pool = of_gen_pool_get(np, "iram", 0); if (!pool) {
dev_err(&pdev->dev, "iram pool not available\n"); return -ENOMEM;
}
dev->iram_pool = pool;
/* Get vdoa_data if supported by the platform */
dev->vdoa = coda_get_vdoa_data(); if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER) return -EPROBE_DEFER;
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) return ret;
/* allocate auxiliary per-device buffers for the BIT processor */ if (dev->devtype->product == CODA_DX6) {
ret = coda_alloc_aux_buf(dev, &dev->workbuf,
dev->devtype->workbuf_size, "workbuf",
dev->debugfs_root); if (ret < 0) goto err_v4l2_register;
}
if (dev->devtype->tempbuf_size) {
ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
dev->devtype->tempbuf_size, "tempbuf",
dev->debugfs_root); if (ret < 0) goto err_v4l2_register;
}
dev->workqueue = alloc_ordered_workqueue("coda", WQ_MEM_RECLAIM); if (!dev->workqueue) {
dev_err(&pdev->dev, "unable to alloc workqueue\n");
ret = -ENOMEM; goto err_v4l2_register;
}
platform_set_drvdata(pdev, dev);
/* * Start activated so we can directly call coda_hw_init in * coda_fw_callback regardless of whether CONFIG_PM is * enabled or whether the device is associated with a PM domain.
*/
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = coda_firmware_request(dev); if (ret) goto err_alloc_workqueue; return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.