{ },
};
+/* default configuration stream 64x64 yuv422 */
static const unsigned char jpeg_soi[] = {0xFF, 0xD8};
static const unsigned char jpeg_app0[] = {0xFF, 0xE0, 0x00, 0x10, 0x4A,
0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00,
mxc_jpeg_enc_mode_go(dev, reg);
goto job_unlock;
}
+ if (ctx->mode == MXC_JPEG_DECODE && ctx->dht_needed) {
+ ctx->dht_needed = false;
+ dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n");
+ goto job_unlock;
+ }
if (ctx->mode == MXC_JPEG_ENCODE) {
payload_size = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));
vb2_set_plane_payload(dst_buf, 0, payload_size);
static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
int slot,
- struct mxc_jpeg_dev *jpeg,
+ struct mxc_jpeg_ctx *ctx,
struct vb2_buffer *src_buf, struct vb2_buffer *dst_buf)
{
+ struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
void __iomem *reg = jpeg->base_reg;
struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
+ struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
+ dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
+ dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
+ unsigned int cfg_stream_size = jpeg->slot_data[slot].cfg_stream_size;
+ if (ctx->dht_needed) {
+ /*
+ * use the config descriptor to inject a default huffman table
+ * by chaining it before the decoding descriptor
+ */
+ cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
+ cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ cfg_desc->buf_base1 = 0;
+ cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16;
+ cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT;
+ cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2;
+ cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);
+ cfg_desc->stm_bufbase = cfg_stream_handle;
+ cfg_desc->stm_bufsize = mxc_jpeg_align(cfg_stream_size, 1024);
+ print_descriptor_info(jpeg->dev, cfg_desc);
+ }
+
+ desc->next_descpt_ptr = 0; /* end of chain */
mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
mxc_jpeg_set_bufsize(desc,
mxc_jpeg_align(vb2_plane_size(src_buf, 0), 1024));
print_descriptor_info(jpeg->dev, desc);
-
- /* validate the decoding descriptor */
- mxc_jpeg_set_desc(desc_handle, reg, slot);
+ if (ctx->dht_needed) {
+ /* validate the configuration descriptor */
+ mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);
+ } else {
+ /* validate the decoding descriptor */
+ mxc_jpeg_set_desc(desc_handle, reg, slot);
+ }
}
static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
return sos_length; /* not swaped */
}
-static void mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
- u32 fourcc,
- u16 w, u16 h)
+static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
+ u32 fourcc,
+ u16 w, u16 h)
{
- int offset = 0;
+ unsigned int offset = 0;
u8 *cfg = (u8 *)cfg_stream_vaddr;
struct mxc_jpeg_sof *sof;
struct mxc_jpeg_sos *sos;
memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi));
offset += sizeof(jpeg_eoi);
+
+ return offset;
}
static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
goto end;
}
+ /*
+ * TODO: this reset should be removed, once we figure out
+ * how to overcome hardware issues both on encoder and decoder
+ */
mxc_jpeg_sw_reset(reg);
mxc_jpeg_enable(reg);
mxc_jpeg_set_l_endian(reg, 1);
} else {
dev_dbg(dev, "Decoding on slot %d\n", slot);
print_nbuf_to_eoi(dev, src_buf, 0);
- mxc_jpeg_config_dec_desc(dst_buf, slot, jpeg, src_buf, dst_buf);
+ mxc_jpeg_config_dec_desc(dst_buf, slot, ctx, src_buf, dst_buf);
mxc_jpeg_dec_mode_go(dev, reg);
}
end:
stream.addr = src_addr;
stream.end = size;
stream.loc = 0;
+ ctx->dht_needed = true;
while (notfound) {
byte = get_byte(&stream);
if (byte == -1)
if (byte == 0)
continue;
switch (byte) {
+ case DHT:
+ /* DHT marker present, no need to inject default one */
+ ctx->dht_needed = false;
+ break;
case SOF2: /* Progressive DCF frame definition */
dev_err(dev,
"Progressive JPEG isn't supported by hardware");
sof.width, sof.height);
return -EINVAL;
}
- if (sof.width > 0x2000 || sof.height > 0x2000) {
+ if (sof.width > MXC_JPEG_MAX_WIDTH ||
+ sof.height > MXC_JPEG_MAX_HEIGHT) {
dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n",
sof.width, sof.height);
return -EINVAL;
}
+ if (sof.width < MXC_JPEG_MIN_WIDTH ||
+ sof.height < MXC_JPEG_MIN_HEIGHT) {
+ dev_err(dev, "JPEG width or height should be > 64: %dx%d\n",
+ sof.width, sof.height);
+ return -EINVAL;
+ }
if (sof.components_no > MXC_JPEG_MAX_COMPONENTS) {
dev_err(dev, "JPEG number of components should be <=%d",
MXC_JPEG_MAX_COMPONENTS);
MXC_JPEG_MAX_HEIGHT,
q_data->fmt->v_align,
0);
+ /*
+ * the config stream contains a huffman table, use it
+ * to inject a default huffman table for decoder
+ */
+ if (q_data->fmt->flags == MXC_JPEG_FMT_TYPE_ENC) {
+ jpeg->slot_data[ctx->slot].cfg_stream_size =
+ mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
+ V4L2_PIX_FMT_YUYV,
+ MXC_JPEG_MIN_WIDTH,
+ MXC_JPEG_MIN_HEIGHT);
+ }
} else {
/*
* align down the resolution for CAST IP,
q_data->fmt->v_align,
0);
if (q_data->fmt->flags == MXC_JPEG_FMT_TYPE_RAW)
+ jpeg->slot_data[ctx->slot].cfg_stream_size =
mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
q_data->fmt->fourcc,
q_data->w_adjusted,