From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mailout4.w1.samsung.com ([210.118.77.14]:13082 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755854AbaHEPgs (ORCPT ); Tue, 5 Aug 2014 11:36:48 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N9U00DI4BCYLQ70@mailout4.w1.samsung.com> for linux-media@vger.kernel.org; Tue, 05 Aug 2014 16:36:35 +0100 (BST) From: Kamil Debski To: 'Philipp Zabel' , linux-media@vger.kernel.org Cc: 'Mauro Carvalho Chehab' , 'Fabio Estevam' , 'Hans Verkuil' , 'Nicolas Dufresne' , kernel@pengutronix.de References: <1406129325-10771-1-git-send-email-p.zabel@pengutronix.de> <1406129325-10771-9-git-send-email-p.zabel@pengutronix.de> In-reply-to: <1406129325-10771-9-git-send-email-p.zabel@pengutronix.de> Subject: RE: [PATCH 8/8] [media] coda: move BIT specific functions into separate file Date: Tue, 05 Aug 2014 17:36:47 +0200 Message-id: <0c3d01cfb0c3$11d81980$35884c80$%debski@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit Content-language: pl Sender: linux-media-owner@vger.kernel.org List-ID: Hi Philipp, I have some errors from checkpatch for this patch. Please fix them. ERROR: return is not a function, parentheses are not required #86: FILE: drivers/media/platform/coda/coda-bit.c:40: + return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0); WARNING: quoted string split across lines #681: FILE: drivers/media/platform/coda/coda-bit.c:635: + v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s," + " Version: %u.%u.%u\n", WARNING: quoted string split across lines #695: FILE: drivers/media/platform/coda/coda-bit.c:649: + v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: " + "%u.%u.%u\n", major, minor, releas And many, many following warnings: "WARNING: line over 80 characters". Please check if these lines *REALLY* need to be such long. Best wishes, -- Kamil Debski Samsung R&D Institute Poland > -----Original Message----- > From: Philipp Zabel [mailto:p.zabel@pengutronix.de] > Sent: Wednesday, July 23, 2014 5:29 PM > To: linux-media@vger.kernel.org > Cc: Mauro Carvalho Chehab; Kamil Debski; Fabio Estevam; Hans Verkuil; > Nicolas Dufresne; kernel@pengutronix.de; Philipp Zabel > Subject: [PATCH 8/8] [media] coda: move BIT specific functions into > separate file > > This patch moves the BIT processor specific coda_context_ops, the > firmware > upload and other related functions from coda-common.c into coda-bit.c. > > Signed-off-by: Philipp Zabel > --- > drivers/media/platform/coda/Makefile | 2 +- > drivers/media/platform/coda/coda-bit.c | 1810 > ++++++++++++++++++++++++++++ > drivers/media/platform/coda/coda-common.c | 1857 +-------------------- > -------- > drivers/media/platform/coda/coda.h | 56 + > 4 files changed, 1893 insertions(+), 1832 deletions(-) > create mode 100644 drivers/media/platform/coda/coda-bit.c > > diff --git a/drivers/media/platform/coda/Makefile > b/drivers/media/platform/coda/Makefile > index 0e59fbd..3543291 100644 > --- a/drivers/media/platform/coda/Makefile > +++ b/drivers/media/platform/coda/Makefile > @@ -1,3 +1,3 @@ > -coda-objs := coda-common.o coda-h264.o > +coda-objs := coda-common.o coda-bit.o coda-h264.o > > obj-$(CONFIG_VIDEO_CODA) += coda.o > diff --git a/drivers/media/platform/coda/coda-bit.c > b/drivers/media/platform/coda/coda-bit.c > new file mode 100644 > index 0000000..1d2716d > --- /dev/null > +++ b/drivers/media/platform/coda/coda-bit.c > @@ -0,0 +1,1810 @@ > +/* > + * Coda multi-standard codec IP - BIT processor functions > + * > + * Copyright (C) 2012 Vista Silicon S.L. > + * Javier Martin, > + * Xavier Duret > + * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix > + * > + * This program is free software; you can redistribute it and/or > modify > + * it under the terms of the GNU General Public License as published > by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "coda.h" > + > +#define CODA7_PS_BUF_SIZE 0x28000 > +#define CODA9_PS_SAVE_SIZE (512 * 1024) > + > +#define CODA_DEFAULT_GAMMA 4096 > +#define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */ > + > +static inline int coda_is_initialized(struct coda_dev *dev) > +{ > + return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0); > +} > + > +static inline unsigned long coda_isbusy(struct coda_dev *dev) > +{ > + return coda_read(dev, CODA_REG_BIT_BUSY); > +} > + > +static int coda_wait_timeout(struct coda_dev *dev) > +{ > + unsigned long timeout = jiffies + msecs_to_jiffies(1000); > + > + while (coda_isbusy(dev)) { > + if (time_after(jiffies, timeout)) > + return -ETIMEDOUT; > + } > + return 0; > +} > + > +static void coda_command_async(struct coda_ctx *ctx, int cmd) > +{ > + struct coda_dev *dev = ctx->dev; > + > + if (dev->devtype->product == CODA_960 || > + dev->devtype->product == CODA_7541) { > + /* Restore context related registers to CODA */ > + coda_write(dev, ctx->bit_stream_param, > + CODA_REG_BIT_BIT_STREAM_PARAM); > + coda_write(dev, ctx->frm_dis_flg, > + CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > + coda_write(dev, ctx->frame_mem_ctrl, > + CODA_REG_BIT_FRAME_MEM_CTRL); > + coda_write(dev, ctx->workbuf.paddr, > CODA_REG_BIT_WORK_BUF_ADDR); > + } > + > + if (dev->devtype->product == CODA_960) { > + coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); > + coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); > + } > + > + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > + > + coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); > + coda_write(dev, ctx->params.codec_mode, > CODA_REG_BIT_RUN_COD_STD); > + coda_write(dev, ctx->params.codec_mode_aux, > CODA7_REG_BIT_RUN_AUX_STD); > + > + coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); > +} > + > +static int coda_command_sync(struct coda_ctx *ctx, int cmd) > +{ > + struct coda_dev *dev = ctx->dev; > + > + coda_command_async(ctx, cmd); > + return coda_wait_timeout(dev); > +} > + > +int coda_hw_reset(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + unsigned long timeout; > + unsigned int idx; > + int ret; > + > + if (!dev->rstc) > + return -ENOENT; > + > + idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); > + > + if (dev->devtype->product == CODA_960) { > + timeout = jiffies + msecs_to_jiffies(100); > + coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); > + while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { > + if (time_after(jiffies, timeout)) > + return -ETIME; > + cpu_relax(); > + } > + } > + > + ret = reset_control_reset(dev->rstc); > + if (ret < 0) > + return ret; > + > + if (dev->devtype->product == CODA_960) > + coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); > + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > + coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); > + ret = coda_wait_timeout(dev); > + coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); > + > + return ret; > +} > + > +static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) > +{ > + struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > + struct coda_dev *dev = ctx->dev; > + u32 rd_ptr; > + > + rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); > + kfifo->out = (kfifo->in & ~kfifo->mask) | > + (rd_ptr - ctx->bitstream.paddr); > + if (kfifo->out > kfifo->in) > + kfifo->out -= kfifo->mask + 1; > +} > + > +static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) > +{ > + struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > + struct coda_dev *dev = ctx->dev; > + u32 rd_ptr, wr_ptr; > + > + rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); > + coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); > + wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); > + coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > +} > + > +static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) > +{ > + struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > + struct coda_dev *dev = ctx->dev; > + u32 wr_ptr; > + > + wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); > + coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > +} > + > +static int coda_bitstream_queue(struct coda_ctx *ctx, struct > vb2_buffer *src_buf) > +{ > + u32 src_size = vb2_get_plane_payload(src_buf, 0); > + u32 n; > + > + n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), > src_size); > + if (n < src_size) > + return -ENOSPC; > + > + dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx- > >bitstream.paddr, > + ctx->bitstream.size, DMA_TO_DEVICE); > + > + src_buf->v4l2_buf.sequence = ctx->qsequence++; > + > + return 0; > +} > + > +static bool coda_bitstream_try_queue(struct coda_ctx *ctx, > + struct vb2_buffer *src_buf) > +{ > + int ret; > + > + if (coda_get_bitstream_payload(ctx) + > + vb2_get_plane_payload(src_buf, 0) + 512 >= ctx- > >bitstream.size) > + return false; > + > + if (vb2_plane_vaddr(src_buf, 0) == NULL) { > + v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty > buffer\n"); > + return true; > + } > + > + ret = coda_bitstream_queue(ctx, src_buf); > + if (ret < 0) { > + v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer > overflow\n"); > + return false; > + } > + /* Sync read pointer to device */ > + if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) > + coda_kfifo_sync_to_device_write(ctx); > + > + ctx->hold = false; > + > + return true; > +} > + > +void coda_fill_bitstream(struct coda_ctx *ctx) > +{ > + struct vb2_buffer *src_buf; > + struct coda_timestamp *ts; > + > + while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { > + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > + > + if (coda_bitstream_try_queue(ctx, src_buf)) { > + /* > + * Source buffer is queued in the bitstream > ringbuffer; > + * queue the timestamp and mark source buffer as done > + */ > + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); > + > + ts = kmalloc(sizeof(*ts), GFP_KERNEL); > + if (ts) { > + ts->sequence = src_buf->v4l2_buf.sequence; > + ts->timecode = src_buf->v4l2_buf.timecode; > + ts->timestamp = src_buf->v4l2_buf.timestamp; > + list_add_tail(&ts->list, &ctx->timestamp_list); > + } > + > + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); > + } else { > + break; > + } > + } > +} > + > +void coda_bit_stream_end_flag(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + > + ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; > + > + if ((dev->devtype->product == CODA_960) && > + coda_isbusy(dev) && > + (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { > + /* If this context is currently running, update the > hardware flag */ > + coda_write(dev, ctx->bit_stream_param, > CODA_REG_BIT_BIT_STREAM_PARAM); > + } > +} > + > +static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 > value) > +{ > + struct coda_dev *dev = ctx->dev; > + u32 *p = ctx->parabuf.vaddr; > + > + if (dev->devtype->product == CODA_DX6) > + p[index] = value; > + else > + p[index ^ 1] = value; > +} > + > +static void coda_free_framebuffers(struct coda_ctx *ctx) > +{ > + int i; > + > + for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) > + coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]); > +} > + > +static int coda_alloc_framebuffers(struct coda_ctx *ctx, > + struct coda_q_data *q_data, u32 fourcc) > +{ > + struct coda_dev *dev = ctx->dev; > + int width, height; > + dma_addr_t paddr; > + int ysize; > + int ret; > + int i; > + > + if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || > + ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) { > + width = round_up(q_data->width, 16); > + height = round_up(q_data->height, 16); > + } else { > + width = round_up(q_data->width, 8); > + height = q_data->height; > + } > + ysize = width * height; > + > + /* Allocate frame buffers */ > + for (i = 0; i < ctx->num_internal_frames; i++) { > + size_t size; > + char *name; > + > + size = ysize + ysize / 2; > + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && > + dev->devtype->product != CODA_DX6) > + size += ysize / 4; > + name = kasprintf(GFP_KERNEL, "fb%d", i); > + ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], > + size, name); > + kfree(name); > + if (ret < 0) { > + coda_free_framebuffers(ctx); > + return ret; > + } > + } > + > + /* Register frame buffers in the parameter buffer */ > + for (i = 0; i < ctx->num_internal_frames; i++) { > + paddr = ctx->internal_frames[i].paddr; > + coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */ > + coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ > + coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + > ysize/4); /* Cr */ > + > + /* mvcol buffer for h.264 */ > + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && > + dev->devtype->product != CODA_DX6) > + coda_parabuf_write(ctx, 96 + i, > + ctx->internal_frames[i].paddr + > + ysize + ysize/4 + ysize/4); > + } > + > + /* mvcol buffer for mpeg4 */ > + if ((dev->devtype->product != CODA_DX6) && > + (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4)) > + coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr + > + ysize + ysize/4 + ysize/4); > + > + return 0; > +} > + > +static void coda_free_context_buffers(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + > + coda_free_aux_buf(dev, &ctx->slicebuf); > + coda_free_aux_buf(dev, &ctx->psbuf); > + if (dev->devtype->product != CODA_DX6) > + coda_free_aux_buf(dev, &ctx->workbuf); > +} > + > +static int coda_alloc_context_buffers(struct coda_ctx *ctx, > + struct coda_q_data *q_data) > +{ > + struct coda_dev *dev = ctx->dev; > + size_t size; > + int ret; > + > + if (dev->devtype->product == CODA_DX6) > + return 0; > + > + if (ctx->psbuf.vaddr) { > + v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); > + return -EBUSY; > + } > + if (ctx->slicebuf.vaddr) { > + v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n"); > + return -EBUSY; > + } > + if (ctx->workbuf.vaddr) { > + v4l2_err(&dev->v4l2_dev, "context buffer still > allocated\n"); > + ret = -EBUSY; > + return -ENOMEM; > + } > + > + if (q_data->fourcc == V4L2_PIX_FMT_H264) { > + /* worst case slice size */ > + size = (DIV_ROUND_UP(q_data->width, 16) * > + DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; > + ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, > "slicebuf"); > + if (ret < 0) { > + v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte > slice buffer", > + ctx->slicebuf.size); > + return ret; > + } > + } > + > + if (dev->devtype->product == CODA_7541) { > + ret = coda_alloc_context_buf(ctx, &ctx->psbuf, > CODA7_PS_BUF_SIZE, "psbuf"); > + if (ret < 0) { > + v4l2_err(&dev->v4l2_dev, "failed to allocate psmem > buffer"); > + goto err; > + } > + } > + > + size = dev->devtype->workbuf_size; > + if (dev->devtype->product == CODA_960 && > + q_data->fourcc == V4L2_PIX_FMT_H264) > + size += CODA9_PS_SAVE_SIZE; > + ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, > "workbuf"); > + if (ret < 0) { > + v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte > context buffer", > + ctx->workbuf.size); > + goto err; > + } > + > + return 0; > + > +err: > + coda_free_context_buffers(ctx); > + return ret; > +} > + > +static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer > *buf, > + int header_code, u8 *header, int *size) > +{ > + struct coda_dev *dev = ctx->dev; > + size_t bufsize; > + int ret; > + int i; > + > + if (dev->devtype->product == CODA_960) > + memset(vb2_plane_vaddr(buf, 0), 0, 64); > + > + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), > + CODA_CMD_ENC_HEADER_BB_START); > + bufsize = vb2_plane_size(buf, 0); > + if (dev->devtype->product == CODA_960) > + bufsize /= 1024; > + coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); > + coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); > + ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); > + if (ret < 0) { > + v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER > timeout\n"); > + return ret; > + } > + > + if (dev->devtype->product == CODA_960) { > + for (i = 63; i > 0; i--) > + if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0) > + break; > + *size = i + 1; > + } else { > + *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - > + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); > + } > + memcpy(header, vb2_plane_vaddr(buf, 0), *size); > + > + return 0; > +} > + > +static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t > size) > +{ > + phys_addr_t ret; > + > + size = round_up(size, 1024); > + if (size > iram->remaining) > + return 0; > + iram->remaining -= size; > + > + ret = iram->next_paddr; > + iram->next_paddr += size; > + > + return ret; > +} > + > +static void coda_setup_iram(struct coda_ctx *ctx) > +{ > + struct coda_iram_info *iram_info = &ctx->iram_info; > + struct coda_dev *dev = ctx->dev; > + int mb_width; > + int dbk_bits; > + int bit_bits; > + int ip_bits; > + > + memset(iram_info, 0, sizeof(*iram_info)); > + iram_info->next_paddr = dev->iram.paddr; > + iram_info->remaining = dev->iram.size; > + > + switch (dev->devtype->product) { > + case CODA_7541: > + dbk_bits = CODA7_USE_HOST_DBK_ENABLE | > CODA7_USE_DBK_ENABLE; > + bit_bits = CODA7_USE_HOST_BIT_ENABLE | > CODA7_USE_BIT_ENABLE; > + ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; > + break; > + case CODA_960: > + dbk_bits = CODA9_USE_HOST_DBK_ENABLE | > CODA9_USE_DBK_ENABLE; > + bit_bits = CODA9_USE_HOST_BIT_ENABLE | > CODA7_USE_BIT_ENABLE; > + ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; > + break; > + default: /* CODA_DX6 */ > + return; > + } > + > + if (ctx->inst_type == CODA_INST_ENCODER) { > + struct coda_q_data *q_data_src; > + > + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > + mb_width = DIV_ROUND_UP(q_data_src->width, 16); > + > + /* Prioritize in case IRAM is too small for everything */ > + if (dev->devtype->product == CODA_7541) { > + iram_info->search_ram_size = round_up(mb_width * 16 * > + 36 + 2048, 1024); > + iram_info->search_ram_paddr = > coda_iram_alloc(iram_info, > + iram_info->search_ram_size); > + if (!iram_info->search_ram_paddr) { > + pr_err("IRAM is smaller than the search ram > size\n"); > + goto out; > + } > + iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE | > + CODA7_USE_ME_ENABLE; > + } > + > + /* Only H.264BP and H.263P3 are considered */ > + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * > mb_width); > + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * > mb_width); > + if (!iram_info->buf_dbk_c_use) > + goto out; > + iram_info->axi_sram_use |= dbk_bits; > + > + iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * > mb_width); > + if (!iram_info->buf_bit_use) > + goto out; > + iram_info->axi_sram_use |= bit_bits; > + > + iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, > 128 * mb_width); > + if (!iram_info->buf_ip_ac_dc_use) > + goto out; > + iram_info->axi_sram_use |= ip_bits; > + > + /* OVL and BTP disabled for encoder */ > + } else if (ctx->inst_type == CODA_INST_DECODER) { > + struct coda_q_data *q_data_dst; > + > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + mb_width = DIV_ROUND_UP(q_data_dst->width, 16); > + > + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * > mb_width); > + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * > mb_width); > + if (!iram_info->buf_dbk_c_use) > + goto out; > + iram_info->axi_sram_use |= dbk_bits; > + > + iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * > mb_width); > + if (!iram_info->buf_bit_use) > + goto out; > + iram_info->axi_sram_use |= bit_bits; > + > + iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, > 128 * mb_width); > + if (!iram_info->buf_ip_ac_dc_use) > + goto out; > + iram_info->axi_sram_use |= ip_bits; > + > + /* OVL and BTP unused as there is no VC1 support yet */ > + } > + > +out: > + if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) > + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > + "IRAM smaller than needed\n"); > + > + if (dev->devtype->product == CODA_7541) { > + /* TODO - Enabling these causes picture errors on CODA7541 > */ > + if (ctx->inst_type == CODA_INST_DECODER) { > + /* fw 1.4.50 */ > + iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE > | > + CODA7_USE_IP_ENABLE); > + } else { > + /* fw 13.4.29 */ > + iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE > | > + CODA7_USE_HOST_DBK_ENABLE | > + CODA7_USE_IP_ENABLE | > + CODA7_USE_DBK_ENABLE); > + } > + } > +} > + > +static u32 coda_supported_firmwares[] = { > + CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), > + CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), > + CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5), > +}; > + > +static bool coda_firmware_supported(u32 vernum) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) > + if (vernum == coda_supported_firmwares[i]) > + return true; > + return false; > +} > + > +int coda_check_firmware(struct coda_dev *dev) > +{ > + u16 product, major, minor, release; > + u32 data; > + int 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; > + > + coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); > + coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > + coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); > + coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); > + coda_write(dev, CODA_COMMAND_FIRMWARE_GET, > CODA_REG_BIT_RUN_COMMAND); > + if (coda_wait_timeout(dev)) { > + v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); > + ret = -EIO; > + goto err_run_cmd; > + } > + > + if (dev->devtype->product == CODA_960) { > + data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV); > + v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n", > + data); > + } > + > + /* Check we are compatible with the loaded firmware */ > + data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM); > + product = CODA_FIRMWARE_PRODUCT(data); > + major = CODA_FIRMWARE_MAJOR(data); > + minor = CODA_FIRMWARE_MINOR(data); > + release = CODA_FIRMWARE_RELEASE(data); > + > + clk_disable_unprepare(dev->clk_per); > + clk_disable_unprepare(dev->clk_ahb); > + > + if (product != dev->devtype->product) { > + v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s," > + " Version: %u.%u.%u\n", > + coda_product_name(dev->devtype->product), > + coda_product_name(product), major, minor, release); > + return -EINVAL; > + } > + > + v4l2_info(&dev->v4l2_dev, "Initialized %s.\n", > + coda_product_name(product)); > + > + if (coda_firmware_supported(data)) { > + v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n", > + major, minor, release); > + } else { > + v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: " > + "%u.%u.%u\n", major, minor, release); > + } > + > + return 0; > + > +err_run_cmd: > + clk_disable_unprepare(dev->clk_ahb); > +err_clk_ahb: > + clk_disable_unprepare(dev->clk_per); > +err_clk_per: > + return ret; > +} > + > +/* > + * Encoder context operations > + */ > + > +static int coda_start_encoding(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; > + struct coda_q_data *q_data_src, *q_data_dst; > + u32 bitstream_buf, bitstream_size; > + struct vb2_buffer *buf; > + int gamma, ret, value; > + u32 dst_fourcc; > + > + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + dst_fourcc = q_data_dst->fourcc; > + > + /* Allocate per-instance buffers */ > + ret = coda_alloc_context_buffers(ctx, q_data_src); > + if (ret < 0) > + return ret; > + > + buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); > + bitstream_size = q_data_dst->sizeimage; > + > + if (!coda_is_initialized(dev)) { > + v4l2_err(v4l2_dev, "coda is not initialized.\n"); > + return -EFAULT; > + } > + > + mutex_lock(&dev->coda_mutex); > + > + coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); > + coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx- > >reg_idx)); > + coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx- > >reg_idx)); > + switch (dev->devtype->product) { > + case CODA_DX6: > + coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | > + CODADX6_STREAM_BUF_PIC_RESET, > CODA_REG_BIT_STREAM_CTRL); > + break; > + case CODA_960: > + coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); > + /* fallthrough */ > + case CODA_7541: > + coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | > + CODA7_STREAM_BUF_PIC_RESET, > CODA_REG_BIT_STREAM_CTRL); > + break; > + } > + > + value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL); > + value &= ~(1 << 2 | 0x7 << 9); > + ctx->frame_mem_ctrl = value; > + coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL); > + > + if (dev->devtype->product == CODA_DX6) { > + /* Configure the coda */ > + coda_write(dev, dev->iram.paddr, > CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); > + } > + > + /* Could set rotation here if needed */ > + switch (dev->devtype->product) { > + case CODA_DX6: > + value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << > CODADX6_PICWIDTH_OFFSET; > + value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > + break; > + case CODA_7541: > + if (dst_fourcc == V4L2_PIX_FMT_H264) { > + value = (round_up(q_data_src->width, 16) & > + CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; > + value |= (round_up(q_data_src->height, 16) & > + CODA7_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > + break; > + } > + /* fallthrough */ > + case CODA_960: > + value = (q_data_src->width & CODA7_PICWIDTH_MASK) << > CODA7_PICWIDTH_OFFSET; > + value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > + } > + coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); > + coda_write(dev, ctx->params.framerate, > + CODA_CMD_ENC_SEQ_SRC_F_RATE); > + > + ctx->params.codec_mode = ctx->codec->mode; > + switch (dst_fourcc) { > + case V4L2_PIX_FMT_MPEG4: > + if (dev->devtype->product == CODA_960) > + coda_write(dev, CODA9_STD_MPEG4, > CODA_CMD_ENC_SEQ_COD_STD); > + else > + coda_write(dev, CODA_STD_MPEG4, > CODA_CMD_ENC_SEQ_COD_STD); > + coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); > + break; > + case V4L2_PIX_FMT_H264: > + if (dev->devtype->product == CODA_960) > + coda_write(dev, CODA9_STD_H264, > CODA_CMD_ENC_SEQ_COD_STD); > + else > + coda_write(dev, CODA_STD_H264, > CODA_CMD_ENC_SEQ_COD_STD); > + if (ctx->params.h264_deblk_enabled) { > + value = ((ctx->params.h264_deblk_alpha & > + CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) << > + CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | > + ((ctx->params.h264_deblk_beta & > + CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) << > + CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET); > + } else { > + value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET; > + } > + coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); > + break; > + default: > + v4l2_err(v4l2_dev, > + "dst format (0x%08x) invalid.\n", dst_fourcc); > + ret = -EINVAL; > + goto out; > + } > + > + switch (ctx->params.slice_mode) { > + case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: > + value = 0; > + break; > + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: > + value = (ctx->params.slice_max_mb & > CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; > + value |= (1 & CODA_SLICING_UNIT_MASK) << > CODA_SLICING_UNIT_OFFSET; > + value |= 1 & CODA_SLICING_MODE_MASK; > + break; > + case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: > + value = (ctx->params.slice_max_bits & > CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; > + value |= (0 & CODA_SLICING_UNIT_MASK) << > CODA_SLICING_UNIT_OFFSET; > + value |= 1 & CODA_SLICING_MODE_MASK; > + break; > + } > + coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); > + value = ctx->params.gop_size & CODA_GOP_SIZE_MASK; > + coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); > + > + if (ctx->params.bitrate) { > + /* Rate control enabled */ > + value = (ctx->params.bitrate & > CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET; > + value |= 1 & CODA_RATECONTROL_ENABLE_MASK; > + if (dev->devtype->product == CODA_960) > + value |= BIT(31); /* disable autoskip */ > + } else { > + value = 0; > + } > + coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); > + > + coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); > + coda_write(dev, ctx->params.intra_refresh, > + CODA_CMD_ENC_SEQ_INTRA_REFRESH); > + > + coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); > + coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); > + > + > + value = 0; > + if (dev->devtype->product == CODA_960) > + gamma = CODA9_DEFAULT_GAMMA; > + else > + gamma = CODA_DEFAULT_GAMMA; > + if (gamma > 0) { > + coda_write(dev, (gamma & CODA_GAMMA_MASK) << > CODA_GAMMA_OFFSET, > + CODA_CMD_ENC_SEQ_RC_GAMMA); > + } > + > + if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) { > + coda_write(dev, > + ctx->params.h264_min_qp << CODA_QPMIN_OFFSET | > + ctx->params.h264_max_qp << CODA_QPMAX_OFFSET, > + CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); > + } > + if (dev->devtype->product == CODA_960) { > + if (ctx->params.h264_max_qp) > + value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET; > + if (CODA_DEFAULT_GAMMA > 0) > + value |= 1 << CODA9_OPTION_GAMMA_OFFSET; > + } else { > + if (CODA_DEFAULT_GAMMA > 0) { > + if (dev->devtype->product == CODA_DX6) > + value |= 1 << CODADX6_OPTION_GAMMA_OFFSET; > + else > + value |= 1 << CODA7_OPTION_GAMMA_OFFSET; > + } > + if (ctx->params.h264_min_qp) > + value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET; > + if (ctx->params.h264_max_qp) > + value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET; > + } > + coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); > + > + coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE); > + > + coda_setup_iram(ctx); > + > + if (dst_fourcc == V4L2_PIX_FMT_H264) { > + switch (dev->devtype->product) { > + case CODA_DX6: > + value = FMO_SLICE_SAVE_BUF_SIZE << 7; > + coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); > + break; > + case CODA_7541: > + coda_write(dev, ctx->iram_info.search_ram_paddr, > + CODA7_CMD_ENC_SEQ_SEARCH_BASE); > + coda_write(dev, ctx->iram_info.search_ram_size, > + CODA7_CMD_ENC_SEQ_SEARCH_SIZE); > + break; > + case CODA_960: > + coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION); > + coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT); > + } > + } > + > + ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); > + if (ret < 0) { > + v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); > + goto out; > + } > + > + if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { > + v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); > + ret = -EFAULT; > + goto out; > + } > + > + if (dev->devtype->product == CODA_960) > + ctx->num_internal_frames = 4; > + else > + ctx->num_internal_frames = 2; > + ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); > + if (ret < 0) { > + v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); > + goto out; > + } > + > + coda_write(dev, ctx->num_internal_frames, > CODA_CMD_SET_FRAME_BUF_NUM); > + coda_write(dev, q_data_src->bytesperline, > + CODA_CMD_SET_FRAME_BUF_STRIDE); > + if (dev->devtype->product == CODA_7541) { > + coda_write(dev, q_data_src->bytesperline, > + CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); > + } > + if (dev->devtype->product != CODA_DX6) { > + coda_write(dev, ctx->iram_info.buf_bit_use, > + CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); > + coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, > + CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); > + coda_write(dev, ctx->iram_info.buf_dbk_y_use, > + CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); > + coda_write(dev, ctx->iram_info.buf_dbk_c_use, > + CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); > + coda_write(dev, ctx->iram_info.buf_ovl_use, > + CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); > + if (dev->devtype->product == CODA_960) { > + coda_write(dev, ctx->iram_info.buf_btp_use, > + CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); > + > + /* FIXME */ > + coda_write(dev, ctx->internal_frames[2].paddr, > CODA9_CMD_SET_FRAME_SUBSAMP_A); > + coda_write(dev, ctx->internal_frames[3].paddr, > CODA9_CMD_SET_FRAME_SUBSAMP_B); > + } > + } > + > + ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); > + if (ret < 0) { > + v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); > + goto out; > + } > + > + /* Save stream headers */ > + buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + switch (dst_fourcc) { > + case V4L2_PIX_FMT_H264: > + /* > + * Get SPS in the first frame and copy it to an > + * intermediate buffer. > + */ > + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, > + &ctx->vpu_header[0][0], > + &ctx->vpu_header_size[0]); > + if (ret < 0) > + goto out; > + > + /* > + * Get PPS in the first frame and copy it to an > + * intermediate buffer. > + */ > + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, > + &ctx->vpu_header[1][0], > + &ctx->vpu_header_size[1]); > + if (ret < 0) > + goto out; > + > + /* > + * Length of H.264 headers is variable and thus it might > not be > + * aligned for the coda to append the encoded frame. In > that is > + * the case a filler NAL must be added to header 2. > + */ > + ctx->vpu_header_size[2] = coda_h264_padding( > + (ctx->vpu_header_size[0] + > + ctx->vpu_header_size[1]), > + ctx->vpu_header[2]); > + break; > + case V4L2_PIX_FMT_MPEG4: > + /* > + * Get VOS in the first frame and copy it to an > + * intermediate buffer > + */ > + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, > + &ctx->vpu_header[0][0], > + &ctx->vpu_header_size[0]); > + if (ret < 0) > + goto out; > + > + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, > + &ctx->vpu_header[1][0], > + &ctx->vpu_header_size[1]); > + if (ret < 0) > + goto out; > + > + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, > + &ctx->vpu_header[2][0], > + &ctx->vpu_header_size[2]); > + if (ret < 0) > + goto out; > + break; > + default: > + /* No more formats need to save headers at the moment */ > + break; > + } > + > +out: > + mutex_unlock(&dev->coda_mutex); > + return ret; > +} > + > +static int coda_prepare_encode(struct coda_ctx *ctx) > +{ > + struct coda_q_data *q_data_src, *q_data_dst; > + struct vb2_buffer *src_buf, *dst_buf; > + struct coda_dev *dev = ctx->dev; > + int force_ipicture; > + int quant_param = 0; > + u32 picture_y, picture_cb, picture_cr; > + u32 pic_stream_buffer_addr, pic_stream_buffer_size; > + u32 dst_fourcc; > + > + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + dst_fourcc = q_data_dst->fourcc; > + > + src_buf->v4l2_buf.sequence = ctx->osequence; > + dst_buf->v4l2_buf.sequence = ctx->osequence; > + ctx->osequence++; > + > + /* > + * Workaround coda firmware BUG that only marks the first > + * frame as IDR. This is a problem for some decoders that can't > + * recover when a frame is lost. > + */ > + if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) { > + src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; > + src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; > + } else { > + src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; > + src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; > + } > + > + if (dev->devtype->product == CODA_960) > + coda_set_gdi_regs(ctx); > + > + /* > + * Copy headers at the beginning of the first frame for H.264 > only. > + * In MPEG4 they are already copied by the coda. > + */ > + if (src_buf->v4l2_buf.sequence == 0) { > + pic_stream_buffer_addr = > + vb2_dma_contig_plane_dma_addr(dst_buf, 0) + > + ctx->vpu_header_size[0] + > + ctx->vpu_header_size[1] + > + ctx->vpu_header_size[2]; > + pic_stream_buffer_size = CODA_MAX_FRAME_SIZE - > + ctx->vpu_header_size[0] - > + ctx->vpu_header_size[1] - > + ctx->vpu_header_size[2]; > + memcpy(vb2_plane_vaddr(dst_buf, 0), > + &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); > + memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx- > >vpu_header_size[0], > + &ctx->vpu_header[1][0], ctx->vpu_header_size[1]); > + memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx- > >vpu_header_size[0] + > + ctx->vpu_header_size[1], &ctx->vpu_header[2][0], > + ctx->vpu_header_size[2]); > + } else { > + pic_stream_buffer_addr = > + vb2_dma_contig_plane_dma_addr(dst_buf, 0); > + pic_stream_buffer_size = CODA_MAX_FRAME_SIZE; > + } > + > + if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { > + force_ipicture = 1; > + switch (dst_fourcc) { > + case V4L2_PIX_FMT_H264: > + quant_param = ctx->params.h264_intra_qp; > + break; > + case V4L2_PIX_FMT_MPEG4: > + quant_param = ctx->params.mpeg4_intra_qp; > + break; > + default: > + v4l2_warn(&ctx->dev->v4l2_dev, > + "cannot set intra qp, fmt not supported\n"); > + break; > + } > + } else { > + force_ipicture = 0; > + switch (dst_fourcc) { > + case V4L2_PIX_FMT_H264: > + quant_param = ctx->params.h264_inter_qp; > + break; > + case V4L2_PIX_FMT_MPEG4: > + quant_param = ctx->params.mpeg4_inter_qp; > + break; > + default: > + v4l2_warn(&ctx->dev->v4l2_dev, > + "cannot set inter qp, fmt not supported\n"); > + break; > + } > + } > + > + /* submit */ > + coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, > CODA_CMD_ENC_PIC_ROT_MODE); > + coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); > + > + > + picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); > + switch (q_data_src->fourcc) { > + case V4L2_PIX_FMT_YVU420: > + /* Switch Cb and Cr for YVU420 format */ > + picture_cr = picture_y + q_data_src->bytesperline * > + q_data_src->height; > + picture_cb = picture_cr + q_data_src->bytesperline / 2 * > + q_data_src->height / 2; > + break; > + case V4L2_PIX_FMT_YUV420: > + default: > + picture_cb = picture_y + q_data_src->bytesperline * > + q_data_src->height; > + picture_cr = picture_cb + q_data_src->bytesperline / 2 * > + q_data_src->height / 2; > + break; > + } > + > + if (dev->devtype->product == CODA_960) { > + coda_write(dev, 4/*FIXME: 0*/, > CODA9_CMD_ENC_PIC_SRC_INDEX); > + coda_write(dev, q_data_src->width, > CODA9_CMD_ENC_PIC_SRC_STRIDE); > + coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); > + > + coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y); > + coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB); > + coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR); > + } else { > + coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); > + coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); > + coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); > + } > + coda_write(dev, force_ipicture << 1 & 0x2, > + CODA_CMD_ENC_PIC_OPTION); > + > + coda_write(dev, pic_stream_buffer_addr, > CODA_CMD_ENC_PIC_BB_START); > + coda_write(dev, pic_stream_buffer_size / 1024, > + CODA_CMD_ENC_PIC_BB_SIZE); > + > + if (!ctx->streamon_out) { > + /* After streamoff on the output side, set the stream end > flag */ > + ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; > + coda_write(dev, ctx->bit_stream_param, > CODA_REG_BIT_BIT_STREAM_PARAM); > + } > + > + if (dev->devtype->product != CODA_DX6) > + coda_write(dev, ctx->iram_info.axi_sram_use, > + CODA7_REG_BIT_AXI_SRAM_USE); > + > + coda_command_async(ctx, CODA_COMMAND_PIC_RUN); > + > + return 0; > +} > + > +static void coda_finish_encode(struct coda_ctx *ctx) > +{ > + struct vb2_buffer *src_buf, *dst_buf; > + struct coda_dev *dev = ctx->dev; > + u32 wr_ptr, start_ptr; > + > + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + > + /* Get results from the coda */ > + start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); > + wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > + > + /* Calculate bytesused field */ > + if (dst_buf->v4l2_buf.sequence == 0) { > + vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr + > + ctx->vpu_header_size[0] + > + ctx->vpu_header_size[1] + > + ctx->vpu_header_size[2]); > + } else { > + vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr); > + } > + > + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", > + wr_ptr - start_ptr); > + > + coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM); > + coda_read(dev, CODA_RET_ENC_PIC_FLAG); > + > + if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) { > + dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; > + dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; > + } else { > + dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; > + dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; > + } > + > + dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; > + dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; > + dst_buf->v4l2_buf.flags |= > + src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; > + dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; > + > + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); > + > + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > + v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); > + > + ctx->gopcounter--; > + if (ctx->gopcounter < 0) > + ctx->gopcounter = ctx->params.gop_size - 1; > + > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "job finished: encoding frame (%d) (%s)\n", > + dst_buf->v4l2_buf.sequence, > + (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? > + "KEYFRAME" : "PFRAME"); > +} > + > +static void coda_seq_end_work(struct work_struct *work) > +{ > + struct coda_ctx *ctx = container_of(work, struct coda_ctx, > seq_end_work); > + struct coda_dev *dev = ctx->dev; > + > + mutex_lock(&ctx->buffer_mutex); > + mutex_lock(&dev->coda_mutex); > + > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx, > __func__); > + if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { > + v4l2_err(&dev->v4l2_dev, > + "CODA_COMMAND_SEQ_END failed\n"); > + } > + > + kfifo_init(&ctx->bitstream_fifo, > + ctx->bitstream.vaddr, ctx->bitstream.size); > + > + coda_free_framebuffers(ctx); > + coda_free_context_buffers(ctx); > + > + mutex_unlock(&dev->coda_mutex); > + mutex_unlock(&ctx->buffer_mutex); > +} > + > +static void coda_bit_release(struct coda_ctx *ctx) > +{ > + coda_free_framebuffers(ctx); > + coda_free_context_buffers(ctx); > +} > + > +const struct coda_context_ops coda_bit_encode_ops = { > + .queue_init = coda_encoder_queue_init, > + .start_streaming = coda_start_encoding, > + .prepare_run = coda_prepare_encode, > + .finish_run = coda_finish_encode, > + .seq_end_work = coda_seq_end_work, > + .release = coda_bit_release, > +}; > + > +/* > + * Decoder context operations > + */ > + > +static int __coda_start_decoding(struct coda_ctx *ctx) > +{ > + struct coda_q_data *q_data_src, *q_data_dst; > + u32 bitstream_buf, bitstream_size; > + struct coda_dev *dev = ctx->dev; > + int width, height; > + u32 src_fourcc; > + u32 val; > + int ret; > + > + /* Start decoding */ > + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + bitstream_buf = ctx->bitstream.paddr; > + bitstream_size = ctx->bitstream.size; > + src_fourcc = q_data_src->fourcc; > + > + /* Allocate per-instance buffers */ > + ret = coda_alloc_context_buffers(ctx, q_data_src); > + if (ret < 0) > + return ret; > + > + coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); > + > + /* Update coda bitstream read and write pointers from kfifo */ > + coda_kfifo_sync_to_device_full(ctx); > + > + ctx->display_idx = -1; > + ctx->frm_dis_flg = 0; > + coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > + > + coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE, > + CODA_REG_BIT_BIT_STREAM_PARAM); > + > + coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); > + coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); > + val = 0; > + if ((dev->devtype->product == CODA_7541) || > + (dev->devtype->product == CODA_960)) > + val |= CODA_REORDER_ENABLE; > + coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); > + > + ctx->params.codec_mode = ctx->codec->mode; > + if (dev->devtype->product == CODA_960 && > + src_fourcc == V4L2_PIX_FMT_MPEG4) > + ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4; > + else > + ctx->params.codec_mode_aux = 0; > + if (src_fourcc == V4L2_PIX_FMT_H264) { > + if (dev->devtype->product == CODA_7541) { > + coda_write(dev, ctx->psbuf.paddr, > + CODA_CMD_DEC_SEQ_PS_BB_START); > + coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), > + CODA_CMD_DEC_SEQ_PS_BB_SIZE); > + } > + if (dev->devtype->product == CODA_960) { > + coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN); > + coda_write(dev, 512, > CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE); > + } > + } > + if (dev->devtype->product != CODA_960) > + coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE); > + > + if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { > + v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT > timeout\n"); > + coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); > + return -ETIMEDOUT; > + } > + > + /* Update kfifo out pointer from coda bitstream read pointer */ > + coda_kfifo_sync_from_device(ctx); > + > + coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); > + > + if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { > + v4l2_err(&dev->v4l2_dev, > + "CODA_COMMAND_SEQ_INIT failed, error code = %d\n", > + coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); > + return -EAGAIN; > + } > + > + val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); > + if (dev->devtype->product == CODA_DX6) { > + width = (val >> CODADX6_PICWIDTH_OFFSET) & > CODADX6_PICWIDTH_MASK; > + height = val & CODADX6_PICHEIGHT_MASK; > + } else { > + width = (val >> CODA7_PICWIDTH_OFFSET) & > CODA7_PICWIDTH_MASK; > + height = val & CODA7_PICHEIGHT_MASK; > + } > + > + if (width > q_data_dst->width || height > q_data_dst->height) { > + v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", > + width, height, q_data_dst->width, q_data_dst- > >height); > + return -EINVAL; > + } > + > + width = round_up(width, 16); > + height = round_up(height, 16); > + > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: > %dx%d\n", > + __func__, ctx->idx, width, height); > + > + ctx->num_internal_frames = coda_read(dev, > CODA_RET_DEC_SEQ_FRAME_NEED); > + if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { > + v4l2_err(&dev->v4l2_dev, > + "not enough framebuffers to decode (%d < %d)\n", > + CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); > + return -EINVAL; > + } > + > + if (src_fourcc == V4L2_PIX_FMT_H264) { > + u32 left_right; > + u32 top_bottom; > + > + left_right = coda_read(dev, > CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); > + top_bottom = coda_read(dev, > CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); > + > + q_data_dst->rect.left = (left_right >> 10) & 0x3ff; > + q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff; > + q_data_dst->rect.width = width - q_data_dst->rect.left - > + (left_right & 0x3ff); > + q_data_dst->rect.height = height - q_data_dst->rect.top - > + (top_bottom & 0x3ff); > + } > + > + ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); > + if (ret < 0) > + return ret; > + > + /* Tell the decoder how many frame buffers we allocated. */ > + coda_write(dev, ctx->num_internal_frames, > CODA_CMD_SET_FRAME_BUF_NUM); > + coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE); > + > + if (dev->devtype->product != CODA_DX6) { > + /* Set secondary AXI IRAM */ > + coda_setup_iram(ctx); > + > + coda_write(dev, ctx->iram_info.buf_bit_use, > + CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); > + coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, > + CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); > + coda_write(dev, ctx->iram_info.buf_dbk_y_use, > + CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); > + coda_write(dev, ctx->iram_info.buf_dbk_c_use, > + CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); > + coda_write(dev, ctx->iram_info.buf_ovl_use, > + CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); > + if (dev->devtype->product == CODA_960) > + coda_write(dev, ctx->iram_info.buf_btp_use, > + CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); > + } > + > + if (dev->devtype->product == CODA_960) { > + coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); > + > + coda_write(dev, 0x20262024, > CODA9_CMD_SET_FRAME_CACHE_SIZE); > + coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET | > + 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | > + 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | > + 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, > + CODA9_CMD_SET_FRAME_CACHE_CONFIG); > + } > + > + if (src_fourcc == V4L2_PIX_FMT_H264) { > + coda_write(dev, ctx->slicebuf.paddr, > + CODA_CMD_SET_FRAME_SLICE_BB_START); > + coda_write(dev, ctx->slicebuf.size / 1024, > + CODA_CMD_SET_FRAME_SLICE_BB_SIZE); > + } > + > + if (dev->devtype->product == CODA_7541) { > + int max_mb_x = 1920 / 16; > + int max_mb_y = 1088 / 16; > + int max_mb_num = max_mb_x * max_mb_y; > + > + coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | > max_mb_y, > + CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); > + } else if (dev->devtype->product == CODA_960) { > + int max_mb_x = 1920 / 16; > + int max_mb_y = 1088 / 16; > + int max_mb_num = max_mb_x * max_mb_y; > + > + coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | > max_mb_y, > + CODA9_CMD_SET_FRAME_MAX_DEC_SIZE); > + } > + > + if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { > + v4l2_err(&ctx->dev->v4l2_dev, > + "CODA_COMMAND_SET_FRAME_BUF timeout\n"); > + return -ETIMEDOUT; > + } > + > + return 0; > +} > + > +static int coda_start_decoding(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + int ret; > + > + mutex_lock(&dev->coda_mutex); > + ret = __coda_start_decoding(ctx); > + mutex_unlock(&dev->coda_mutex); > + > + return ret; > +} > + > +static int coda_prepare_decode(struct coda_ctx *ctx) > +{ > + struct vb2_buffer *dst_buf; > + struct coda_dev *dev = ctx->dev; > + struct coda_q_data *q_data_dst; > + u32 stridey, height; > + u32 picture_y, picture_cb, picture_cr; > + > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + > + if (ctx->params.rot_mode & CODA_ROT_90) { > + stridey = q_data_dst->height; > + height = q_data_dst->width; > + } else { > + stridey = q_data_dst->width; > + height = q_data_dst->height; > + } > + > + /* Try to copy source buffer contents into the bitstream > ringbuffer */ > + mutex_lock(&ctx->bitstream_mutex); > + coda_fill_bitstream(ctx); > + mutex_unlock(&ctx->bitstream_mutex); > + > + if (coda_get_bitstream_payload(ctx) < 512 && > + (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "bitstream payload: %d, skipping\n", > + coda_get_bitstream_payload(ctx)); > + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); > + return -EAGAIN; > + } > + > + /* Run coda_start_decoding (again) if not yet initialized */ > + if (!ctx->initialized) { > + int ret = __coda_start_decoding(ctx); > + > + if (ret < 0) { > + v4l2_err(&dev->v4l2_dev, "failed to start > decoding\n"); > + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx- > >fh.m2m_ctx); > + return -EAGAIN; > + } else { > + ctx->initialized = 1; > + } > + } > + > + if (dev->devtype->product == CODA_960) > + coda_set_gdi_regs(ctx); > + > + /* Set rotator output */ > + picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); > + if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { > + /* Switch Cr and Cb for YVU420 format */ > + picture_cr = picture_y + stridey * height; > + picture_cb = picture_cr + stridey / 2 * height / 2; > + } else { > + picture_cb = picture_y + stridey * height; > + picture_cr = picture_cb + stridey / 2 * height / 2; > + } > + > + if (dev->devtype->product == CODA_960) { > + /* > + * The CODA960 seems to have an internal list of buffers > with > + * 64 entries that includes the registered frame buffers as > + * well as the rotator buffer output. > + * ROT_INDEX needs to be < 0x40, but > ctx- > >num_internal_frames. > + */ > + coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf- > >v4l2_buf.index, > + CODA9_CMD_DEC_PIC_ROT_INDEX); > + coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y); > + coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB); > + coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR); > + coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE); > + } else { > + coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); > + coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); > + coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); > + coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); > + } > + coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, > + CODA_CMD_DEC_PIC_ROT_MODE); > + > + switch (dev->devtype->product) { > + case CODA_DX6: > + /* TBD */ > + case CODA_7541: > + coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); > + break; > + case CODA_960: > + coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /* > 'hardcode to use interrupt disable mode'? */ > + break; > + } > + > + coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); > + > + coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); > + coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); > + > + if (dev->devtype->product != CODA_DX6) > + coda_write(dev, ctx->iram_info.axi_sram_use, > + CODA7_REG_BIT_AXI_SRAM_USE); > + > + coda_kfifo_sync_to_device_full(ctx); > + > + coda_command_async(ctx, CODA_COMMAND_PIC_RUN); > + > + return 0; > +} > + > +static void coda_finish_decode(struct coda_ctx *ctx) > +{ > + struct coda_dev *dev = ctx->dev; > + struct coda_q_data *q_data_src; > + struct coda_q_data *q_data_dst; > + struct vb2_buffer *dst_buf; > + struct coda_timestamp *ts; > + int width, height; > + int decoded_idx; > + int display_idx; > + u32 src_fourcc; > + int success; > + u32 err_mb; > + u32 val; > + > + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > + > + /* Update kfifo out pointer from coda bitstream read pointer */ > + coda_kfifo_sync_from_device(ctx); > + > + /* > + * in stream-end mode, the read pointer can overshoot the write > pointer > + * by up to 512 bytes > + */ > + if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { > + if (coda_get_bitstream_payload(ctx) >= CODA_MAX_FRAME_SIZE > - 512) > + kfifo_init(&ctx->bitstream_fifo, > + ctx->bitstream.vaddr, ctx->bitstream.size); > + } > + > + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > + src_fourcc = q_data_src->fourcc; > + > + val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); > + if (val != 1) > + pr_err("DEC_PIC_SUCCESS = %d\n", val); > + > + success = val & 0x1; > + if (!success) > + v4l2_err(&dev->v4l2_dev, "decode failed\n"); > + > + if (src_fourcc == V4L2_PIX_FMT_H264) { > + if (val & (1 << 3)) > + v4l2_err(&dev->v4l2_dev, > + "insufficient PS buffer space (%d bytes)\n", > + ctx->psbuf.size); > + if (val & (1 << 2)) > + v4l2_err(&dev->v4l2_dev, > + "insufficient slice buffer space (%d > bytes)\n", > + ctx->slicebuf.size); > + } > + > + val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); > + width = (val >> 16) & 0xffff; > + height = val & 0xffff; > + > + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > + > + /* frame crop information */ > + if (src_fourcc == V4L2_PIX_FMT_H264) { > + u32 left_right; > + u32 top_bottom; > + > + left_right = coda_read(dev, > CODA_RET_DEC_PIC_CROP_LEFT_RIGHT); > + top_bottom = coda_read(dev, > CODA_RET_DEC_PIC_CROP_TOP_BOTTOM); > + > + if (left_right == 0xffffffff && top_bottom == 0xffffffff) { > + /* Keep current crop information */ > + } else { > + struct v4l2_rect *rect = &q_data_dst->rect; > + > + rect->left = left_right >> 16 & 0xffff; > + rect->top = top_bottom >> 16 & 0xffff; > + rect->width = width - rect->left - > + (left_right & 0xffff); > + rect->height = height - rect->top - > + (top_bottom & 0xffff); > + } > + } else { > + /* no cropping */ > + } > + > + err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); > + if (err_mb > 0) > + v4l2_err(&dev->v4l2_dev, > + "errors in %d macroblocks\n", err_mb); > + > + if (dev->devtype->product == CODA_7541) { > + val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); > + if (val == 0) { > + /* not enough bitstream data */ > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "prescan failed: %d\n", val); > + ctx->hold = true; > + return; > + } > + } > + > + ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx- > >reg_idx)); > + > + /* > + * The previous display frame was copied out by the rotator, > + * now it can be overwritten again > + */ > + if (ctx->display_idx >= 0 && > + ctx->display_idx < ctx->num_internal_frames) { > + ctx->frm_dis_flg &= ~(1 << ctx->display_idx); > + coda_write(dev, ctx->frm_dis_flg, > + CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > + } > + > + /* > + * The index of the last decoded frame, not necessarily in > + * display order, and the index of the next display frame. > + * The latter could have been decoded in a previous run. > + */ > + decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); > + display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); > + > + if (decoded_idx == -1) { > + /* no frame was decoded, but we might have a display frame > */ > + if (display_idx >= 0 && display_idx < ctx- > >num_internal_frames) > + ctx->sequence_offset++; > + else if (ctx->display_idx < 0) > + ctx->hold = true; > + } else if (decoded_idx == -2) { > + /* no frame was decoded, we still return the remaining > buffers */ > + } else if (decoded_idx < 0 || decoded_idx >= ctx- > >num_internal_frames) { > + v4l2_err(&dev->v4l2_dev, > + "decoded frame index out of range: %d\n", > decoded_idx); > + } else { > + ts = list_first_entry(&ctx->timestamp_list, > + struct coda_timestamp, list); > + list_del(&ts->list); > + val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; > + val -= ctx->sequence_offset; > + if (val != (ts->sequence & 0xffff)) { > + v4l2_err(&dev->v4l2_dev, > + "sequence number mismatch (%d(%d) != %d)\n", > + val, ctx->sequence_offset, ts->sequence); > + } > + ctx->frame_timestamps[decoded_idx] = *ts; > + kfree(ts); > + > + val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7; > + if (val == 0) > + ctx->frame_types[decoded_idx] = > V4L2_BUF_FLAG_KEYFRAME; > + else if (val == 1) > + ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME; > + else > + ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME; > + > + ctx->frame_errors[decoded_idx] = err_mb; > + } > + > + if (display_idx == -1) { > + /* > + * no more frames to be decoded, but there could still > + * be rotator output to dequeue > + */ > + ctx->hold = true; > + } else if (display_idx == -3) { > + /* possibly prescan failure */ > + } else if (display_idx < 0 || display_idx >= ctx- > >num_internal_frames) { > + v4l2_err(&dev->v4l2_dev, > + "presentation frame index out of range: %d\n", > + display_idx); > + } > + > + /* If a frame was copied out, return it */ > + if (ctx->display_idx >= 0 && > + ctx->display_idx < ctx->num_internal_frames) { > + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > + dst_buf->v4l2_buf.sequence = ctx->osequence++; > + > + dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | > + V4L2_BUF_FLAG_PFRAME | > + V4L2_BUF_FLAG_BFRAME); > + dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx- > >display_idx]; > + ts = &ctx->frame_timestamps[ctx->display_idx]; > + dst_buf->v4l2_buf.timecode = ts->timecode; > + dst_buf->v4l2_buf.timestamp = ts->timestamp; > + > + vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); > + > + v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ? > + VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); > + > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "job finished: decoding frame (%d) (%s)\n", > + dst_buf->v4l2_buf.sequence, > + (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? > + "KEYFRAME" : "PFRAME"); > + } else { > + v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > + "job finished: no frame decoded\n"); > + } > + > + /* The rotator will copy the current display frame next time */ > + ctx->display_idx = display_idx; > +} > + > +const struct coda_context_ops coda_bit_decode_ops = { > + .queue_init = coda_decoder_queue_init, > + .start_streaming = coda_start_decoding, > + .prepare_run = coda_prepare_decode, > + .finish_run = coda_finish_decode, > + .seq_end_work = coda_seq_end_work, > + .release = coda_bit_release, > +}; > + > +irqreturn_t coda_irq_handler(int irq, void *data) > +{ > + struct coda_dev *dev = data; > + struct coda_ctx *ctx; > + > + /* read status register to attend the IRQ */ > + coda_read(dev, CODA_REG_BIT_INT_STATUS); > + coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, > + CODA_REG_BIT_INT_CLEAR); > + > + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); > + if (ctx == NULL) { > + v4l2_err(&dev->v4l2_dev, "Instance released before the end > of transaction\n"); > + mutex_unlock(&dev->coda_mutex); > + return IRQ_HANDLED; > + } > + > + if (ctx->aborting) { > + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > + "task has been aborted\n"); > + } > + > + if (coda_isbusy(ctx->dev)) { > + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > + "coda is still busy!!!!\n"); > + return IRQ_NONE; > + } > + > + complete(&ctx->completion); > + > + return IRQ_HANDLED; > +} > diff --git a/drivers/media/platform/coda/coda-common.c > b/drivers/media/platform/coda/coda-common.c > index 5226dea..3b3a980 100644 > --- a/drivers/media/platform/coda/coda-common.c > +++ b/drivers/media/platform/coda/coda-common.c > @@ -48,12 +48,6 @@ > #define CODA_PARA_BUF_SIZE (10 * 1024) > #define CODA_ISRAM_SIZE (2048 * 2) > > -#define CODA7_PS_BUF_SIZE 0x28000 > -#define CODA9_PS_SAVE_SIZE (512 * 1024) > - > -#define CODA_DEFAULT_GAMMA 4096 > -#define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */ > - > #define MIN_W 176 > #define MIN_H 144 > > @@ -63,7 +57,7 @@ > > #define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) > > -static int coda_debug; > +int coda_debug; > module_param(coda_debug, int, 0644); > MODULE_PARM_DESC(coda_debug, "Debug level (0-1)"); > > @@ -88,128 +82,6 @@ unsigned int coda_read(struct coda_dev *dev, u32 > reg) > return data; > } > > -static inline unsigned long coda_isbusy(struct coda_dev *dev) > -{ > - return coda_read(dev, CODA_REG_BIT_BUSY); > -} > - > -static inline int coda_is_initialized(struct coda_dev *dev) > -{ > - return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0); > -} > - > -static int coda_wait_timeout(struct coda_dev *dev) > -{ > - unsigned long timeout = jiffies + msecs_to_jiffies(1000); > - > - while (coda_isbusy(dev)) { > - if (time_after(jiffies, timeout)) > - return -ETIMEDOUT; > - } > - return 0; > -} > - > -static void coda_command_async(struct coda_ctx *ctx, int cmd) > -{ > - struct coda_dev *dev = ctx->dev; > - > - if (dev->devtype->product == CODA_960 || > - dev->devtype->product == CODA_7541) { > - /* Restore context related registers to CODA */ > - coda_write(dev, ctx->bit_stream_param, > - CODA_REG_BIT_BIT_STREAM_PARAM); > - coda_write(dev, ctx->frm_dis_flg, > - CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > - coda_write(dev, ctx->frame_mem_ctrl, > - CODA_REG_BIT_FRAME_MEM_CTRL); > - coda_write(dev, ctx->workbuf.paddr, > CODA_REG_BIT_WORK_BUF_ADDR); > - } > - > - if (dev->devtype->product == CODA_960) { > - coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); > - coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); > - } > - > - coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > - > - coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); > - coda_write(dev, ctx->params.codec_mode, > CODA_REG_BIT_RUN_COD_STD); > - coda_write(dev, ctx->params.codec_mode_aux, > CODA7_REG_BIT_RUN_AUX_STD); > - > - coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); > -} > - > -static int coda_command_sync(struct coda_ctx *ctx, int cmd) > -{ > - struct coda_dev *dev = ctx->dev; > - > - coda_command_async(ctx, cmd); > - return coda_wait_timeout(dev); > -} > - > -static int coda_hw_reset(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - unsigned long timeout; > - unsigned int idx; > - int ret; > - > - if (!dev->rstc) > - return -ENOENT; > - > - idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); > - > - if (dev->devtype->product == CODA_960) { > - timeout = jiffies + msecs_to_jiffies(100); > - coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); > - while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { > - if (time_after(jiffies, timeout)) > - return -ETIME; > - cpu_relax(); > - } > - } > - > - ret = reset_control_reset(dev->rstc); > - if (ret < 0) > - return ret; > - > - if (dev->devtype->product == CODA_960) > - coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); > - coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > - coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); > - ret = coda_wait_timeout(dev); > - coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); > - > - return ret; > -} > - > -static void coda_bit_stream_end_flag(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - > - ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; > - > - if ((dev->devtype->product == CODA_960) && > - coda_isbusy(dev) && > - (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { > - /* If this context is currently running, update the > hardware flag */ > - coda_write(dev, ctx->bit_stream_param, > CODA_REG_BIT_BIT_STREAM_PARAM); > - } > -} > - > -static struct coda_q_data *get_q_data(struct coda_ctx *ctx, > - enum v4l2_buf_type type) > -{ > - switch (type) { > - case V4L2_BUF_TYPE_VIDEO_OUTPUT: > - return &(ctx->q_data[V4L2_M2M_SRC]); > - case V4L2_BUF_TYPE_VIDEO_CAPTURE: > - return &(ctx->q_data[V4L2_M2M_DST]); > - default: > - return NULL; > - } > -} > - > /* > * Array of all formats supported by any version of Coda: > */ > @@ -330,7 +202,7 @@ static void coda_get_max_dimensions(struct coda_dev > *dev, > *max_h = h; > } > > -static char *coda_product_name(int product) > +const char *coda_product_name(int product) > { > static char buf[9]; > > @@ -804,124 +676,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops > = { > .vidioc_unsubscribe_event = v4l2_event_unsubscribe, > }; > > -static int __coda_start_decoding(struct coda_ctx *ctx); > - > -static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) > -{ > - return kfifo_len(&ctx->bitstream_fifo); > -} > - > -static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) > -{ > - struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > - struct coda_dev *dev = ctx->dev; > - u32 rd_ptr; > - > - rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); > - kfifo->out = (kfifo->in & ~kfifo->mask) | > - (rd_ptr - ctx->bitstream.paddr); > - if (kfifo->out > kfifo->in) > - kfifo->out -= kfifo->mask + 1; > -} > - > -static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) > -{ > - struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > - struct coda_dev *dev = ctx->dev; > - u32 rd_ptr, wr_ptr; > - > - rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); > - coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); > - wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); > - coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > -} > - > -static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) > -{ > - struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; > - struct coda_dev *dev = ctx->dev; > - u32 wr_ptr; > - > - wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); > - coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > -} > - > -static int coda_bitstream_queue(struct coda_ctx *ctx, struct > vb2_buffer *src_buf) > -{ > - u32 src_size = vb2_get_plane_payload(src_buf, 0); > - u32 n; > - > - n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0), > src_size); > - if (n < src_size) > - return -ENOSPC; > - > - dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx- > >bitstream.paddr, > - ctx->bitstream.size, DMA_TO_DEVICE); > - > - src_buf->v4l2_buf.sequence = ctx->qsequence++; > - > - return 0; > -} > - > -static bool coda_bitstream_try_queue(struct coda_ctx *ctx, > - struct vb2_buffer *src_buf) > -{ > - int ret; > - > - if (coda_get_bitstream_payload(ctx) + > - vb2_get_plane_payload(src_buf, 0) + 512 >= ctx- > >bitstream.size) > - return false; > - > - if (vb2_plane_vaddr(src_buf, 0) == NULL) { > - v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty > buffer\n"); > - return true; > - } > - > - ret = coda_bitstream_queue(ctx, src_buf); > - if (ret < 0) { > - v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer > overflow\n"); > - return false; > - } > - /* Sync read pointer to device */ > - if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) > - coda_kfifo_sync_to_device_write(ctx); > - > - ctx->hold = false; > - > - return true; > -} > - > -static void coda_fill_bitstream(struct coda_ctx *ctx) > -{ > - struct vb2_buffer *src_buf; > - struct coda_timestamp *ts; > - > - while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { > - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > - > - if (coda_bitstream_try_queue(ctx, src_buf)) { > - /* > - * Source buffer is queued in the bitstream > ringbuffer; > - * queue the timestamp and mark source buffer as done > - */ > - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); > - > - ts = kmalloc(sizeof(*ts), GFP_KERNEL); > - if (ts) { > - ts->sequence = src_buf->v4l2_buf.sequence; > - ts->timecode = src_buf->v4l2_buf.timecode; > - ts->timestamp = src_buf->v4l2_buf.timestamp; > - list_add_tail(&ts->list, &ctx->timestamp_list); > - } > - > - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); > - } else { > - break; > - } > - } > -} > - > -static void coda_set_gdi_regs(struct coda_ctx *ctx) > +void coda_set_gdi_regs(struct coda_ctx *ctx) > { > struct gdi_tiled_map *tiled_map = &ctx->tiled_map; > struct coda_dev *dev = ctx->dev; > @@ -945,264 +700,6 @@ static void coda_set_gdi_regs(struct coda_ctx > *ctx) > /* > * Mem-to-mem operations. > */ > -static int coda_prepare_decode(struct coda_ctx *ctx) > -{ > - struct vb2_buffer *dst_buf; > - struct coda_dev *dev = ctx->dev; > - struct coda_q_data *q_data_dst; > - u32 stridey, height; > - u32 picture_y, picture_cb, picture_cr; > - > - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - > - if (ctx->params.rot_mode & CODA_ROT_90) { > - stridey = q_data_dst->height; > - height = q_data_dst->width; > - } else { > - stridey = q_data_dst->width; > - height = q_data_dst->height; > - } > - > - /* Try to copy source buffer contents into the bitstream > ringbuffer */ > - mutex_lock(&ctx->bitstream_mutex); > - coda_fill_bitstream(ctx); > - mutex_unlock(&ctx->bitstream_mutex); > - > - if (coda_get_bitstream_payload(ctx) < 512 && > - (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "bitstream payload: %d, skipping\n", > - coda_get_bitstream_payload(ctx)); > - v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); > - return -EAGAIN; > - } > - > - /* Run coda_start_decoding (again) if not yet initialized */ > - if (!ctx->initialized) { > - int ret = __coda_start_decoding(ctx); > - if (ret < 0) { > - v4l2_err(&dev->v4l2_dev, "failed to start > decoding\n"); > - v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx- > >fh.m2m_ctx); > - return -EAGAIN; > - } else { > - ctx->initialized = 1; > - } > - } > - > - if (dev->devtype->product == CODA_960) > - coda_set_gdi_regs(ctx); > - > - /* Set rotator output */ > - picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0); > - if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) { > - /* Switch Cr and Cb for YVU420 format */ > - picture_cr = picture_y + stridey * height; > - picture_cb = picture_cr + stridey / 2 * height / 2; > - } else { > - picture_cb = picture_y + stridey * height; > - picture_cr = picture_cb + stridey / 2 * height / 2; > - } > - > - if (dev->devtype->product == CODA_960) { > - /* > - * The CODA960 seems to have an internal list of buffers > with > - * 64 entries that includes the registered frame buffers as > - * well as the rotator buffer output. > - * ROT_INDEX needs to be < 0x40, but > ctx- > >num_internal_frames. > - */ > - coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf- > >v4l2_buf.index, > - CODA9_CMD_DEC_PIC_ROT_INDEX); > - coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y); > - coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB); > - coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR); > - coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE); > - } else { > - coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y); > - coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB); > - coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR); > - coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE); > - } > - coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, > - CODA_CMD_DEC_PIC_ROT_MODE); > - > - switch (dev->devtype->product) { > - case CODA_DX6: > - /* TBD */ > - case CODA_7541: > - coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); > - break; > - case CODA_960: > - coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /* > 'hardcode to use interrupt disable mode'? */ > - break; > - } > - > - coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); > - > - coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); > - coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); > - > - if (dev->devtype->product != CODA_DX6) > - coda_write(dev, ctx->iram_info.axi_sram_use, > - CODA7_REG_BIT_AXI_SRAM_USE); > - > - coda_kfifo_sync_to_device_full(ctx); > - coda_command_async(ctx, CODA_COMMAND_PIC_RUN); > - > - return 0; > -} > - > -static int coda_prepare_encode(struct coda_ctx *ctx) > -{ > - struct coda_q_data *q_data_src, *q_data_dst; > - struct vb2_buffer *src_buf, *dst_buf; > - struct coda_dev *dev = ctx->dev; > - int force_ipicture; > - int quant_param = 0; > - u32 picture_y, picture_cb, picture_cr; > - u32 pic_stream_buffer_addr, pic_stream_buffer_size; > - u32 dst_fourcc; > - > - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); > - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - dst_fourcc = q_data_dst->fourcc; > - > - src_buf->v4l2_buf.sequence = ctx->osequence; > - dst_buf->v4l2_buf.sequence = ctx->osequence; > - ctx->osequence++; > - > - /* > - * Workaround coda firmware BUG that only marks the first > - * frame as IDR. This is a problem for some decoders that can't > - * recover when a frame is lost. > - */ > - if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) { > - src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; > - src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; > - } else { > - src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; > - src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; > - } > - > - if (dev->devtype->product == CODA_960) > - coda_set_gdi_regs(ctx); > - > - /* > - * Copy headers at the beginning of the first frame for H.264 > only. > - * In MPEG4 they are already copied by the coda. > - */ > - if (src_buf->v4l2_buf.sequence == 0) { > - pic_stream_buffer_addr = > - vb2_dma_contig_plane_dma_addr(dst_buf, 0) + > - ctx->vpu_header_size[0] + > - ctx->vpu_header_size[1] + > - ctx->vpu_header_size[2]; > - pic_stream_buffer_size = CODA_MAX_FRAME_SIZE - > - ctx->vpu_header_size[0] - > - ctx->vpu_header_size[1] - > - ctx->vpu_header_size[2]; > - memcpy(vb2_plane_vaddr(dst_buf, 0), > - &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); > - memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx- > >vpu_header_size[0], > - &ctx->vpu_header[1][0], ctx->vpu_header_size[1]); > - memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx- > >vpu_header_size[0] + > - ctx->vpu_header_size[1], &ctx->vpu_header[2][0], > - ctx->vpu_header_size[2]); > - } else { > - pic_stream_buffer_addr = > - vb2_dma_contig_plane_dma_addr(dst_buf, 0); > - pic_stream_buffer_size = CODA_MAX_FRAME_SIZE; > - } > - > - if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) { > - force_ipicture = 1; > - switch (dst_fourcc) { > - case V4L2_PIX_FMT_H264: > - quant_param = ctx->params.h264_intra_qp; > - break; > - case V4L2_PIX_FMT_MPEG4: > - quant_param = ctx->params.mpeg4_intra_qp; > - break; > - default: > - v4l2_warn(&ctx->dev->v4l2_dev, > - "cannot set intra qp, fmt not supported\n"); > - break; > - } > - } else { > - force_ipicture = 0; > - switch (dst_fourcc) { > - case V4L2_PIX_FMT_H264: > - quant_param = ctx->params.h264_inter_qp; > - break; > - case V4L2_PIX_FMT_MPEG4: > - quant_param = ctx->params.mpeg4_inter_qp; > - break; > - default: > - v4l2_warn(&ctx->dev->v4l2_dev, > - "cannot set inter qp, fmt not supported\n"); > - break; > - } > - } > - > - /* submit */ > - coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, > CODA_CMD_ENC_PIC_ROT_MODE); > - coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); > - > - > - picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); > - switch (q_data_src->fourcc) { > - case V4L2_PIX_FMT_YVU420: > - /* Switch Cb and Cr for YVU420 format */ > - picture_cr = picture_y + q_data_src->bytesperline * > - q_data_src->height; > - picture_cb = picture_cr + q_data_src->bytesperline / 2 * > - q_data_src->height / 2; > - break; > - case V4L2_PIX_FMT_YUV420: > - default: > - picture_cb = picture_y + q_data_src->bytesperline * > - q_data_src->height; > - picture_cr = picture_cb + q_data_src->bytesperline / 2 * > - q_data_src->height / 2; > - break; > - } > - > - if (dev->devtype->product == CODA_960) { > - coda_write(dev, 4/*FIXME: 0*/, > CODA9_CMD_ENC_PIC_SRC_INDEX); > - coda_write(dev, q_data_src->width, > CODA9_CMD_ENC_PIC_SRC_STRIDE); > - coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); > - > - coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y); > - coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB); > - coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR); > - } else { > - coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); > - coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); > - coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR); > - } > - coda_write(dev, force_ipicture << 1 & 0x2, > - CODA_CMD_ENC_PIC_OPTION); > - > - coda_write(dev, pic_stream_buffer_addr, > CODA_CMD_ENC_PIC_BB_START); > - coda_write(dev, pic_stream_buffer_size / 1024, > - CODA_CMD_ENC_PIC_BB_SIZE); > - > - if (!ctx->streamon_out) { > - /* After streamoff on the output side, set the stream end > flag */ > - ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; > - coda_write(dev, ctx->bit_stream_param, > CODA_REG_BIT_BIT_STREAM_PARAM); > - } > - > - if (dev->devtype->product != CODA_DX6) > - coda_write(dev, ctx->iram_info.axi_sram_use, > - CODA7_REG_BIT_AXI_SRAM_USE); > - > - coda_command_async(ctx, CODA_COMMAND_PIC_RUN); > - > - return 0; > -} > > static void coda_device_run(void *m2m_priv) > { > @@ -1212,37 +709,6 @@ static void coda_device_run(void *m2m_priv) > queue_work(dev->workqueue, &ctx->pic_run_work); > } > > -static void coda_free_framebuffers(struct coda_ctx *ctx); > -static void coda_free_context_buffers(struct coda_ctx *ctx); > - > -static void coda_seq_end_work(struct work_struct *work) > -{ > - struct coda_ctx *ctx = container_of(work, struct coda_ctx, > seq_end_work); > - struct coda_dev *dev = ctx->dev; > - > - mutex_lock(&ctx->buffer_mutex); > - mutex_lock(&dev->coda_mutex); > - > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx, > __func__); > - if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { > - v4l2_err(&dev->v4l2_dev, > - "CODA_COMMAND_SEQ_END failed\n"); > - } > - > - kfifo_init(&ctx->bitstream_fifo, > - ctx->bitstream.vaddr, ctx->bitstream.size); > - > - coda_free_framebuffers(ctx); > - coda_free_context_buffers(ctx); > - > - mutex_unlock(&dev->coda_mutex); > - mutex_unlock(&ctx->buffer_mutex); > -} > - > -static void coda_finish_decode(struct coda_ctx *ctx); > -static void coda_finish_encode(struct coda_ctx *ctx); > - > static void coda_pic_run_work(struct work_struct *work) > { > struct coda_ctx *ctx = container_of(work, struct coda_ctx, > pic_run_work); > @@ -1502,20 +968,8 @@ static void coda_buf_queue(struct vb2_buffer *vb) > } > } > > -static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 > value) > -{ > - struct coda_dev *dev = ctx->dev; > - u32 *p = ctx->parabuf.vaddr; > - > - if (dev->devtype->product == CODA_DX6) > - p[index] = value; > - else > - p[index ^ 1] = value; > -} > - > -static int coda_alloc_aux_buf(struct coda_dev *dev, > - struct coda_aux_buf *buf, size_t size, > - const char *name, struct dentry *parent) > +int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, > + size_t size, const char *name, struct dentry > *parent) > { > buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf- > >paddr, > GFP_KERNEL); > @@ -1536,15 +990,8 @@ static int coda_alloc_aux_buf(struct coda_dev > *dev, > return 0; > } > > -static inline int coda_alloc_context_buf(struct coda_ctx *ctx, > - struct coda_aux_buf *buf, size_t size, > - const char *name) > -{ > - return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx- > >debugfs_entry); > -} > - > -static void coda_free_aux_buf(struct coda_dev *dev, > - struct coda_aux_buf *buf) > +void coda_free_aux_buf(struct coda_dev *dev, > + struct coda_aux_buf *buf) > { > if (buf->vaddr) { > dma_free_coherent(&dev->plat_dev->dev, buf->size, > @@ -1555,538 +1002,21 @@ static void coda_free_aux_buf(struct coda_dev > *dev, > debugfs_remove(buf->dentry); > } > > -static void coda_free_framebuffers(struct coda_ctx *ctx) > +static int coda_start_streaming(struct vb2_queue *q, unsigned int > count) > { > - int i; > + struct coda_ctx *ctx = vb2_get_drv_priv(q); > + struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; > + struct coda_q_data *q_data_src, *q_data_dst; > + u32 dst_fourcc; > + int ret = 0; > > - for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) > - coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]); > -} > - > -static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct > coda_q_data *q_data, u32 fourcc) > -{ > - struct coda_dev *dev = ctx->dev; > - int width, height; > - dma_addr_t paddr; > - int ysize; > - int ret; > - int i; > - > - if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || > - ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) { > - width = round_up(q_data->width, 16); > - height = round_up(q_data->height, 16); > - } else { > - width = round_up(q_data->width, 8); > - height = q_data->height; > - } > - ysize = width * height; > - > - /* Allocate frame buffers */ > - for (i = 0; i < ctx->num_internal_frames; i++) { > - size_t size; > - char *name; > - > - size = ysize + ysize / 2; > - if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && > - dev->devtype->product != CODA_DX6) > - size += ysize / 4; > - name = kasprintf(GFP_KERNEL, "fb%d", i); > - ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], > - size, name); > - kfree(name); > - if (ret < 0) { > - coda_free_framebuffers(ctx); > - return ret; > - } > - } > - > - /* Register frame buffers in the parameter buffer */ > - for (i = 0; i < ctx->num_internal_frames; i++) { > - paddr = ctx->internal_frames[i].paddr; > - coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */ > - coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ > - coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + > ysize/4); /* Cr */ > - > - /* mvcol buffer for h.264 */ > - if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 && > - dev->devtype->product != CODA_DX6) > - coda_parabuf_write(ctx, 96 + i, > - ctx->internal_frames[i].paddr + > - ysize + ysize/4 + ysize/4); > - } > - > - /* mvcol buffer for mpeg4 */ > - if ((dev->devtype->product != CODA_DX6) && > - (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4)) > - coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr + > - ysize + ysize/4 + ysize/4); > - > - return 0; > -} > - > -static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t > size) > -{ > - phys_addr_t ret; > - > - size = round_up(size, 1024); > - if (size > iram->remaining) > - return 0; > - iram->remaining -= size; > - > - ret = iram->next_paddr; > - iram->next_paddr += size; > - > - return ret; > -} > - > -static void coda_setup_iram(struct coda_ctx *ctx) > -{ > - struct coda_iram_info *iram_info = &ctx->iram_info; > - struct coda_dev *dev = ctx->dev; > - int mb_width; > - int dbk_bits; > - int bit_bits; > - int ip_bits; > - > - memset(iram_info, 0, sizeof(*iram_info)); > - iram_info->next_paddr = dev->iram.paddr; > - iram_info->remaining = dev->iram.size; > - > - switch (dev->devtype->product) { > - case CODA_7541: > - dbk_bits = CODA7_USE_HOST_DBK_ENABLE | > CODA7_USE_DBK_ENABLE; > - bit_bits = CODA7_USE_HOST_BIT_ENABLE | > CODA7_USE_BIT_ENABLE; > - ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; > - break; > - case CODA_960: > - dbk_bits = CODA9_USE_HOST_DBK_ENABLE | > CODA9_USE_DBK_ENABLE; > - bit_bits = CODA9_USE_HOST_BIT_ENABLE | > CODA7_USE_BIT_ENABLE; > - ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; > - break; > - default: /* CODA_DX6 */ > - return; > - } > - > - if (ctx->inst_type == CODA_INST_ENCODER) { > - struct coda_q_data *q_data_src; > - > - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > - mb_width = DIV_ROUND_UP(q_data_src->width, 16); > - > - /* Prioritize in case IRAM is too small for everything */ > - if (dev->devtype->product == CODA_7541) { > - iram_info->search_ram_size = round_up(mb_width * 16 * > - 36 + 2048, 1024); > - iram_info->search_ram_paddr = > coda_iram_alloc(iram_info, > - iram_info->search_ram_size); > - if (!iram_info->search_ram_paddr) { > - pr_err("IRAM is smaller than the search ram > size\n"); > - goto out; > - } > - iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE | > - CODA7_USE_ME_ENABLE; > - } > - > - /* Only H.264BP and H.263P3 are considered */ > - iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * > mb_width); > - iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * > mb_width); > - if (!iram_info->buf_dbk_c_use) > - goto out; > - iram_info->axi_sram_use |= dbk_bits; > - > - iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * > mb_width); > - if (!iram_info->buf_bit_use) > - goto out; > - iram_info->axi_sram_use |= bit_bits; > - > - iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, > 128 * mb_width); > - if (!iram_info->buf_ip_ac_dc_use) > - goto out; > - iram_info->axi_sram_use |= ip_bits; > - > - /* OVL and BTP disabled for encoder */ > - } else if (ctx->inst_type == CODA_INST_DECODER) { > - struct coda_q_data *q_data_dst; > - > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - mb_width = DIV_ROUND_UP(q_data_dst->width, 16); > - > - iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * > mb_width); > - iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * > mb_width); > - if (!iram_info->buf_dbk_c_use) > - goto out; > - iram_info->axi_sram_use |= dbk_bits; > - > - iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * > mb_width); > - if (!iram_info->buf_bit_use) > - goto out; > - iram_info->axi_sram_use |= bit_bits; > - > - iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, > 128 * mb_width); > - if (!iram_info->buf_ip_ac_dc_use) > - goto out; > - iram_info->axi_sram_use |= ip_bits; > - > - /* OVL and BTP unused as there is no VC1 support yet */ > - } > - > -out: > - if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) > - v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > - "IRAM smaller than needed\n"); > - > - if (dev->devtype->product == CODA_7541) { > - /* TODO - Enabling these causes picture errors on CODA7541 > */ > - if (ctx->inst_type == CODA_INST_DECODER) { > - /* fw 1.4.50 */ > - iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE > | > - CODA7_USE_IP_ENABLE); > - } else { > - /* fw 13.4.29 */ > - iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE > | > - CODA7_USE_HOST_DBK_ENABLE | > - CODA7_USE_IP_ENABLE | > - CODA7_USE_DBK_ENABLE); > - } > - } > -} > - > -static void coda_free_context_buffers(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - > - coda_free_aux_buf(dev, &ctx->slicebuf); > - coda_free_aux_buf(dev, &ctx->psbuf); > - if (dev->devtype->product != CODA_DX6) > - coda_free_aux_buf(dev, &ctx->workbuf); > -} > - > -static int coda_alloc_context_buffers(struct coda_ctx *ctx, > - struct coda_q_data *q_data) > -{ > - struct coda_dev *dev = ctx->dev; > - size_t size; > - int ret; > - > - if (dev->devtype->product == CODA_DX6) > - return 0; > - > - if (ctx->psbuf.vaddr) { > - v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n"); > - return -EBUSY; > - } > - if (ctx->slicebuf.vaddr) { > - v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n"); > - return -EBUSY; > - } > - if (ctx->workbuf.vaddr) { > - v4l2_err(&dev->v4l2_dev, "context buffer still > allocated\n"); > - ret = -EBUSY; > - return -ENOMEM; > - } > - > - if (q_data->fourcc == V4L2_PIX_FMT_H264) { > - /* worst case slice size */ > - size = (DIV_ROUND_UP(q_data->width, 16) * > - DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512; > - ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, > "slicebuf"); > - if (ret < 0) { > - v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte > slice buffer", > - ctx->slicebuf.size); > - return ret; > - } > - } > - > - if (dev->devtype->product == CODA_7541) { > - ret = coda_alloc_context_buf(ctx, &ctx->psbuf, > CODA7_PS_BUF_SIZE, "psbuf"); > - if (ret < 0) { > - v4l2_err(&dev->v4l2_dev, "failed to allocate psmem > buffer"); > - goto err; > - } > - } > - > - size = dev->devtype->workbuf_size; > - if (dev->devtype->product == CODA_960 && > - q_data->fourcc == V4L2_PIX_FMT_H264) > - size += CODA9_PS_SAVE_SIZE; > - ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, > "workbuf"); > - if (ret < 0) { > - v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte > context buffer", > - ctx->workbuf.size); > - goto err; > - } > - > - return 0; > - > -err: > - coda_free_context_buffers(ctx); > - return ret; > -} > - > -static int __coda_start_decoding(struct coda_ctx *ctx) > -{ > - struct coda_q_data *q_data_src, *q_data_dst; > - u32 bitstream_buf, bitstream_size; > - struct coda_dev *dev = ctx->dev; > - int width, height; > - u32 src_fourcc; > - u32 val; > - int ret; > - > - /* Start decoding */ > - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - bitstream_buf = ctx->bitstream.paddr; > - bitstream_size = ctx->bitstream.size; > - src_fourcc = q_data_src->fourcc; > - > - /* Allocate per-instance buffers */ > - ret = coda_alloc_context_buffers(ctx, q_data_src); > - if (ret < 0) > - return ret; > - > - coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); > - > - /* Update coda bitstream read and write pointers from kfifo */ > - coda_kfifo_sync_to_device_full(ctx); > - > - ctx->display_idx = -1; > - ctx->frm_dis_flg = 0; > - coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > - > - coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE, > - CODA_REG_BIT_BIT_STREAM_PARAM); > - > - coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); > - coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); > - val = 0; > - if ((dev->devtype->product == CODA_7541) || > - (dev->devtype->product == CODA_960)) > - val |= CODA_REORDER_ENABLE; > - coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); > - > - ctx->params.codec_mode = ctx->codec->mode; > - if (dev->devtype->product == CODA_960 && > - src_fourcc == V4L2_PIX_FMT_MPEG4) > - ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4; > - else > - ctx->params.codec_mode_aux = 0; > - if (src_fourcc == V4L2_PIX_FMT_H264) { > - if (dev->devtype->product == CODA_7541) { > - coda_write(dev, ctx->psbuf.paddr, > - CODA_CMD_DEC_SEQ_PS_BB_START); > - coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), > - CODA_CMD_DEC_SEQ_PS_BB_SIZE); > - } > - if (dev->devtype->product == CODA_960) { > - coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN); > - coda_write(dev, 512, > CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE); > - } > - } > - if (dev->devtype->product != CODA_960) { > - coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE); > - } > - > - if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { > - v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT > timeout\n"); > - coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); > - return -ETIMEDOUT; > - } > - > - /* Update kfifo out pointer from coda bitstream read pointer */ > - coda_kfifo_sync_from_device(ctx); > - > - coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); > - > - if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { > - v4l2_err(&dev->v4l2_dev, > - "CODA_COMMAND_SEQ_INIT failed, error code = %d\n", > - coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); > - return -EAGAIN; > - } > - > - val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); > - if (dev->devtype->product == CODA_DX6) { > - width = (val >> CODADX6_PICWIDTH_OFFSET) & > CODADX6_PICWIDTH_MASK; > - height = val & CODADX6_PICHEIGHT_MASK; > - } else { > - width = (val >> CODA7_PICWIDTH_OFFSET) & > CODA7_PICWIDTH_MASK; > - height = val & CODA7_PICHEIGHT_MASK; > - } > - > - if (width > q_data_dst->width || height > q_data_dst->height) { > - v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", > - width, height, q_data_dst->width, q_data_dst- > >height); > - return -EINVAL; > - } > - > - width = round_up(width, 16); > - height = round_up(height, 16); > - > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: > %dx%d\n", > - __func__, ctx->idx, width, height); > - > - ctx->num_internal_frames = coda_read(dev, > CODA_RET_DEC_SEQ_FRAME_NEED); > - if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { > - v4l2_err(&dev->v4l2_dev, > - "not enough framebuffers to decode (%d < %d)\n", > - CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); > - return -EINVAL; > - } > - > - if (src_fourcc == V4L2_PIX_FMT_H264) { > - u32 left_right; > - u32 top_bottom; > - > - left_right = coda_read(dev, > CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); > - top_bottom = coda_read(dev, > CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); > - > - q_data_dst->rect.left = (left_right >> 10) & 0x3ff; > - q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff; > - q_data_dst->rect.width = width - q_data_dst->rect.left - > - (left_right & 0x3ff); > - q_data_dst->rect.height = height - q_data_dst->rect.top - > - (top_bottom & 0x3ff); > - } > - > - ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); > - if (ret < 0) > - return ret; > - > - /* Tell the decoder how many frame buffers we allocated. */ > - coda_write(dev, ctx->num_internal_frames, > CODA_CMD_SET_FRAME_BUF_NUM); > - coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE); > - > - if (dev->devtype->product != CODA_DX6) { > - /* Set secondary AXI IRAM */ > - coda_setup_iram(ctx); > - > - coda_write(dev, ctx->iram_info.buf_bit_use, > - CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); > - coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, > - CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); > - coda_write(dev, ctx->iram_info.buf_dbk_y_use, > - CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); > - coda_write(dev, ctx->iram_info.buf_dbk_c_use, > - CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); > - coda_write(dev, ctx->iram_info.buf_ovl_use, > - CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); > - if (dev->devtype->product == CODA_960) > - coda_write(dev, ctx->iram_info.buf_btp_use, > - CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); > - } > - > - if (dev->devtype->product == CODA_960) { > - coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); > - > - coda_write(dev, 0x20262024, > CODA9_CMD_SET_FRAME_CACHE_SIZE); > - coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET | > - 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | > - 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET | > - 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET, > - CODA9_CMD_SET_FRAME_CACHE_CONFIG); > - } > - > - if (src_fourcc == V4L2_PIX_FMT_H264) { > - coda_write(dev, ctx->slicebuf.paddr, > - CODA_CMD_SET_FRAME_SLICE_BB_START); > - coda_write(dev, ctx->slicebuf.size / 1024, > - CODA_CMD_SET_FRAME_SLICE_BB_SIZE); > - } > - > - if (dev->devtype->product == CODA_7541) { > - int max_mb_x = 1920 / 16; > - int max_mb_y = 1088 / 16; > - int max_mb_num = max_mb_x * max_mb_y; > - > - coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | > max_mb_y, > - CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); > - } else if (dev->devtype->product == CODA_960) { > - int max_mb_x = 1920 / 16; > - int max_mb_y = 1088 / 16; > - int max_mb_num = max_mb_x * max_mb_y; > - > - coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | > max_mb_y, > - CODA9_CMD_SET_FRAME_MAX_DEC_SIZE); > - } > - > - if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { > - v4l2_err(&ctx->dev->v4l2_dev, > - "CODA_COMMAND_SET_FRAME_BUF timeout\n"); > - return -ETIMEDOUT; > - } > - > - return 0; > -} > - > -static int coda_start_decoding(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - int ret; > - > - mutex_lock(&dev->coda_mutex); > - ret = __coda_start_decoding(ctx); > - mutex_unlock(&dev->coda_mutex); > - > - return ret; > -} > - > -static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer > *buf, > - int header_code, u8 *header, int *size) > -{ > - struct coda_dev *dev = ctx->dev; > - size_t bufsize; > - int ret; > - int i; > - > - if (dev->devtype->product == CODA_960) > - memset(vb2_plane_vaddr(buf, 0), 0, 64); > - > - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), > - CODA_CMD_ENC_HEADER_BB_START); > - bufsize = vb2_plane_size(buf, 0); > - if (dev->devtype->product == CODA_960) > - bufsize /= 1024; > - coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); > - coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); > - ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); > - if (ret < 0) { > - v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER > timeout\n"); > - return ret; > - } > - > - if (dev->devtype->product == CODA_960) { > - for (i = 63; i > 0; i--) > - if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0) > - break; > - *size = i + 1; > - } else { > - *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - > - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); > - } > - memcpy(header, vb2_plane_vaddr(buf, 0), *size); > - > - return 0; > -} > - > -static int coda_start_encoding(struct coda_ctx *ctx); > - > -static int coda_start_streaming(struct vb2_queue *q, unsigned int > count) > -{ > - struct coda_ctx *ctx = vb2_get_drv_priv(q); > - struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; > - struct coda_q_data *q_data_src, *q_data_dst; > - u32 dst_fourcc; > - int ret = 0; > - > - 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) { > - /* copy the buffers that where queued before streamon > */ > - mutex_lock(&ctx->bitstream_mutex); > - coda_fill_bitstream(ctx); > - mutex_unlock(&ctx->bitstream_mutex); > + 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) { > + /* copy the buffers that where queued before streamon > */ > + mutex_lock(&ctx->bitstream_mutex); > + coda_fill_bitstream(ctx); > + mutex_unlock(&ctx->bitstream_mutex); > > if (coda_get_bitstream_payload(ctx) < 512) > return -EINVAL; > @@ -2134,337 +1064,6 @@ static int coda_start_streaming(struct > vb2_queue *q, unsigned int count) > return ret; > } > > -static int coda_start_encoding(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - struct v4l2_device *v4l2_dev = &dev->v4l2_dev; > - struct coda_q_data *q_data_src, *q_data_dst; > - u32 bitstream_buf, bitstream_size; > - struct vb2_buffer *buf; > - int gamma, ret, value; > - u32 dst_fourcc; > - > - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - dst_fourcc = q_data_dst->fourcc; > - > - /* Allocate per-instance buffers */ > - ret = coda_alloc_context_buffers(ctx, q_data_src); > - if (ret < 0) > - return ret; > - > - buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); > - bitstream_size = q_data_dst->sizeimage; > - > - if (!coda_is_initialized(dev)) { > - v4l2_err(v4l2_dev, "coda is not initialized.\n"); > - return -EFAULT; > - } > - > - mutex_lock(&dev->coda_mutex); > - > - coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); > - coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx- > >reg_idx)); > - coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx- > >reg_idx)); > - switch (dev->devtype->product) { > - case CODA_DX6: > - coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | > - CODADX6_STREAM_BUF_PIC_RESET, > CODA_REG_BIT_STREAM_CTRL); > - break; > - case CODA_960: > - coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); > - /* fallthrough */ > - case CODA_7541: > - coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | > - CODA7_STREAM_BUF_PIC_RESET, > CODA_REG_BIT_STREAM_CTRL); > - break; > - } > - > - value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL); > - value &= ~(1 << 2 | 0x7 << 9); > - ctx->frame_mem_ctrl = value; > - coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL); > - > - if (dev->devtype->product == CODA_DX6) { > - /* Configure the coda */ > - coda_write(dev, dev->iram.paddr, > CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); > - } > - > - /* Could set rotation here if needed */ > - switch (dev->devtype->product) { > - case CODA_DX6: > - value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << > CODADX6_PICWIDTH_OFFSET; > - value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > - break; > - case CODA_7541: > - if (dst_fourcc == V4L2_PIX_FMT_H264) { > - value = (round_up(q_data_src->width, 16) & > - CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; > - value |= (round_up(q_data_src->height, 16) & > - CODA7_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > - break; > - } > - /* fallthrough */ > - case CODA_960: > - value = (q_data_src->width & CODA7_PICWIDTH_MASK) << > CODA7_PICWIDTH_OFFSET; > - value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << > CODA_PICHEIGHT_OFFSET; > - } > - coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); > - coda_write(dev, ctx->params.framerate, > - CODA_CMD_ENC_SEQ_SRC_F_RATE); > - > - ctx->params.codec_mode = ctx->codec->mode; > - switch (dst_fourcc) { > - case V4L2_PIX_FMT_MPEG4: > - if (dev->devtype->product == CODA_960) > - coda_write(dev, CODA9_STD_MPEG4, > CODA_CMD_ENC_SEQ_COD_STD); > - else > - coda_write(dev, CODA_STD_MPEG4, > CODA_CMD_ENC_SEQ_COD_STD); > - coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); > - break; > - case V4L2_PIX_FMT_H264: > - if (dev->devtype->product == CODA_960) > - coda_write(dev, CODA9_STD_H264, > CODA_CMD_ENC_SEQ_COD_STD); > - else > - coda_write(dev, CODA_STD_H264, > CODA_CMD_ENC_SEQ_COD_STD); > - if (ctx->params.h264_deblk_enabled) { > - value = ((ctx->params.h264_deblk_alpha & > - CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) << > - CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | > - ((ctx->params.h264_deblk_beta & > - CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) << > - CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET); > - } else { > - value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET; > - } > - coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); > - break; > - default: > - v4l2_err(v4l2_dev, > - "dst format (0x%08x) invalid.\n", dst_fourcc); > - ret = -EINVAL; > - goto out; > - } > - > - switch (ctx->params.slice_mode) { > - case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: > - value = 0; > - break; > - case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB: > - value = (ctx->params.slice_max_mb & > CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; > - value |= (1 & CODA_SLICING_UNIT_MASK) << > CODA_SLICING_UNIT_OFFSET; > - value |= 1 & CODA_SLICING_MODE_MASK; > - break; > - case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES: > - value = (ctx->params.slice_max_bits & > CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET; > - value |= (0 & CODA_SLICING_UNIT_MASK) << > CODA_SLICING_UNIT_OFFSET; > - value |= 1 & CODA_SLICING_MODE_MASK; > - break; > - } > - coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); > - value = ctx->params.gop_size & CODA_GOP_SIZE_MASK; > - coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); > - > - if (ctx->params.bitrate) { > - /* Rate control enabled */ > - value = (ctx->params.bitrate & > CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET; > - value |= 1 & CODA_RATECONTROL_ENABLE_MASK; > - if (dev->devtype->product == CODA_960) > - value |= BIT(31); /* disable autoskip */ > - } else { > - value = 0; > - } > - coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); > - > - coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); > - coda_write(dev, ctx->params.intra_refresh, > - CODA_CMD_ENC_SEQ_INTRA_REFRESH); > - > - coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); > - coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); > - > - > - value = 0; > - if (dev->devtype->product == CODA_960) > - gamma = CODA9_DEFAULT_GAMMA; > - else > - gamma = CODA_DEFAULT_GAMMA; > - if (gamma > 0) { > - coda_write(dev, (gamma & CODA_GAMMA_MASK) << > CODA_GAMMA_OFFSET, > - CODA_CMD_ENC_SEQ_RC_GAMMA); > - } > - > - if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) { > - coda_write(dev, > - ctx->params.h264_min_qp << CODA_QPMIN_OFFSET | > - ctx->params.h264_max_qp << CODA_QPMAX_OFFSET, > - CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); > - } > - if (dev->devtype->product == CODA_960) { > - if (ctx->params.h264_max_qp) > - value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET; > - if (CODA_DEFAULT_GAMMA > 0) > - value |= 1 << CODA9_OPTION_GAMMA_OFFSET; > - } else { > - if (CODA_DEFAULT_GAMMA > 0) { > - if (dev->devtype->product == CODA_DX6) > - value |= 1 << CODADX6_OPTION_GAMMA_OFFSET; > - else > - value |= 1 << CODA7_OPTION_GAMMA_OFFSET; > - } > - if (ctx->params.h264_min_qp) > - value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET; > - if (ctx->params.h264_max_qp) > - value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET; > - } > - coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); > - > - coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE); > - > - coda_setup_iram(ctx); > - > - if (dst_fourcc == V4L2_PIX_FMT_H264) { > - switch (dev->devtype->product) { > - case CODA_DX6: > - value = FMO_SLICE_SAVE_BUF_SIZE << 7; > - coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); > - break; > - case CODA_7541: > - coda_write(dev, ctx->iram_info.search_ram_paddr, > - CODA7_CMD_ENC_SEQ_SEARCH_BASE); > - coda_write(dev, ctx->iram_info.search_ram_size, > - CODA7_CMD_ENC_SEQ_SEARCH_SIZE); > - break; > - case CODA_960: > - coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION); > - coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT); > - } > - } > - > - ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); > - if (ret < 0) { > - v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); > - goto out; > - } > - > - if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { > - v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); > - ret = -EFAULT; > - goto out; > - } > - > - if (dev->devtype->product == CODA_960) > - ctx->num_internal_frames = 4; > - else > - ctx->num_internal_frames = 2; > - ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); > - if (ret < 0) { > - v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); > - goto out; > - } > - > - coda_write(dev, ctx->num_internal_frames, > CODA_CMD_SET_FRAME_BUF_NUM); > - coda_write(dev, q_data_src->bytesperline, > - CODA_CMD_SET_FRAME_BUF_STRIDE); > - if (dev->devtype->product == CODA_7541) { > - coda_write(dev, q_data_src->bytesperline, > - CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); > - } > - if (dev->devtype->product != CODA_DX6) { > - coda_write(dev, ctx->iram_info.buf_bit_use, > - CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); > - coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, > - CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); > - coda_write(dev, ctx->iram_info.buf_dbk_y_use, > - CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); > - coda_write(dev, ctx->iram_info.buf_dbk_c_use, > - CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); > - coda_write(dev, ctx->iram_info.buf_ovl_use, > - CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); > - if (dev->devtype->product == CODA_960) { > - coda_write(dev, ctx->iram_info.buf_btp_use, > - CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); > - > - /* FIXME */ > - coda_write(dev, ctx->internal_frames[2].paddr, > CODA9_CMD_SET_FRAME_SUBSAMP_A); > - coda_write(dev, ctx->internal_frames[3].paddr, > CODA9_CMD_SET_FRAME_SUBSAMP_B); > - } > - } > - > - ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); > - if (ret < 0) { > - v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); > - goto out; > - } > - > - /* Save stream headers */ > - buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - switch (dst_fourcc) { > - case V4L2_PIX_FMT_H264: > - /* > - * Get SPS in the first frame and copy it to an > - * intermediate buffer. > - */ > - ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, > - &ctx->vpu_header[0][0], > - &ctx->vpu_header_size[0]); > - if (ret < 0) > - goto out; > - > - /* > - * Get PPS in the first frame and copy it to an > - * intermediate buffer. > - */ > - ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, > - &ctx->vpu_header[1][0], > - &ctx->vpu_header_size[1]); > - if (ret < 0) > - goto out; > - > - /* > - * Length of H.264 headers is variable and thus it might > not be > - * aligned for the coda to append the encoded frame. In > that is > - * the case a filler NAL must be added to header 2. > - */ > - ctx->vpu_header_size[2] = coda_h264_padding( > - (ctx->vpu_header_size[0] + > - ctx->vpu_header_size[1]), > - ctx->vpu_header[2]); > - break; > - case V4L2_PIX_FMT_MPEG4: > - /* > - * Get VOS in the first frame and copy it to an > - * intermediate buffer > - */ > - ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, > - &ctx->vpu_header[0][0], > - &ctx->vpu_header_size[0]); > - if (ret < 0) > - goto out; > - > - ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, > - &ctx->vpu_header[1][0], > - &ctx->vpu_header_size[1]); > - if (ret < 0) > - goto out; > - > - ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, > - &ctx->vpu_header[2][0], > - &ctx->vpu_header_size[2]); > - if (ret < 0) > - goto out; > - break; > - default: > - /* No more formats need to save headers at the moment */ > - break; > - } > - > -out: > - mutex_unlock(&dev->coda_mutex); > - return ret; > -} > - > static void coda_stop_streaming(struct vb2_queue *q) > { > struct coda_ctx *ctx = vb2_get_drv_priv(q); > @@ -2664,8 +1263,8 @@ static int coda_queue_init(struct coda_ctx *ctx, > struct vb2_queue *vq) > return vb2_queue_init(vq); > } > > -static int coda_encoder_queue_init(void *priv, struct vb2_queue > *src_vq, > - struct vb2_queue *dst_vq) > +int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, > + struct vb2_queue *dst_vq) > { > int ret; > > @@ -2684,8 +1283,8 @@ static int coda_encoder_queue_init(void *priv, > struct vb2_queue *src_vq, > return coda_queue_init(priv, dst_vq); > } > > -static int coda_decoder_queue_init(void *priv, struct vb2_queue > *src_vq, > - struct vb2_queue *dst_vq) > +int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, > + struct vb2_queue *dst_vq) > { > int ret; > > @@ -2845,38 +1444,14 @@ err_coda_max: > return ret; > } > > -static void coda_bit_release(struct coda_ctx *ctx) > -{ > - coda_free_framebuffers(ctx); > - coda_free_context_buffers(ctx); > -} > - > -struct coda_context_ops coda_encode_ops = { > - .queue_init = coda_encoder_queue_init, > - .start_streaming = coda_start_encoding, > - .prepare_run = coda_prepare_encode, > - .finish_run = coda_finish_encode, > - .seq_end_work = coda_seq_end_work, > - .release = coda_bit_release, > -}; > - > -struct coda_context_ops coda_decode_ops = { > - .queue_init = coda_decoder_queue_init, > - .start_streaming = coda_start_decoding, > - .prepare_run = coda_prepare_decode, > - .finish_run = coda_finish_decode, > - .seq_end_work = coda_seq_end_work, > - .release = coda_bit_release, > -}; > - > static int coda_encoder_open(struct file *file) > { > - return coda_open(file, CODA_INST_ENCODER, &coda_encode_ops); > + return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops); > } > > static int coda_decoder_open(struct file *file) > { > - return coda_open(file, CODA_INST_DECODER, &coda_decode_ops); > + return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops); > } > > static int coda_release(struct file *file) > @@ -2940,316 +1515,6 @@ static const struct v4l2_file_operations > coda_decoder_fops = { > .mmap = v4l2_m2m_fop_mmap, > }; > > -static void coda_finish_decode(struct coda_ctx *ctx) > -{ > - struct coda_dev *dev = ctx->dev; > - struct coda_q_data *q_data_src; > - struct coda_q_data *q_data_dst; > - struct vb2_buffer *dst_buf; > - struct coda_timestamp *ts; > - int width, height; > - int decoded_idx; > - int display_idx; > - u32 src_fourcc; > - int success; > - u32 err_mb; > - u32 val; > - > - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - > - /* Update kfifo out pointer from coda bitstream read pointer */ > - coda_kfifo_sync_from_device(ctx); > - > - /* > - * in stream-end mode, the read pointer can overshoot the write > pointer > - * by up to 512 bytes > - */ > - if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { > - if (coda_get_bitstream_payload(ctx) >= CODA_MAX_FRAME_SIZE > - 512) > - kfifo_init(&ctx->bitstream_fifo, > - ctx->bitstream.vaddr, ctx->bitstream.size); > - } > - > - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); > - src_fourcc = q_data_src->fourcc; > - > - val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); > - if (val != 1) > - pr_err("DEC_PIC_SUCCESS = %d\n", val); > - > - success = val & 0x1; > - if (!success) > - v4l2_err(&dev->v4l2_dev, "decode failed\n"); > - > - if (src_fourcc == V4L2_PIX_FMT_H264) { > - if (val & (1 << 3)) > - v4l2_err(&dev->v4l2_dev, > - "insufficient PS buffer space (%d bytes)\n", > - ctx->psbuf.size); > - if (val & (1 << 2)) > - v4l2_err(&dev->v4l2_dev, > - "insufficient slice buffer space (%d > bytes)\n", > - ctx->slicebuf.size); > - } > - > - val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); > - width = (val >> 16) & 0xffff; > - height = val & 0xffff; > - > - q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); > - > - /* frame crop information */ > - if (src_fourcc == V4L2_PIX_FMT_H264) { > - u32 left_right; > - u32 top_bottom; > - > - left_right = coda_read(dev, > CODA_RET_DEC_PIC_CROP_LEFT_RIGHT); > - top_bottom = coda_read(dev, > CODA_RET_DEC_PIC_CROP_TOP_BOTTOM); > - > - if (left_right == 0xffffffff && top_bottom == 0xffffffff) { > - /* Keep current crop information */ > - } else { > - struct v4l2_rect *rect = &q_data_dst->rect; > - > - rect->left = left_right >> 16 & 0xffff; > - rect->top = top_bottom >> 16 & 0xffff; > - rect->width = width - rect->left - > - (left_right & 0xffff); > - rect->height = height - rect->top - > - (top_bottom & 0xffff); > - } > - } else { > - /* no cropping */ > - } > - > - err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); > - if (err_mb > 0) > - v4l2_err(&dev->v4l2_dev, > - "errors in %d macroblocks\n", err_mb); > - > - if (dev->devtype->product == CODA_7541) { > - val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); > - if (val == 0) { > - /* not enough bitstream data */ > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "prescan failed: %d\n", val); > - ctx->hold = true; > - return; > - } > - } > - > - ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx- > >reg_idx)); > - > - /* > - * The previous display frame was copied out by the rotator, > - * now it can be overwritten again > - */ > - if (ctx->display_idx >= 0 && > - ctx->display_idx < ctx->num_internal_frames) { > - ctx->frm_dis_flg &= ~(1 << ctx->display_idx); > - coda_write(dev, ctx->frm_dis_flg, > - CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); > - } > - > - /* > - * The index of the last decoded frame, not necessarily in > - * display order, and the index of the next display frame. > - * The latter could have been decoded in a previous run. > - */ > - decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); > - display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); > - > - if (decoded_idx == -1) { > - /* no frame was decoded, but we might have a display frame > */ > - if (display_idx >= 0 && display_idx < ctx- > >num_internal_frames) > - ctx->sequence_offset++; > - else if (ctx->display_idx < 0) > - ctx->hold = true; > - } else if (decoded_idx == -2) { > - /* no frame was decoded, we still return the remaining > buffers */ > - } else if (decoded_idx < 0 || decoded_idx >= ctx- > >num_internal_frames) { > - v4l2_err(&dev->v4l2_dev, > - "decoded frame index out of range: %d\n", > decoded_idx); > - } else { > - ts = list_first_entry(&ctx->timestamp_list, > - struct coda_timestamp, list); > - list_del(&ts->list); > - val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1; > - val -= ctx->sequence_offset; > - if (val != (ts->sequence & 0xffff)) { > - v4l2_err(&dev->v4l2_dev, > - "sequence number mismatch (%d(%d) != %d)\n", > - val, ctx->sequence_offset, ts->sequence); > - } > - ctx->frame_timestamps[decoded_idx] = *ts; > - kfree(ts); > - > - val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7; > - if (val == 0) > - ctx->frame_types[decoded_idx] = > V4L2_BUF_FLAG_KEYFRAME; > - else if (val == 1) > - ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME; > - else > - ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME; > - > - ctx->frame_errors[decoded_idx] = err_mb; > - } > - > - if (display_idx == -1) { > - /* > - * no more frames to be decoded, but there could still > - * be rotator output to dequeue > - */ > - ctx->hold = true; > - } else if (display_idx == -3) { > - /* possibly prescan failure */ > - } else if (display_idx < 0 || display_idx >= ctx- > >num_internal_frames) { > - v4l2_err(&dev->v4l2_dev, > - "presentation frame index out of range: %d\n", > - display_idx); > - } > - > - /* If a frame was copied out, return it */ > - if (ctx->display_idx >= 0 && > - ctx->display_idx < ctx->num_internal_frames) { > - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > - dst_buf->v4l2_buf.sequence = ctx->osequence++; > - > - dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME | > - V4L2_BUF_FLAG_PFRAME | > - V4L2_BUF_FLAG_BFRAME); > - dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx- > >display_idx]; > - ts = &ctx->frame_timestamps[ctx->display_idx]; > - dst_buf->v4l2_buf.timecode = ts->timecode; > - dst_buf->v4l2_buf.timestamp = ts->timestamp; > - > - vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2); > - > - v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ? > - VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); > - > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "job finished: decoding frame (%d) (%s)\n", > - dst_buf->v4l2_buf.sequence, > - (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? > - "KEYFRAME" : "PFRAME"); > - } else { > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "job finished: no frame decoded\n"); > - } > - > - /* The rotator will copy the current display frame next time */ > - ctx->display_idx = display_idx; > -} > - > -static void coda_finish_encode(struct coda_ctx *ctx) > -{ > - struct vb2_buffer *src_buf, *dst_buf; > - struct coda_dev *dev = ctx->dev; > - u32 wr_ptr, start_ptr; > - > - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); > - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); > - > - /* Get results from the coda */ > - start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); > - wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); > - > - /* Calculate bytesused field */ > - if (dst_buf->v4l2_buf.sequence == 0) { > - vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr + > - ctx->vpu_header_size[0] + > - ctx->vpu_header_size[1] + > - ctx->vpu_header_size[2]); > - } else { > - vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr); > - } > - > - v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n", > - wr_ptr - start_ptr); > - > - coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM); > - coda_read(dev, CODA_RET_ENC_PIC_FLAG); > - > - if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) { > - dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; > - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME; > - } else { > - dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME; > - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME; > - } > - > - dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp; > - dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; > - dst_buf->v4l2_buf.flags |= > - src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; > - dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode; > - > - v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); > - > - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); > - v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); > - > - ctx->gopcounter--; > - if (ctx->gopcounter < 0) > - ctx->gopcounter = ctx->params.gop_size - 1; > - > - v4l2_dbg(1, coda_debug, &dev->v4l2_dev, > - "job finished: encoding frame (%d) (%s)\n", > - dst_buf->v4l2_buf.sequence, > - (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? > - "KEYFRAME" : "PFRAME"); > -} > - > -static irqreturn_t coda_irq_handler(int irq, void *data) > -{ > - struct coda_dev *dev = data; > - struct coda_ctx *ctx; > - > - /* read status register to attend the IRQ */ > - coda_read(dev, CODA_REG_BIT_INT_STATUS); > - coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, > - CODA_REG_BIT_INT_CLEAR); > - > - ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); > - if (ctx == NULL) { > - v4l2_err(&dev->v4l2_dev, "Instance released before the end > of transaction\n"); > - mutex_unlock(&dev->coda_mutex); > - return IRQ_HANDLED; > - } > - > - if (ctx->aborting) { > - v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > - "task has been aborted\n"); > - } > - > - if (coda_isbusy(ctx->dev)) { > - v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, > - "coda is still busy!!!!\n"); > - return IRQ_NONE; > - } > - > - complete(&ctx->completion); > - > - return IRQ_HANDLED; > -} > - > -static u32 coda_supported_firmwares[] = { > - CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), > - CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), > - CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5), > -}; > - > -static bool coda_firmware_supported(u32 vernum) > -{ > - int i; > - > - for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) > - if (vernum == coda_supported_firmwares[i]) > - return true; > - return false; > -} > - > static int coda_hw_init(struct coda_dev *dev) > { > u32 data; > @@ -3346,76 +1611,6 @@ err_clk_per: > return ret; > } > > -static int coda_check_firmware(struct coda_dev *dev) > -{ > - u16 product, major, minor, release; > - u32 data; > - int 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; > - > - coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); > - coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); > - coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); > - coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); > - coda_write(dev, CODA_COMMAND_FIRMWARE_GET, > CODA_REG_BIT_RUN_COMMAND); > - if (coda_wait_timeout(dev)) { > - v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); > - ret = -EIO; > - goto err_run_cmd; > - } > - > - if (dev->devtype->product == CODA_960) { > - data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV); > - v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n", > - data); > - } > - > - /* Check we are compatible with the loaded firmware */ > - data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM); > - product = CODA_FIRMWARE_PRODUCT(data); > - major = CODA_FIRMWARE_MAJOR(data); > - minor = CODA_FIRMWARE_MINOR(data); > - release = CODA_FIRMWARE_RELEASE(data); > - > - clk_disable_unprepare(dev->clk_per); > - clk_disable_unprepare(dev->clk_ahb); > - > - if (product != dev->devtype->product) { > - v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s," > - " Version: %u.%u.%u\n", > - coda_product_name(dev->devtype->product), > - coda_product_name(product), major, minor, release); > - return -EINVAL; > - } > - > - v4l2_info(&dev->v4l2_dev, "Initialized %s.\n", > - coda_product_name(product)); > - > - if (coda_firmware_supported(data)) { > - v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n", > - major, minor, release); > - } else { > - v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: " > - "%u.%u.%u\n", major, minor, release); > - } > - > - return 0; > - > -err_run_cmd: > - clk_disable_unprepare(dev->clk_ahb); > -err_clk_ahb: > - clk_disable_unprepare(dev->clk_per); > -err_clk_per: > - return ret; > -} > - > static int coda_register_device(struct coda_dev *dev, struct > video_device *vfd) > { > vfd->release = video_device_release_empty, > diff --git a/drivers/media/platform/coda/coda.h > b/drivers/media/platform/coda/coda.h > index 84e0829..bbc18c0 100644 > --- a/drivers/media/platform/coda/coda.h > +++ b/drivers/media/platform/coda/coda.h > @@ -228,4 +228,60 @@ struct coda_ctx { > struct dentry *debugfs_entry; > }; > > +extern int coda_debug; > + > +void coda_write(struct coda_dev *dev, u32 data, u32 reg); > +unsigned int coda_read(struct coda_dev *dev, u32 reg); > + > +int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, > + size_t size, const char *name, struct dentry > *parent); > +void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf > *buf); > + > +static inline int coda_alloc_context_buf(struct coda_ctx *ctx, > + struct coda_aux_buf *buf, size_t size, > + const char *name) > +{ > + return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx- > >debugfs_entry); > +} > + > +int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, > + struct vb2_queue *dst_vq); > +int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, > + struct vb2_queue *dst_vq); > + > +int coda_hw_reset(struct coda_ctx *ctx); > + > +void coda_fill_bitstream(struct coda_ctx *ctx); > + > +void coda_set_gdi_regs(struct coda_ctx *ctx); > + > +static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx, > + enum v4l2_buf_type type) > +{ > + switch (type) { > + case V4L2_BUF_TYPE_VIDEO_OUTPUT: > + return &(ctx->q_data[V4L2_M2M_SRC]); > + case V4L2_BUF_TYPE_VIDEO_CAPTURE: > + return &(ctx->q_data[V4L2_M2M_DST]); > + default: > + return NULL; > + } > +} > + > +const char *coda_product_name(int product); > + > +int coda_check_firmware(struct coda_dev *dev); > + > +static inline int coda_get_bitstream_payload(struct coda_ctx *ctx) > +{ > + return kfifo_len(&ctx->bitstream_fifo); > +} > + > +void coda_bit_stream_end_flag(struct coda_ctx *ctx); > + > int coda_h264_padding(int size, char *p); > + > +extern const struct coda_context_ops coda_bit_encode_ops; > +extern const struct coda_context_ops coda_bit_decode_ops; > + > +irqreturn_t coda_irq_handler(int irq, void *data); > -- > 2.0.1