From: Cho KyongHo Date: Mon, 30 Mar 2015 10:51:59 +0000 (+0900) Subject: [COMMON] media: smfc: add basic function of compression by H/W X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=912afd755a13d45e5324a78037d244512a6144aa;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: smfc: add basic function of compression by H/W Now it is able to compress an image with H/W. Change-Id: I420e4908b1e3c36818ae4be0b548d8c51ddb3fcc Signed-off-by: Cho KyongHo --- diff --git a/drivers/media/platform/exynos/smfc/Makefile b/drivers/media/platform/exynos/smfc/Makefile index 966637807901..3b802490fe8e 100644 --- a/drivers/media/platform/exynos/smfc/Makefile +++ b/drivers/media/platform/exynos/smfc/Makefile @@ -3,4 +3,4 @@ # http://www.samsung.com # -obj-$(CONFIG_VIDEO_EXYNOS_SMFC) += smfc.o +obj-$(CONFIG_VIDEO_EXYNOS_SMFC) += smfc.o smfc-regs.o diff --git a/drivers/media/platform/exynos/smfc/smfc-regs.c b/drivers/media/platform/exynos/smfc/smfc-regs.c new file mode 100644 index 000000000000..dd37a8bc88ea --- /dev/null +++ b/drivers/media/platform/exynos/smfc/smfc-regs.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * The H/W handling file of Samsung Exynos SMFC Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "smfc.h" + +void smfc_hwconfigure_reset(struct smfc_dev *smfc) +{ + u32 cfg = __raw_readl(smfc->reg + REG_JPEG_CNTL) & ~((1 << 29) | 3); + __raw_writel(cfg, smfc->reg + REG_JPEG_CNTL); + __raw_writel(cfg | (1 << 29), smfc->reg + REG_JPEG_CNTL); +} + +/* + * Quantization tables in ZIG-ZAG order provided by IOC/IEC 10918-1 K.1 and K.2 + * for YUV420 and YUV422 + */ +static const unsigned char default_luma_qtbl[SMFC_MCU_SIZE] __aligned(64) = { + 16, 11, 12, 14, 12, 10, 16, 14, + 13, 14, 18, 17, 16, 19, 24, 40, + 26, 24, 22, 22, 24, 49, 35, 37, + 29, 40, 58, 51, 61, 60, 57, 51, + 56, 55, 64, 72, 92, 78, 64, 68, + 87, 69, 55, 56, 80, 109, 81, 87, + 95, 98, 103, 104, 103, 62, 77, 113, + 121, 112, 100, 120, 92, 101, 103, 99, +}; + +static const unsigned char default_chroma_qtbl[SMFC_MCU_SIZE] __aligned(64) = { + 17, 18, 18, 24, 21, 24, 47, 26, + 26, 47, 99, 66, 56, 66, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, +}; + +/* ITU Luminace Huffman Table */ +static unsigned int ITU_H_TBL_LEN_DC_LUMINANCE[] = { + 0x01050100, 0x01010101, 0x00000001, 0x00000000 +}; +static unsigned int ITU_H_TBL_VAL_DC_LUMINANCE[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x00000000 +}; + +/* ITU Chrominace Huffman Table */ +static unsigned int ITU_H_TBL_LEN_DC_CHROMINANCE[] = { + 0x01010300, 0x01010101, 0x00010101, 0x00000000 +}; +static unsigned int ITU_H_TBL_VAL_DC_CHROMINANCE[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x00000000 +}; + +/* ITU Luminace Huffman Table */ +static unsigned int ITU_H_TBL_LEN_AC_LUMINANCE[] = { + 0x03010200, 0x03040203, 0x04040505, 0x7d010000 +}; + +static unsigned int ITU_H_TBL_VAL_AC_LUMINANCE[] = { + 0x00030201, 0x12051104, 0x06413121, 0x07615113, + 0x32147122, 0x08a19181, 0xc1b14223, 0xf0d15215, + 0x72623324, 0x160a0982, 0x1a191817, 0x28272625, + 0x35342a29, 0x39383736, 0x4544433a, 0x49484746, + 0x5554534a, 0x59585756, 0x6564635a, 0x69686766, + 0x7574736a, 0x79787776, 0x8584837a, 0x89888786, + 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4, + 0xb2aaa9a8, 0xb6b5b4b3, 0xbab9b8b7, 0xc5c4c3c2, + 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9, + 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5, + 0x0000faf9 +}; + +/* ITU Chrominace Huffman Table */ +static u32 ITU_H_TBL_LEN_AC_CHROMINANCE[] = { + 0x02010200, 0x04030404, 0x04040507, 0x77020100 +}; +static u32 ITU_H_TBL_VAL_AC_CHROMINANCE[] = { + 0x03020100, 0x21050411, 0x41120631, 0x71610751, + 0x81322213, 0x91421408, 0x09c1b1a1, 0xf0523323, + 0xd1726215, 0x3424160a, 0x17f125e1, 0x261a1918, + 0x2a292827, 0x38373635, 0x44433a39, 0x48474645, + 0x54534a49, 0x58575655, 0x64635a59, 0x68676665, + 0x74736a69, 0x78777675, 0x83827a79, 0x87868584, + 0x928a8988, 0x96959493, 0x9a999897, 0xa5a4a3a2, + 0xa9a8a7a6, 0xb4b3b2aa, 0xb8b7b6b5, 0xc3c2bab9, + 0xc7c6c5c4, 0xd2cac9c8, 0xd6d5d4d3, 0xdad9d8d7, + 0xe5e4e3e2, 0xe9e8e7e6, 0xf4f3f2ea, 0xf8f7f6f5, + 0x0000faf9 +}; + +/* to suppress warning or error message about out-of-aaray-bound */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +/* tables and qunatization tables configuration to H/W for compression */ +static inline u32 smfc_calc_quantizers(unsigned int idx, unsigned int factor, + const unsigned char tbl[]) +{ + u32 val = max(min((tbl[idx] * factor + 50) / 100, 255U), 1U); + val |= max(min((tbl[idx + 1] * factor + 50) / 100, 255U), 1U) << 8; + val |= max(min((tbl[idx + 2] * factor + 50) / 100, 255U), 1U) << 16; + val |= max(min((tbl[idx + 3] * factor + 50) / 100, 255U), 1U) << 24; + return val; +} +#pragma GCC diagnostic pop + +void smfc_hwconfigure_tables(struct smfc_ctx *ctx) +{ + size_t i; + void __iomem *base = ctx->smfc->reg; + unsigned int factor = ctx->quality_factor; + factor = (factor < 50) ? 5000 / factor : 200 - factor * 2; + + /* Quantizer table 0 */ + for (i = 0; i < SMFC_MCU_SIZE; i += 4) { + __raw_writel(smfc_calc_quantizers(i, factor, default_luma_qtbl), + base + REG_QTBL_BASE + i); + __raw_writel( + smfc_calc_quantizers(i, factor, default_chroma_qtbl), + base + REG_QTBL_BASE + SMFC_MCU_SIZE + i); + } + + /* Huffman tables */ + for (i = 0; i < 4; i++) { + __raw_writel(ITU_H_TBL_LEN_DC_LUMINANCE[i], + base + REG_HTBL_LUMA_DCLEN + i * sizeof(u32)); + __raw_writel(ITU_H_TBL_VAL_DC_LUMINANCE[i], + base + REG_HTBL_LUMA_DCVAL + i * sizeof(u32)); + __raw_writel(ITU_H_TBL_LEN_DC_CHROMINANCE[i], + base + REG_HTBL_CHROMA_DCLEN + i * sizeof(u32)); + __raw_writel(ITU_H_TBL_VAL_DC_CHROMINANCE[i], + base + REG_HTBL_CHROMA_DCVAL + i * sizeof(u32)); + __raw_writel(ITU_H_TBL_LEN_AC_LUMINANCE[i], + base + REG_HTBL_LUMA_ACLEN + i * sizeof(u32)); + __raw_writel(ITU_H_TBL_LEN_AC_CHROMINANCE[i], + base + REG_HTBL_CHROMA_ACLEN + i * sizeof(u32)); + } + + for (i = 0; i < ARRAY_SIZE(ITU_H_TBL_VAL_AC_LUMINANCE); i++) + __raw_writel(ITU_H_TBL_VAL_AC_LUMINANCE[i], + base + REG_HTBL_LUMA_ACVAL + i * sizeof(u32)); + + for (i = 0; i < ARRAY_SIZE(ITU_H_TBL_VAL_AC_CHROMINANCE); i++) + __raw_writel(ITU_H_TBL_VAL_AC_CHROMINANCE[i], + base + REG_HTBL_CHROMA_ACVAL + i * sizeof(u32)); + + __raw_writel(VAL_TABLE_SELECT, base + REG_TABLE_SELECT); + __raw_writel(SMFC_DHT_LEN, base + REG_DHT_LEN); +} + + +static void smfc_hwconfigure_image_base(struct smfc_ctx *ctx, + struct vb2_buffer *vb2buf) +{ + dma_addr_t addr; + unsigned int i; + bool multiplane = + (ctx->img_fmt->num_buffers == ctx->img_fmt->num_planes); + + if (multiplane) { + /* Note that this includes a single-plane format such as YUYV */ + for (i = 0; i < ctx->img_fmt->num_buffers; i++) { + addr = vb2_dma_sg_plane_dma_addr(vb2buf, i); + __raw_writel((u32)addr, + ctx->smfc->reg + REG_MAIN_IMAGE_BASE(i)); + } + } else { + addr = vb2_dma_sg_plane_dma_addr(vb2buf, i); + + for (i = 0; i < ctx->img_fmt->num_planes; i++) { + __raw_writel((u32)addr, + ctx->smfc->reg + REG_MAIN_IMAGE_BASE(i)); + addr += (ctx->width * ctx->height * + ctx->img_fmt->bpp_pix[i]) / 8; + } + } +} + +static u32 smfc_hwconfigure_jpeg_base(struct smfc_ctx *ctx, + struct vb2_buffer *vb2buf) +{ + dma_addr_t addr; + + BUG_ON(vb2buf->num_planes != 1); + addr = vb2_dma_sg_plane_dma_addr(vb2buf, 0); + __raw_writel((u32)addr, ctx->smfc->reg + REG_MAIN_JPEG_BASE); + return (u32)addr; +} + +/* [hfactor - 1][vfactor - 1]: 444, 422V, 422, 420 */ +static u32 smfc_get_jpeg_format(unsigned int hfactor, unsigned int vfactor) +{ + static unsigned char jpeg_regfmt[2][2] = { {1, 4}, {2, 3} }; + return jpeg_regfmt[hfactor - 1][vfactor - 1] << 24; +} + +void smfc_hwconfigure_image(struct smfc_ctx *ctx) +{ + struct vb2_v4l2_buffer *vb2buf_img, *vb2buf_jpg; + u32 stream_address; + u32 format = ctx->img_fmt->regcfg; + + __raw_writel(ctx->width | (ctx->height << 16), + ctx->smfc->reg + REG_MAIN_IMAGE_SIZE); + + if (!(ctx->flags & SMFC_CTX_COMPRESS)) { + vb2buf_img = v4l2_m2m_next_dst_buf(ctx->m2mctx); + vb2buf_jpg = v4l2_m2m_next_src_buf(ctx->m2mctx); + } else { + vb2buf_img = v4l2_m2m_next_src_buf(ctx->m2mctx); + vb2buf_jpg = v4l2_m2m_next_dst_buf(ctx->m2mctx); + /* + * H/W JPEG does not allow upscaling of chroma components + * during compression + */ + format |= smfc_get_jpeg_format( + max(ctx->chroma_hfactor, ctx->img_fmt->chroma_hfactor), + max(ctx->chroma_vfactor, ctx->img_fmt->chroma_vfactor)); + } + + smfc_hwconfigure_image_base(ctx, &vb2buf_img->vb2_buf); + stream_address = smfc_hwconfigure_jpeg_base(ctx, &vb2buf_jpg->vb2_buf); + + __raw_writel(format, ctx->smfc->reg + REG_MAIN_IMAGE_FORMAT); + __raw_writel(vb2_plane_size(&vb2buf_jpg->vb2_buf, 0) - + (stream_address & SMFC_ADDR_ALIGN_MASK), + ctx->smfc->reg + REG_MAIN_MAX_STREAM_SIZE); +} + +void smfc_hwconfigure_start(struct smfc_ctx *ctx) +{ + u32 cfg; + void __iomem *base = ctx->smfc->reg; + + /* configure "Error max compressed size" interrupt */ + cfg = __raw_readl(base + REG_INT_EN); + __raw_writel(cfg | (1 << 11), base + REG_INT_EN); + + cfg = __raw_readl(base + REG_JPEG_CNTL) & ~3; + cfg |= !(ctx->flags & SMFC_CTX_COMPRESS) ? 1 : 2; + cfg |= 1 << 19; /* update huffman table from SFR */ + cfg |= 1 << 28; /* enables interrupt */ + cfg |= 1 << 29; /* Release reset */ + + writel(cfg, base + REG_JPEG_CNTL); +} + +bool smfc_hwstatus_okay(struct smfc_dev *smfc) +{ + u32 val = __raw_readl(smfc->reg + REG_INT_STATUS); + if (!val) { + dev_err(smfc->dev, "Interrupt with no status change\n"); + return false; + } + + if ((val & ~2)) { + dev_err(smfc->dev, "Error interrupt %#010x\n", val); + return false; + } + + return true; +} diff --git a/drivers/media/platform/exynos/smfc/smfc-regs.h b/drivers/media/platform/exynos/smfc/smfc-regs.h index 03e8982b5b80..6c4edd601e84 100644 --- a/drivers/media/platform/exynos/smfc/smfc-regs.h +++ b/drivers/media/platform/exynos/smfc/smfc-regs.h @@ -12,17 +12,63 @@ #ifndef _MEDIA_EXYNOS_SMFC_REGS_H_ #define _MEDIA_EXYNOS_SMFC_REGS_H_ +/********** JPEG STANDARD *****************************************************/ +#define SMFC_MCU_SIZE 64 + /********** H/W RESTRICTIONS **************************************************/ #define SMFC_MAX_WIDTH 16368U #define SMFC_MAX_HEIGHT 16368U #define SMFC_MIN_WIDTH 8U #define SMFC_MIN_HEIGHT 8U +#define SMFC_ADDR_ALIGN_MASK (16 - 1) /* 128-bit align */ +/********** H/W REGISTERS and DEFAULT VALUES **********************************/ +#define REG_JPEG_CNTL 0x000 +#define REG_INT_EN 0x004 +#define REG_TIMER_COUNT 0x008 +#define REG_INT_STATUS 0x00C +#define REG_MAIN_IMAGE_SIZE 0x014 +#define REG_MAIN_JPEG_BASE 0x010 +#define REG_MAIN_IMAGE_BASE(n) (0x018 + (n) * 12) #define REG_MAIN_IMAGE_FORMAT 0x040 -#define REG_SECD_IMAGE_FORMAT 0x0B8 +#define REG_MAIN_STREAM_SIZE 0x044 +#define REG_MAIN_MAX_STREAM_SIZE 0x06C #define REG_IP_VERSION_NUMBER 0x064 +#define REG_SECD_IMAGE_FORMAT 0x0B8 + +#define REG_TABLE_SELECT 0x03C +/* + * Component 0: Q-table 0, AC/DC table 0 + * Component 1 and 2: Q-table 1, AC/DC table 1 + */ +#define VAL_TABLE_SELECT 0xF14 +/* 64 reigsters for four quantization tables are prepared */ +#define REG_QTBL_BASE 0x100 +/* + * Total 112 registers for huffman tables: + * 0x200 - 4 DC Luma code lengths registers + * 0x210 - 4 DC Luma values registers + * 0x220 - 4 DC Chroma code lengths registers + * 0x230 - 4 DC Chroma values registers + * 0x240 - 4 AC Luma code lengths registers + * 0x250 - 44 AC Luma values registers + * 0x300 - 4 AC Chroma code lengths registers + * 0x310 - 44 ACChroma values registers + */ +#define REG_HTBL_BASE 0x200 +# define REG_HTBL_LUMA_DCLEN REG_HTBL_BASE +# define REG_HTBL_LUMA_DCVAL (REG_HTBL_LUMA_DCLEN + 4 * sizeof(u32)) +# define REG_HTBL_CHROMA_DCLEN (REG_HTBL_LUMA_DCVAL + 4 * sizeof(u32)) +# define REG_HTBL_CHROMA_DCVAL (REG_HTBL_CHROMA_DCLEN + 4 * sizeof(u32)) +# define REG_HTBL_LUMA_ACLEN (REG_HTBL_CHROMA_DCVAL + 4 * sizeof(u32)) +# define REG_HTBL_LUMA_ACVAL (REG_HTBL_LUMA_ACLEN + 4 * sizeof(u32)) +# define REG_HTBL_CHROMA_ACLEN (REG_HTBL_LUMA_ACVAL + 44 * sizeof(u32)) +# define REG_HTBL_CHROMA_ACVAL (REG_HTBL_CHROMA_ACLEN + 4 * sizeof(u32)) +#define REG_DHT_LEN 0x04C +#define SMFC_DHT_LEN 0x1A2 + /* Value definitions of MAIN/SECONDARY_IMAGE_FORMAT */ enum { IMGSEL_GRAY, diff --git a/drivers/media/platform/exynos/smfc/smfc.c b/drivers/media/platform/exynos/smfc/smfc.c index 444d103b20c4..eacb32bf7b09 100644 --- a/drivers/media/platform/exynos/smfc/smfc.c +++ b/drivers/media/platform/exynos/smfc/smfc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,6 @@ #include #include "smfc.h" -#include "smfc-regs.h" /* SMFC SPECIFIC DEVICE CAPABILITIES */ /* set if H/W supports for decompression */ @@ -274,6 +274,33 @@ static const char *buf_type_name(__u32 type) static irqreturn_t exynos_smfc_irq_handler(int irq, void *priv) { + struct smfc_dev *smfc = priv; + struct smfc_ctx *ctx = v4l2_m2m_get_curr_priv(smfc->m2mdev); + enum vb2_buffer_state state = VB2_BUF_STATE_DONE; + struct vb2_v4l2_buffer *vb_capture; + + vb_capture = v4l2_m2m_dst_buf_remove(ctx->m2mctx); + + if (smfc_hwstatus_okay(smfc)) { + vb2_set_plane_payload(&vb_capture->vb2_buf, 0, + smfc_get_streamsize(smfc)); + } else { + state = VB2_BUF_STATE_ERROR; + smfc_hwconfigure_reset(smfc); + } + + if (!IS_ERR(smfc->clk_gate)) { + clk_disable(smfc->clk_gate); + if (!IS_ERR(smfc->clk_gate2)) + clk_disable(smfc->clk_gate2); + } + + pm_runtime_put(smfc->dev); + + v4l2_m2m_buf_done(v4l2_m2m_src_buf_remove(ctx->m2mctx), state); + v4l2_m2m_buf_done(vb_capture, state); + v4l2_m2m_job_finish(smfc->m2mdev, ctx->m2mctx); + return IRQ_HANDLED; } @@ -432,6 +459,7 @@ static int exynos_smfc_open(struct file *filp) * default image format: YUYV * default size: 16x8 * default chroma subsampling for JPEG: YUV422 + * default quality factor for compression: 96 */ ctx->img_fmt = SMFC_DEFAULT_OUTPUT_FORMAT; ctx->width = SMFC_MIN_WIDTH << ctx->img_fmt->chroma_hfactor; @@ -439,6 +467,7 @@ static int exynos_smfc_open(struct file *filp) ctx->chroma_hfactor = ctx->img_fmt->chroma_hfactor; ctx->chroma_vfactor = ctx->img_fmt->chroma_vfactor; ctx->flags |= SMFC_CTX_COMPRESS; + ctx->quality_factor = 96; ctx->smfc = smfc; @@ -793,27 +822,35 @@ static int smfc_v4l2_s_fmt(struct file *filp, void *fh, struct v4l2_format *f) static int smfc_v4l2_reqbufs(struct file *filp, void *fh, struct v4l2_requestbuffers *reqbufs) { - struct smfc_ctx *ctx = v4l2_fh_to_smfc_ctx(fh); - return v4l2_m2m_reqbufs(filp, ctx->m2mctx, reqbufs); + return v4l2_m2m_reqbufs(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, reqbufs); } static int smfc_v4l2_querybuf(struct file *filp, void *fh, struct v4l2_buffer *buf) { - struct smfc_ctx *ctx = v4l2_fh_to_smfc_ctx(fh); - return v4l2_m2m_querybuf(filp, ctx->m2mctx, buf); + return v4l2_m2m_querybuf(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, buf); } static int smfc_v4l2_qbuf(struct file *filp, void *fh, struct v4l2_buffer *buf) { - struct smfc_ctx *ctx = v4l2_fh_to_smfc_ctx(fh); - return v4l2_m2m_qbuf(filp, ctx->m2mctx, buf); + return v4l2_m2m_qbuf(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, buf); } static int smfc_v4l2_dqbuf(struct file *filp, void *fh, struct v4l2_buffer *buf) { - struct smfc_ctx *ctx = v4l2_fh_to_smfc_ctx(fh); - return v4l2_m2m_dqbuf(filp, ctx->m2mctx, buf); + return v4l2_m2m_dqbuf(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, buf); +} + +static int smfc_v4l2_streamon(struct file *filp, void *fh, + enum v4l2_buf_type type) +{ + return v4l2_m2m_streamon(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, type); +} + +static int smfc_v4l2_streamoff(struct file *filp, void *fh, + enum v4l2_buf_type type) +{ + return v4l2_m2m_streamoff(filp, v4l2_fh_to_smfc_ctx(fh)->m2mctx, type); } static const struct v4l2_ioctl_ops smfc_v4l2_ioctl_ops = { @@ -838,11 +875,41 @@ static const struct v4l2_ioctl_ops smfc_v4l2_ioctl_ops = { .vidioc_querybuf = smfc_v4l2_querybuf, .vidioc_qbuf = smfc_v4l2_qbuf, .vidioc_dqbuf = smfc_v4l2_dqbuf, + .vidioc_streamon = smfc_v4l2_streamon, + .vidioc_streamoff = smfc_v4l2_streamoff, }; static void smfc_m2m_device_run(void *priv) { - /* TODO: H/W initialization */ + struct smfc_ctx *ctx = priv; + int ret; + + ret = in_irq() ? pm_runtime_get(ctx->smfc->dev) : + pm_runtime_get_sync(ctx->smfc->dev); + if (ret < 0) { + pr_err("Failed to enable power\n"); + /* TODO: error current frame */ + } + + if (!IS_ERR(ctx->smfc->clk_gate)) { + ret = clk_enable(ctx->smfc->clk_gate); + if (!ret && !IS_ERR(ctx->smfc->clk_gate2)) { + ret = clk_enable(ctx->smfc->clk_gate2); + if (ret) + clk_disable(ctx->smfc->clk_gate); + } + } + + if (ret < 0) { + dev_err(ctx->smfc->dev, "Failed to enable clocks\n"); + pm_runtime_put(ctx->smfc->dev); + /* TODO: error current frame */ + } + + smfc_hwconfigure_reset(ctx->smfc); + smfc_hwconfigure_tables(ctx); + smfc_hwconfigure_image(ctx); + smfc_hwconfigure_start(ctx); } static void smfc_m2m_job_abort(void *priv) @@ -1036,6 +1103,10 @@ static int exynos_smfc_probe(struct platform_device *pdev) if (ret < 0) return ret; + ret = iovmm_activate(&pdev->dev); + if (ret < 0) + return ret; + platform_set_drvdata(pdev, smfc); dev_info(&pdev->dev, "Probed H/W Version: %02x.%02x.%04x\n", diff --git a/drivers/media/platform/exynos/smfc/smfc.h b/drivers/media/platform/exynos/smfc/smfc.h index 6ab0dfc9b21d..ba0f17382e9e 100644 --- a/drivers/media/platform/exynos/smfc/smfc.h +++ b/drivers/media/platform/exynos/smfc/smfc.h @@ -12,6 +12,8 @@ #ifndef _MEDIA_EXYNOS_SMFC_H_ #define _MEDIA_EXYNOS_SMFC_H_ +#include "smfc-regs.h" + #define MODULE_NAME "exynos-jpeg" struct device; @@ -62,6 +64,7 @@ struct smfc_ctx { /* JPEG chroma subsampling factors */ unsigned char chroma_hfactor; unsigned char chroma_vfactor; + unsigned int quality_factor; }; static inline struct smfc_ctx *v4l2_fh_to_smfc_ctx(struct v4l2_fh *fh) @@ -82,4 +85,15 @@ static inline bool smfc_is_compressed_type(struct smfc_ctx *ctx, __u32 type) return !(ctx->flags & SMFC_CTX_COMPRESS) == V4L2_TYPE_IS_OUTPUT(type); } +/* H/W Configuration */ +void smfc_hwconfigure_tables(struct smfc_ctx *ctx); +void smfc_hwconfigure_image(struct smfc_ctx *ctx); +void smfc_hwconfigure_start(struct smfc_ctx *ctx); +bool smfc_hwstatus_okay(struct smfc_dev *smfc); +void smfc_hwconfigure_reset(struct smfc_dev *smfc); +static inline u32 smfc_get_streamsize(struct smfc_dev *smfc) +{ + return __raw_readl(smfc->reg + REG_MAIN_STREAM_SIZE); +} + #endif /* _MEDIA_EXYNOS_SMFC_H_ */