CHROMIUM: [media] rockchip-vpu: reconstructs hw codes for futher chips
authorJeffy Chen <jeffy.chen@rock-chips.com>
Fri, 3 Jun 2016 07:56:14 +0000 (15:56 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 30 Jun 2016 12:03:07 +0000 (20:03 +0800)
Change-Id: I3ad3a5220d5dc5b952d9e0e11f7142bc30a144f9
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
drivers/media/platform/rockchip-vpu/Makefile
drivers/media/platform/rockchip-vpu/rk3288_vpu_hw.c [new file with mode: 0644]
drivers/media/platform/rockchip-vpu/rk3288_vpu_hw_vp8e.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_enc.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.c
drivers/media/platform/rockchip-vpu/rockchip_vpu_hw.h

index 5f7eb74334447a56729185ac906ceb0c9447ca62..36ef18a250d1804fda1c55166ccd83faac90e110 100644 (file)
@@ -5,6 +5,7 @@ rockchip-vpu-y += rockchip_vpu.o \
                rockchip_vpu_dec.o \
                rockchip_vpu_enc.o \
                rockchip_vpu_hw.o \
+               rk3288_vpu_hw.o \
                rk3288_vpu_hw_h264d.o \
                rk3288_vpu_hw_vp8d.o \
                rk3288_vpu_hw_vp8e.o
diff --git a/drivers/media/platform/rockchip-vpu/rk3288_vpu_hw.c b/drivers/media/platform/rockchip-vpu/rk3288_vpu_hw.c
new file mode 100644 (file)
index 0000000..a810f91
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Rockchip VPU codec driver
+ *
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
+ *     Jeffy Chen <jeffy.chen@rock-chips.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "rockchip_vpu_common.h"
+
+#include "rk3288_vpu_regs.h"
+
+/*
+ * Interrupt handlers.
+ */
+
+int rk3288_vpu_enc_irq(int irq, struct rockchip_vpu_dev *vpu)
+{
+       u32 status = vepu_read(vpu, VEPU_REG_INTERRUPT);
+
+       vepu_write(vpu, 0, VEPU_REG_INTERRUPT);
+
+       if (status & VEPU_REG_INTERRUPT_BIT) {
+               vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+               return 0;
+       }
+
+       return -1;
+}
+
+int rk3288_vpu_dec_irq(int irq, struct rockchip_vpu_dev *vpu)
+{
+       u32 status = vdpu_read(vpu, VDPU_REG_INTERRUPT);
+
+       vdpu_write(vpu, 0, VDPU_REG_INTERRUPT);
+
+       vpu_debug(3, "vdpu_irq status: %08x\n", status);
+
+       if (status & VDPU_REG_INTERRUPT_DEC_IRQ) {
+               vdpu_write(vpu, 0, VDPU_REG_CONFIG);
+               return 0;
+       }
+
+       return -1;
+}
+
+/*
+ * Initialization/clean-up.
+ */
+
+void rk3288_vpu_enc_reset(struct rockchip_vpu_ctx *ctx)
+{
+       struct rockchip_vpu_dev *vpu = ctx->dev;
+
+       vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
+       vepu_write(vpu, 0, VEPU_REG_ENC_CTRL);
+       vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+}
+
+void rk3288_vpu_dec_reset(struct rockchip_vpu_ctx *ctx)
+{
+       struct rockchip_vpu_dev *vpu = ctx->dev;
+
+       vdpu_write(vpu, VDPU_REG_INTERRUPT_DEC_IRQ_DIS, VDPU_REG_INTERRUPT);
+       vdpu_write(vpu, 0, VDPU_REG_CONFIG);
+}
index 190de141a6cf05a8fbda99fbedd27b2ed3328cb4..0fc0bf91424e8c5503fdb46b6df5abccded92d6e 100644 (file)
 #define VP8_CABAC_CTX_OFFSET                   192
 #define VP8_CABAC_CTX_SIZE                     ((55 + 96) << 3)
 
-#define VP8_KEY_FRAME_HDR_SIZE                 10
-#define VP8_INTER_FRAME_HDR_SIZE               3
-
-#define VP8_FRAME_TAG_KEY_FRAME_BIT            BIT(0)
-#define VP8_FRAME_TAG_LENGTH_SHIFT             5
-#define VP8_FRAME_TAG_LENGTH_MASK              (0x7ffff << 5)
-
 /**
  * struct rk3288_vpu_vp8e_ctrl_buf - hardware control buffer layout
  * @ext_hdr_size:      Ext header size in bytes (written by hardware).
@@ -49,59 +42,6 @@ struct rk3288_vpu_vp8e_ctrl_buf {
        u8 rsvd[1016];
 };
 
-/*
- * The hardware takes care only of ext hdr and dct partition. The software
- * must take care of frame header.
- *
- * Buffer layout as received from hardware:
- *   |<--gap-->|<--ext hdr-->|<-gap->|<---dct part---
- *   |<-------dct part offset------->|
- *
- * Required buffer layout:
- *   |<--hdr-->|<--ext hdr-->|<---dct part---
- */
-void rk3288_vpu_vp8e_assemble_bitstream(struct rockchip_vpu_ctx *ctx,
-                                       struct rockchip_vpu_buf *dst_buf)
-{
-       struct vb2_v4l2_buffer *vb2_dst = to_vb2_v4l2_buffer(&dst_buf->vb.vb2_buf);
-       size_t ext_hdr_size = dst_buf->vp8e.ext_hdr_size;
-       size_t dct_size = dst_buf->vp8e.dct_size;
-       size_t hdr_size = dst_buf->vp8e.hdr_size;
-       size_t dst_size;
-       size_t tag_size;
-       void *dst;
-       u32 *tag;
-
-       dst_size = vb2_plane_size(&dst_buf->vb.vb2_buf, 0);
-       dst = vb2_plane_vaddr(&dst_buf->vb.vb2_buf, 0);
-       tag = dst; /* To access frame tag words. */
-
-       if (WARN_ON(hdr_size + ext_hdr_size + dct_size > dst_size))
-               return;
-       if (WARN_ON(dst_buf->vp8e.dct_offset + dct_size > dst_size))
-               return;
-
-       memmove(dst + hdr_size + ext_hdr_size,
-               dst + dst_buf->vp8e.dct_offset, dct_size);
-       memcpy(dst, dst_buf->vp8e.header, hdr_size);
-
-       /* Patch frame tag at first 32-bit word of the frame. */
-       if (vb2_dst->flags & V4L2_BUF_FLAG_KEYFRAME) {
-               tag_size = VP8_KEY_FRAME_HDR_SIZE;
-               tag[0] &= ~VP8_FRAME_TAG_KEY_FRAME_BIT;
-       } else {
-               tag_size = VP8_INTER_FRAME_HDR_SIZE;
-               tag[0] |= VP8_FRAME_TAG_KEY_FRAME_BIT;
-       }
-
-       tag[0] &= ~VP8_FRAME_TAG_LENGTH_MASK;
-       tag[0] |= (hdr_size + ext_hdr_size - tag_size)
-                                               << VP8_FRAME_TAG_LENGTH_SHIFT;
-
-       vb2_set_plane_payload(&dst_buf->vb.vb2_buf, 0,
-                               hdr_size + ext_hdr_size + dct_size);
-}
-
 static inline unsigned int ref_luma_size(unsigned int w, unsigned int h)
 {
        return round_up(w, MB_DIM) * round_up(h, MB_DIM);
index 2ff64a965dc5192c4ad7909d1a6a032394483208..0a10392a0fee714874a35107ac48387acc287767 100644 (file)
@@ -1162,7 +1162,7 @@ static void rockchip_vpu_buf_finish(struct vb2_buffer *vb)
                struct rockchip_vpu_buf *buf;
 
                buf = vb_to_buf(vb);
-               rk3288_vpu_vp8e_assemble_bitstream(ctx, buf);
+               rockchip_vpu_vp8e_assemble_bitstream(ctx, buf);
        }
 
        vpu_debug_leave();
index 989a4cafc8979ca0c2cdb869a0fa0e7f886378fd..3959d9f2c957e2a0b2ca6761b52187968fd8f90a 100644 (file)
 
 #include <linux/dma-iommu.h>
 
-#include "rk3288_vpu_regs.h"
+/* Various parameters specific to VP8 encoder. */
+#define VP8_KEY_FRAME_HDR_SIZE                  10
+#define VP8_INTER_FRAME_HDR_SIZE                3
+
+#define VP8_FRAME_TAG_KEY_FRAME_BIT             BIT(0)
+#define VP8_FRAME_TAG_LENGTH_SHIFT              5
+#define VP8_FRAME_TAG_LENGTH_MASK               (0x7ffff << 5)
 
 /**
  * struct rockchip_vpu_variant - information about VPU hardware variant
@@ -68,6 +74,7 @@ static const struct rockchip_vpu_variant rockchip_vpu_variants[] = {
  * @exit:      Clean-up after streaming. Called from VB2 .stop_streaming()
  *             when streaming from first of both enabled queues is being
  *             disabled.
+ * @irq:       Handle {en,de}code irq. Check and clear interrupt.
  * @run:       Start single {en,de)coding run. Called from non-atomic context
  *             to indicate that a pair of buffers is ready and the hardware
  *             should be programmed and started.
@@ -78,6 +85,7 @@ struct rockchip_vpu_codec_ops {
        int (*init)(struct rockchip_vpu_ctx *);
        void (*exit)(struct rockchip_vpu_ctx *);
 
+       int (*irq)(int, struct rockchip_vpu_dev *);
        void (*run)(struct rockchip_vpu_ctx *);
        void (*done)(struct rockchip_vpu_ctx *, enum vb2_buffer_state);
        void (*reset)(struct rockchip_vpu_ctx *);
@@ -136,14 +144,9 @@ static void rockchip_vpu_power_off(struct rockchip_vpu_dev *vpu)
 static irqreturn_t vepu_irq(int irq, void *dev_id)
 {
        struct rockchip_vpu_dev *vpu = dev_id;
-       u32 status = vepu_read(vpu, VEPU_REG_INTERRUPT);
-
-       vepu_write(vpu, 0, VEPU_REG_INTERRUPT);
-
-       if (status & VEPU_REG_INTERRUPT_BIT) {
-               struct rockchip_vpu_ctx *ctx = vpu->current_ctx;
+       struct rockchip_vpu_ctx *ctx = vpu->current_ctx;
 
-               vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
+       if (!ctx->hw.codec_ops->irq(irq, vpu)) {
                rockchip_vpu_power_off(vpu);
                cancel_delayed_work(&vpu->watchdog_work);
 
@@ -156,16 +159,9 @@ static irqreturn_t vepu_irq(int irq, void *dev_id)
 static irqreturn_t vdpu_irq(int irq, void *dev_id)
 {
        struct rockchip_vpu_dev *vpu = dev_id;
-       u32 status = vdpu_read(vpu, VDPU_REG_INTERRUPT);
-
-       vdpu_write(vpu, 0, VDPU_REG_INTERRUPT);
-
-       vpu_debug(3, "vdpu_irq status: %08x\n", status);
-
-       if (status & VDPU_REG_INTERRUPT_DEC_IRQ) {
-               struct rockchip_vpu_ctx *ctx = vpu->current_ctx;
+       struct rockchip_vpu_ctx *ctx = vpu->current_ctx;
 
-               vdpu_write(vpu, 0, VDPU_REG_CONFIG);
+       if (!ctx->hw.codec_ops->irq(irq, vpu)) {
                rockchip_vpu_power_off(vpu);
                cancel_delayed_work(&vpu->watchdog_work);
 
@@ -364,44 +360,30 @@ void rockchip_vpu_hw_remove(struct rockchip_vpu_dev *vpu)
        clk_disable_unprepare(vpu->aclk_vcodec);
 }
 
-static void rockchip_vpu_enc_reset(struct rockchip_vpu_ctx *ctx)
-{
-       struct rockchip_vpu_dev *vpu = ctx->dev;
-
-       vepu_write(vpu, VEPU_REG_INTERRUPT_DIS_BIT, VEPU_REG_INTERRUPT);
-       vepu_write(vpu, 0, VEPU_REG_ENC_CTRL);
-       vepu_write(vpu, 0, VEPU_REG_AXI_CTRL);
-}
-
-static void rockchip_vpu_dec_reset(struct rockchip_vpu_ctx *ctx)
-{
-       struct rockchip_vpu_dev *vpu = ctx->dev;
-
-       vdpu_write(vpu, VDPU_REG_INTERRUPT_DEC_IRQ_DIS, VDPU_REG_INTERRUPT);
-       vdpu_write(vpu, 0, VDPU_REG_CONFIG);
-}
-
 static const struct rockchip_vpu_codec_ops mode_ops[] = {
        [RK3288_VPU_CODEC_VP8E] = {
                .init = rk3288_vpu_vp8e_init,
                .exit = rk3288_vpu_vp8e_exit,
+               .irq = rk3288_vpu_enc_irq,
                .run = rk3288_vpu_vp8e_run,
                .done = rk3288_vpu_vp8e_done,
-               .reset = rockchip_vpu_enc_reset,
+               .reset = rk3288_vpu_enc_reset,
        },
        [RK3288_VPU_CODEC_VP8D] = {
                .init = rk3288_vpu_vp8d_init,
                .exit = rk3288_vpu_vp8d_exit,
+               .irq = rk3288_vpu_dec_irq,
                .run = rk3288_vpu_vp8d_run,
                .done = rockchip_vpu_run_done,
-               .reset = rockchip_vpu_dec_reset,
+               .reset = rk3288_vpu_dec_reset,
        },
        [RK3288_VPU_CODEC_H264D] = {
                .init = rk3288_vpu_h264d_init,
                .exit = rk3288_vpu_h264d_exit,
+               .irq = rk3288_vpu_dec_irq,
                .run = rk3288_vpu_h264d_run,
                .done = rockchip_vpu_run_done,
-               .reset = rockchip_vpu_dec_reset,
+               .reset = rk3288_vpu_dec_reset,
        },
 };
 
@@ -428,3 +410,59 @@ void rockchip_vpu_deinit(struct rockchip_vpu_ctx *ctx)
 {
        ctx->hw.codec_ops->exit(ctx);
 }
+
+/*
+ * The hardware takes care only of ext hdr and dct partition. The software
+ * must take care of frame header.
+ *
+ * Buffer layout as received from hardware:
+ *   |<--gap-->|<--ext hdr-->|<-gap->|<---dct part---
+ *   |<-------dct part offset------->|
+ *
+ * Required buffer layout:
+ *   |<--hdr-->|<--ext hdr-->|<---dct part---
+ */
+void rockchip_vpu_vp8e_assemble_bitstream(struct rockchip_vpu_ctx *ctx,
+                                       struct rockchip_vpu_buf *dst_buf)
+{
+       struct vb2_v4l2_buffer *vb2_dst = to_vb2_v4l2_buffer(&dst_buf->vb.vb2_buf);
+       size_t ext_hdr_size = dst_buf->vp8e.ext_hdr_size;
+       size_t dct_size = dst_buf->vp8e.dct_size;
+       size_t hdr_size = dst_buf->vp8e.hdr_size;
+       size_t dst_size;
+       size_t tag_size;
+       void *dst;
+       u32 *tag;
+
+       dst_size = vb2_plane_size(&dst_buf->vb.vb2_buf, 0);
+       dst = vb2_plane_vaddr(&dst_buf->vb.vb2_buf, 0);
+       tag = dst; /* To access frame tag words. */
+
+       if (WARN_ON(hdr_size + ext_hdr_size + dct_size > dst_size))
+               return;
+       if (WARN_ON(dst_buf->vp8e.dct_offset + dct_size > dst_size))
+               return;
+
+       vpu_debug(1, "%s: hdr_size = %d, ext_hdr_size = %d, dct_size = %d\n",
+                       __func__, hdr_size, ext_hdr_size, dct_size);
+
+       memmove(dst + hdr_size + ext_hdr_size,
+               dst + dst_buf->vp8e.dct_offset, dct_size);
+       memcpy(dst, dst_buf->vp8e.header, hdr_size);
+
+       /* Patch frame tag at first 32-bit word of the frame. */
+       if (vb2_dst->flags & V4L2_BUF_FLAG_KEYFRAME) {
+               tag_size = VP8_KEY_FRAME_HDR_SIZE;
+               tag[0] &= ~VP8_FRAME_TAG_KEY_FRAME_BIT;
+       } else {
+               tag_size = VP8_INTER_FRAME_HDR_SIZE;
+               tag[0] |= VP8_FRAME_TAG_KEY_FRAME_BIT;
+       }
+
+       tag[0] &= ~VP8_FRAME_TAG_LENGTH_MASK;
+       tag[0] |= (hdr_size + ext_hdr_size - tag_size)
+                                               << VP8_FRAME_TAG_LENGTH_SHIFT;
+
+       vb2_set_plane_payload(&dst_buf->vb.vb2_buf, 0,
+                               hdr_size + ext_hdr_size + dct_size);
+}
index 9b446fe8cdc41ff5b45edb2b3e0a7146f5984dbd..540b40002f96501ef6ff95540ddfb592d5780e79 100644 (file)
@@ -164,6 +164,12 @@ void rockchip_vpu_deinit(struct rockchip_vpu_ctx *ctx);
 
 void rockchip_vpu_run(struct rockchip_vpu_ctx *ctx);
 
+/* Ops for rk3288 vpu */
+int rk3288_vpu_enc_irq(int irq, struct rockchip_vpu_dev *vpu);
+int rk3288_vpu_dec_irq(int irq, struct rockchip_vpu_dev *vpu);
+void rk3288_vpu_enc_reset(struct rockchip_vpu_ctx *ctx);
+void rk3288_vpu_dec_reset(struct rockchip_vpu_ctx *ctx);
+
 /* Run ops for rk3288 H264 decoder */
 int rk3288_vpu_h264d_init(struct rockchip_vpu_ctx *ctx);
 void rk3288_vpu_h264d_exit(struct rockchip_vpu_ctx *ctx);
@@ -182,7 +188,7 @@ void rk3288_vpu_vp8e_done(struct rockchip_vpu_ctx *ctx,
                          enum vb2_buffer_state result);
 const struct rockchip_reg_params *rk3288_vpu_vp8e_get_dummy_params(void);
 
-void rk3288_vpu_vp8e_assemble_bitstream(struct rockchip_vpu_ctx *ctx,
+void rockchip_vpu_vp8e_assemble_bitstream(struct rockchip_vpu_ctx *ctx,
                                        struct rockchip_vpu_buf *dst_buf);
 
 #endif /* ROCKCHIP_VPU_HW_H_ */