decode: support multi-instance on stream mode. [1/1]
authorHui Zhang <hui.zhang@amlogic.com>
Thu, 27 Feb 2020 08:10:45 +0000 (16:10 +0800)
committerZhi Zhou <zhi.zhou@amlogic.com>
Fri, 15 May 2020 11:31:05 +0000 (04:31 -0700)
PD#SWPL-21360

Problem:
can not support multi-instance on stream mode.

Solution:
1. parser's wp and rp operations have been separated from decode.
2. remove register rw of parser from the stream input pipeline.
3. opitimize stbuf involves the struct and adds series of ops fun.
4. defualt used ops with esparser of stbuf, we can force switch
    non-parser mode used by the flag "enable_stream_mode_multi_dec"
    on stream_input.
echo 1 > /sys/module/decoder_common/parameters/enable_stream_mode_multi_dec

Verify:
u212, ab301
1. pass the base playeback that be tested by dailiang.
2. pass the dvb playback that be tested by chenyuanyuan.
3. pass cts testing for media that be tested by zhanggan.

Change-Id: I20abb42f894bee92bd11870b5e293b0f0a941930
Signed-off-by: Hui Zhang <hui.zhang@amlogic.com>
42 files changed:
drivers/amvdec_ports/aml_vcodec_adapt.c
drivers/amvdec_ports/aml_vcodec_adapt.h
drivers/amvdec_ports/vdec_drv_if.h
drivers/frame_provider/decoder/avs/avs.c
drivers/frame_provider/decoder/avs/avsp_trans.c
drivers/frame_provider/decoder/avs2/vavs2.c
drivers/frame_provider/decoder/avs_multi/avs_multi.c
drivers/frame_provider/decoder/h264/vh264.c
drivers/frame_provider/decoder/h264_multi/vmh264.c
drivers/frame_provider/decoder/h265/vh265.c
drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
drivers/frame_provider/decoder/real/vreal.c
drivers/frame_provider/decoder/utils/vdec.c
drivers/frame_provider/decoder/utils/vdec.h
drivers/frame_provider/decoder/vav1/vav1.c
drivers/frame_provider/decoder/vp9/vvp9.c
drivers/stream_input/Makefile
drivers/stream_input/amports/adec.c
drivers/stream_input/amports/adec.h
drivers/stream_input/amports/amports_priv.h
drivers/stream_input/amports/amstream.c
drivers/stream_input/amports/stream_buffer_base.c [new file with mode: 0644]
drivers/stream_input/amports/stream_buffer_base.h [new file with mode: 0644]
drivers/stream_input/amports/stream_buffer_interface.c [new file with mode: 0644]
drivers/stream_input/amports/streambuf.c [new file with mode: 0644]
drivers/stream_input/amports/streambuf.h [new file with mode: 0644]
drivers/stream_input/amports/streambuf_reg.h [new file with mode: 0644]
drivers/stream_input/amports/thread_rw.c [new file with mode: 0644]
drivers/stream_input/amports/thread_rw.h [new file with mode: 0644]
drivers/stream_input/parser/demux/hw_demux/hwdemux_inject.c
drivers/stream_input/parser/esparser.c
drivers/stream_input/parser/hw_demux/aml_dmx.c
drivers/stream_input/parser/psparser.c
drivers/stream_input/parser/rmparser.c
drivers/stream_input/parser/streambuf.c [deleted file]
drivers/stream_input/parser/streambuf.h [deleted file]
drivers/stream_input/parser/streambuf_reg.h [deleted file]
drivers/stream_input/parser/thread_rw.c [deleted file]
drivers/stream_input/parser/thread_rw.h [deleted file]
drivers/stream_input/parser/tsdemux.c

index b87d0c882c19f0dc39ceef9af7ccbc7c949e79a8..67a29bb0c89191dbad1591ad833939bf931fae6b 100644 (file)
@@ -32,8 +32,8 @@
 #include <linux/amlogic/media/utils/aformat.h>
 #include <linux/amlogic/media/registers/register.h>
 #include "../stream_input/amports/adec.h"
-#include "../stream_input/parser/streambuf.h"
-#include "../stream_input/parser/streambuf_reg.h"
+#include "../stream_input/amports/streambuf.h"
+#include "../stream_input/amports/streambuf_reg.h"
 #include "../stream_input/parser/tsdemux.h"
 #include "../stream_input/parser/psparser.h"
 #include "../stream_input/parser/esparser.h"
@@ -202,7 +202,7 @@ static void change_vbufsize(struct vdec_s *vdec,
                return;
        }
 
-       if (pvbuf->for_4k) {
+       if (vdec->port->is_4k) {
                pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
 
                if (vdec->port_flag & PORT_FLAG_DRM)
@@ -246,7 +246,7 @@ static void audio_component_release(struct stream_port_s *port,
                case 3:
                        adec_release(port->vformat);
                case 2:
-                       stbuf_release(pbuf, false);
+                       stbuf_release(pbuf);
                case 1:
                        ;
        }
@@ -262,7 +262,7 @@ static int audio_component_init(struct stream_port_s *port,
                return 0;
        }
 
-       r = stbuf_init(pbuf, NULL, false);
+       r = stbuf_init(pbuf, NULL);
        if (r < 0)
                return r;
 
@@ -293,7 +293,6 @@ struct stream_buf_s *pbuf, int release_num)
        struct vdec_s *vdec = ada_ctx->vdec;
 
        struct vdec_s *slave = NULL;
-       bool is_multidec = !vdec_single(vdec);
 
        switch (release_num) {
        default:
@@ -315,7 +314,7 @@ struct stream_buf_s *pbuf, int release_num)
 
        case 2: {
                if ((port->type & PORT_TYPE_FRAME) == 0)
-               stbuf_release(pbuf, is_multidec);
+               stbuf_release(pbuf);
        }
 
        case 1:
@@ -338,15 +337,15 @@ static int video_component_init(struct stream_port_s *port,
 
        if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088
                || port->vformat == VFORMAT_H264_4K2K) {
-               pbuf->for_4k = 1;
+               port->is_4k = true;
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX
                                && port->vformat == VFORMAT_H264)
                        vdec_poweron(VDEC_HEVC);
        } else
-               pbuf->for_4k = 0;
+               port->is_4k = false;
 
        if (port->type & PORT_TYPE_FRAME) {
-               ret = vdec_init(vdec, pbuf->for_4k);
+               ret = vdec_init(vdec, port->is_4k);
                if (ret < 0) {
                        v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "failed\n");
                        video_component_release(port, pbuf, 2);
@@ -367,14 +366,14 @@ static int video_component_init(struct stream_port_s *port,
                }
        }
 
-       ret = stbuf_init(pbuf, vdec, false);
+       ret = stbuf_init(pbuf, vdec);
        if (ret < 0) {
                v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "stbuf_init failed\n");
                return ret;
        }
 
        /* todo: set path based on port flag */
-       ret = vdec_init(vdec, pbuf->for_4k);
+       ret = vdec_init(vdec, port->is_4k);
        if (ret < 0) {
                v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
                video_component_release(port, pbuf, 2);
@@ -382,7 +381,7 @@ static int video_component_init(struct stream_port_s *port,
        }
 
        if (vdec_dual(vdec)) {
-               ret = vdec_init(vdec->slave, pbuf->for_4k);
+               ret = vdec_init(vdec->slave, port->is_4k);
                if (ret < 0) {
                        v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
                        video_component_release(port, pbuf, 2);
@@ -543,7 +542,7 @@ static int vdec_ports_init(struct aml_vdec_adapt *ada_ctx)
 
        if ((vdec->port->type & PORT_TYPE_VIDEO)
                && (vdec->port_flag & PORT_FLAG_VFORMAT)) {
-               pvbuf->for_4k = 0;
+               vdec->port->is_4k = false;
                if (has_hevc_vdec()) {
                        if (vdec->port->vformat == VFORMAT_HEVC
                                || vdec->port->vformat == VFORMAT_VP9)
index b73b9ff6f936ad253397518b7eaa6e3cbf0137df..d09f5f0245d8e3fa37e0841f2ac4a71facd72744 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <linux/amlogic/media/utils/vformat.h>
 #include <linux/amlogic/media/utils/amstream.h>
-#include "../stream_input/parser/streambuf.h"
+#include "../stream_input/amports/streambuf.h"
 #include "aml_vcodec_drv.h"
 
 struct aml_vdec_adapt {
index a5ab7358f668166d124c298493f21818415ee063..579e499cdcfa6a42c791fb8df93f812f690c5c1c 100644 (file)
@@ -23,7 +23,7 @@
 #include "aml_vcodec_drv.h"
 #include "aml_vcodec_dec.h"
 #include "aml_vcodec_util.h"
-#include "../stream_input/parser/streambuf.h"
+#include "../stream_input/amports/streambuf.h"
 
 #define AML_VIDEO_MAGIC CODEC_MODE('A', 'M', 'L', 'V')
 
index b97cb33d663a8b9539e89f58248222f9354bc001..b6e500f27447a5adf63db625d158899e491eca1a 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/amlogic/media/vfm/vframe_receiver.h>
 #include <linux/amlogic/media/vfm/vframe.h>
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
 #include "../utils/amvdec.h"
 #include <linux/amlogic/media/registers/register.h>
 #include "../../../stream_input/amports/amports_priv.h"
index b5dc44468278103722d0f5afe52672b9c01f420c..a92dbb9a8b89cdc1af38548c886dad73d5537e2d 100644 (file)
@@ -36,7 +36,7 @@
 /* #include <mach/am_regs.h> */
 #include <linux/module.h>
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
 #include "../utils/amvdec.h"
 #include <linux/amlogic/media/registers/register.h>
 #include "../../../stream_input/amports/amports_priv.h"
index 4c2cb54b4e6a53c6ffc71e32ba3aeb104b1d3c58..2de21c176106d333d14f14784bbed180d60fc4f4 100644 (file)
@@ -6925,7 +6925,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
        if (dec->next_again_flag &&
                (!vdec_frame_based(vdec))) {
                u32 parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+                       STBUF_READ(&vdec->vbuf, get_wp);
                if (parser_wr_ptr >= dec->pre_parser_wr_ptr &&
                        (parser_wr_ptr - dec->pre_parser_wr_ptr) <
                        again_threshold) {
@@ -6940,8 +6940,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                && pre_decode_buf_level != 0) {
                u32 rp, wp, level;
 
-               rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-               wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+               rp = STBUF_READ(&vdec->vbuf, get_rp);
+               wp = STBUF_READ(&vdec->vbuf, get_wp);
                if (wp < rp)
                        level = vdec->input.size + wp - rp;
                else
@@ -7001,9 +7001,12 @@ static void run(struct vdec_s *vdec, unsigned long mask,
        dec->vdec_cb = callback;
        /* dec->chunk = vdec_prepare_input(vdec); */
        hevc_reset_core(vdec);
-       dec->pre_parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+
+       if (vdec_stream_based(vdec)) {
+               dec->pre_parser_wr_ptr =
+                       STBUF_READ(&vdec->vbuf, get_wp);
                dec->next_again_flag = 0;
+       }
 
        r = vdec_prepare_input(vdec, &dec->chunk);
        if (r < 0) {
@@ -7242,10 +7245,10 @@ static void avs2_dump_state(struct vdec_s *vdec)
                READ_VREG(HEVC_STREAM_RD_PTR));
        avs2_print(dec, 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        avs2_print(dec, 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (input_frame_based(vdec) &&
                (debug & PRINT_FLAG_VDEC_DATA)
index f041bf7e92fa06ec44df8d60bd742499d5421cb9..dd5a7b6b17464298b14478820c378da323ab89e5 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/amlogic/media/vfm/vframe_receiver.h>
 #include <linux/amlogic/media/vfm/vframe.h>
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
 #include "../utils/amvdec.h"
 #include <linux/amlogic/media/registers/register.h>
 #include "../../../stream_input/amports/amports_priv.h"
@@ -3042,7 +3042,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                hw->again_flag &&
                (!vdec_frame_based(vdec))) {
                u32 parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+                       STBUF_READ(&vdec->vbuf, get_rp);
                if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
                        (parser_wr_ptr - hw->pre_parser_wr_ptr) <
                        again_threshold) {
@@ -3380,8 +3380,8 @@ static void check_timer_func(unsigned long arg)
                                READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                                READ_VREG(VLD_MEM_VIFIFO_WP),
                                READ_VREG(VLD_MEM_VIFIFO_RP),
-                               READ_PARSER_REG(PARSER_VIDEO_RP),
-                               READ_PARSER_REG(PARSER_VIDEO_WP));
+                               STBUF_READ(&vdec->vbuf, get_rp),
+                               STBUF_READ(&vdec->vbuf, get_wp));
                }
        }
 
@@ -3478,9 +3478,10 @@ void (*callback)(struct vdec_s *, void *),
        int size, ret;
        /* reset everything except DOS_TOP[1] and APB_CBUS[0]*/
 
-       hw->pre_parser_wr_ptr =
-               READ_PARSER_REG(PARSER_VIDEO_WP);
-
+       if (vdec_stream_based(vdec)) {
+               hw->pre_parser_wr_ptr =
+                       STBUF_READ(&vdec->vbuf, get_wp);
+       }
 #if 1
 #if DEBUG_MULTI_FLAG > 0
        if (hw->decode_pic_count == 0) {
@@ -3574,8 +3575,8 @@ void (*callback)(struct vdec_s *, void *),
                        READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                        READ_VREG(VLD_MEM_VIFIFO_WP),
                        READ_VREG(VLD_MEM_VIFIFO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_WP),
+                       STBUF_READ(&vdec->vbuf, get_rp),
+                       STBUF_READ(&vdec->vbuf, get_wp),
                        size);
 
 
@@ -3785,10 +3786,10 @@ static void vmavs_dump_state(struct vdec_s *vdec)
                READ_VREG(VLD_MEM_VIFIFO_RP));
        debug_print(hw, 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        debug_print(hw, 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (vdec_frame_based(vdec) &&
                (debug &        PRINT_FRAMEBASE_DATA)
index 34701470c35fe579aaaff01590d4d9c6efce206f..03a1dbabd0afe7b800137b5b86975da18157a8ae 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../utils/amvdec.h"
 #include "vh264.h"
-#include "../../../stream_input/parser/streambuf.h"
+#include "../../../stream_input/amports/streambuf.h"
 #include <linux/delay.h>
 #include <linux/amlogic/media/video_sink/video.h>
 #include <linux/amlogic/tee.h>
index 22eab2b0208affab73f650aeb3961bda6d8d4525..7e0787459968b89017a8534ab687bab7c41c2453 100644 (file)
@@ -49,7 +49,7 @@
 #include "../utils/vdec.h"
 #include "../utils/amvdec.h"
 #include "../h264/vh264.h"
-#include "../../../stream_input/parser/streambuf.h"
+#include "../../../stream_input/amports/streambuf.h"
 #include <linux/delay.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
 #include "../utils/decoder_mmu_box.h"
@@ -6771,10 +6771,10 @@ static void vmh264_dump_state(struct vdec_s *vdec)
                READ_VREG(VLD_MEM_VIFIFO_RP));
        dpb_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        dpb_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (input_frame_based(vdec) &&
                dpb_is_debug(DECODE_ID(hw),
@@ -8633,8 +8633,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                && pre_decode_buf_level != 0) {
                u32 rp, wp, level;
 
-               rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-               wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+               rp = STBUF_READ(&vdec->vbuf, get_rp);
+               wp = STBUF_READ(&vdec->vbuf, get_wp);
                if (wp < rp)
                        level = vdec->input.size + wp - rp;
                else
@@ -8665,8 +8665,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
        }
        if (hw->next_again_flag &&
                (!vdec_frame_based(vdec))) {
-               u32 parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+               u32 parser_wr_ptr = STBUF_READ(&vdec->vbuf, get_wp);
                if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
                        (parser_wr_ptr - hw->pre_parser_wr_ptr) <
                        again_threshold) {
@@ -8791,9 +8790,11 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                        kfifo_len(&hw->display_q));
        }
 
-       hw->pre_parser_wr_ptr =
-               READ_PARSER_REG(PARSER_VIDEO_WP);
-       hw->next_again_flag = 0;
+       if (vdec_stream_based(vdec)) {
+               hw->pre_parser_wr_ptr =
+                       STBUF_READ(&vdec->vbuf, get_wp);
+               hw->next_again_flag = 0;
+       }
 
        if (hw->reset_bufmgr_flag ||
                ((error_proc_policy & 0x40) &&
@@ -8887,8 +8888,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                        READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                        READ_VREG(VLD_MEM_VIFIFO_WP),
                        READ_VREG(VLD_MEM_VIFIFO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_WP),
+                       STBUF_READ(&vdec->vbuf, get_rp),
+                       STBUF_READ(&vdec->vbuf, get_wp),
                        size);
 
        start_process_time(hw);
index 5accb873e31bb5e7202ef9900ad2603c04c658bc..d99b77027d55151c1d4717e6986fd748d23330b3 100644 (file)
@@ -9390,6 +9390,7 @@ static int hevc_recover(struct hevc_state_s *hevc)
        unsigned int hevc_stream_control;
        unsigned int hevc_stream_fifo_ctl;
        unsigned int hevc_stream_buf_size;
+       struct vdec_s *vdec = hw_to_vdec(hevc);
 
        mutex_lock(&vh265_mutex);
 #if 0
@@ -9413,8 +9414,14 @@ static int hevc_recover(struct hevc_state_s *hevc)
        msleep(20);
        ret = 0;
        /* reset */
-       WRITE_PARSER_REG(PARSER_VIDEO_RP, READ_VREG(HEVC_STREAM_RD_PTR));
-       SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
+       if (vdec_stream_based(vdec)) {
+               STBUF_WRITE(&vdec->vbuf, set_rp,
+                       READ_VREG(HEVC_STREAM_RD_PTR));
+
+               if (!vdec->vbuf.no_parser)
+                       SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
+                               ES_VID_MAN_RD_PTR);
+       }
 
        hevc_stream_start_addr = READ_VREG(HEVC_STREAM_START_ADDR);
        hevc_stream_end_addr = READ_VREG(HEVC_STREAM_END_ADDR);
@@ -12478,8 +12485,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                        && pre_decode_buf_level != 0) {
                        u32 rp, wp, level;
 
-                       rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-                       wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+                       rp = STBUF_READ(&vdec->vbuf, get_rp);
+                       wp = STBUF_READ(&vdec->vbuf, get_wp);
                        if (wp < rp)
                                level = vdec->input.size + wp - rp;
                        else
@@ -12493,7 +12500,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
        if (hevc->next_again_flag &&
                (!vdec_frame_based(vdec))) {
                u32 parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+                       STBUF_READ(&vdec->vbuf, get_wp);
                if (parser_wr_ptr >= hevc->pre_parser_wr_ptr &&
                        (parser_wr_ptr - hevc->pre_parser_wr_ptr) <
                        again_threshold) {
@@ -12595,9 +12602,11 @@ static void run(struct vdec_s *vdec, unsigned long mask,
        hevc_reset_core(vdec);
 
 #ifdef AGAIN_HAS_THRESHOLD
-       hevc->pre_parser_wr_ptr =
-               READ_PARSER_REG(PARSER_VIDEO_WP);
-       hevc->next_again_flag = 0;
+       if (vdec_stream_based(vdec)) {
+               hevc->pre_parser_wr_ptr =
+                       STBUF_READ(&vdec->vbuf, get_wp);
+               hevc->next_again_flag = 0;
+       }
 #endif
        r = vdec_prepare_input(vdec, &hevc->chunk);
        if (r < 0) {
@@ -12631,8 +12640,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                READ_VREG(HEVC_STREAM_LEVEL),
                READ_VREG(HEVC_STREAM_WR_PTR),
                READ_VREG(HEVC_STREAM_RD_PTR),
-               READ_PARSER_REG(PARSER_VIDEO_RP),
-               READ_PARSER_REG(PARSER_VIDEO_WP),
+               STBUF_READ(&vdec->vbuf, get_rp),
+               STBUF_READ(&vdec->vbuf, get_wp),
                hevc->start_shift_bytes
                );
        if ((get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA) &&
@@ -13153,10 +13162,10 @@ static void vh265_dump_state(struct vdec_s *vdec)
                READ_VREG(HEVC_STREAM_RD_PTR));
        hevc_print(hevc, 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        hevc_print(hevc, 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (input_frame_based(vdec) &&
                (get_dbg_flag(hevc) & PRINT_FRAMEBASE_DATA)
index 33b787ab37b78105d1c3370d4eb6b952a122bf79..413ce8123c446b453c894823df6c7e8e2d17b8e2 100644 (file)
@@ -721,10 +721,10 @@ static void vmjpeg_dump_state(struct vdec_s *vdec)
                READ_VREG(VLD_MEM_VIFIFO_RP));
        mmjpeg_debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        mmjpeg_debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
        if (input_frame_based(vdec) &&
                debug_enable & PRINT_FRAMEBASE_DATA
                ) {
@@ -802,7 +802,7 @@ static void check_timer_func(unsigned long arg)
                "%s: %d,buftl=%x:%x:%x:%x\n",
                __func__, __LINE__,
                READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
-               READ_PARSER_REG(PARSER_VIDEO_WP),
+               STBUF_READ(&vdec->vbuf, get_wp),
                READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                READ_VREG(VLD_MEM_VIFIFO_WP));
 
@@ -1151,8 +1151,8 @@ static unsigned long run_ready(struct vdec_s *vdec,
                && pre_decode_buf_level != 0) {
                u32 rp, wp, level;
 
-               rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-               wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+               rp = STBUF_READ(&vdec->vbuf, get_rp);
+               wp = STBUF_READ(&vdec->vbuf, get_wp);
                if (wp < rp)
                        level = vdec->input.size + wp - rp;
                else
@@ -1205,7 +1205,7 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                "%s: %d,r=%d,buftl=%x:%x:%x\n",
                        __func__, __LINE__, ret,
                        READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
-                       READ_PARSER_REG(PARSER_VIDEO_WP),
+                       STBUF_READ(&vdec->vbuf, get_rp),
                        READ_VREG(VLD_MEM_VIFIFO_WP));
 
                hw->dec_result = DEC_RESULT_AGAIN;
index 27d62a978c19b7e2bdf038952288f56ab2bece15..411668891ff95725b2afc738e2bcf7896878ed09 100644 (file)
@@ -2572,10 +2572,11 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
                READ_VREG(VLD_MEM_VIFIFO_RP));
        debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
+
        if (vdec_frame_based(vdec) &&
                debug_enable & PRINT_FRAMEBASE_DATA
                ) {
@@ -2950,8 +2951,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                && pre_decode_buf_level != 0) {
                u32 rp, wp, level;
 
-               rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-               wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+               rp = STBUF_READ(&vdec->vbuf, get_rp);
+               wp = STBUF_READ(&vdec->vbuf, get_wp);
                if (wp < rp)
                        level = vdec->input.size + wp - rp;
                else
@@ -2967,7 +2968,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                if (hw->next_again_flag&&
                        (!vdec_frame_based(vdec))) {
                        u32 parser_wr_ptr =
-                               READ_PARSER_REG(PARSER_VIDEO_WP);
+                               STBUF_READ(&vdec->vbuf, get_wp);
                        if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
                                (parser_wr_ptr - hw->pre_parser_wr_ptr) <
                                again_threshold) {
@@ -3056,9 +3057,11 @@ void (*callback)(struct vdec_s *, void *),
        hw->vdec_cb = callback;
 
 #ifdef AGAIN_HAS_THRESHOLD
+       if (vdec_stream_based(vdec)) {
                hw->pre_parser_wr_ptr =
-                       READ_PARSER_REG(PARSER_VIDEO_WP);
+                       STBUF_READ(&vdec->vbuf, get_wp);
                hw->next_again_flag = 0;
+       }
 #endif
 
        size = vdec_prepare_input(vdec, &hw->chunk);
@@ -3136,8 +3139,8 @@ void (*callback)(struct vdec_s *, void *),
                        READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                        READ_VREG(VLD_MEM_VIFIFO_WP),
                        READ_VREG(VLD_MEM_VIFIFO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_RP),
-                       READ_PARSER_REG(PARSER_VIDEO_WP),
+                       STBUF_READ(&vdec->vbuf, get_rp),
+                       STBUF_READ(&vdec->vbuf, get_wp),
                        size);
 
        if (vdec->mvfrm && hw->chunk)
index c6bea5bfe531717b96d7a326ba8dc1fadb5ce0b0..9cf5629273ccb2c8154567360ebfe99a563754a1 100644 (file)
@@ -1800,10 +1800,11 @@ static void vmpeg4_dump_state(struct vdec_s *vdec)
                READ_VREG(VLD_MEM_VIFIFO_RP));
        mmpeg4_debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        mmpeg4_debug_print(DECODE_ID(hw), 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
+
        if (vdec_frame_based(vdec) &&
                debug_enable & PRINT_FRAMEBASE_DATA) {
                int jj;
@@ -2182,8 +2183,8 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
                && pre_decode_buf_level != 0) {
                u32 rp, wp, level;
 
-               rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-               wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+               rp = STBUF_READ(&vdec->vbuf, get_rp);
+               wp = STBUF_READ(&vdec->vbuf, get_wp);
                if (wp < rp)
                        level = vdec->input.size + wp - rp;
                else
@@ -2329,8 +2330,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
                READ_VREG(VLD_MEM_VIFIFO_LEVEL),
                READ_VREG(VLD_MEM_VIFIFO_WP),
                READ_VREG(VLD_MEM_VIFIFO_RP),
-               READ_PARSER_REG(PARSER_VIDEO_RP),
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_rp),
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        hw->dec_result = DEC_RESULT_NONE;
        if (vdec->mc_loaded) {
index a752f78fe8e2001f7184cb1316d3350d7f47bc2f..49bd408bbb06881edb5157c9ee465679b094d6a1 100644 (file)
@@ -41,8 +41,8 @@
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../utils/amvdec.h"
 
-#include "../../../stream_input/parser/streambuf.h"
-#include "../../../stream_input/parser/streambuf_reg.h"
+#include "../../../stream_input/amports/streambuf.h"
+#include "../../../stream_input/amports/streambuf_reg.h"
 #include "../../../stream_input/parser/rmparser.h"
 
 #include "vreal.h"
index e2993a618a13dec38cb320abc40d7f12ff5b7fb4..dfcd1c89d86c8d1218bc95e030ff20474c3e6f50 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/time.h>
 
 #include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/streambuf.h"
 #include "vdec.h"
 #include "vdec_trace.h"
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
@@ -126,6 +127,8 @@ static int enable_mvdec_info = 1;
 
 int decode_underflow = 0;
 
+int enable_stream_mode_multi_dec;
+
 #define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
 
 struct am_reg {
@@ -771,8 +774,8 @@ void vdec_update_streambuff_status(void)
                        (vdec->need_more_data & VDEC_NEED_MORE_DATA)) {
                        u32 rp, wp, level;
 
-                       rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-                       wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+                       rp = STBUF_READ(&vdec->vbuf, get_rp);
+                       wp = STBUF_READ(&vdec->vbuf, get_wp);
                        if (wp < rp)
                                level = input->size + wp - rp;
                        else
@@ -1258,13 +1261,13 @@ static void vdec_sync_input_read(struct vdec_s *vdec)
                                other =
                                vdec_get_associate(vdec)->input.swap_rp;
                                if (me > other) {
-                                       WRITE_PARSER_REG(PARSER_VIDEO_RP,
-                                               vdec_get_associate(vdec)->
-                                               input.swap_rp);
+                                       STBUF_WRITE(&vdec->vbuf, set_rp,
+                                               vdec_get_associate(vdec)->input.swap_rp);
                                        return;
                                }
                        }
-                       WRITE_PARSER_REG(PARSER_VIDEO_RP,
+
+                       STBUF_WRITE(&vdec->vbuf, set_rp,
                                READ_VREG(VLD_MEM_VIFIFO_RP));
                } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
                        me = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
@@ -1273,20 +1276,19 @@ static void vdec_sync_input_read(struct vdec_s *vdec)
                                me += 1ULL << 32;
                        other = vdec_get_associate(vdec)->input.streaming_rp;
                        if (me > other) {
-                               WRITE_PARSER_REG(PARSER_VIDEO_RP,
-                                       vdec_get_associate(vdec)->
-                                       input.swap_rp);
+                               STBUF_WRITE(&vdec->vbuf, set_rp,
+                                       vdec_get_associate(vdec)->input.swap_rp);
                                return;
                        }
 
-                       WRITE_PARSER_REG(PARSER_VIDEO_RP,
+                       STBUF_WRITE(&vdec->vbuf, set_rp,
                                READ_VREG(HEVC_STREAM_RD_PTR));
                }
        } else if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
-               WRITE_PARSER_REG(PARSER_VIDEO_RP,
+               STBUF_WRITE(&vdec->vbuf, set_rp,
                        READ_VREG(VLD_MEM_VIFIFO_RP));
        } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
-               WRITE_PARSER_REG(PARSER_VIDEO_RP,
+               STBUF_WRITE(&vdec->vbuf, set_rp,
                        READ_VREG(HEVC_STREAM_RD_PTR));
        }
 }
@@ -1298,10 +1300,10 @@ static void vdec_sync_input_write(struct vdec_s *vdec)
 
        if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
                WRITE_VREG(VLD_MEM_VIFIFO_WP,
-                       READ_PARSER_REG(PARSER_VIDEO_WP));
+                       STBUF_READ(&vdec->vbuf, get_wp));
        } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
                WRITE_VREG(HEVC_STREAM_WR_PTR,
-                       READ_PARSER_REG(PARSER_VIDEO_WP));
+                       STBUF_READ(&vdec->vbuf, get_wp));
        }
 }
 
@@ -1474,6 +1476,10 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
                                WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
                                        (0x11 << 16) | (1<<10));
 
+                               if (vdec->vbuf.no_parser)
+                                       SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
+                                               7 << 3);
+
                                /* sync with front end */
                                vdec_sync_input_read(vdec);
                                vdec_sync_input_write(vdec);
@@ -1509,6 +1515,9 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
 
                                wp = READ_VREG(HEVC_STREAM_WR_PTR);
 
+                               if (vdec->vbuf.no_parser)
+                                       SET_VREG_MASK(HEVC_STREAM_CONTROL,
+                                               7 << 4);
                                /*pr_info("vdec: restore context\r\n");*/
                        }
 
@@ -1528,13 +1537,15 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
                                WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
                                WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start);
                                WRITE_VREG(VLD_MEM_VIFIFO_WP,
-                                       READ_PARSER_REG(PARSER_VIDEO_WP));
-
+                                       STBUF_READ(&vdec->vbuf, get_wp));
                                rp = READ_VREG(VLD_MEM_VIFIFO_RP);
 
                                /* enable */
                                WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
                                        (0x11 << 16) | (1<<10));
+                               if (vdec->vbuf.no_parser)
+                                       SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
+                                               7 << 3);
 
                                wp = READ_VREG(VLD_MEM_VIFIFO_WP);
 
@@ -1546,13 +1557,14 @@ int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
                                WRITE_VREG(HEVC_STREAM_RD_PTR,
                                        input->start);
                                WRITE_VREG(HEVC_STREAM_WR_PTR,
-                                       READ_PARSER_REG(PARSER_VIDEO_WP));
-
+                                       STBUF_READ(&vdec->vbuf, get_wp));
                                rp = READ_VREG(HEVC_STREAM_RD_PTR);
                                wp = READ_VREG(HEVC_STREAM_WR_PTR);
                                fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
                                                >> 16) & 0x7f;
-
+                               if (vdec->vbuf.no_parser)
+                                       SET_VREG_MASK(HEVC_STREAM_CONTROL,
+                                               7 << 4);
                                /* enable */
                        }
                }
@@ -1582,10 +1594,15 @@ void vdec_enable_input(struct vdec_s *vdec)
                SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1));
        else if (input->target == VDEC_INPUT_TARGET_HEVC) {
                SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
-               if (vdec_stream_based(vdec))
-                       CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
-               else
+               if (vdec_stream_based(vdec)) {
+                       if (vdec->vbuf.no_parser)
+                               /*set endian for non-parser mode. */
+                               SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+                       else
+                               CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+               } else
                        SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+
                SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29));
        }
 }
@@ -1624,10 +1641,10 @@ bool vdec_has_more_input(struct vdec_s *vdec)
        else {
                if (input->target == VDEC_INPUT_TARGET_VLD)
                        return READ_VREG(VLD_MEM_VIFIFO_WP) !=
-                               READ_PARSER_REG(PARSER_VIDEO_WP);
+                               STBUF_READ(&vdec->vbuf, get_wp);
                else {
                        return (READ_VREG(HEVC_STREAM_WR_PTR) & ~0x3) !=
-                               (READ_PARSER_REG(PARSER_VIDEO_WP) & ~0x3);
+                               (STBUF_READ(&vdec->vbuf, get_wp) & ~0x3);
                }
        }
 }
@@ -2153,13 +2170,15 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
         *todo: VFM patch control should be configurable,
         * for now all stream based input uses default VFM path.
         */
-       if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
-               if (vdec_core->vfm_vdec == NULL) {
-                       pr_debug("vdec_init set vfm decoder %p\n", vdec);
-                       vdec_core->vfm_vdec = vdec;
-               } else {
-                       pr_info("vdec_init vfm path busy.\n");
-                       return -EBUSY;
+       if (!enable_stream_mode_multi_dec) {
+               if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
+                       if (vdec_core->vfm_vdec == NULL) {
+                               pr_debug("vdec_init set vfm decoder %p\n", vdec);
+                               vdec_core->vfm_vdec = vdec;
+                       } else {
+                               pr_info("vdec_init vfm path busy.\n");
+                               return -EBUSY;
+                       }
                }
        }
 
@@ -2186,8 +2205,13 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
        atomic_set(&p->inirq_flag, 0);
        atomic_set(&p->inirq_thread_flag, 0);
        /* todo */
-       if (!vdec_dual(vdec))
-               p->use_vfm_path = vdec_stream_based(vdec);
+       if (!vdec_dual(vdec)) {
+               p->use_vfm_path =
+                       enable_stream_mode_multi_dec ?
+                       vdec_single(vdec) :
+                       vdec_stream_based(vdec);
+       }
+
        if (debugflags & 0x4)
                p->use_vfm_path = 1;
        /* vdec_dev_reg.flag = 0; */
@@ -2199,6 +2223,20 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
 #ifdef FRAME_CHECK
        vdec_frame_check_init(vdec);
 #endif
+       /* stream buffer init. */
+       if (vdec->vbuf.ops) {
+               r = vdec->vbuf.ops->init(&vdec->vbuf, vdec);
+               if (r) {
+                       pr_err("%s stream buffer init err (%d)\n", dev_name, r);
+
+                       mutex_lock(&vdec_mutex);
+                       inited_vcodec_num--;
+                       mutex_unlock(&vdec_mutex);
+
+                       goto error;
+               }
+       }
+
        p->dev = platform_device_register_data(
                                &vdec_core->vdec_core_platform_device->dev,
                                dev_name,
@@ -2241,15 +2279,17 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
                /* create IONVIDEO instance and connect decoder's
                 * vf_provider interface to it
                 */
-               if (p->type != VDEC_TYPE_FRAME_BLOCK) {
-                       r = -ENODEV;
-                       pr_err("vdec: Incorrect decoder type\n");
+               if (!enable_stream_mode_multi_dec) {
+                       if (p->type != VDEC_TYPE_FRAME_BLOCK) {
+                               r = -ENODEV;
+                               pr_err("vdec: Incorrect decoder type\n");
 
-                       mutex_lock(&vdec_mutex);
-                       inited_vcodec_num--;
-                       mutex_unlock(&vdec_mutex);
+                               mutex_lock(&vdec_mutex);
+                               inited_vcodec_num--;
+                               mutex_unlock(&vdec_mutex);
 
-                       goto error;
+                               goto error;
+                       }
                }
 
                if (strncmp("disable", vfm_path, strlen("disable"))) {
@@ -2557,6 +2597,10 @@ void vdec_release(struct vdec_s *vdec)
        platform_device_unregister(vdec->dev);
        /*Check if the vdec still in connected list, if yes, delete it*/
        vdec_connect_list_force_clear(vdec_core, vdec);
+
+       if (vdec->vbuf.ops)
+               vdec->vbuf.ops->release(&vdec->vbuf);
+
        pr_debug("vdec_release instance %p, total %d\n", vdec,
                atomic_read(&vdec_core->vdec_nr));
        vdec_destroy(vdec);
@@ -2903,8 +2947,8 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
                if (input && input_stream_based(input) && !input->eos) {
                        u32 rp, wp, level;
 
-                       rp = READ_PARSER_REG(PARSER_VIDEO_RP);
-                       wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+                       rp = STBUF_READ(&vdec->vbuf, get_rp);
+                       wp = STBUF_READ(&vdec->vbuf, get_wp);
                        if (wp < rp)
                                level = input->size + wp - rp;
                        else
@@ -4523,6 +4567,29 @@ static ssize_t show_debug(struct class *class,
 }
 #endif
 
+int show_stream_buffer_status(char *buf,
+       int (*callback) (struct stream_buf_s *, char *))
+{
+       char *pbuf = buf;
+       struct vdec_s *vdec;
+       struct vdec_core_s *core = vdec_core;
+       u64 flags = vdec_core_lock(vdec_core);
+
+       list_for_each_entry(vdec,
+               &core->connected_vdec_list, list) {
+               if ((vdec->status == VDEC_STATUS_CONNECTED
+                       || vdec->status == VDEC_STATUS_ACTIVE)) {
+                       if (vdec_frame_based(vdec))
+                               continue;
+                       pbuf += callback(&vdec->vbuf, pbuf);
+               }
+       }
+       vdec_core_unlock(vdec_core, flags);
+
+       return pbuf - buf;
+}
+EXPORT_SYMBOL(show_stream_buffer_status);
+
 static ssize_t store_vdec_vfm_path(struct class *class,
                 struct class_attribute *attr,
                 const char *buf, size_t count)
@@ -5447,6 +5514,10 @@ MODULE_PARM_DESC(max_di_instance,
 module_param(debug_vdetect, int, 0664);
 MODULE_PARM_DESC(debug_vdetect, "\n debug_vdetect\n");
 
+module_param(enable_stream_mode_multi_dec, int, 0664);
+EXPORT_SYMBOL(enable_stream_mode_multi_dec);
+MODULE_PARM_DESC(enable_stream_mode_multi_dec,
+       "\n enable multi-decoding on stream mode. \n");
 /*
 *module_init(vdec_module_init);
 *module_exit(vdec_module_exit);
index 12fa840f119622625047fcdb4f901e2a57b29d14..f99185024b4f98d0f8c6e030e4323cf3d5406b6f 100644 (file)
@@ -31,6 +31,8 @@
 #define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VDEC
 #include <trace/events/meson_atrace.h>
 /*#define CONFIG_AM_VDEC_DV*/
+#include "../../../stream_input/amports/streambuf.h"
+#include "../../../stream_input/amports/stream_buffer_base.h"
 
 #include "vdec_input.h"
 #include "frame_check.h"
@@ -178,6 +180,7 @@ struct vdec_s {
        struct vdec_s *master;
        struct vdec_s *slave;
        struct stream_port_s *port;
+       struct stream_buf_s vbuf;
        int status;
        int next_status;
        int type;
@@ -460,4 +463,7 @@ extern u32  vdec_get_frame_vdec(struct vdec_s *vdec,  struct vframe_counter_s *t
 
 int vdec_get_frame_num(struct vdec_s *vdec);
 
+int show_stream_buffer_status(char *buf,
+       int (*callback) (struct stream_buf_s *, char *));
+
 #endif                         /* VDEC_H */
index e84ee3e3c59faec7252dedf3489c5cf0efbacabf..93578b52ecd23e8bf26f767db43b1aad19a6709c 100644 (file)
@@ -9284,10 +9284,10 @@ static void av1_dump_state(struct vdec_s *vdec)
                READ_VREG(HEVC_STREAM_RD_PTR));
        av1_print(hw, 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        av1_print(hw, 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (input_frame_based(vdec) &&
                (debug & PRINT_FLAG_VDEC_DATA)
index c9aee913523ca14533a567f91f7dc2911912fadb..acf2db8ddd0e48b668adb86fc6c5248b1f01b0b8 100644 (file)
@@ -10463,10 +10463,10 @@ static void vp9_dump_state(struct vdec_s *vdec)
                READ_VREG(HEVC_STREAM_RD_PTR));
        vp9_print(pbi, 0,
                "PARSER_VIDEO_RP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_RP));
+               STBUF_READ(&vdec->vbuf, get_rp));
        vp9_print(pbi, 0,
                "PARSER_VIDEO_WP=0x%x\n",
-               READ_PARSER_REG(PARSER_VIDEO_WP));
+               STBUF_READ(&vdec->vbuf, get_wp));
 
        if (input_frame_based(vdec) &&
                (debug & PRINT_FLAG_VDEC_DATA)
index a6cedab98fe6a4b8320bac1895a159a80b11f09e..36efa1480c6c4ad67460bd6fdd75e9b32b0284ab 100644 (file)
@@ -2,8 +2,11 @@ obj-m  +=       stream_input.o
 
 stream_input-objs      +=      amports/amstream.o
 stream_input-objs      +=      amports/adec.o
-stream_input-objs      +=      parser/thread_rw.o
-stream_input-objs      +=      parser/streambuf.o
+stream_input-objs      +=      amports/thread_rw.o
+stream_input-objs      +=      amports/streambuf.o
+stream_input-objs      +=      amports/stream_buffer_base.o
+stream_input-objs      +=      amports/stream_buffer_interface.o
+
 stream_input-objs      +=      parser/esparser.o
 stream_input-objs      +=      parser/tsdemux.o
 stream_input-objs      +=      parser/psparser.o
index 5bca205c42624cfe35cf3667811635729e4cf52d..08283882a03c1fc9b19b18248f64cb7791aebb81 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/amlogic/media/frame_sync/ptsserv.h>
 #include <linux/amlogic/media/registers/register.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
 #include <linux/module.h>
 #include <linux/of.h>
 #include "amports_priv.h"
index f06f73ad39b04d2333e61145918b3207a171ecd4..1ad276f8583b6b8d66807483d545ce212d545121 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef ADEC_H
 #define ADEC_H
 
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
 #include <linux/amlogic/media/utils/aformat.h>
 
 extern s32 adec_init(struct stream_port_s *port);
index b09118d1905756221be6d76abe0f00bc2bb4c2bb..ffead011e3e95f24dcf7d63d87c80e34e8f732fa 100644 (file)
@@ -17,7 +17,7 @@
 
 #ifndef AMPORTS_PRIV_HEAD_HH
 #define AMPORTS_PRIV_HEAD_HH
-#include "../parser/streambuf.h"
+#include "../amports/streambuf.h"
 #include "../../common/media_clock/switch/amports_gate.h"
 #include <linux/amlogic/media/vfm/vframe.h>
 #include <linux/amlogic/media/registers/register.h>
index 9f747e4ec4542e7bff656aee379da1c6ba13dc7a..916a65654026a118c65d67bb57cbf74937c2fef7 100644 (file)
@@ -56,8 +56,8 @@
 /* #include <mach/mod_gate.h> */
 /* #include <mach/power_gate.h> */
 #endif
-#include "../parser/streambuf.h"
-#include "../parser/streambuf_reg.h"
+#include "../amports/streambuf.h"
+#include "../amports/streambuf_reg.h"
 #include "../parser/tsdemux.h"
 #include "../parser/psparser.h"
 #include "../parser/esparser.h"
@@ -67,7 +67,7 @@
 #include "amports_priv.h"
 #include <linux/amlogic/media/utils/amports_config.h>
 #include <linux/amlogic/media/frame_sync/tsync_pcr.h>
-#include "../parser/thread_rw.h"
+#include "../amports/thread_rw.h"
 #include <linux/firmware.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
@@ -83,6 +83,7 @@
 #include "../../common/chips/chips.h"
 #include "../../common/chips/decoder_cpu_ver_info.h"
 #include "../subtitle/subtitle.h"
+#include "stream_buffer_base.h"
 
 //#define G12A_BRINGUP_DEBUG
 
@@ -122,6 +123,8 @@ static int def_vstreambuf_sizeM =
        (DEFAULT_VIDEO_BUFFER_SIZE >> 20);
 static int slow_input;
 
+extern int enable_stream_mode_multi_dec;
+
 /* #define DATA_DEBUG */
 static int use_bufferlevelx10000 = 10000;
 static int reset_canuse_buferlevel(int level);
@@ -520,7 +523,7 @@ static void amstream_change_vbufsize(struct port_priv_s *priv,
                pr_info("streambuf is alloced before\n");
                return;
        }
-       if (pvbuf->for_4k) {
+       if (priv->port->is_4k) {
                pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
                if (priv->vdec->port_flag & PORT_FLAG_DRM)
                        pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP;
@@ -547,7 +550,7 @@ static bool port_get_inited(struct port_priv_s *priv)
        if (port->type & PORT_TYPE_VIDEO) {
                struct vdec_s *vdec = priv->vdec;
 
-               return vdec->port_flag & PORT_FLAG_INITED;
+               return vdec ? vdec->port_flag & PORT_FLAG_INITED : 0;
        }
 
        return port->flag & PORT_FLAG_INITED;
@@ -571,20 +574,16 @@ static void port_set_inited(struct port_priv_s *priv)
 static void video_port_release(struct port_priv_s *priv,
          struct stream_buf_s *pbuf, int release_num)
 {
-       struct stream_port_s *port = priv->port;
        struct vdec_s *vdec = priv->vdec;
        struct vdec_s *slave = NULL;
-       bool is_multidec = !vdec_single(vdec);
+
+       if (!vdec)
+               return;
 
        switch (release_num) {
        default:
        /*fallthrough*/
        case 0:         /*release all */
-       /*fallthrough*/
-       case 4:
-               if ((port->type & PORT_TYPE_FRAME) == 0)
-                       esparser_release(pbuf);
-       /*fallthrough*/
        case 3:
                if (vdec->slave)
                        slave = vdec->slave;
@@ -593,10 +592,6 @@ static void video_port_release(struct port_priv_s *priv,
                        vdec_release(slave);
                priv->vdec = NULL;
        /*fallthrough*/
-       case 2:
-               if ((port->type & PORT_TYPE_FRAME) == 0)
-                       stbuf_release(pbuf, is_multidec);
-       /*fallthrough*/
        case 1:
                ;
        }
@@ -620,13 +615,13 @@ static int video_port_init(struct port_priv_s *priv,
        if (port->vformat == VFORMAT_H264_4K2K ||
                (priv->vdec->sys_info->height *
                        priv->vdec->sys_info->width) > 1920*1088) {
-               pbuf->for_4k = 1;
+               port->is_4k = true;
                if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
                                && port->vformat == VFORMAT_H264) {
                        vdec_poweron(VDEC_HEVC);
                }
        } else {
-               pbuf->for_4k = 0;
+               port->is_4k = false;
        }
 
        if (port->type & PORT_TYPE_FRAME) {
@@ -636,7 +631,6 @@ static int video_port_init(struct port_priv_s *priv,
                if (r < 0) {
                        pr_err("video_port_init %d, vdec_init failed\n",
                                __LINE__);
-                       video_port_release(priv, pbuf, 2);
                        return r;
                }
 
@@ -647,9 +641,9 @@ static int video_port_init(struct port_priv_s *priv,
                                (priv->vdec->sys_info->height *
                                priv->vdec->sys_info->width) > 1920*1088);
                        if (r < 0) {
+                               vdec_release(vdec);
                                pr_err("video_port_init %d, vdec_init failed\n",
                                        __LINE__);
-                               video_port_release(priv, pbuf, 2);
                                return r;
                        }
                }
@@ -667,12 +661,6 @@ static int video_port_init(struct port_priv_s *priv,
                }
        }
 
-       r = stbuf_init(pbuf, vdec, false);
-       if (r < 0) {
-               pr_err("video_port_init %d, stbuf_init failed\n", __LINE__);
-               return r;
-       }
-
        /* todo: set path based on port flag */
        r = vdec_init(vdec,
                (priv->vdec->sys_info->height *
@@ -680,8 +668,7 @@ static int video_port_init(struct port_priv_s *priv,
 
        if (r < 0) {
                pr_err("video_port_init %d, vdec_init failed\n", __LINE__);
-               video_port_release(priv, pbuf, 2);
-               return r;
+               goto err;
        }
 
        if (vdec_dual(vdec)) {
@@ -689,25 +676,20 @@ static int video_port_init(struct port_priv_s *priv,
                        (priv->vdec->sys_info->height *
                        priv->vdec->sys_info->width) > 1920*1088);
                if (r < 0) {
-                       pr_err("video_port_init %d, vdec_init failed\n",
-                               __LINE__);
-                       video_port_release(priv, pbuf, 2);
-                       return r;
-               }
-       }
-
-       if (port->type & PORT_TYPE_ES) {
-               r = esparser_init(pbuf, vdec);
-               if (r < 0) {
-                       video_port_release(priv, pbuf, 3);
-                       pr_err("esparser_init() failed\n");
-                       return r;
+                       pr_err("video_port_init %d, vdec_init failed\n", __LINE__);
+                       goto err;
                }
        }
 
-       pbuf->flag |= BUF_FLAG_IN_USE;
-
        return 0;
+err:
+       if (vdec->slave)
+               vdec_release(vdec->slave);
+       if (vdec)
+               vdec_release(vdec);
+       priv->vdec = NULL;
+
+       return r;
 }
 
 static void audio_port_release(struct stream_port_s *port,
@@ -725,7 +707,7 @@ static void audio_port_release(struct stream_port_s *port,
                adec_release(port->vformat);
        /*fallthrough*/
        case 2:
-               stbuf_release(pbuf, false);
+               stbuf_release(pbuf);
        /*fallthrough*/
        case 1:
                ;
@@ -755,9 +737,9 @@ static int audio_port_reset(struct stream_port_s *port,
        pr_info("audio_port_reset begin\n");
        pts_stop(PTS_TYPE_AUDIO);
 
-       stbuf_release(pbuf, false);
+       stbuf_release(pbuf);
 
-       r = stbuf_init(pbuf, NULL, false);
+       r = stbuf_init(pbuf, NULL);
        if (r < 0) {
                mutex_unlock(&amstream_mutex);
                return r;
@@ -804,9 +786,9 @@ static int sub_port_reset(struct stream_port_s *port,
 
        port->flag &= (~PORT_FLAG_INITED);
 
-       stbuf_release(pbuf, false);
+       stbuf_release(pbuf);
 
-       r = stbuf_init(pbuf, NULL, false);
+       r = stbuf_init(pbuf, NULL);
        if (r < 0)
                return r;
 
@@ -838,7 +820,7 @@ static int audio_port_init(struct stream_port_s *port,
                return 0;
        }
 
-       r = stbuf_init(pbuf, NULL, false);
+       r = stbuf_init(pbuf, NULL);
        if (r < 0)
                return r;
        r = adec_init(port);
@@ -865,14 +847,14 @@ static void sub_port_release(struct stream_port_s *port,
                /* this is es sub */
                esparser_release(pbuf);
        }
-       stbuf_release(pbuf, false);
+       stbuf_release(pbuf);
        sub_port_inited = 0;
 }
 
 static int sub_port_init(struct stream_port_s *port, struct stream_buf_s *pbuf)
 {
        int r;
-       r = stbuf_init(pbuf, NULL, false);
+       r = stbuf_init(pbuf, NULL);
        if (r < 0)
                return r;
        if ((port->flag & PORT_FLAG_SID) == 0) {
@@ -958,72 +940,70 @@ static int amstream_port_init(struct port_priv_s *priv)
        }
 
        if ((port->type & PORT_TYPE_VIDEO) &&
-               (vdec->port_flag & PORT_FLAG_VFORMAT)) {
-               pvbuf->for_4k = 0;
-               if (has_hevc_vdec()) {
-                       if (port->vformat == VFORMAT_HEVC ||
-                               port->vformat == VFORMAT_AVS2 ||
-                               port->vformat == VFORMAT_AV1 ||
-                               port->vformat == VFORMAT_VP9)
-                               pvbuf = &bufs[BUF_TYPE_HEVC];
+               (port->flag & PORT_FLAG_VFORMAT)) {
+               if (vdec_stream_based(vdec)) {
+                       struct stream_buf_ops *ops = NULL;
+                       struct parser_args pars = {
+                               .vid = (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
+                               .aid = (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
+                               .sid = (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
+                               .pcrid = (port->pcr_inited == 1) ? port->pcrid : 0xffff,
+                       };
+
+                       if (port->type & PORT_TYPE_MPTS) {
+                               ops = get_tsparser_stbuf_ops();
+                       } else if (port->type & PORT_TYPE_MPPS) {
+                               ops = get_psparser_stbuf_ops();
+                       } else {
+                               ops = !vdec_single(vdec) ?
+                                       get_stbuf_ops() :
+                                       get_esparser_stbuf_ops();
+
+                               /* def used stbuf with parser if the feature disable. */
+                               if (!enable_stream_mode_multi_dec)
+                                       ops = get_esparser_stbuf_ops();
+                       }
+
+                       r = stream_buffer_base_init(&vdec->vbuf, ops, &pars);
+                       if (r) {
+                               mutex_unlock(&priv->mutex);
+                               pr_err("stream buffer base init failed\n");
+                               goto error2;
+                       }
                }
+
                mutex_lock(&priv->mutex);
-               r = video_port_init(priv, pvbuf);
+               r = video_port_init(priv, &vdec->vbuf);
                if (r < 0) {
                        mutex_unlock(&priv->mutex);
-                       pr_err("video_port_init  failed\n");
+                       pr_err("video_port_init failed\n");
                        goto error2;
                }
                mutex_unlock(&priv->mutex);
        }
 
-       if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) {
-               r = sub_port_init(port, psbuf);
-               if (r < 0) {
-                       pr_err("sub_port_init  failed\n");
-                       goto error3;
-               }
-       }
-
-       if (port->type & PORT_TYPE_MPTS) {
-               if (has_hevc_vdec()) {
-                       r = tsdemux_init(
-                       (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
+       if ((port->type & PORT_TYPE_MPTS) &&
+               !(port->flag & PORT_FLAG_VFORMAT)) {
+               r = tsdemux_init(0xffff,
                        (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
                        (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
                        (port->pcr_inited == 1) ? port->pcrid : 0xffff,
-                       (port->vformat == VFORMAT_HEVC) ||
-                       (port->vformat == VFORMAT_AVS2) ||
-                       (port->vformat == VFORMAT_AV1) ||
-                       (port->vformat == VFORMAT_VP9),
-                       vdec);
-               } else {
-                       r = tsdemux_init(
-                       (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
-                       (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
-                       (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
-                       (port->pcr_inited == 1) ? port->pcrid : 0xffff,
-                       0,
-                       vdec);
-               }
-
+                       0, vdec);
                if (r < 0) {
                        pr_err("tsdemux_init  failed\n");
                        goto error4;
                }
                tsync_pcr_start();
        }
-       if (port->type & PORT_TYPE_MPPS) {
-               r = psparser_init(
-                       (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
-                       (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
-                       (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
-                       priv->vdec);
+
+       if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) {
+               r = sub_port_init(port, psbuf);
                if (r < 0) {
-                       pr_err("psparser_init  failed\n");
-                       goto error5;
+                       pr_err("sub_port_init  failed\n");
+                       goto error3;
                }
        }
+
 #ifdef CONFIG_AM_VDEC_REAL
        if (port->type & PORT_TYPE_RM) {
                rm_set_vasid(
@@ -1052,12 +1032,11 @@ static int amstream_port_init(struct port_priv_s *priv)
        mutex_unlock(&amstream_mutex);
        return 0;
        /*errors follow here */
-error5:
-       tsdemux_release();
+
 error4:
        sub_port_release(port, psbuf);
 error3:
-       video_port_release(priv, pvbuf, 0);
+       video_port_release(priv, &priv->vdec->vbuf, 0);
 error2:
        audio_port_release(port, pabuf, 0);
 error1:
@@ -1068,20 +1047,12 @@ error1:
 static int amstream_port_release(struct port_priv_s *priv)
 {
        struct stream_port_s *port = priv->port;
-       struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
+       struct stream_buf_s *pvbuf = &priv->vdec->vbuf;
        struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
        struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
 
-       if (has_hevc_vdec()) {
-               if (port->vformat == VFORMAT_HEVC
-                       || port->vformat == VFORMAT_AVS2
-                       || port->vformat == VFORMAT_AV1
-                       || port->vformat == VFORMAT_VP9)
-                       pvbuf = &bufs[BUF_TYPE_HEVC];
-       }
-
-       if (port->type & PORT_TYPE_MPTS) {
-               vdec_disconnect(priv->vdec);
+       if ((port->type & PORT_TYPE_MPTS) &&
+               !(port->flag & PORT_FLAG_VFORMAT)) {
                tsync_pcr_stop();
                tsdemux_release();
        }
@@ -1144,14 +1115,8 @@ static ssize_t amstream_vbuf_write(struct file *file, const char *buf,
                                        size_t count, loff_t *ppos)
 {
        struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
-       struct stream_port_s *port = priv->port;
-       struct stream_buf_s *pbuf = NULL;
+       struct stream_buf_s *pbuf = &priv->vdec->vbuf;
        int r;
-       if (has_hevc_vdec()) {
-               pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] :
-                       &bufs[BUF_TYPE_VIDEO];
-       } else
-               pbuf = &bufs[BUF_TYPE_VIDEO];
 
        if (!(port_get_inited(priv))) {
                r = amstream_port_init(priv);
@@ -1162,7 +1127,7 @@ static ssize_t amstream_vbuf_write(struct file *file, const char *buf,
        if (priv->vdec->port_flag & PORT_FLAG_DRM)
                r = drm_write(file, pbuf, buf, count);
        else
-               r = esparser_write(file, pbuf, buf, count);
+               r = stream_buffer_write(file, pbuf, buf, count);
        if (slow_input) {
                pr_info("slow_input: es codec write size %x\n", r);
                msleep(3000);
@@ -1226,18 +1191,9 @@ static ssize_t amstream_mpts_write(struct file *file, const char *buf,
        struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
        struct stream_port_s *port = priv->port;
        struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
-       struct stream_buf_s *pvbuf = NULL;
+       struct stream_buf_s *pvbuf = &priv->vdec->vbuf;
        int r = 0;
 
-       if (has_hevc_vdec()) {
-               pvbuf = (port->vformat == VFORMAT_HEVC ||
-                                       port->vformat == VFORMAT_AVS2 ||
-                                       port->vformat == VFORMAT_AV1 ||
-                                       port->vformat == VFORMAT_VP9) ?
-                       &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO];
-       } else
-               pvbuf = &bufs[BUF_TYPE_VIDEO];
-
        if (!(port_get_inited(priv))) {
                r = amstream_port_init(priv);
                if (r < 0)
@@ -1656,10 +1612,12 @@ static int amstream_open(struct inode *inode, struct file *file)
                }
        }
 
-       if ((port->flag & PORT_FLAG_IN_USE) &&
-               ((port->type & PORT_TYPE_FRAME) == 0)) {
-               mutex_unlock(&amstream_mutex);
-               return -EBUSY;
+       if (!enable_stream_mode_multi_dec) {
+               if ((port->flag & PORT_FLAG_IN_USE) &&
+                       ((port->type & PORT_TYPE_FRAME) == 0)) {
+                       mutex_unlock(&amstream_mutex);
+                       return -EBUSY;
+               }
        }
 
        /* check other ports conflicts for audio */
@@ -1824,9 +1782,8 @@ static int amstream_release(struct inode *inode, struct file *file)
 #else
                        if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
                                && port->vformat == VFORMAT_H264
-                               && bufs[BUF_TYPE_VIDEO].for_4k) {
+                               && port->is_4k) {
                                vdec_poweroff(VDEC_HEVC);
-                               bufs[BUF_TYPE_VIDEO].for_4k = 0;
                        }
 
                        if ((port->vformat == VFORMAT_HEVC
@@ -2046,25 +2003,17 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
        switch (parm.cmd) {
        case AMSTREAM_SET_VB_START:
                if ((this->type & PORT_TYPE_VIDEO) &&
-                       ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
-                       if (has_hevc_vdec())
-                               bufs[BUF_TYPE_HEVC].buf_start = parm.data_32;
-                       bufs[BUF_TYPE_VIDEO].buf_start = parm.data_32;
+                       ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+                       priv->vdec->vbuf.buf_start = parm.data_32;
                } else
                        r = -EINVAL;
                break;
        case AMSTREAM_SET_VB_SIZE:
                if ((this->type & PORT_TYPE_VIDEO) &&
-                       ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
-                       if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
-                               if (has_hevc_vdec()) {
-                                       r = stbuf_change_size(
-                                               &bufs[BUF_TYPE_HEVC],
-                                               parm.data_32,
-                                               false);
-                               }
+                       ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+                       if (priv->vdec->vbuf.flag & BUF_FLAG_ALLOC) {
                                r += stbuf_change_size(
-                                               &bufs[BUF_TYPE_VIDEO],
+                                               &priv->vdec->vbuf,
                                                parm.data_32,
                                                false);
                        }
@@ -2176,11 +2125,9 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
                        r = -EINVAL;
                else if (this->type & PORT_TYPE_FRAME)
                        r = vdec_set_pts(priv->vdec, parm.data_32);
-               else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
-                       r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC],
-                               parm.data_32);
-               else if (this->type & PORT_TYPE_VIDEO)
-                       r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO],
+               else if ((this->type & PORT_TYPE_VIDEO) ||
+                       (this->type & PORT_TYPE_HEVC))
+                       r = es_vpts_checkin(&priv->vdec->vbuf,
                                parm.data_32);
                else if (this->type & PORT_TYPE_AUDIO)
                        r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO],
@@ -2199,25 +2146,13 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
                                 * life sequence or multi-tasking management
                                 */
                                r = vdec_set_pts64(priv->vdec, pts);
-                       } else if (has_hevc_vdec()) {
-                               if (this->type & PORT_TYPE_HEVC) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_HEVC], pts);
-                               } else if (this->type & PORT_TYPE_VIDEO) {
+                       } else if ((this->type & PORT_TYPE_HEVC) ||
+                                       (this->type & PORT_TYPE_VIDEO)) {
                                        r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_VIDEO], pts);
-                               } else if (this->type & PORT_TYPE_AUDIO) {
+                                       &priv->vdec->vbuf, pts);
+                       } else if (this->type & PORT_TYPE_AUDIO) {
                                        r = es_vpts_checkin_us64(
                                        &bufs[BUF_TYPE_AUDIO], pts);
-                               }
-                       } else {
-                               if (this->type & PORT_TYPE_VIDEO) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_VIDEO], pts);
-                               } else if (this->type & PORT_TYPE_AUDIO) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_AUDIO], pts);
-                               }
                        }
                }
                break;
@@ -2265,9 +2200,7 @@ static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
                tsdemux_set_demux(parm.data_32);
                break;
        case AMSTREAM_SET_VIDEO_DELAY_LIMIT_MS:
-               if (has_hevc_vdec())
-                       bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = parm.data_32;
-               bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = parm.data_32;
+               priv->vdec->vbuf.max_buffer_delay_ms = parm.data_32;
                break;
        case AMSTREAM_SET_AUDIO_DELAY_LIMIT_MS:
                bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = parm.data_32;
@@ -2377,25 +2310,21 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
                        struct am_ioctl_parm_ex *p = &parm;
                        struct stream_buf_s *buf = NULL;
 
-                       buf = (this->vformat == VFORMAT_HEVC ||
-                               this->vformat == VFORMAT_AVS2 ||
-                               this->vformat == VFORMAT_AV1 ||
-                               this->vformat == VFORMAT_VP9) ?
-                               &bufs[BUF_TYPE_HEVC] :
-                               &bufs[BUF_TYPE_VIDEO];
+                       mutex_unlock(&amstream_mutex);
+
+                       /*
+                        *todo: check upper layer for decoder
+                        * handler lifecycle
+                        */
+                       if (priv->vdec == NULL) {
+                               r = -EINVAL;
+                               mutex_unlock(&amstream_mutex);
+                               break;
+                       }
 
                        if (this->type & PORT_TYPE_FRAME) {
                                struct vdec_input_status_s status;
 
-                               /*
-                                *todo: check upper layer for decoder
-                                * handler lifecycle
-                                */
-                               if (priv->vdec == NULL) {
-                                       r = -EINVAL;
-                                       break;
-                               }
-
                                r = vdec_input_get_status(&priv->vdec->input,
                                                        &status);
                                if (r == 0) {
@@ -2405,13 +2334,16 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
                                        p->status.read_pointer =
                                                        status.read_pointer;
                                }
+                               mutex_unlock(&amstream_mutex);
                                break;
                        }
 
+                       buf = &priv->vdec->vbuf;
                        p->status.size = stbuf_canusesize(buf);
                        p->status.data_len = stbuf_level(buf);
                        p->status.free_len = stbuf_space(buf);
                        p->status.read_pointer = stbuf_rp(buf);
+                       mutex_unlock(&amstream_mutex);
                } else
                        r = -EINVAL;
                break;
@@ -2753,25 +2685,18 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
 
        case AMSTREAM_IOC_VB_START:
                if ((this->type & PORT_TYPE_VIDEO) &&
-                       ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
-                       if (has_hevc_vdec())
-                               bufs[BUF_TYPE_HEVC].buf_start = arg;
-                       bufs[BUF_TYPE_VIDEO].buf_start = arg;
+                       ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+                       priv->vdec->vbuf.buf_start = arg;
                } else
                        r = -EINVAL;
                break;
 
        case AMSTREAM_IOC_VB_SIZE:
                if ((this->type & PORT_TYPE_VIDEO) &&
-                       ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
-                       if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
-                               if (has_hevc_vdec()) {
-                                       r = stbuf_change_size(
-                                               &bufs[BUF_TYPE_HEVC],
-                                               arg, false);
-                               }
+                       ((priv->vdec->vbuf.flag & BUF_FLAG_IN_USE) == 0)) {
+                       if (priv->vdec->vbuf.flag & BUF_FLAG_ALLOC) {
                                r += stbuf_change_size(
-                                               &bufs[BUF_TYPE_VIDEO],
+                                               &priv->vdec->vbuf,
                                                arg, false);
                        }
                } else
@@ -2864,25 +2789,21 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
                        struct am_io_param *p = &para;
                        struct stream_buf_s *buf = NULL;
 
-                       buf = (this->vformat == VFORMAT_HEVC ||
-                                       this->vformat == VFORMAT_AVS2 ||
-                                       this->vformat == VFORMAT_AV1 ||
-                                       this->vformat == VFORMAT_VP9) ?
-                               &bufs[BUF_TYPE_HEVC] :
-                               &bufs[BUF_TYPE_VIDEO];
+                       mutex_lock(&amstream_mutex);
+
+                       /*
+                        *todo: check upper layer for decoder
+                        * handler lifecycle
+                        */
+                       if (priv->vdec == NULL) {
+                               r = -EINVAL;
+                               mutex_unlock(&amstream_mutex);
+                               break;
+                       }
 
                        if (this->type & PORT_TYPE_FRAME) {
                                struct vdec_input_status_s status;
 
-                               /*
-                                *todo: check upper layer for decoder
-                                * handler lifecycle
-                                */
-                               if (priv->vdec == NULL) {
-                                       r = -EINVAL;
-                                       break;
-                               }
-
                                r = vdec_input_get_status(&priv->vdec->input,
                                                        &status);
                                if (r == 0) {
@@ -2895,15 +2816,19 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
                                                sizeof(para)))
                                                r = -EFAULT;
                                }
+                               mutex_unlock(&amstream_mutex);
                                break;
                        }
 
+                       buf = &priv->vdec->vbuf;
                        p->status.size = stbuf_canusesize(buf);
                        p->status.data_len = stbuf_level(buf);
                        p->status.free_len = stbuf_space(buf);
                        p->status.read_pointer = stbuf_rp(buf);
                        if (copy_to_user((void *)arg, p, sizeof(para)))
                                r = -EFAULT;
+
+                       mutex_unlock(&amstream_mutex);
                        return r;
                }
                r = -EINVAL;
@@ -2962,10 +2887,9 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
                        r = -EINVAL;
                else if (this->type & PORT_TYPE_FRAME)
                        r = vdec_set_pts(priv->vdec, arg);
-               else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
-                       r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], arg);
-               else if (this->type & PORT_TYPE_VIDEO)
-                       r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], arg);
+               else if ((this->type & PORT_TYPE_VIDEO) ||
+                       (this->type & PORT_TYPE_HEVC))
+                       r = es_vpts_checkin(&priv->vdec->vbuf, arg);
                else if (this->type & PORT_TYPE_AUDIO)
                        r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], arg);
                break;
@@ -2987,25 +2911,13 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
                                 */
                                if (priv->vdec)
                                        r = vdec_set_pts64(priv->vdec, pts);
-                       } else if (has_hevc_vdec()) {
-                               if (this->type & PORT_TYPE_HEVC) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_HEVC], pts);
-                               } else if (this->type & PORT_TYPE_VIDEO) {
+                       } else if ((this->type & PORT_TYPE_HEVC) ||
+                                       (this->type & PORT_TYPE_VIDEO)) {
                                        r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_VIDEO], pts);
-                               } else if (this->type & PORT_TYPE_AUDIO) {
+                                       &priv->vdec->vbuf, pts);
+                       } else if (this->type & PORT_TYPE_AUDIO) {
                                        r = es_vpts_checkin_us64(
                                        &bufs[BUF_TYPE_AUDIO], pts);
-                               }
-                       } else {
-                               if (this->type & PORT_TYPE_VIDEO) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_VIDEO], pts);
-                               } else if (this->type & PORT_TYPE_AUDIO) {
-                                       r = es_vpts_checkin_us64(
-                                       &bufs[BUF_TYPE_AUDIO], pts);
-                               }
                        }
                }
                break;
@@ -3368,15 +3280,13 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
                tsdemux_set_demux((int)arg);
                break;
        case AMSTREAM_IOC_SET_VIDEO_DELAY_LIMIT_MS:
-               if (has_hevc_vdec())
-                       bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = (int)arg;
-               bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = (int)arg;
+               priv->vdec->vbuf.max_buffer_delay_ms = (int)arg;
                break;
        case AMSTREAM_IOC_SET_AUDIO_DELAY_LIMIT_MS:
                bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = (int)arg;
                break;
        case AMSTREAM_IOC_GET_VIDEO_DELAY_LIMIT_MS:
-               put_user(bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms, (int *)arg);
+               put_user(priv->vdec->vbuf.max_buffer_delay_ms, (int *)arg);
                break;
        case AMSTREAM_IOC_GET_AUDIO_DELAY_LIMIT_MS:
                put_user(bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms, (int *)arg);
@@ -3805,6 +3715,53 @@ static ssize_t ports_show(struct class *class, struct class_attribute *attr,
        return pbuf - buf;
 }
 
+static int show_vbuf_status_cb(struct stream_buf_s *p, char *buf)
+{
+       char *pbuf = buf;
+
+       if (!p->buf_start)
+               return 0;
+       /*type */
+       pbuf += sprintf(pbuf, "Video-%d buffer:", p->id);
+       /*flag */
+       pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag);
+       if (p->flag & BUF_FLAG_ALLOC)
+               pbuf += sprintf(pbuf, "%s ", "Alloc");
+       else
+               pbuf += sprintf(pbuf, "%s ", "Unalloc");
+       if (p->flag & BUF_FLAG_IN_USE)
+               pbuf += sprintf(pbuf, "%s ", "Used");
+       else
+               pbuf += sprintf(pbuf, "%s ", "Noused");
+       if (p->flag & BUF_FLAG_PARSER)
+               pbuf += sprintf(pbuf, "%s ", "Parser");
+       else
+               pbuf += sprintf(pbuf, "%s ", "noParser");
+       if (p->flag & BUF_FLAG_FIRST_TSTAMP)
+               pbuf += sprintf(pbuf, "%s ", "firststamp");
+       else
+               pbuf += sprintf(pbuf, "%s ", "nofirststamp");
+       pbuf += sprintf(pbuf, ")\n");
+
+       /*buf stats */
+       pbuf += sprintf(pbuf, "\tbuf addr:%p\n", (void *)p->buf_start);
+       pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size);
+       pbuf += sprintf(pbuf, "\tbuf canusesize:%#x\n", p->canusebuf_size);
+       pbuf += sprintf(pbuf, "\tbuf regbase:%#lx\n", p->reg_base);
+
+       if (p->reg_base && p->flag & BUF_FLAG_IN_USE) {
+               pbuf += sprintf(pbuf, "\tbuf level:%#x\n",
+                               stbuf_level(p));
+               pbuf += sprintf(pbuf, "\tbuf space:%#x\n",
+                               stbuf_space(p));
+               pbuf += sprintf(pbuf, "\tbuf read pointer:%#x\n",
+                               stbuf_rp(p));
+       } else
+               pbuf += sprintf(pbuf, "\tbuf no used.\n");
+
+       return pbuf - buf;
+}
+
 static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
                                                 char *buf)
 {
@@ -3816,6 +3773,10 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
 
        for (i = 0; i < amstream_buf_num; i++) {
                p = &bufs[i];
+
+               if (!p->buf_start)
+                       continue;
+
                /*type */
                pbuf += sprintf(pbuf, "%s buffer:", buf_type[p->type]);
                /*flag */
@@ -3948,6 +3909,8 @@ static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
                }
        }
 
+       pbuf += show_stream_buffer_status(pbuf, show_vbuf_status_cb);
+
        return pbuf - buf;
 }
 
@@ -3956,16 +3919,11 @@ static ssize_t videobufused_show(struct class *class,
 {
        char *pbuf = buf;
        struct stream_buf_s *p = NULL;
-       struct stream_buf_s *p_hevc = NULL;
 
        p = &bufs[0];
-       if (has_hevc_vdec())
-               p_hevc = &bufs[BUF_TYPE_HEVC];
 
        if (p->flag & BUF_FLAG_IN_USE)
                pbuf += sprintf(pbuf, "%d ", 1);
-       else if (has_hevc_vdec() && (p_hevc->flag & BUF_FLAG_IN_USE))
-               pbuf += sprintf(pbuf, "%d ", 1);
        else
                pbuf += sprintf(pbuf, "%d ", 0);
        return 1;
@@ -4376,8 +4334,6 @@ static int amstream_remove(struct platform_device *pdev)
        int i;
        struct stream_port_s *st;
 
-       if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC)
-               stbuf_change_size(&bufs[BUF_TYPE_VIDEO], 0, false);
        if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC)
                stbuf_change_size(&bufs[BUF_TYPE_AUDIO], 0, false);
        stbuf_fetch_release();
@@ -4482,7 +4438,6 @@ MODULE_PARM_DESC(def_vstreambuf_sizeM,
 module_param(slow_input, uint, 0664);
 MODULE_PARM_DESC(slow_input, "\n amstream slow_input\n");
 
-
 MODULE_DESCRIPTION("AMLOGIC streaming port driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
diff --git a/drivers/stream_input/amports/stream_buffer_base.c b/drivers/stream_input/amports/stream_buffer_base.c
new file mode 100644 (file)
index 0000000..e6dc5f1
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_buffer_base.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "amports_priv.h"
+#include "stream_buffer_base.h"
+#include "thread_rw.h"
+
+#define DEFAULT_VIDEO_BUFFER_SIZE              (1024 * 1024 * 3)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K           (1024 * 1024 * 6)
+#define DEFAULT_VIDEO_BUFFER_SIZE_TVP          (1024 * 1024 * 10)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP       (1024 * 1024 * 15)
+
+static struct stream_buf_s vdec_buf_def = {
+       .reg_base       = VLD_MEM_VIFIFO_REG_BASE,
+       .type           = BUF_TYPE_VIDEO,
+       .buf_start      = 0,
+       .buf_size       = DEFAULT_VIDEO_BUFFER_SIZE,
+       .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
+       .first_tstamp   = INVALID_PTS
+};
+
+static struct stream_buf_s hevc_buf_def = {
+       .reg_base       = HEVC_STREAM_REG_BASE,
+       .type           = BUF_TYPE_HEVC,
+       .buf_start      = 0,
+       .buf_size       = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+       .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+       .first_tstamp   = INVALID_PTS
+};
+
+static struct stream_buf_s *get_def_parms(int f)
+{
+       switch (f) {
+       case VFORMAT_HEVC:
+       case VFORMAT_AVS2:
+       case VFORMAT_AV1:
+       case VFORMAT_VP9:
+               return &hevc_buf_def;
+       default:
+               return &vdec_buf_def;
+       }
+}
+
+int stream_buffer_base_init(struct stream_buf_s *stbuf,
+                               struct stream_buf_ops *ops,
+                               struct parser_args *pars)
+{
+       struct vdec_s *vdec =
+               container_of(stbuf, struct vdec_s, vbuf);
+       struct stream_port_s *port = NULL;
+       u32 format, width, height;
+
+       /* sanity check. */
+       if (WARN_ON(!stbuf) || WARN_ON(!ops))
+               return -EINVAL;
+
+       port    = vdec->port;
+       format  = vdec->port->vformat;
+       width   = vdec->sys_info->width;
+       height  = vdec->sys_info->height;
+
+       memcpy(stbuf, get_def_parms(format),
+               sizeof(*stbuf));
+
+       stbuf->id       = vdec->id;
+       stbuf->is_hevc  = ((format == VFORMAT_HEVC) ||
+                       (format == VFORMAT_AVS2) ||
+                       (format == VFORMAT_AV1) ||
+                       (format == VFORMAT_VP9));
+       stbuf->for_4k   = ((width * height) >
+                       (1920 * 1088)) ? 1 : 0;
+       stbuf->is_multi_inst = !vdec_single(vdec);
+       memcpy(&stbuf->pars, pars, sizeof(*pars));
+
+       /* register ops func. */
+       stbuf->ops      = ops;
+
+       return 0;
+}
+EXPORT_SYMBOL(stream_buffer_base_init);
+
+void stream_buffer_set_ext_buf(struct stream_buf_s *stbuf,
+                              ulong addr,
+                              u32 size)
+{
+       stbuf->ext_buf_addr     = addr;
+       stbuf->buf_size         = size;
+}
+EXPORT_SYMBOL(stream_buffer_set_ext_buf);
+
+ssize_t stream_buffer_write_ex(struct file *file,
+                      struct stream_buf_s *stbuf,
+                      const char __user *buf,
+                      size_t count, int flags)
+{
+       int r;
+       u32 len = count;
+
+       if (buf == NULL || count == 0)
+               return -EINVAL;
+
+       if (stbuf_space(stbuf) < count) {
+               if ((flags & 2) || ((file != NULL) &&
+                               (file->f_flags & O_NONBLOCK))) {
+                       len = stbuf_space(stbuf);
+                       if (len < 256)  /* <1k.do eagain, */
+                               return -EAGAIN;
+               } else {
+                       len = min(stbuf_canusesize(stbuf) / 8, len);
+                       if (stbuf_space(stbuf) < len) {
+                               r = stbuf_wait_space(stbuf, len);
+                               if (r < 0)
+                                       return r;
+                       }
+               }
+       }
+
+       stbuf->last_write_jiffies64 = jiffies_64;
+       stbuf->is_phybuf = (flags & 1);
+
+       len = min_t(u32, len, count);
+
+       r = stbuf->ops->write(stbuf, buf, len);
+
+       return r;
+}
+EXPORT_SYMBOL(stream_buffer_write_ex);
+
+int stream_buffer_write(struct file *file,
+                      struct stream_buf_s *stbuf,
+                      const char *buf,
+                      size_t count)
+{
+       if (stbuf->write_thread)
+               return threadrw_write(file, stbuf, buf, count);
+       else
+               return stream_buffer_write_ex(file, stbuf, buf, count, 0);
+}
+EXPORT_SYMBOL(stream_buffer_write);
+
diff --git a/drivers/stream_input/amports/stream_buffer_base.h b/drivers/stream_input/amports/stream_buffer_base.h
new file mode 100644 (file)
index 0000000..e7a107f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_buffer_base.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef STREAM_BUFFER_INTERFACE_H
+#define STREAM_BUFFER_INTERFACE_H
+#include "streambuf.h"
+#include "streambuf_reg.h"
+
+#define STBUF_READ(s, func, args...)                   \
+({                                                     \
+       u32 ret = 0;                                    \
+       if ((s) && (s)->ops)                            \
+               ret = (s)->ops->func((s), ##args);      \
+       ret;                                            \
+})
+
+#define STBUF_WRITE(s, func, args...)                  \
+({                                                     \
+       if ((s) && (s)->ops)                            \
+               (s)->ops->func((s), ##args);            \
+})
+
+extern struct stream_buf_ops *get_stbuf_ops(void);
+extern struct stream_buf_ops *get_esparser_stbuf_ops(void);
+extern struct stream_buf_ops *get_tsparser_stbuf_ops(void);
+extern struct stream_buf_ops *get_psparser_stbuf_ops(void);
+
+int stream_buffer_base_init(struct stream_buf_s *stbuf,
+                           struct stream_buf_ops *ops,
+                           struct parser_args *pars);
+
+void stream_buffer_set_ext_buf(struct stream_buf_s *stbuf,
+                          ulong addr,
+                          u32 size);
+
+int stream_buffer_write(struct file *file,
+                       struct stream_buf_s *stbuf,
+                       const char *buf,
+                       size_t count);
+
+ssize_t stream_buffer_write_ex(struct file *file,
+                          struct stream_buf_s *stbuf,
+                          const char __user *buf,
+                          size_t count,
+                          int flags);
+
+#endif /* STREAM_BUFFER_INTERFACE_H */
+
diff --git a/drivers/stream_input/amports/stream_buffer_interface.c b/drivers/stream_input/amports/stream_buffer_interface.c
new file mode 100644 (file)
index 0000000..71e83d0
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/stream_bufffer_interface.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "stream_buffer_base.h"
+#include "amports_priv.h"
+#include "thread_rw.h"
+
+#define MEM_NAME "stbuf"
+#define MAP_RANGE (SZ_1M)
+
+static void stream_buffer_release(struct stream_buf_s *stbuf);
+
+static const char *type_to_str(int t)
+{
+       switch (t) {
+       case BUF_TYPE_VIDEO:
+               return "VIDEO";
+       case BUF_TYPE_AUDIO:
+               return "AUDIO";
+       case BUF_TYPE_SUBTITLE:
+               return "SUB";
+       case BUF_TYPE_USERDATA:
+               return "USER";
+       case BUF_TYPE_HEVC:
+               return "HEVC";
+       default:
+               return "ERR";
+       }
+}
+
+static int type_to_pts(int t)
+{
+       switch (t) {
+       case BUF_TYPE_VIDEO:
+               return PTS_TYPE_VIDEO;
+       case BUF_TYPE_HEVC:
+               return PTS_TYPE_HEVC;
+       default:
+               return PTS_TYPE_MAX;
+       }
+}
+
+static int stream_buffer_init(struct stream_buf_s *stbuf, struct vdec_s *vdec)
+{
+       int ret = 0;
+       u32 flags = CODEC_MM_FLAGS_DMA;
+       bool is_secure = 0;
+       u32 addr = 0;
+       int pages = 0;
+       u32 size;
+
+       if (stbuf->buf_start)
+               return 0;
+
+       snprintf(stbuf->name, sizeof(stbuf->name),
+               "%s-%d", MEM_NAME, vdec->id);
+
+       if (stbuf->ext_buf_addr) {
+               addr    = stbuf->ext_buf_addr;
+               size    = stbuf->buf_size;
+       } else {
+               flags |= CODEC_MM_FLAGS_FOR_VDECODER;
+               if (vdec->port_flag & PORT_FLAG_DRM) {
+                       flags |= CODEC_MM_FLAGS_TVP;
+                       is_secure = true;
+               }
+
+               size = PAGE_ALIGN(stbuf->buf_size);
+               pages = (size >> PAGE_SHIFT);
+               addr = codec_mm_alloc_for_dma(stbuf->name,
+                               pages, PAGE_SHIFT + 4, flags);
+               if (!addr) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               ret = vdec_set_input_buffer(vdec, addr, size);
+               if (ret) {
+                       pr_err("[%d]: set input buffer err.\n", stbuf->id);
+                       goto err;
+               }
+       }
+
+       atomic_set(&stbuf->payload, 0);
+       init_waitqueue_head(&stbuf->wq);
+
+       stbuf->buf_start        = addr;
+       stbuf->buf_wp           = addr;
+       stbuf->buf_rp           = addr;
+       stbuf->buf_size         = size;
+       stbuf->is_secure        = is_secure;
+       stbuf->no_parser        = true;
+       stbuf->buf_page_num     = pages;
+       stbuf->canusebuf_size   = size;
+
+       /* init pts server. */
+       ret = pts_start(type_to_pts(stbuf->type));
+       if (ret < 0) {
+               pr_err("[%d]: pts server failed\n", stbuf->id);
+               //goto err;//fixme
+       }
+
+       /* init thread write. */
+       if (!(vdec_get_debug_flags() & 1) &&
+               !codec_mm_video_tvp_enabled()) {
+               int block_size = PAGE_SIZE << 4;
+               int buf_num = (2 * SZ_1M) / (PAGE_SIZE << 4);
+
+               stbuf->write_thread =
+                       threadrw_alloc(buf_num, block_size,
+                                      stream_buffer_write_ex, 0);
+       }
+
+       stbuf->flag |= BUF_FLAG_ALLOC;
+       stbuf->flag |= BUF_FLAG_IN_USE;
+
+       pr_info("[%d]: [%s-%s] addr: %lx, size: %x, thrRW: %d, extbuf: %d, secure: %d\n",
+               stbuf->id, type_to_str(stbuf->type), stbuf->name,
+               stbuf->buf_start, stbuf->buf_size,
+               !!stbuf->write_thread,
+               !!stbuf->ext_buf_addr,
+               stbuf->is_secure);
+
+       return 0;
+err:
+       stream_buffer_release(stbuf);
+
+       return ret;
+}
+
+static void stream_buffer_release(struct stream_buf_s *stbuf)
+{
+       if (stbuf->write_thread)
+               threadrw_release(stbuf);
+
+       pts_stop(type_to_pts(stbuf->type));
+
+       if (stbuf->flag & BUF_FLAG_ALLOC && stbuf->buf_start) {
+               if (!stbuf->ext_buf_addr)
+                       codec_mm_free_for_dma(MEM_NAME, stbuf->buf_start);
+
+               stbuf->flag             &= ~BUF_FLAG_ALLOC;
+               stbuf->ext_buf_addr     = 0;
+               stbuf->buf_start        = 0;
+               stbuf->is_secure        = false;
+       }
+       stbuf->flag &= ~BUF_FLAG_IN_USE;
+}
+
+static int get_free_space(struct stream_buf_s *stbuf)
+{
+       u32 len = stbuf->buf_size;
+       int idle = 0;
+
+       if (!atomic_read(&stbuf->payload) && (stbuf->buf_rp == stbuf->buf_wp))
+               idle = len;
+       else if (stbuf->buf_wp > stbuf->buf_rp)
+               idle = len - (stbuf->buf_wp - stbuf->buf_rp);
+       else if (stbuf->buf_wp < stbuf->buf_rp)
+               idle = stbuf->buf_rp - stbuf->buf_wp;
+
+       /*pr_info("[%d]: wp: %x, rp: %x, payload: %d, free space: %d\n",
+               stbuf->id, stbuf->buf_wp, stbuf->buf_rp,
+               atomic_read(&stbuf->payload), idle);*/
+
+       return idle;
+}
+
+static int aml_copy_from_user(void *to, const void *from, ulong n)
+{
+       int ret =0;
+
+       if (likely(access_ok(VERIFY_READ, from, n)))
+               ret = copy_from_user(to, from, n);
+       else
+               memcpy(to, from, n);
+
+       return ret;
+}
+
+static int stream_buffer_copy(struct stream_buf_s *stbuf, const u8 *buf, u32 size)
+{
+       int ret = 0;
+       void *src = NULL, *dst = NULL;
+       int i, len;
+
+       for (i = 0; i < size; i += MAP_RANGE) {
+               len = ((size - i) > MAP_RANGE) ? MAP_RANGE : size - i;
+               src = stbuf->is_phybuf ?
+                       codec_mm_vmap((ulong) buf + i, len) :
+                       (void *) buf;
+               dst = codec_mm_vmap(stbuf->buf_wp + i, len);
+               if (!src || !dst) {
+                       ret = -EFAULT;
+                       pr_err("[%d]: %s, src or dst is invalid.\n",
+                               stbuf->id,  __func__);
+                       goto err;
+               }
+
+               if (aml_copy_from_user(dst, src, len)) {
+                       ret = -EAGAIN;
+                       goto err;
+               }
+
+               codec_mm_dma_flush(dst, len, DMA_TO_DEVICE);
+               codec_mm_unmap_phyaddr(dst);
+
+               if (stbuf->is_phybuf)
+                       codec_mm_unmap_phyaddr(src);
+       }
+
+       return 0;
+err:
+       if (stbuf->is_phybuf && src)
+               codec_mm_unmap_phyaddr(src);
+       if (dst)
+               codec_mm_unmap_phyaddr(dst);
+       return ret;
+}
+
+static int rb_push_data(struct stream_buf_s *stbuf, const u8 *in, u32 size)
+{
+       int ret, len;
+       u32 wp = stbuf->buf_wp;
+       u32 sp = (stbuf->buf_wp + size);
+       u32 ep = (stbuf->buf_start + stbuf->buf_size);
+
+       len = sp > ep ? ep - wp : size;
+
+       if (!stbuf->ext_buf_addr) {
+               ret = stream_buffer_copy(stbuf, in, len);
+               if (ret)
+                       return ret;
+       }
+
+       stbuf->ops->set_wp(stbuf, (wp + len >= ep) ?
+               stbuf->buf_start : (wp + len));
+
+       if (stbuf->buf_wp == stbuf->buf_rp) {
+               pr_debug("[%d]: stream buffer is full, payload: %d\n",
+                       stbuf->id, atomic_read(&stbuf->payload));
+       }
+
+       return len;
+}
+
+static int stream_buffer_write_inner(struct stream_buf_s *stbuf,
+                                    const u8 *in, u32 size)
+{
+       if (in == NULL || size > stbuf->buf_size) {
+               pr_err("[%d]: params are not valid.\n", stbuf->id);
+               return -1;
+       }
+
+       if (get_free_space(stbuf) < size)
+               return -EAGAIN;
+
+       return rb_push_data(stbuf, in, size);
+}
+
+static u32 stream_buffer_get_wp(struct stream_buf_s *stbuf)
+{
+       return stbuf->buf_wp;
+}
+
+static void stream_buffer_set_wp(struct stream_buf_s *stbuf, u32 val)
+{
+       int len = (val >= stbuf->buf_wp) ? (val - stbuf->buf_wp) :
+               ((stbuf->buf_start + stbuf->buf_size) - stbuf->buf_wp);
+
+       stbuf->buf_wp = val;
+       atomic_add(len, &stbuf->payload);
+}
+
+static u32 stream_buffer_get_rp(struct stream_buf_s *stbuf)
+{
+       return stbuf->buf_rp;
+}
+
+static void stream_buffer_set_rp(struct stream_buf_s *stbuf, u32 val)
+{
+       int len = (val >= stbuf->buf_rp) ? (val - stbuf->buf_rp) :
+               ((stbuf->buf_start + stbuf->buf_size) - stbuf->buf_rp);
+
+       stbuf->buf_rp = val;
+       atomic_sub(len, &stbuf->payload);
+}
+
+static struct stream_buf_ops stream_buffer_ops = {
+       .init   = stream_buffer_init,
+       .release = stream_buffer_release,
+       .write  = stream_buffer_write_inner,
+       .get_wp = stream_buffer_get_wp,
+       .set_wp = stream_buffer_set_wp,
+       .get_rp = stream_buffer_get_rp,
+       .set_rp = stream_buffer_set_rp,
+};
+
+struct stream_buf_ops *get_stbuf_ops(void)
+{
+       return &stream_buffer_ops;
+}
+EXPORT_SYMBOL(get_stbuf_ops);
+
diff --git a/drivers/stream_input/amports/streambuf.c b/drivers/stream_input/amports/streambuf.c
new file mode 100644 (file)
index 0000000..20aa640
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/streambuf.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/iomap.h>
+#include <asm/cacheflush.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+/* #include <mach/am_regs.h> */
+
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "streambuf_reg.h"
+#include "streambuf.h"
+#include <linux/amlogic/media/utils/amports_config.h>
+#include "../amports/amports_priv.h"
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+
+#define STBUF_SIZE   (64*1024)
+#define STBUF_WAIT_INTERVAL  (HZ/100)
+#define MEM_NAME "streambuf"
+
+void *fetchbuf = 0;
+
+static s32 _stbuf_alloc(struct stream_buf_s *buf, bool is_secure)
+{
+       if (buf->buf_size == 0)
+               return -ENOBUFS;
+
+       while (buf->buf_start == 0) {
+               int flags = CODEC_MM_FLAGS_DMA;
+
+               buf->buf_page_num = PAGE_ALIGN(buf->buf_size) / PAGE_SIZE;
+               if (buf->type == BUF_TYPE_SUBTITLE)
+                       flags = CODEC_MM_FLAGS_DMA_CPU;
+
+               /*
+                *if 4k,
+                *used cma first,for less mem fragments.
+                */
+               if (((buf->type == BUF_TYPE_HEVC) ||
+                       (buf->type == BUF_TYPE_VIDEO)) &&
+                       buf->for_4k)
+                       flags |= CODEC_MM_FLAGS_CMA_FIRST;
+               if (buf->buf_size > 20 * 1024 * 1024)
+                       flags |= CODEC_MM_FLAGS_CMA_FIRST;
+
+               if ((buf->type == BUF_TYPE_HEVC) ||
+                       (buf->type == BUF_TYPE_VIDEO)) {
+                       flags |= CODEC_MM_FLAGS_FOR_VDECODER;
+               } else if (buf->type == BUF_TYPE_AUDIO) {
+                       flags |= CODEC_MM_FLAGS_FOR_ADECODER;
+                       flags |= CODEC_MM_FLAGS_DMA_CPU;
+               }
+
+               if (is_secure)
+                       flags |= CODEC_MM_FLAGS_TVP;
+
+               buf->buf_start = codec_mm_alloc_for_dma(MEM_NAME,
+                       buf->buf_page_num, 4+PAGE_SHIFT, flags);
+               if (!buf->buf_start) {
+                       int is_video = (buf->type == BUF_TYPE_HEVC) ||
+                                       (buf->type == BUF_TYPE_VIDEO);
+                       if (is_video && buf->buf_size >= 9 * SZ_1M) {/*min 6M*/
+                               int old_size = buf->buf_size;
+
+                               buf->buf_size  =
+                                       PAGE_ALIGN(buf->buf_size * 2/3);
+                               pr_info("%s stbuf alloced size = %d failed try small %d size\n",
+                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
+                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
+                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
+                               "Subtitle", old_size, buf->buf_size);
+                               continue;
+                       }
+                       pr_info("%s stbuf alloced size = %d failed\n",
+                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
+                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
+                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
+                               "Subtitle", buf->buf_size);
+                       return -ENOMEM;
+               }
+
+               buf->is_secure = is_secure;
+
+               pr_debug("%s stbuf alloced at %p, secure = %d, size = %d\n",
+                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
+                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
+                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
+                               "Subtitle", (void *)buf->buf_start,
+                               buf->is_secure,
+                               buf->buf_size);
+       }
+
+       buf->canusebuf_size = buf->buf_size;
+       buf->flag |= BUF_FLAG_ALLOC;
+
+       return 0;
+}
+
+int stbuf_change_size(struct stream_buf_s *buf, int size, bool is_secure)
+{
+       unsigned long old_buf;
+       int old_size, old_pagenum;
+       int ret;
+
+       pr_info("buffersize=%d,%d,start=%p, secure=%d\n", size, buf->buf_size,
+                       (void *)buf->buf_start, is_secure);
+
+       if (buf->buf_size == size && buf->buf_start != 0)
+               return 0;
+
+       old_buf = buf->buf_start;
+       old_size = buf->buf_size;
+       old_pagenum = buf->buf_page_num;
+       buf->buf_start = 0;
+       buf->buf_size = size;
+       ret = size;
+
+       if (size == 0 ||
+               _stbuf_alloc(buf, is_secure) == 0) {
+               /*
+                * size=0:We only free the old memory;
+                * alloc ok,changed to new buffer
+                */
+               if (old_buf != 0) {
+                       codec_mm_free_for_dma(MEM_NAME, old_buf);
+               }
+
+               if (size == 0)
+                       buf->is_secure = false;
+
+               pr_info("changed the (%d) buffer size from %d to %d\n",
+                               buf->type, old_size, size);
+               return 0;
+       } else {
+               /* alloc failed */
+               buf->buf_start = old_buf;
+               buf->buf_size = old_size;
+               buf->buf_page_num = old_pagenum;
+               pr_info("changed the (%d) buffer size from %d to %d,failed\n",
+                               buf->type, old_size, size);
+       }
+
+       return ret;
+}
+
+int stbuf_fetch_init(void)
+{
+       if (NULL != fetchbuf)
+               return 0;
+
+       fetchbuf = (void *)__get_free_pages(GFP_KERNEL,
+                                               get_order(FETCHBUF_SIZE));
+
+       if (!fetchbuf) {
+               pr_info("%s: Can not allocate fetch working buffer\n",
+                               __func__);
+               return -ENOMEM;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(stbuf_fetch_init);
+
+void stbuf_fetch_release(void)
+{
+       if (0 && fetchbuf) {
+               /* always don't free.for safe alloc/free*/
+               free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE));
+               fetchbuf = 0;
+       }
+}
+
+static void _stbuf_timer_func(unsigned long arg)
+{
+       struct stream_buf_s *p = (struct stream_buf_s *)arg;
+
+       if (stbuf_space(p) < p->wcnt) {
+               p->timer.expires = jiffies + STBUF_WAIT_INTERVAL;
+
+               add_timer(&p->timer);
+       } else
+               wake_up_interruptible(&p->wq);
+
+}
+
+u32 stbuf_level(struct stream_buf_s *buf)
+{
+       if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
+               if (buf->no_parser) {
+                       int level = buf->buf_wp - buf->buf_rp;
+                       if (level < 0)
+                               level += buf->buf_size;
+                       return level;
+               } else {
+                       if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) {
+                               int level = READ_PARSER_REG(PARSER_VIDEO_WP) -
+                                       READ_PARSER_REG(PARSER_VIDEO_RP);
+                               if (level < 0)
+                                       level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) -
+                                       READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8;
+                               return (u32)level;
+                       } else
+                               return (buf->type == BUF_TYPE_HEVC) ?
+                                       READ_VREG(HEVC_STREAM_LEVEL) :
+                                       _READ_ST_REG(LEVEL);
+               }
+       }
+
+       return _READ_ST_REG(LEVEL);
+}
+
+u32 stbuf_rp(struct stream_buf_s *buf)
+{
+       if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
+               if (buf->no_parser)
+                       return buf->buf_rp;
+               else {
+                       if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1)
+                               return READ_PARSER_REG(PARSER_VIDEO_RP);
+                       else
+                               return (buf->type == BUF_TYPE_HEVC) ?
+                                       READ_VREG(HEVC_STREAM_RD_PTR) :
+                                       _READ_ST_REG(RP);
+               }
+       }
+
+       return _READ_ST_REG(RP);
+}
+
+u32 stbuf_space(struct stream_buf_s *buf)
+{
+       /* reserved space for safe write,
+        *   the parser fifo size is 1024byts, so reserve it
+        */
+       int size;
+
+       size = buf->canusebuf_size - stbuf_level(buf);
+
+       if (buf->canusebuf_size >= buf->buf_size / 2) {
+               /* old reversed value,tobe full, reversed only... */
+               size = size - 6 * 1024;
+       }
+
+       if ((buf->type == BUF_TYPE_VIDEO)
+               || (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC))
+               size -= READ_PARSER_REG(PARSER_VIDEO_HOLE);
+
+       return size > 0 ? size : 0;
+}
+
+u32 stbuf_size(struct stream_buf_s *buf)
+{
+       return buf->buf_size;
+}
+
+u32 stbuf_canusesize(struct stream_buf_s *buf)
+{
+       return buf->canusebuf_size;
+}
+
+s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec)
+{
+       s32 r;
+       u32 dummy;
+       u32 addr32;
+
+       VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
+
+       if (!buf->buf_start) {
+               r = _stbuf_alloc(buf, (vdec) ?
+                       vdec->port_flag & PORT_FLAG_DRM : 0);
+               if (r < 0)
+                       return r;
+       }
+       addr32 = buf->buf_start & 0xffffffff;
+       init_waitqueue_head(&buf->wq);
+
+       /*
+        * For multidec, do not touch HW stream buffers during port
+        * init and release.
+        */
+       if ((buf->type == BUF_TYPE_VIDEO) || (buf->type == BUF_TYPE_HEVC)) {
+               if (vdec) {
+                       if (vdec_stream_based(vdec))
+                               vdec_set_input_buffer(vdec, addr32,
+                                               buf->buf_size);
+                       else
+                               return vdec_set_input_buffer(vdec, addr32,
+                                               buf->buf_size);
+               }
+       }
+
+       buf->write_thread = 0;
+       if (((vdec && !vdec_single(vdec)) || (buf->is_multi_inst)) &&
+               (vdec_get_debug_flags() & 0x2) == 0)
+               return 0;
+       if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) {
+               CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1);
+               WRITE_VREG(HEVC_STREAM_START_ADDR, addr32);
+               WRITE_VREG(HEVC_STREAM_END_ADDR, addr32 + buf->buf_size);
+               WRITE_VREG(HEVC_STREAM_RD_PTR, addr32);
+               WRITE_VREG(HEVC_STREAM_WR_PTR, addr32);
+
+               return 0;
+       }
+
+       if (buf->type == BUF_TYPE_VIDEO) {
+               VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
+
+               _WRITE_ST_REG(CONTROL, 0);
+               /* reset VLD before setting all pointers */
+               WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0);
+               /*TODO: only > m6*/
+#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+               WRITE_VREG(DOS_SW_RESET0, (1 << 4));
+               WRITE_VREG(DOS_SW_RESET0, 0);
+#else
+               WRITE_RESET_REG(RESET0_REGISTER, RESET_VLD);
+#endif
+
+               dummy = READ_RESET_REG(RESET0_REGISTER);
+               WRITE_VREG(POWER_CTL_VLD, 1 << 4);
+       } else if (buf->type == BUF_TYPE_AUDIO) {
+               _WRITE_ST_REG(CONTROL, 0);
+
+               WRITE_AIU_REG(AIU_AIFIFO_GBIT, 0x80);
+       }
+
+       if (buf->type == BUF_TYPE_SUBTITLE) {
+               WRITE_PARSER_REG(PARSER_SUB_RP, addr32);
+               WRITE_PARSER_REG(PARSER_SUB_START_PTR, addr32);
+               WRITE_PARSER_REG(PARSER_SUB_END_PTR,
+                                          addr32 + buf->buf_size - 8);
+
+               return 0;
+       }
+
+       _WRITE_ST_REG(START_PTR, addr32);
+       _WRITE_ST_REG(CURR_PTR, addr32);
+       _WRITE_ST_REG(END_PTR, addr32 + buf->buf_size - 8);
+
+       _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
+       _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
+
+       _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL);
+       _WRITE_ST_REG(WP, addr32);
+
+       _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
+       _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
+
+       _SET_ST_REG_MASK(CONTROL,
+                       (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN |
+                       MEM_CTRL_EMPTY_EN);
+
+       if (buf->no_parser)
+               _SET_ST_REG_MASK(CONTROL, 7 << 3);
+
+       return 0;
+}
+EXPORT_SYMBOL(stbuf_init);
+
+void stbuf_vdec2_init(struct stream_buf_s *buf)
+{
+
+       _WRITE_VDEC2_ST_REG(CONTROL, 0);
+
+       _WRITE_VDEC2_ST_REG(START_PTR, _READ_ST_REG(START_PTR));
+       _WRITE_VDEC2_ST_REG(END_PTR, _READ_ST_REG(END_PTR));
+       _WRITE_VDEC2_ST_REG(CURR_PTR, _READ_ST_REG(CURR_PTR));
+
+       _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL | MEM_BUFCTRL_INIT);
+       _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL);
+
+       _WRITE_VDEC2_ST_REG(BUF_CTRL, MEM_BUFCTRL_INIT);
+       _WRITE_VDEC2_ST_REG(BUF_CTRL, 0);
+
+       _WRITE_VDEC2_ST_REG(CONTROL,
+                       (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN
+                       | MEM_CTRL_EMPTY_EN);
+}
+
+s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count)
+{
+       struct stream_buf_s *p = stream_buf;
+       long time_out = 200;
+
+       p->wcnt = count;
+
+       setup_timer(&p->timer, _stbuf_timer_func, (ulong) p);
+
+       mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL);
+
+       if (wait_event_interruptible_timeout
+               (p->wq, stbuf_space(p) >= count,
+                msecs_to_jiffies(time_out)) == 0) {
+               del_timer_sync(&p->timer);
+
+               return -EAGAIN;
+       }
+
+       del_timer_sync(&p->timer);
+
+       return 0;
+}
+
+void stbuf_release(struct stream_buf_s *buf)
+{
+       int r;
+
+       buf->first_tstamp = INVALID_PTS;
+
+       r = stbuf_init(buf, NULL);/* reinit buffer */
+       if (r < 0)
+               pr_err("stbuf_release %d, stbuf_init failed\n", __LINE__);
+
+       if (buf->flag & BUF_FLAG_ALLOC && buf->buf_start) {
+               codec_mm_free_for_dma(MEM_NAME, buf->buf_start);
+               buf->flag &= ~BUF_FLAG_ALLOC;
+               buf->buf_start = 0;
+               buf->is_secure = false;
+       }
+       buf->flag &= ~BUF_FLAG_IN_USE;
+}
+EXPORT_SYMBOL(stbuf_release);
+
+u32 stbuf_sub_rp_get(void)
+{
+       return READ_PARSER_REG(PARSER_SUB_RP);
+}
+
+void stbuf_sub_rp_set(unsigned int sub_rp)
+{
+       WRITE_PARSER_REG(PARSER_SUB_RP, sub_rp);
+       return;
+}
+
+u32 stbuf_sub_wp_get(void)
+{
+       return READ_PARSER_REG(PARSER_SUB_WP);
+}
+
+u32 stbuf_sub_start_get(void)
+{
+       return READ_PARSER_REG(PARSER_SUB_START_PTR);
+}
+
+u32 parser_get_wp(struct stream_buf_s *vb)
+{
+       return READ_PARSER_REG(PARSER_VIDEO_WP);
+}
+EXPORT_SYMBOL(parser_get_wp);
+
+void parser_set_wp(struct stream_buf_s *vb, u32 val)
+{
+       WRITE_PARSER_REG(PARSER_VIDEO_WP, val);
+}
+EXPORT_SYMBOL(parser_set_wp);
+
+u32 parser_get_rp(struct stream_buf_s *vb)
+{
+       return READ_PARSER_REG(PARSER_VIDEO_RP);
+}
+EXPORT_SYMBOL(parser_get_rp);
+
+void parser_set_rp(struct stream_buf_s *vb, u32 val)
+{
+       WRITE_PARSER_REG(PARSER_VIDEO_RP, val);
+}
+EXPORT_SYMBOL(parser_set_rp);
+
diff --git a/drivers/stream_input/amports/streambuf.h b/drivers/stream_input/amports/streambuf.h
new file mode 100644 (file)
index 0000000..8e4d2e3
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/streambuf.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef STREAMBUF_H
+#define STREAMBUF_H
+#include <linux/amlogic/media/utils/amports_config.h>
+
+#define BUF_FLAG_ALLOC          0x01
+#define BUF_FLAG_IN_USE         0x02
+#define BUF_FLAG_PARSER         0x04
+#define BUF_FLAG_FIRST_TSTAMP   0x08
+#define BUF_FLAG_IOMEM          0x10
+
+#define BUF_TYPE_VIDEO      0
+#define BUF_TYPE_AUDIO      1
+#define BUF_TYPE_SUBTITLE   2
+#define BUF_TYPE_USERDATA   3
+#define BUF_TYPE_HEVC       4
+#define BUF_MAX_NUM         5
+
+#define INVALID_PTS 0xffffffff
+
+#define FETCHBUF_SIZE   (64*1024)
+#define USER_DATA_SIZE  (8*1024)
+
+struct vdec_s;
+struct stream_buf_s;
+
+struct parser_args {
+       u32 vid;
+       u32 aid;
+       u32 sid;
+       u32 pcrid;
+};
+
+struct stream_buf_ops {
+       int (*init) (struct stream_buf_s *, struct vdec_s *);
+       void (*release) (struct stream_buf_s *);
+       int (*write) (struct stream_buf_s *, const u8 *, u32);
+       u32 (*get_wp) (struct stream_buf_s *);
+       void (*set_wp) (struct stream_buf_s *, u32);
+       u32 (*get_rp) (struct stream_buf_s *);
+       void (*set_rp) (struct stream_buf_s *, u32);
+};
+
+struct stream_buf_s {
+       int id;
+       u8 name[16];
+       s32 flag;
+       u32 type;
+       unsigned long buf_start;
+       struct page *buf_pages;
+       int buf_page_num;
+       u32 buf_size;
+       u32 default_buf_size;
+       u32 canusebuf_size;
+       u32 first_tstamp;
+       const ulong reg_base;
+       wait_queue_head_t wq;
+       struct timer_list timer;
+       u32 wcnt;
+       u32 buf_wp;
+       u32 buf_rp;
+       u32 max_buffer_delay_ms;
+       u64 last_write_jiffies64;
+       void *write_thread;
+       int for_4k;
+       bool is_secure;
+       bool is_multi_inst;
+       bool no_parser;
+       bool is_phybuf;
+       bool is_hevc;
+       ulong ext_buf_addr;
+       atomic_t payload;
+       struct parser_args pars;
+       struct stream_buf_ops *ops;
+} /*stream_buf_t */;
+
+struct stream_port_s {
+       /* driver info */
+       const char *name;
+       struct device *class_dev;
+       const struct file_operations *fops;
+
+       /* ports control */
+       s32 type;
+       s32 flag;
+       s32 pcr_inited;
+
+       /* decoder info */
+       s32 vformat;
+       s32 aformat;
+       s32 achanl;
+       s32 asamprate;
+       s32 adatawidth;
+
+       /* parser info */
+       u32 vid;
+       u32 aid;
+       u32 sid;
+       u32 pcrid;
+       bool is_4k;
+} /*stream_port_t */;
+enum drm_level_e {
+       DRM_LEVEL1 = 1,
+       DRM_LEVEL2 = 2,
+       DRM_LEVEL3 = 3,
+       DRM_NONE = 4,
+};
+
+struct drm_info {
+       enum drm_level_e drm_level;
+       u32 drm_flag;
+       u32 drm_hasesdata;
+       u32 drm_priv;
+       u32 drm_pktsize;
+       u32 drm_pktpts;
+       u32 drm_phy;
+       u32 drm_vir;
+       u32 drm_remap;
+       u32 data_offset;
+       u32 handle;
+       u32 extpad[7];
+} /*drminfo_t */;
+
+#define TYPE_DRMINFO_V2  0x100
+#define TYPE_DRMINFO   0x80
+#define TYPE_PATTERN   0x40
+
+struct vdec_s;
+
+extern void *fetchbuf;
+
+extern u32 stbuf_level(struct stream_buf_s *buf);
+extern u32 stbuf_rp(struct stream_buf_s *buf);
+extern u32 stbuf_space(struct stream_buf_s *buf);
+extern u32 stbuf_size(struct stream_buf_s *buf);
+extern u32 stbuf_canusesize(struct stream_buf_s *buf);
+extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec);
+extern s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count);
+extern void stbuf_release(struct stream_buf_s *buf);
+extern int stbuf_change_size(struct stream_buf_s *buf, int size,
+                               bool is_secure);
+extern int stbuf_fetch_init(void);
+extern void stbuf_fetch_release(void);
+extern u32 stbuf_sub_rp_get(void);
+extern void stbuf_sub_rp_set(unsigned int sub_rp);
+extern u32 stbuf_sub_wp_get(void);
+extern u32 stbuf_sub_start_get(void);
+extern u32 stbuf_userdata_start_get(void);
+extern struct stream_buf_s *get_stream_buffer(int id);
+
+extern void stbuf_vdec2_init(struct stream_buf_s *buf);
+
+u32 parser_get_wp(struct stream_buf_s *vb);
+void parser_set_wp(struct stream_buf_s *vb, u32 val);
+u32 parser_get_rp(struct stream_buf_s *vb);
+void parser_set_rp(struct stream_buf_s *vb, u32 val);
+
+#endif /* STREAMBUF_H */
diff --git a/drivers/stream_input/amports/streambuf_reg.h b/drivers/stream_input/amports/streambuf_reg.h
new file mode 100644 (file)
index 0000000..5f0c8ca
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/streambuf_reg.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef STREAMBUF_REG_H
+#define STREAMBUF_REG_H
+
+#define HEVC_STREAM_REG_BASE        HEVC_STREAM_START_ADDR
+
+#define VLD_MEM_VIFIFO_REG_BASE     VLD_MEM_VIFIFO_START_PTR
+#define AIU_MEM_AIFIFO_REG_BASE     AIU_MEM_AIFIFO_START_PTR
+
+#define START_PTR   0
+#define CURR_PTR    1
+#define END_PTR     2
+#define BYTES_AVAIL 3
+#define CONTROL     4
+#define WP          5
+#define RP          6
+#define LEVEL       7
+#define BUF_CTRL    8
+
+/*
+ *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
+ *#define _WRITE_ST_REG(r, val) \
+ *    __raw_writel(val, (volatile void __iomem *)(buf->reg_base+(r<<2)))
+ *#define _WRITE_ST_REG_BITS(r, val, s, e) \
+ *    __raw_writel((((_READ_ST_REG(r) & \
+ *    (((1L<<(e)-1)<<(s))-1)<<(s)))|((unsigned)((val)&((1L<<(e))-1))<<(s))), \
+ *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
+ *#define _SET_ST_REG_MASK(r, val) \
+ *    __raw_writel(_READ_ST_REG(r)| (val), \
+ *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
+ *#define _CLR_ST_REG_MASK(r, val) \
+ *    __raw_writel(_READ_ST_REG(r)&~(val), \
+ *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
+ *#define _READ_ST_REG(r) \
+ *    (__raw_readl((volatile void __iomem *)(buf->reg_base+(r<<2))))
+ *
+ *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD
+ *#define _READ_VDEC2_ST_REG(r) \
+ *    (__raw_readl((volatile void __iomem *)(buf->reg_base + \
+ *    DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \
+ *    DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2))))
+ *#define _WRITE_VDEC2_ST_REG(r, val) \
+ *    __raw_writel(val, (volatile void __iomem *)(buf->reg_base + \
+ *    DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \
+ *    DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2)))
+ *#endif
+ *
+ *#define MEM_BUFCTRL_MANUAL      (1<<1)
+ *#define MEM_BUFCTRL_INIT        (1<<0)
+ *#define MEM_LEVEL_CNT_BIT       18
+ *#define MEM_FIFO_CNT_BIT        16
+ *#define MEM_FILL_ON_LEVEL       (1<<10)
+ *#define MEM_CTRL_EMPTY_EN       (1<<2)
+ *#define MEM_CTRL_FILL_EN        (1<<1)
+ *#define MEM_CTRL_INIT           (1<<0)
+ *
+ *#else
+ *#define _WRITE_ST_REG(r, val) \
+ *WRITE_MPEG_REG(buf->reg_base + (r), \
+ *                                             (val))
+ *#define _WRITE_ST_REG_BITS(r, val, s, e)\
+ * WRITE_MPEG_REG(buf->reg_base + (r), \
+ *                                             (val), (s), (e))
+ *#define _SET_ST_REG_MASK(r, val) SET_MPEG_REG_MASK(buf->reg_base + \
+ *                                             (r), (val))
+ *#define _CLR_ST_REG_MASK(r, val)  CLEAR_MPEG_REG_MASK(buf->reg_base + \
+ *                                             (r), (val))
+ *#define _READ_ST_REG(r) READ_MPEG_REG(buf->reg_base + (r))
+ *#endif
+ */
+
+ /*TODO*/
+#define _WRITE_ST_REG(r, val)  do { \
+       if (buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) \
+               codec_dosbus_write((buf->reg_base+(r)), (val)); \
+       else \
+               codec_aiubus_write((buf->reg_base+(r)), (val)); \
+       } while (0)
+#define _READ_ST_REG(r) \
+       ((buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) ? \
+        codec_dosbus_read(buf->reg_base+(r)) : \
+        codec_aiubus_read(buf->reg_base+(r)))
+
+#define _SET_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r) | (val))
+#define _CLR_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r)&~(val))
+#define _READ_VDEC2_ST_REG(r) (codec_dosbus_read(\
+                       (VDEC2_VLD_MEM_VIFIFO_START_PTR+(r))))
+#define _WRITE_VDEC2_ST_REG(r, val) codec_dosbus_write(\
+               (VDEC2_VLD_MEM_VIFIFO_START_PTR+r), val)
+#define MEM_BUFCTRL_MANUAL      (1<<1)
+#define MEM_BUFCTRL_INIT        (1<<0)
+#define MEM_LEVEL_CNT_BIT       18
+#define MEM_FIFO_CNT_BIT        16
+#define MEM_FILL_ON_LEVEL       (1<<10)
+#define MEM_CTRL_EMPTY_EN       (1<<2)
+#define MEM_CTRL_FILL_EN        (1<<1)
+#define MEM_CTRL_INIT           (1<<0)
+#endif /* STREAMBUF_REG_H */
diff --git a/drivers/stream_input/amports/thread_rw.c b/drivers/stream_input/amports/thread_rw.c
new file mode 100644 (file)
index 0000000..0d386ce
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/thread_rw.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+
+/* #include <mach/am_regs.h> */
+#include <linux/delay.h>
+
+#include "streambuf.h"
+#include "amports_priv.h"
+#include "thread_rw.h"
+
+#define BUF_NAME "fetchbuf"
+
+#define DEFAULT_BLOCK_SIZE (64*1024)
+
+struct threadrw_buf {
+       void *vbuffer;
+       dma_addr_t dma_handle;
+       int write_off;
+       int data_size;
+       int buffer_size;
+       int from_cma;
+};
+
+#define MAX_MM_BUFFER_NUM 16
+struct threadrw_write_task {
+       struct file *file;
+       struct delayed_work write_work;
+       DECLARE_KFIFO_PTR(datafifo, void *);
+       DECLARE_KFIFO_PTR(freefifo, void *);
+       int bufs_num;
+       int max_bufs;
+       int errors;
+       spinlock_t lock;
+       struct mutex mutex;
+       struct stream_buf_s *sbuf;
+       int buffered_data_size;
+       int passed_data_len;
+       int buffer_size;
+       int def_block_size;
+       int data_offset;
+       int writework_on;
+       unsigned long codec_mm_buffer[MAX_MM_BUFFER_NUM];
+       int manual_write;
+       int failed_onmore;
+       wait_queue_head_t wq;
+       ssize_t (*write)(struct file *,
+               struct stream_buf_s *,
+               const char __user *,
+               size_t, int);
+       struct threadrw_buf buf[1];
+       /*don't add any after buf[] define */
+};
+
+static int free_task_buffers(struct threadrw_write_task *task);
+
+static struct workqueue_struct *threadrw_wq_get(void)
+{
+       static struct workqueue_struct *threadrw_wq;
+
+       if (!threadrw_wq)
+               threadrw_wq = create_singlethread_workqueue("threadrw");
+       return threadrw_wq;
+}
+
+static int threadrw_schedule_delayed_work(
+               struct threadrw_write_task *task,
+               unsigned long delay)
+{
+       bool ret;
+
+       if (threadrw_wq_get()) {
+               ret = queue_delayed_work(threadrw_wq_get(),
+                       &task->write_work, delay);
+       } else
+               ret = schedule_delayed_work(&task->write_work, delay);
+       if (!ret) {
+               cancel_delayed_work(&task->write_work);
+               if (threadrw_wq_get())
+                       ret = queue_delayed_work(threadrw_wq_get(),
+                                       &task->write_work, 0);
+               else
+                       ret = schedule_delayed_work(&task->write_work, 0);
+       }
+       return 0;
+}
+
+static ssize_t threadrw_write_onece(
+       struct threadrw_write_task *task,
+       struct file *file,
+       struct stream_buf_s *stbuf,
+       const char __user *buf, size_t count)
+{
+       struct threadrw_buf *rwbuf = NULL;
+       int ret = 0;
+       int to_write;
+
+       if (!kfifo_get(&task->freefifo, (void *)&rwbuf)) {
+               if (task->errors)
+                       return task->errors;
+               return -EAGAIN;
+       }
+
+       to_write = min_t(u32, rwbuf->buffer_size, count);
+       if (copy_from_user(rwbuf->vbuffer, buf, to_write)) {
+               kfifo_put(&task->freefifo, (const void *)buf);
+               ret = -EFAULT;
+               goto err;
+       }
+       rwbuf->data_size = to_write;
+       rwbuf->write_off = 0;
+       kfifo_put(&task->datafifo, (const void *)rwbuf);
+       threadrw_schedule_delayed_work(task, 0);
+       return to_write;
+err:
+       return ret;
+}
+
+static ssize_t threadrw_write_in(
+       struct threadrw_write_task *task,
+       struct stream_buf_s *stbuf,
+       const char __user *buf, size_t count)
+{
+       int ret = 0;
+       int off = 0;
+       /* int change to size_t for buffer overflow on OTT-5057 */
+       size_t left = count;
+       int wait_num = 0;
+       unsigned long flags;
+
+       while (left > 0) {
+               ret = threadrw_write_onece(task,
+                               task->file,
+                               stbuf, buf + off, left);
+
+               /* firstly check ret < 0, avoid the risk of -EAGAIN in ret
+                * implicit convert to size_t when compare with "size_t left".
+                */
+               if (ret < 0) {
+                       if (off > 0) {
+                               break;  /*have write ok some data. */
+                       } else if (ret == -EAGAIN) {
+                               if (!(task->file->f_flags & O_NONBLOCK) &&
+                                       (++wait_num < 10)) {
+                                       wait_event_interruptible_timeout(
+                                               task->wq,
+                                               !kfifo_is_empty(
+                                                       &task->freefifo),
+                                               HZ / 100);
+                                       continue;       /* write again. */
+                               }
+                               ret = -EAGAIN;
+                               break;
+                       }
+                       break;  /*to end */
+               } else if (ret >= left) {
+                       off = count;
+                       left = 0;
+               } else if (ret > 0) {
+                       off += ret;
+                       left -= ret;
+               }
+       }
+
+       /*end: */
+       spin_lock_irqsave(&task->lock, flags);
+       if (off > 0) {
+               task->buffered_data_size += off;
+               task->data_offset += off;
+       }
+       spin_unlock_irqrestore(&task->lock, flags);
+       if (off > 0)
+               return off;
+       else
+               return ret;
+}
+
+static int do_write_work_in(struct threadrw_write_task *task)
+{
+       struct threadrw_buf *rwbuf = NULL;
+       int ret;
+       int need_re_write = 0;
+       int write_len = 0;
+       unsigned long flags;
+
+       if (kfifo_is_empty(&task->datafifo))
+               return 0;
+       if (!kfifo_peek(&task->datafifo, (void *)&rwbuf))
+               return 0;
+       if (!task->manual_write &&
+                       rwbuf->from_cma &&
+                       !rwbuf->write_off)
+               codec_mm_dma_flush(rwbuf->vbuffer,
+                                               rwbuf->buffer_size,
+                                               DMA_TO_DEVICE);
+       if (task->manual_write) {
+               ret = task->write(task->file, task->sbuf,
+                       (const char __user *)rwbuf->vbuffer + rwbuf->write_off,
+                       rwbuf->data_size,
+                       2);     /* noblock,virtual addr */
+       } else {
+               ret = task->write(task->file, task->sbuf,
+               (const char __user *)rwbuf->dma_handle + rwbuf->write_off,
+               rwbuf->data_size,
+               3);     /* noblock,phy addr */
+       }
+       if (ret == -EAGAIN) {
+               need_re_write = 0;
+               /*do later retry. */
+       } else if (ret >= rwbuf->data_size) {
+               write_len += rwbuf->data_size;
+               if (kfifo_get(&task->datafifo, (void *)&rwbuf)) {
+                       rwbuf->data_size = 0;
+                       kfifo_put(&task->freefifo, (const void *)rwbuf);
+                       /*wakeup write thread. */
+                       wake_up_interruptible(&task->wq);
+               } else
+                       pr_err("write ok,but kfifo_get data failed.!!!\n");
+               need_re_write = 1;
+       } else if (ret > 0) {
+               rwbuf->data_size -= ret;        /* half data write */
+               rwbuf->write_off += ret;
+               write_len += ret;
+               need_re_write = 1;
+       } else {                /*ret <=0 */
+               pr_err("get errors ret=%d size=%d\n", ret,
+                       rwbuf->data_size);
+               task->errors = ret;
+       }
+       if (write_len > 0) {
+               spin_lock_irqsave(&task->lock, flags);
+               task->passed_data_len += write_len;
+               spin_unlock_irqrestore(&task->lock, flags);
+       }
+       return need_re_write;
+
+}
+
+static void do_write_work(struct work_struct *work)
+{
+       struct threadrw_write_task *task = container_of(work,
+                                       struct threadrw_write_task,
+                                       write_work.work);
+       int need_retry = 1;
+
+       task->writework_on = 1;
+       while (need_retry) {
+               mutex_lock(&task->mutex);
+               need_retry = do_write_work_in(task);
+               mutex_unlock(&task->mutex);
+       }
+       threadrw_schedule_delayed_work(task, HZ / 10);
+       task->writework_on = 0;
+}
+
+static int alloc_task_buffers_inlock(struct threadrw_write_task *task,
+               int new_bubffers,
+               int block_size)
+{
+       struct threadrw_buf *rwbuf;
+       int i;
+       int used_codec_mm = task->manual_write ? 0 : 1;
+       int new_num = new_bubffers;
+       int mm_slot = -1;
+       int start_idx = task->bufs_num;
+       int total_mm = 0;
+       unsigned long addr;
+
+       if (codec_mm_get_total_size() < 80 ||
+               codec_mm_get_free_size() < 40)
+               used_codec_mm = 0;
+       if (task->bufs_num + new_num > task->max_bufs)
+               new_num = task->max_bufs - task->bufs_num;
+       for (i = 0; i < MAX_MM_BUFFER_NUM; i++) {
+               if (task->codec_mm_buffer[i] == 0) {
+                       mm_slot = i;
+                       break;
+               }
+       }
+       if (mm_slot < 0)
+               used_codec_mm = 0;
+       if (block_size <= 0)
+               block_size = DEFAULT_BLOCK_SIZE;
+
+       if (used_codec_mm && (block_size * new_num) >= 128 * 1024) {
+               total_mm = ALIGN(block_size * new_num, (1 << 17));
+               addr =
+                               codec_mm_alloc_for_dma(BUF_NAME,
+                                       total_mm / PAGE_SIZE, 0,
+                                       CODEC_MM_FLAGS_DMA_CPU);
+               if (addr != 0) {
+                       task->codec_mm_buffer[mm_slot] = addr;
+                       task->buffer_size += total_mm;
+               } else {
+                       used_codec_mm = 0;
+               }
+       }
+       for (i = 0; i < new_num; i++) {
+               int bufidx = start_idx + i;
+
+               rwbuf = &task->buf[bufidx];
+               rwbuf->buffer_size = block_size;
+               if (used_codec_mm) {
+                       unsigned long start_addr =
+                                       task->codec_mm_buffer[mm_slot];
+                       if (i == new_num - 1)
+                               rwbuf->buffer_size = total_mm -
+                                               block_size * i;
+                       rwbuf->dma_handle = (dma_addr_t) start_addr +
+                                               block_size * i;
+                       rwbuf->vbuffer = codec_mm_phys_to_virt(
+                                               rwbuf->dma_handle);
+                       rwbuf->from_cma = 1;
+
+               } else {
+                       rwbuf->vbuffer = dma_alloc_coherent(
+                                       amports_get_dma_device(),
+                                       rwbuf->buffer_size,
+                                       &rwbuf->dma_handle, GFP_KERNEL);
+                       if (!rwbuf->vbuffer) {
+                               rwbuf->buffer_size = 0;
+                               rwbuf->dma_handle = 0;
+                               task->bufs_num = bufidx;
+                               break;
+                       }
+                       rwbuf->from_cma = 0;
+                       task->buffer_size += rwbuf->buffer_size;
+               }
+
+               kfifo_put(&task->freefifo, (const void *)rwbuf);
+               task->bufs_num = bufidx + 1;
+       }
+       if (start_idx > 0 ||/*have buffers before*/
+               task->bufs_num >= 3 ||
+               task->bufs_num == new_num) {
+               if (!task->def_block_size)
+                       task->def_block_size = task->buf[0].buffer_size;
+               return 0;       /*must >=3 for swap buffers. */
+       }
+       if (task->bufs_num > 0)
+               free_task_buffers(task);
+       return -1;
+}
+
+static int free_task_buffers(struct threadrw_write_task *task)
+{
+       int i;
+
+       for (i = 0; i < MAX_MM_BUFFER_NUM; i++) {
+               if (task->codec_mm_buffer[i])
+                       codec_mm_free_for_dma(BUF_NAME,
+                               task->codec_mm_buffer[i]);
+       }
+       for (i = 0; i < task->bufs_num; i++) {
+               if (task->buf[i].vbuffer && task->buf[i].from_cma == 0)
+                       dma_free_coherent(amports_get_dma_device(),
+                               task->buf[i].buffer_size,
+                               task->buf[i].vbuffer,
+                               task->buf[i].dma_handle);
+       }
+       return 0;
+}
+
+static struct threadrw_write_task *threadrw_alloc_in(int num,
+               int block_size,
+               ssize_t (*write)(struct file *,
+                       struct stream_buf_s *,
+                       const char __user *, size_t, int),
+                       int flags)
+{
+       int max_bufs = num;
+       int task_buffer_size;
+       struct threadrw_write_task *task;
+       int ret;
+
+       if (!(flags & 1)) /*not audio*/
+               max_bufs = 300; /*can great for video bufs.*/
+       task_buffer_size = sizeof(struct threadrw_write_task) +
+                               sizeof(struct threadrw_buf) * max_bufs;
+       task = vmalloc(task_buffer_size);
+
+       if (!task)
+               return NULL;
+       memset(task, 0, task_buffer_size);
+
+       spin_lock_init(&task->lock);
+       mutex_init(&task->mutex);
+       INIT_DELAYED_WORK(&task->write_work, do_write_work);
+       init_waitqueue_head(&task->wq);
+       ret = kfifo_alloc(&task->datafifo, max_bufs, GFP_KERNEL);
+       if (ret)
+               goto err1;
+       ret = kfifo_alloc(&task->freefifo, max_bufs, GFP_KERNEL);
+       if (ret)
+               goto err2;
+       task->write = write;
+       task->file = NULL;
+       task->buffer_size = 0;
+       task->manual_write = flags & 1;
+       task->max_bufs = max_bufs;
+       mutex_lock(&task->mutex);
+       ret = alloc_task_buffers_inlock(task, num, block_size);
+       mutex_unlock(&task->mutex);
+       if (ret < 0)
+               goto err3;
+       threadrw_wq_get();      /*start thread. */
+       return task;
+
+err3:
+       kfifo_free(&task->freefifo);
+err2:
+       kfifo_free(&task->datafifo);
+err1:
+       vfree(task);
+       pr_err("alloc threadrw failed num:%d,block:%d\n", num, block_size);
+       return NULL;
+}
+
+/*
+ *fifo data size;
+ */
+
+void threadrw_update_buffer_level(struct stream_buf_s *stbuf,
+       int parsed_size)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+       unsigned long flags;
+
+       if (task)
+       {
+               spin_lock_irqsave(&task->lock, flags);
+               task->buffered_data_size -= parsed_size;
+               spin_unlock_irqrestore(&task->lock, flags);
+       }
+
+}
+EXPORT_SYMBOL(threadrw_update_buffer_level);
+
+int threadrw_buffer_level(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task)
+               return task->buffered_data_size;
+       return 0;
+}
+
+int threadrw_buffer_size(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task)
+               return task->buffer_size;
+       return 0;
+}
+
+int threadrw_datafifo_len(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task)
+               return kfifo_len(&task->datafifo);
+       return 0;
+}
+
+int threadrw_freefifo_len(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task)
+               return kfifo_len(&task->freefifo);
+       return 0;
+}
+int threadrw_support_more_buffers(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (!task)
+               return 0;
+       if (task->failed_onmore)
+               return 0;
+       return task->max_bufs - task->bufs_num;
+}
+
+/*
+ *data len out fifo;
+ */
+int threadrw_passed_len(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task)
+               return task->passed_data_len;
+       return 0;
+
+}
+/*
+ *all data writed.;
+ */
+int threadrw_dataoffset(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+       int offset = 0;
+
+       if (task)
+               return task->data_offset;
+       return offset;
+
+}
+
+ssize_t threadrw_write(struct file *file, struct stream_buf_s *stbuf,
+                                          const char __user *buf, size_t count)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+       ssize_t size;
+
+       if (!task->file) {
+               task->file = file;
+               task->sbuf = stbuf;
+       }
+       mutex_lock(&task->mutex);
+       size = threadrw_write_in(task, stbuf, buf, count);
+       mutex_unlock(&task->mutex);
+       return size;
+}
+
+int threadrw_flush_buffers(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+       int max_retry = 20;
+
+       if (!task)
+               return 0;
+       while (!kfifo_is_empty(&task->datafifo) && max_retry-- > 0) {
+               threadrw_schedule_delayed_work(task, 0);
+               msleep(20);
+       }
+       if (!kfifo_is_empty(&task->datafifo))
+               return -1;/*data not flushed*/
+       return 0;
+}
+int threadrw_alloc_more_buffer_size(
+       struct stream_buf_s *stbuf,
+       int size)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+       int block_size;
+       int new_num;
+       int ret = -1;
+       int old_num;
+
+       if (!task)
+               return -1;
+       mutex_lock(&task->mutex);
+       block_size = task->def_block_size;
+       if (block_size == 0)
+               block_size = 32 * 1024;
+       new_num = size / block_size;
+       old_num = task->bufs_num;
+       if (new_num == 0)
+               new_num = 1;
+       else if (new_num > task->max_bufs - task->bufs_num)
+               new_num = task->max_bufs - task->bufs_num;
+       if (new_num != 0)
+               ret = alloc_task_buffers_inlock(task, new_num,
+                       block_size);
+       mutex_unlock(&task->mutex);
+       pr_info("threadrw add more buffer from %d -> %d for size %d\n",
+               old_num, task->bufs_num,
+               size);
+       if (ret < 0 || old_num == task->bufs_num)
+               task->failed_onmore = 1;
+       return ret;
+}
+
+void *threadrw_alloc(int num,
+               int block_size,
+                       ssize_t (*write)(struct file *,
+                               struct stream_buf_s *,
+                               const char __user *,
+                               size_t, int),
+                               int flags)
+{
+       return threadrw_alloc_in(num, block_size, write, flags);
+}
+
+void threadrw_release(struct stream_buf_s *stbuf)
+{
+       struct threadrw_write_task *task = stbuf->write_thread;
+
+       if (task) {
+               wake_up_interruptible(&task->wq);
+               cancel_delayed_work_sync(&task->write_work);
+               mutex_lock(&task->mutex);
+               free_task_buffers(task);
+               mutex_unlock(&task->mutex);
+               kfifo_free(&task->freefifo);
+               kfifo_free(&task->datafifo);
+               vfree(task);
+       }
+       stbuf->write_thread = NULL;
+}
diff --git a/drivers/stream_input/amports/thread_rw.h b/drivers/stream_input/amports/thread_rw.h
new file mode 100644 (file)
index 0000000..4a93dee
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * drivers/amlogic/media/stream_input/parser/thread_rw.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef THREAD_RW_H
+#define THREAD_RW_H
+#include "../../stream_input/amports/streambuf_reg.h"
+#include "../../stream_input/amports/streambuf.h"
+#include "../../stream_input/parser/esparser.h"
+#include "../../stream_input/amports/amports_priv.h"
+
+ssize_t threadrw_write(struct file *file,
+               struct stream_buf_s *stbuf,
+               const char __user *buf,
+               size_t count);
+
+void *threadrw_alloc(int num,
+               int block_size,
+                       ssize_t (*write)(struct file *,
+                               struct stream_buf_s *,
+                               const char __user *,
+                               size_t, int),
+                               int flags);/*flags &1: manual mode*/
+
+void threadrw_release(struct stream_buf_s *stbuf);
+
+int threadrw_buffer_level(struct stream_buf_s *stbuf);
+int threadrw_buffer_size(struct stream_buf_s *stbuf);
+int threadrw_datafifo_len(struct stream_buf_s *stbuf);
+int threadrw_freefifo_len(struct stream_buf_s *stbuf);
+int threadrw_passed_len(struct stream_buf_s *stbuf);
+int threadrw_flush_buffers(struct stream_buf_s *stbuf);
+int threadrw_dataoffset(struct stream_buf_s *stbuf);
+int threadrw_alloc_more_buffer_size(
+       struct stream_buf_s *stbuf,
+       int size);
+int threadrw_support_more_buffers(struct stream_buf_s *stbuf);
+void threadrw_update_buffer_level(struct stream_buf_s *stbuf,
+       int parsed_size);
+#endif
index 0f201a976faa4b656c14fa52460031c1d145ff6b..a92d238bb252b87fc51114364d29a337a7ea6b2c 100644 (file)
 
 static DECLARE_WAIT_QUEUE_HEAD(wq);
 static u32 fetch_done = 0;
-static void *fetchbuf = NULL;
+static void *fetchbuff = NULL;
 
 static const char tsdemux_fetch_id[] = "tsdemux-fetch-id";
 
-static int stbuf_fetch_init(void)
+static int stbuff_fetch_init(void)
 {
-       if (NULL != fetchbuf)
+       if (NULL != fetchbuff)
                return 0;
        pr_dbg("%s line:%d\n",__FUNCTION__,__LINE__);
 
-       fetchbuf = (void *)__get_free_pages(GFP_KERNEL,
+       fetchbuff = (void *)__get_free_pages(GFP_KERNEL,
                                         get_order(FETCHBUF_SIZE));
-       if (!fetchbuf) {
+       if (!fetchbuff) {
                pr_info("%s: Can not allocate fetch working buffer\n",
                         __func__);
                return -ENOMEM;
        }
        return 0;
 }
-static void stbuf_fetch_release(void)
+static void stbuff_fetch_release(void)
 {
-       if (0 && fetchbuf) {
+       if (0 && fetchbuff) {
                /* always don't free.for safe alloc/free*/
-               free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE));
-               fetchbuf = 0;
+               free_pages((unsigned long)fetchbuff, get_order(FETCHBUF_SIZE));
+               fetchbuff = 0;
        }
 }
 static irqreturn_t parser_isr(int irq, void *dev_id)
@@ -126,7 +126,7 @@ static void _hwdmx_inject_init(HWDMX_Demux *pdmx) {
        if (pdmx->inject_init)
                return ;
 
-       stbuf_fetch_init();
+       stbuff_fetch_init();
 
        r = vdec_request_irq(PARSER_IRQ, parser_isr,
                        "tsdemux-fetch", (void *)tsdemux_fetch_id);
@@ -160,12 +160,12 @@ static int _hwdmx_inject_write(HWDMX_Demux *pdmx, const char *buf, int count) {
                 len = count;
         else {
                 len = min_t(size_t, r, FETCHBUF_SIZE);
-                if (copy_from_user(fetchbuf, p, len))
+                if (copy_from_user(fetchbuff, p, len))
                         return -EFAULT;
 
                 dma_addr =
                         dma_map_single(hwdemux_get_dma_device(),
-                                        fetchbuf,
+                                        fetchbuff,
                                         FETCHBUF_SIZE, DMA_TO_DEVICE);
                 if (dma_mapping_error(hwdemux_get_dma_device(),
                                         dma_addr))
@@ -174,7 +174,7 @@ static int _hwdmx_inject_write(HWDMX_Demux *pdmx, const char *buf, int count) {
 
         fetch_done = 0;
 
-        wmb();          /* Ensure fetchbuf  contents visible */
+        wmb();          /* Ensure fetchbuff  contents visible */
 
         if (isphybuf) {
                 u32 buf_32 = (unsigned long)buf & 0xffffffff;
@@ -212,7 +212,7 @@ void hwdmx_inject_destroy(HWDMX_Demux *pdmx) {
  if (!(pdmx && pdmx->init)) {
         return ;
  }
- stbuf_fetch_release();
+ stbuff_fetch_release();
 
  WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
  vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id);
index f81ba0cc08ad7ce3faf24136643e702bedcccecd..94fafd1824df5b7cf86e3504fba382f5afd3ae78 100644 (file)
 
 #include "../../frame_provider/decoder/utils/vdec.h"
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
 #include "esparser.h"
 #include "../amports/amports_priv.h"
-#include "thread_rw.h"
+#include "../amports/thread_rw.h"
 
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 
@@ -153,8 +153,7 @@ static inline u32 buf_wp(u32 type)
        return wp;
 }
 
-static ssize_t _esparser_write(const char __user *buf,
-               size_t count, struct stream_buf_s *stbuf, int isphybuf)
+static int esparser_stbuf_write(struct stream_buf_s *stbuf, const u8 *buf, u32 count)
 {
        size_t r = count;
        const char __user *p = buf;
@@ -179,7 +178,7 @@ static ssize_t _esparser_write(const char __user *buf,
        wp = buf_wp(type);
 
        if (r > 0) {
-               if (isphybuf)
+               if (stbuf->is_phybuf)
                        len = count;
                else {
                        len = min_t(size_t, r, (size_t) FETCHBUF_SIZE);
@@ -207,7 +206,7 @@ static ssize_t _esparser_write(const char __user *buf,
                                PARSER_AUTOSEARCH, ES_CTRL_BIT,
                                ES_CTRL_WID);
 
-               if (isphybuf) {
+               if (stbuf->is_phybuf) {
                        u32 buf_32 = (unsigned long)buf & 0xffffffff;
                        WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32);
                } else {
@@ -217,7 +216,7 @@ static ssize_t _esparser_write(const char __user *buf,
                }
 
                search_done = 0;
-               if (!(isphybuf & TYPE_PATTERN)) {
+               if (!(stbuf->is_phybuf & TYPE_PATTERN)) {
                        WRITE_PARSER_REG(PARSER_FETCH_CMD,
                                (7 << FETCH_ENDIAN) | len);
                        WRITE_PARSER_REG(PARSER_FETCH_ADDR, search_pattern_map);
@@ -238,7 +237,7 @@ static ssize_t _esparser_write(const char __user *buf,
                        } else {
                                pr_info("W Timeout, but fetch ok,");
                                pr_info("type %d len=%d,wpdiff=%d, isphy %x\n",
-                                type, len, wp - buf_wp(type), isphybuf);
+                                type, len, wp - buf_wp(type), stbuf->is_phybuf);
                        }
                } else if (ret < 0)
                        return -ERESTARTSYS;
@@ -256,6 +255,13 @@ static ssize_t _esparser_write(const char __user *buf,
        return len;
 }
 
+static ssize_t _esparser_write(const char __user *buf,
+               size_t count, struct stream_buf_s *stbuf, int isphybuf)
+{
+       return esparser_stbuf_write(stbuf, buf, count);
+}
+
+
 static ssize_t _esparser_write_s(const char __user *buf,
                        size_t count, struct stream_buf_s *stbuf)
 {
@@ -509,6 +515,11 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
                        /* set stream_fetch_enable */
                        SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
 
+                       if (buf->no_parser) {
+                               /*set endian for non-parser mode */
+                               SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+                       }
+
                        /* set stream_buffer_hole with 256 bytes */
                        SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1 << 29));
                } else {
@@ -523,6 +534,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
                        vdec->input.start);
                WRITE_PARSER_REG(PARSER_VIDEO_END_PTR,
                        vdec->input.start + vdec->input.size - 8);
+
                if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2)) {
                        if (vdec_get_debug_flags() & 0x2)
                                pr_info("%s %d\n", __func__, __LINE__);
@@ -611,6 +623,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
                                           PARSER_INT_HOST_EN_BIT);
        }
        mutex_unlock(&esparser_mutex);
+
        if (!(vdec_get_debug_flags() & 1) &&
                !codec_mm_video_tvp_enabled()) {
                int block_size = (buf->type == BUF_TYPE_AUDIO) ?
@@ -624,6 +637,7 @@ s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
                        (buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
                        /*manul mode for audio*/
        }
+
        return 0;
 
 Err_2:
@@ -908,6 +922,9 @@ ssize_t esparser_write_ex(struct file *file,
 
        mutex_lock(&esparser_mutex);
 
+       if (flags & 1)
+               stbuf->is_phybuf = true;
+
        if (stbuf->type == BUF_TYPE_AUDIO)
                r = _esparser_write_s(buf, len, stbuf);
        else
@@ -982,3 +999,43 @@ void esparser_sub_reset(void)
 
        spin_unlock_irqrestore(&lock, flags);
 }
+
+static int esparser_stbuf_init(struct stream_buf_s *stbuf,
+                              struct vdec_s *vdec)
+{
+       int ret = -1;
+
+       ret = stbuf_init(stbuf, vdec);
+       if (ret)
+               goto out;
+
+       ret = esparser_init(stbuf, vdec);
+       if (!ret)
+               stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+       return ret;
+}
+
+static void esparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+       esparser_release(stbuf);
+
+       stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops esparser_stbuf_ops = {
+       .init   = esparser_stbuf_init,
+       .release = esparser_stbuf_release,
+       .write  = esparser_stbuf_write,
+       .get_wp = parser_get_wp,
+       .set_wp = parser_set_wp,
+       .get_rp = parser_get_rp,
+       .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_esparser_stbuf_ops(void)
+{
+       return &esparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_esparser_stbuf_ops);
+
index 787111e9d448344c8abd7e89d3e40d8d46855043..488f052df2e2483ccd73d61284926f7b95bfc77e 100644 (file)
@@ -45,7 +45,7 @@
 #include <linux/vmalloc.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
-#include "../streambuf.h"
+#include "../../amports/streambuf.h"
 #include "c_stb_define.h"
 #include "c_stb_regs_define.h"
 #include "aml_dvb.h"
index 771314acb9bb22e55a295de50af86ae01098a4be..20c1d1a13e18129bd6500669c2714bbebe5a44f9 100644 (file)
@@ -30,8 +30,8 @@
 #include <linux/uaccess.h>
 /* #include <mach/am_regs.h> */
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
 #include "psparser.h"
 #include "../amports/amports_priv.h"
 
@@ -1153,3 +1153,47 @@ u8 psparser_get_sub_info(struct subtitle_info **sub_infos)
        return 0;
 #endif
 }
+
+static int psparser_stbuf_init(struct stream_buf_s *stbuf,
+                              struct vdec_s *vdec)
+{
+       int ret = -1;
+
+       ret = stbuf_init(stbuf, vdec);
+       if (ret)
+               goto out;
+
+       ret = psparser_init(stbuf->pars.vid,
+                          stbuf->pars.aid,
+                          stbuf->pars.sid,
+                          vdec);
+       if (ret)
+               goto out;
+
+       stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+       return ret;
+}
+
+static void psparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+       psparser_release();
+
+       stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops psparser_stbuf_ops = {
+       .init   = psparser_stbuf_init,
+       .release = psparser_stbuf_release,
+       .get_wp = parser_get_wp,
+       .set_wp = parser_set_wp,
+       .get_rp = parser_get_rp,
+       .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_psparser_stbuf_ops(void)
+{
+       return &psparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_psparser_stbuf_ops);
+
index 9f7a1b0959ac81a33905b890839a709a230a2fb3..902dc5a5b84a27fd0d9524456453947c6d180407 100644 (file)
@@ -30,8 +30,8 @@
 
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../amports/amports_priv.h"
-#include "streambuf.h"
-#include "streambuf_reg.h"
+#include "../amports/streambuf.h"
+#include "../amports/streambuf_reg.h"
 #include <linux/delay.h>
 #include "rmparser.h"
 
diff --git a/drivers/stream_input/parser/streambuf.c b/drivers/stream_input/parser/streambuf.c
deleted file mode 100644 (file)
index 1060770..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * drivers/amlogic/media/stream_input/parser/streambuf.c
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- */
-#define DEBUG
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/amlogic/media/frame_sync/ptsserv.h>
-#include <linux/amlogic/media/utils/vformat.h>
-#include <linux/amlogic/iomap.h>
-#include <asm/cacheflush.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-/* #include <mach/am_regs.h> */
-
-#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../../frame_provider/decoder/utils/vdec.h"
-#include "streambuf_reg.h"
-#include "streambuf.h"
-#include <linux/amlogic/media/utils/amports_config.h>
-#include "../amports/amports_priv.h"
-#include <linux/dma-mapping.h>
-#include <linux/dma-contiguous.h>
-#include <linux/amlogic/media/codec_mm/codec_mm.h>
-
-#define STBUF_SIZE   (64*1024)
-#define STBUF_WAIT_INTERVAL  (HZ/100)
-#define MEM_NAME "streambuf"
-
-void *fetchbuf = 0;
-
-static s32 _stbuf_alloc(struct stream_buf_s *buf, bool is_secure)
-{
-       if (buf->buf_size == 0)
-               return -ENOBUFS;
-
-       while (buf->buf_start == 0) {
-               int flags = CODEC_MM_FLAGS_DMA;
-
-               buf->buf_page_num = PAGE_ALIGN(buf->buf_size) / PAGE_SIZE;
-               if (buf->type == BUF_TYPE_SUBTITLE)
-                       flags = CODEC_MM_FLAGS_DMA_CPU;
-
-               /*
-                *if 4k,
-                *used cma first,for less mem fragments.
-                */
-               if (((buf->type == BUF_TYPE_HEVC) ||
-                       (buf->type == BUF_TYPE_VIDEO)) &&
-                       buf->for_4k)
-                       flags |= CODEC_MM_FLAGS_CMA_FIRST;
-               if (buf->buf_size > 20 * 1024 * 1024)
-                       flags |= CODEC_MM_FLAGS_CMA_FIRST;
-
-               if ((buf->type == BUF_TYPE_HEVC) ||
-                       (buf->type == BUF_TYPE_VIDEO)) {
-                       flags |= CODEC_MM_FLAGS_FOR_VDECODER;
-               } else if (buf->type == BUF_TYPE_AUDIO) {
-                       flags |= CODEC_MM_FLAGS_FOR_ADECODER;
-                       flags |= CODEC_MM_FLAGS_DMA_CPU;
-               }
-
-               if (is_secure)
-                       flags |= CODEC_MM_FLAGS_TVP;
-
-               buf->buf_start = codec_mm_alloc_for_dma(MEM_NAME,
-                       buf->buf_page_num, 4+PAGE_SHIFT, flags);
-               if (!buf->buf_start) {
-                       int is_video = (buf->type == BUF_TYPE_HEVC) ||
-                                       (buf->type == BUF_TYPE_VIDEO);
-                       if (is_video && buf->buf_size >= 9 * SZ_1M) {/*min 6M*/
-                               int old_size = buf->buf_size;
-
-                               buf->buf_size  =
-                                       PAGE_ALIGN(buf->buf_size * 2/3);
-                               pr_info("%s stbuf alloced size = %d failed try small %d size\n",
-                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
-                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
-                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
-                               "Subtitle", old_size, buf->buf_size);
-                               continue;
-                       }
-                       pr_info("%s stbuf alloced size = %d failed\n",
-                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
-                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
-                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
-                               "Subtitle", buf->buf_size);
-                       return -ENOMEM;
-               }
-
-               buf->is_secure = is_secure;
-
-               pr_debug("%s stbuf alloced at %p, secure = %d, size = %d\n",
-                               (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
-                               (buf->type == BUF_TYPE_VIDEO) ? "Video" :
-                               (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
-                               "Subtitle", (void *)buf->buf_start,
-                               buf->is_secure,
-                               buf->buf_size);
-       }
-       if (buf->buf_size < buf->canusebuf_size)
-               buf->canusebuf_size = buf->buf_size;
-       buf->flag |= BUF_FLAG_ALLOC;
-
-       return 0;
-}
-
-int stbuf_change_size(struct stream_buf_s *buf, int size, bool is_secure)
-{
-       unsigned long old_buf;
-       int old_size, old_pagenum;
-       int ret;
-
-       pr_info("buffersize=%d,%d,start=%p, secure=%d\n", size, buf->buf_size,
-                       (void *)buf->buf_start, is_secure);
-
-       if (buf->buf_size == size && buf->buf_start != 0)
-               return 0;
-
-       old_buf = buf->buf_start;
-       old_size = buf->buf_size;
-       old_pagenum = buf->buf_page_num;
-       buf->buf_start = 0;
-       buf->buf_size = size;
-       ret = size;
-
-       if (size == 0 ||
-               _stbuf_alloc(buf, is_secure) == 0) {
-               /*
-                * size=0:We only free the old memory;
-                * alloc ok,changed to new buffer
-                */
-               if (old_buf != 0) {
-                       codec_mm_free_for_dma(MEM_NAME, old_buf);
-               }
-
-               if (size == 0)
-                       buf->is_secure = false;
-
-               pr_info("changed the (%d) buffer size from %d to %d\n",
-                               buf->type, old_size, size);
-               return 0;
-       } else {
-               /* alloc failed */
-               buf->buf_start = old_buf;
-               buf->buf_size = old_size;
-               buf->buf_page_num = old_pagenum;
-               pr_info("changed the (%d) buffer size from %d to %d,failed\n",
-                               buf->type, old_size, size);
-       }
-
-       return ret;
-}
-
-int stbuf_fetch_init(void)
-{
-       if (NULL != fetchbuf)
-               return 0;
-
-       fetchbuf = (void *)__get_free_pages(GFP_KERNEL,
-                                               get_order(FETCHBUF_SIZE));
-
-       if (!fetchbuf) {
-               pr_info("%s: Can not allocate fetch working buffer\n",
-                               __func__);
-               return -ENOMEM;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(stbuf_fetch_init);
-
-void stbuf_fetch_release(void)
-{
-       if (0 && fetchbuf) {
-               /* always don't free.for safe alloc/free*/
-               free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE));
-               fetchbuf = 0;
-       }
-}
-
-static void _stbuf_timer_func(unsigned long arg)
-{
-       struct stream_buf_s *p = (struct stream_buf_s *)arg;
-
-       if (stbuf_space(p) < p->wcnt) {
-               p->timer.expires = jiffies + STBUF_WAIT_INTERVAL;
-
-               add_timer(&p->timer);
-       } else
-               wake_up_interruptible(&p->wq);
-
-}
-
-u32 stbuf_level(struct stream_buf_s *buf)
-{
-       if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
-               if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) {
-                       int level = READ_PARSER_REG(PARSER_VIDEO_WP) -
-                               READ_PARSER_REG(PARSER_VIDEO_RP);
-                       if (level < 0)
-                               level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) -
-                               READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8;
-                       return (u32)level;
-               } else
-                       return (buf->type == BUF_TYPE_HEVC) ?
-                               READ_VREG(HEVC_STREAM_LEVEL) :
-                               _READ_ST_REG(LEVEL);
-       }
-
-       return _READ_ST_REG(LEVEL);
-}
-
-u32 stbuf_rp(struct stream_buf_s *buf)
-{
-       if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
-               if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1)
-                       return READ_PARSER_REG(PARSER_VIDEO_RP);
-               else
-                       return (buf->type == BUF_TYPE_HEVC) ?
-                               READ_VREG(HEVC_STREAM_RD_PTR) :
-                               _READ_ST_REG(RP);
-       }
-
-       return _READ_ST_REG(RP);
-}
-
-u32 stbuf_space(struct stream_buf_s *buf)
-{
-       /* reserved space for safe write,
-        *   the parser fifo size is 1024byts, so reserve it
-        */
-       int size;
-
-       size = buf->canusebuf_size - stbuf_level(buf);
-
-       if (buf->canusebuf_size >= buf->buf_size / 2) {
-               /* old reversed value,tobe full, reversed only... */
-               size = size - 6 * 1024;
-       }
-
-       if ((buf->type == BUF_TYPE_VIDEO)
-               || (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC))
-               size -= READ_PARSER_REG(PARSER_VIDEO_HOLE);
-
-       return size > 0 ? size : 0;
-}
-
-u32 stbuf_size(struct stream_buf_s *buf)
-{
-       return buf->buf_size;
-}
-
-u32 stbuf_canusesize(struct stream_buf_s *buf)
-{
-       return buf->canusebuf_size;
-}
-
-s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec, bool is_multi)
-{
-       s32 r;
-       u32 dummy;
-       u32 addr32;
-
-       VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
-
-       if (!buf->buf_start) {
-               r = _stbuf_alloc(buf, (vdec) ?
-                       vdec->port_flag & PORT_FLAG_DRM : 0);
-               if (r < 0)
-                       return r;
-       }
-       addr32 = buf->buf_start & 0xffffffff;
-       init_waitqueue_head(&buf->wq);
-
-       /*
-        * For multidec, do not touch HW stream buffers during port
-        * init and release.
-        */
-       if ((buf->type == BUF_TYPE_VIDEO) || (buf->type == BUF_TYPE_HEVC)) {
-               if (vdec) {
-                       if (vdec_stream_based(vdec))
-                               vdec_set_input_buffer(vdec, addr32,
-                                               buf->buf_size);
-                       else
-                               return vdec_set_input_buffer(vdec, addr32,
-                                               buf->buf_size);
-               }
-       }
-
-       buf->write_thread = 0;
-       if (((vdec && !vdec_single(vdec)) || (is_multi)) &&
-               (vdec_get_debug_flags() & 0x2) == 0)
-               return 0;
-       if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) {
-               CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1);
-               WRITE_VREG(HEVC_STREAM_START_ADDR, addr32);
-               WRITE_VREG(HEVC_STREAM_END_ADDR, addr32 + buf->buf_size);
-               WRITE_VREG(HEVC_STREAM_RD_PTR, addr32);
-               WRITE_VREG(HEVC_STREAM_WR_PTR, addr32);
-
-               return 0;
-       }
-
-       if (buf->type == BUF_TYPE_VIDEO) {
-               VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
-
-               _WRITE_ST_REG(CONTROL, 0);
-               /* reset VLD before setting all pointers */
-               WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0);
-               /*TODO: only > m6*/
-#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-               WRITE_VREG(DOS_SW_RESET0, (1 << 4));
-               WRITE_VREG(DOS_SW_RESET0, 0);
-#else
-               WRITE_RESET_REG(RESET0_REGISTER, RESET_VLD);
-#endif
-
-               dummy = READ_RESET_REG(RESET0_REGISTER);
-               WRITE_VREG(POWER_CTL_VLD, 1 << 4);
-       } else if (buf->type == BUF_TYPE_AUDIO) {
-               _WRITE_ST_REG(CONTROL, 0);
-
-               WRITE_AIU_REG(AIU_AIFIFO_GBIT, 0x80);
-       }
-
-       if (buf->type == BUF_TYPE_SUBTITLE) {
-               WRITE_PARSER_REG(PARSER_SUB_RP, addr32);
-               WRITE_PARSER_REG(PARSER_SUB_START_PTR, addr32);
-               WRITE_PARSER_REG(PARSER_SUB_END_PTR,
-                                          addr32 + buf->buf_size - 8);
-
-               return 0;
-       }
-
-       _WRITE_ST_REG(START_PTR, addr32);
-       _WRITE_ST_REG(CURR_PTR, addr32);
-       _WRITE_ST_REG(END_PTR, addr32 + buf->buf_size - 8);
-
-       _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
-       _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
-
-       _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL);
-       _WRITE_ST_REG(WP, addr32);
-
-       _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
-       _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
-
-       _SET_ST_REG_MASK(CONTROL,
-                       (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN |
-                       MEM_CTRL_EMPTY_EN);
-       return 0;
-}
-EXPORT_SYMBOL(stbuf_init);
-
-void stbuf_vdec2_init(struct stream_buf_s *buf)
-{
-
-       _WRITE_VDEC2_ST_REG(CONTROL, 0);
-
-       _WRITE_VDEC2_ST_REG(START_PTR, _READ_ST_REG(START_PTR));
-       _WRITE_VDEC2_ST_REG(END_PTR, _READ_ST_REG(END_PTR));
-       _WRITE_VDEC2_ST_REG(CURR_PTR, _READ_ST_REG(CURR_PTR));
-
-       _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL | MEM_BUFCTRL_INIT);
-       _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL);
-
-       _WRITE_VDEC2_ST_REG(BUF_CTRL, MEM_BUFCTRL_INIT);
-       _WRITE_VDEC2_ST_REG(BUF_CTRL, 0);
-
-       _WRITE_VDEC2_ST_REG(CONTROL,
-                       (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN
-                       | MEM_CTRL_EMPTY_EN);
-}
-
-s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count)
-{
-       struct stream_buf_s *p = stream_buf;
-       long time_out = 200;
-
-       p->wcnt = count;
-
-       setup_timer(&p->timer, _stbuf_timer_func, (ulong) p);
-
-       mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL);
-
-       if (wait_event_interruptible_timeout
-               (p->wq, stbuf_space(p) >= count,
-                msecs_to_jiffies(time_out)) == 0) {
-               del_timer_sync(&p->timer);
-
-               return -EAGAIN;
-       }
-
-       del_timer_sync(&p->timer);
-
-       return 0;
-}
-
-void stbuf_release(struct stream_buf_s *buf, bool is_multi)
-{
-       int r;
-
-       buf->first_tstamp = INVALID_PTS;
-
-       r = stbuf_init(buf, NULL, is_multi);/* reinit buffer */
-       if (r < 0)
-               pr_err("stbuf_release %d, stbuf_init failed\n", __LINE__);
-
-       if (buf->flag & BUF_FLAG_ALLOC && buf->buf_start) {
-               codec_mm_free_for_dma(MEM_NAME, buf->buf_start);
-               buf->flag &= ~BUF_FLAG_ALLOC;
-               buf->buf_start = 0;
-               buf->is_secure = false;
-       }
-       buf->flag &= ~BUF_FLAG_IN_USE;
-}
-EXPORT_SYMBOL(stbuf_release);
-
-u32 stbuf_sub_rp_get(void)
-{
-       return READ_PARSER_REG(PARSER_SUB_RP);
-}
-
-void stbuf_sub_rp_set(unsigned int sub_rp)
-{
-       WRITE_PARSER_REG(PARSER_SUB_RP, sub_rp);
-       return;
-}
-
-u32 stbuf_sub_wp_get(void)
-{
-       return READ_PARSER_REG(PARSER_SUB_WP);
-}
-
-u32 stbuf_sub_start_get(void)
-{
-       return READ_PARSER_REG(PARSER_SUB_START_PTR);
-}
diff --git a/drivers/stream_input/parser/streambuf.h b/drivers/stream_input/parser/streambuf.h
deleted file mode 100644 (file)
index d73865e..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * drivers/amlogic/media/stream_input/parser/streambuf.h
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- */
-
-#ifndef STREAMBUF_H
-#define STREAMBUF_H
-#include <linux/amlogic/media/utils/amports_config.h>
-
-#define BUF_FLAG_ALLOC          0x01
-#define BUF_FLAG_IN_USE         0x02
-#define BUF_FLAG_PARSER         0x04
-#define BUF_FLAG_FIRST_TSTAMP   0x08
-#define BUF_FLAG_IOMEM          0x10
-
-#define BUF_TYPE_VIDEO      0
-#define BUF_TYPE_AUDIO      1
-#define BUF_TYPE_SUBTITLE   2
-#define BUF_TYPE_USERDATA   3
-#define BUF_TYPE_HEVC       4
-#define BUF_MAX_NUM         5
-
-#define INVALID_PTS 0xffffffff
-
-#define FETCHBUF_SIZE   (64*1024)
-#define USER_DATA_SIZE  (8*1024)
-
-struct vdec_s;
-
-struct stream_buf_s {
-       s32 flag;
-       u32 type;
-       unsigned long buf_start;
-       struct page *buf_pages;
-       int buf_page_num;
-       u32 buf_size;
-       u32 default_buf_size;
-       u32 canusebuf_size;
-       u32 first_tstamp;
-       const ulong reg_base;
-       wait_queue_head_t wq;
-       struct timer_list timer;
-       u32 wcnt;
-       u32 buf_wp;
-       u32 buf_rp;
-       u32 max_buffer_delay_ms;
-       u64 last_write_jiffies64;
-       void *write_thread;
-       int for_4k;
-       bool is_secure;
-} /*stream_buf_t */;
-
-struct stream_port_s {
-       /* driver info */
-       const char *name;
-       struct device *class_dev;
-       const struct file_operations *fops;
-
-       /* ports control */
-       s32 type;
-       s32 flag;
-       s32 pcr_inited;
-
-       /* decoder info */
-       s32 vformat;
-       s32 aformat;
-       s32 achanl;
-       s32 asamprate;
-       s32 adatawidth;
-
-       /* parser info */
-       u32 vid;
-       u32 aid;
-       u32 sid;
-       u32 pcrid;
-} /*stream_port_t */;
-enum drm_level_e {
-       DRM_LEVEL1 = 1,
-       DRM_LEVEL2 = 2,
-       DRM_LEVEL3 = 3,
-       DRM_NONE = 4,
-};
-
-struct drm_info {
-       enum drm_level_e drm_level;
-       u32 drm_flag;
-       u32 drm_hasesdata;
-       u32 drm_priv;
-       u32 drm_pktsize;
-       u32 drm_pktpts;
-       u32 drm_phy;
-       u32 drm_vir;
-       u32 drm_remap;
-       u32 data_offset;
-       u32 handle;
-       u32 extpad[7];
-} /*drminfo_t */;
-
-#define TYPE_DRMINFO_V2  0x100
-#define TYPE_DRMINFO   0x80
-#define TYPE_PATTERN   0x40
-
-struct vdec_s;
-
-extern void *fetchbuf;
-
-extern u32 stbuf_level(struct stream_buf_s *buf);
-extern u32 stbuf_rp(struct stream_buf_s *buf);
-extern u32 stbuf_space(struct stream_buf_s *buf);
-extern u32 stbuf_size(struct stream_buf_s *buf);
-extern u32 stbuf_canusesize(struct stream_buf_s *buf);
-extern s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec,
-               bool is_multi);
-extern s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count);
-extern void stbuf_release(struct stream_buf_s *buf, bool is_multi);
-extern int stbuf_change_size(struct stream_buf_s *buf, int size,
-                               bool is_secure);
-extern int stbuf_fetch_init(void);
-extern void stbuf_fetch_release(void);
-extern u32 stbuf_sub_rp_get(void);
-extern void stbuf_sub_rp_set(unsigned int sub_rp);
-extern u32 stbuf_sub_wp_get(void);
-extern u32 stbuf_sub_start_get(void);
-extern u32 stbuf_userdata_start_get(void);
-extern struct stream_buf_s *get_stream_buffer(int id);
-
-extern void stbuf_vdec2_init(struct stream_buf_s *buf);
-
-#endif /* STREAMBUF_H */
diff --git a/drivers/stream_input/parser/streambuf_reg.h b/drivers/stream_input/parser/streambuf_reg.h
deleted file mode 100644 (file)
index 5f0c8ca..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * drivers/amlogic/media/stream_input/parser/streambuf_reg.h
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- */
-
-#ifndef STREAMBUF_REG_H
-#define STREAMBUF_REG_H
-
-#define HEVC_STREAM_REG_BASE        HEVC_STREAM_START_ADDR
-
-#define VLD_MEM_VIFIFO_REG_BASE     VLD_MEM_VIFIFO_START_PTR
-#define AIU_MEM_AIFIFO_REG_BASE     AIU_MEM_AIFIFO_START_PTR
-
-#define START_PTR   0
-#define CURR_PTR    1
-#define END_PTR     2
-#define BYTES_AVAIL 3
-#define CONTROL     4
-#define WP          5
-#define RP          6
-#define LEVEL       7
-#define BUF_CTRL    8
-
-/*
- *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6
- *#define _WRITE_ST_REG(r, val) \
- *    __raw_writel(val, (volatile void __iomem *)(buf->reg_base+(r<<2)))
- *#define _WRITE_ST_REG_BITS(r, val, s, e) \
- *    __raw_writel((((_READ_ST_REG(r) & \
- *    (((1L<<(e)-1)<<(s))-1)<<(s)))|((unsigned)((val)&((1L<<(e))-1))<<(s))), \
- *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
- *#define _SET_ST_REG_MASK(r, val) \
- *    __raw_writel(_READ_ST_REG(r)| (val), \
- *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
- *#define _CLR_ST_REG_MASK(r, val) \
- *    __raw_writel(_READ_ST_REG(r)&~(val), \
- *    (volatile void __iomem *)(buf->reg_base+(r<<2)))
- *#define _READ_ST_REG(r) \
- *    (__raw_readl((volatile void __iomem *)(buf->reg_base+(r<<2))))
- *
- *#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD
- *#define _READ_VDEC2_ST_REG(r) \
- *    (__raw_readl((volatile void __iomem *)(buf->reg_base + \
- *    DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \
- *    DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2))))
- *#define _WRITE_VDEC2_ST_REG(r, val) \
- *    __raw_writel(val, (volatile void __iomem *)(buf->reg_base + \
- *    DOS_REG_ADDR(VDEC2_VLD_MEM_VIFIFO_START_PTR) - \
- *    DOS_REG_ADDR(VLD_MEM_VIFIFO_START_PTR) + (r<<2)))
- *#endif
- *
- *#define MEM_BUFCTRL_MANUAL      (1<<1)
- *#define MEM_BUFCTRL_INIT        (1<<0)
- *#define MEM_LEVEL_CNT_BIT       18
- *#define MEM_FIFO_CNT_BIT        16
- *#define MEM_FILL_ON_LEVEL       (1<<10)
- *#define MEM_CTRL_EMPTY_EN       (1<<2)
- *#define MEM_CTRL_FILL_EN        (1<<1)
- *#define MEM_CTRL_INIT           (1<<0)
- *
- *#else
- *#define _WRITE_ST_REG(r, val) \
- *WRITE_MPEG_REG(buf->reg_base + (r), \
- *                                             (val))
- *#define _WRITE_ST_REG_BITS(r, val, s, e)\
- * WRITE_MPEG_REG(buf->reg_base + (r), \
- *                                             (val), (s), (e))
- *#define _SET_ST_REG_MASK(r, val) SET_MPEG_REG_MASK(buf->reg_base + \
- *                                             (r), (val))
- *#define _CLR_ST_REG_MASK(r, val)  CLEAR_MPEG_REG_MASK(buf->reg_base + \
- *                                             (r), (val))
- *#define _READ_ST_REG(r) READ_MPEG_REG(buf->reg_base + (r))
- *#endif
- */
-
- /*TODO*/
-#define _WRITE_ST_REG(r, val)  do { \
-       if (buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) \
-               codec_dosbus_write((buf->reg_base+(r)), (val)); \
-       else \
-               codec_aiubus_write((buf->reg_base+(r)), (val)); \
-       } while (0)
-#define _READ_ST_REG(r) \
-       ((buf->reg_base == VLD_MEM_VIFIFO_REG_BASE) ? \
-        codec_dosbus_read(buf->reg_base+(r)) : \
-        codec_aiubus_read(buf->reg_base+(r)))
-
-#define _SET_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r) | (val))
-#define _CLR_ST_REG_MASK(r, val) _WRITE_ST_REG(r, _READ_ST_REG(r)&~(val))
-#define _READ_VDEC2_ST_REG(r) (codec_dosbus_read(\
-                       (VDEC2_VLD_MEM_VIFIFO_START_PTR+(r))))
-#define _WRITE_VDEC2_ST_REG(r, val) codec_dosbus_write(\
-               (VDEC2_VLD_MEM_VIFIFO_START_PTR+r), val)
-#define MEM_BUFCTRL_MANUAL      (1<<1)
-#define MEM_BUFCTRL_INIT        (1<<0)
-#define MEM_LEVEL_CNT_BIT       18
-#define MEM_FIFO_CNT_BIT        16
-#define MEM_FILL_ON_LEVEL       (1<<10)
-#define MEM_CTRL_EMPTY_EN       (1<<2)
-#define MEM_CTRL_FILL_EN        (1<<1)
-#define MEM_CTRL_INIT           (1<<0)
-#endif /* STREAMBUF_REG_H */
diff --git a/drivers/stream_input/parser/thread_rw.c b/drivers/stream_input/parser/thread_rw.c
deleted file mode 100644 (file)
index 4e4864f..0000000
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * drivers/amlogic/media/stream_input/parser/thread_rw.c
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * 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.
- *
- * 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/kfifo.h>
-#include <linux/workqueue.h>
-#include <linux/dma-mapping.h>
-#include <linux/dma-contiguous.h>
-#include <linux/uaccess.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/amlogic/media/codec_mm/codec_mm.h>
-
-/* #include <mach/am_regs.h> */
-#include <linux/delay.h>
-
-#include "../../stream_input/parser/streambuf.h"
-#include "../../stream_input/amports/amports_priv.h"
-#include "thread_rw.h"
-
-#define BUF_NAME "fetchbuf"
-
-#define DEFAULT_BLOCK_SIZE (64*1024)
-
-struct threadrw_buf {
-       void *vbuffer;
-       dma_addr_t dma_handle;
-       int write_off;
-       int data_size;
-       int buffer_size;
-       int from_cma;
-};
-
-#define MAX_MM_BUFFER_NUM 16
-struct threadrw_write_task {
-       struct file *file;
-       struct delayed_work write_work;
-       DECLARE_KFIFO_PTR(datafifo, void *);
-       DECLARE_KFIFO_PTR(freefifo, void *);
-       int bufs_num;
-       int max_bufs;
-       int errors;
-       spinlock_t lock;
-       struct mutex mutex;
-       struct stream_buf_s *sbuf;
-       int buffered_data_size;
-       int passed_data_len;
-       int buffer_size;
-       int def_block_size;
-       int data_offset;
-       int writework_on;
-       unsigned long codec_mm_buffer[MAX_MM_BUFFER_NUM];
-       int manual_write;
-       int failed_onmore;
-       wait_queue_head_t wq;
-       ssize_t (*write)(struct file *,
-               struct stream_buf_s *,
-               const char __user *,
-               size_t, int);
-       struct threadrw_buf buf[1];
-       /*don't add any after buf[] define */
-};
-
-static int free_task_buffers(struct threadrw_write_task *task);
-
-static struct workqueue_struct *threadrw_wq_get(void)
-{
-       static struct workqueue_struct *threadrw_wq;
-
-       if (!threadrw_wq)
-               threadrw_wq = create_singlethread_workqueue("threadrw");
-       return threadrw_wq;
-}
-
-static int threadrw_schedule_delayed_work(
-               struct threadrw_write_task *task,
-               unsigned long delay)
-{
-       bool ret;
-
-       if (threadrw_wq_get()) {
-               ret = queue_delayed_work(threadrw_wq_get(),
-                       &task->write_work, delay);
-       } else
-               ret = schedule_delayed_work(&task->write_work, delay);
-       if (!ret) {
-               cancel_delayed_work(&task->write_work);
-               if (threadrw_wq_get())
-                       ret = queue_delayed_work(threadrw_wq_get(),
-                                       &task->write_work, 0);
-               else
-                       ret = schedule_delayed_work(&task->write_work, 0);
-       }
-       return 0;
-}
-
-static ssize_t threadrw_write_onece(
-       struct threadrw_write_task *task,
-       struct file *file,
-       struct stream_buf_s *stbuf,
-       const char __user *buf, size_t count)
-{
-       struct threadrw_buf *rwbuf = NULL;
-       int ret = 0;
-       int to_write;
-
-       if (!kfifo_get(&task->freefifo, (void *)&rwbuf)) {
-               if (task->errors)
-                       return task->errors;
-               return -EAGAIN;
-       }
-
-       to_write = min_t(u32, rwbuf->buffer_size, count);
-       if (copy_from_user(rwbuf->vbuffer, buf, to_write)) {
-               kfifo_put(&task->freefifo, (const void *)buf);
-               ret = -EFAULT;
-               goto err;
-       }
-       rwbuf->data_size = to_write;
-       rwbuf->write_off = 0;
-       kfifo_put(&task->datafifo, (const void *)rwbuf);
-       threadrw_schedule_delayed_work(task, 0);
-       return to_write;
-err:
-       return ret;
-}
-
-static ssize_t threadrw_write_in(
-       struct threadrw_write_task *task,
-       struct stream_buf_s *stbuf,
-       const char __user *buf, size_t count)
-{
-       int ret = 0;
-       int off = 0;
-       /* int change to size_t for buffer overflow on OTT-5057 */
-       size_t left = count;
-       int wait_num = 0;
-       unsigned long flags;
-
-       while (left > 0) {
-               ret = threadrw_write_onece(task,
-                               task->file,
-                               stbuf, buf + off, left);
-
-               /* firstly check ret < 0, avoid the risk of -EAGAIN in ret
-                * implicit convert to size_t when compare with "size_t left".
-                */
-               if (ret < 0) {
-                       if (off > 0) {
-                               break;  /*have write ok some data. */
-                       } else if (ret == -EAGAIN) {
-                               if (!(task->file->f_flags & O_NONBLOCK) &&
-                                       (++wait_num < 10)) {
-                                       wait_event_interruptible_timeout(
-                                               task->wq,
-                                               !kfifo_is_empty(
-                                                       &task->freefifo),
-                                               HZ / 100);
-                                       continue;       /* write again. */
-                               }
-                               ret = -EAGAIN;
-                               break;
-                       }
-                       break;  /*to end */
-               } else if (ret >= left) {
-                       off = count;
-                       left = 0;
-               } else if (ret > 0) {
-                       off += ret;
-                       left -= ret;
-               }
-       }
-
-       /*end: */
-       spin_lock_irqsave(&task->lock, flags);
-       if (off > 0) {
-               task->buffered_data_size += off;
-               task->data_offset += off;
-       }
-       spin_unlock_irqrestore(&task->lock, flags);
-       if (off > 0)
-               return off;
-       else
-               return ret;
-}
-
-static int do_write_work_in(struct threadrw_write_task *task)
-{
-       struct threadrw_buf *rwbuf = NULL;
-       int ret;
-       int need_re_write = 0;
-       int write_len = 0;
-       unsigned long flags;
-
-       if (kfifo_is_empty(&task->datafifo))
-               return 0;
-       if (!kfifo_peek(&task->datafifo, (void *)&rwbuf))
-               return 0;
-       if (!task->manual_write &&
-                       rwbuf->from_cma &&
-                       !rwbuf->write_off)
-               codec_mm_dma_flush(rwbuf->vbuffer,
-                                               rwbuf->buffer_size,
-                                               DMA_TO_DEVICE);
-       if (task->manual_write) {
-               ret = task->write(task->file, task->sbuf,
-                       (const char __user *)rwbuf->vbuffer + rwbuf->write_off,
-                       rwbuf->data_size,
-                       2);     /* noblock,virtual addr */
-       } else {
-               ret = task->write(task->file, task->sbuf,
-               (const char __user *)rwbuf->dma_handle + rwbuf->write_off,
-               rwbuf->data_size,
-               3);     /* noblock,phy addr */
-       }
-       if (ret == -EAGAIN) {
-               need_re_write = 0;
-               /*do later retry. */
-       } else if (ret >= rwbuf->data_size) {
-               write_len += rwbuf->data_size;
-               if (kfifo_get(&task->datafifo, (void *)&rwbuf)) {
-                       rwbuf->data_size = 0;
-                       kfifo_put(&task->freefifo, (const void *)rwbuf);
-                       /*wakeup write thread. */
-                       wake_up_interruptible(&task->wq);
-               } else
-                       pr_err("write ok,but kfifo_get data failed.!!!\n");
-               need_re_write = 1;
-       } else if (ret > 0) {
-               rwbuf->data_size -= ret;        /* half data write */
-               rwbuf->write_off += ret;
-               write_len += ret;
-               need_re_write = 1;
-       } else {                /*ret <=0 */
-               pr_err("get errors ret=%d size=%d\n", ret,
-                       rwbuf->data_size);
-               task->errors = ret;
-       }
-       if (write_len > 0) {
-               spin_lock_irqsave(&task->lock, flags);
-               task->passed_data_len += write_len;
-               spin_unlock_irqrestore(&task->lock, flags);
-       }
-       return need_re_write;
-
-}
-
-static void do_write_work(struct work_struct *work)
-{
-       struct threadrw_write_task *task = container_of(work,
-                                       struct threadrw_write_task,
-                                       write_work.work);
-       int need_retry = 1;
-
-       task->writework_on = 1;
-       while (need_retry) {
-               mutex_lock(&task->mutex);
-               need_retry = do_write_work_in(task);
-               mutex_unlock(&task->mutex);
-       }
-       threadrw_schedule_delayed_work(task, HZ / 10);
-       task->writework_on = 0;
-}
-
-static int alloc_task_buffers_inlock(struct threadrw_write_task *task,
-               int new_bubffers,
-               int block_size)
-{
-       struct threadrw_buf *rwbuf;
-       int i;
-       int used_codec_mm = task->manual_write ? 0 : 1;
-       int new_num = new_bubffers;
-       int mm_slot = -1;
-       int start_idx = task->bufs_num;
-       int total_mm = 0;
-       unsigned long addr;
-
-       if (codec_mm_get_total_size() < 80 ||
-               codec_mm_get_free_size() < 40)
-               used_codec_mm = 0;
-       if (task->bufs_num + new_num > task->max_bufs)
-               new_num = task->max_bufs - task->bufs_num;
-       for (i = 0; i < MAX_MM_BUFFER_NUM; i++) {
-               if (task->codec_mm_buffer[i] == 0) {
-                       mm_slot = i;
-                       break;
-               }
-       }
-       if (mm_slot < 0)
-               used_codec_mm = 0;
-       if (block_size <= 0)
-               block_size = DEFAULT_BLOCK_SIZE;
-
-       if (used_codec_mm && (block_size * new_num) >= 128 * 1024) {
-               total_mm = ALIGN(block_size * new_num, (1 << 17));
-               addr =
-                               codec_mm_alloc_for_dma(BUF_NAME,
-                                       total_mm / PAGE_SIZE, 0,
-                                       CODEC_MM_FLAGS_DMA_CPU);
-               if (addr != 0) {
-                       task->codec_mm_buffer[mm_slot] = addr;
-                       task->buffer_size += total_mm;
-               } else {
-                       used_codec_mm = 0;
-               }
-       }
-       for (i = 0; i < new_num; i++) {
-               int bufidx = start_idx + i;
-
-               rwbuf = &task->buf[bufidx];
-               rwbuf->buffer_size = block_size;
-               if (used_codec_mm) {
-                       unsigned long start_addr =
-                                       task->codec_mm_buffer[mm_slot];
-                       if (i == new_num - 1)
-                               rwbuf->buffer_size = total_mm -
-                                               block_size * i;
-                       rwbuf->dma_handle = (dma_addr_t) start_addr +
-                                               block_size * i;
-                       rwbuf->vbuffer = codec_mm_phys_to_virt(
-                                               rwbuf->dma_handle);
-                       rwbuf->from_cma = 1;
-
-               } else {
-                       rwbuf->vbuffer = dma_alloc_coherent(
-                                       amports_get_dma_device(),
-                                       rwbuf->buffer_size,
-                                       &rwbuf->dma_handle, GFP_KERNEL);
-                       if (!rwbuf->vbuffer) {
-                               rwbuf->buffer_size = 0;
-                               rwbuf->dma_handle = 0;
-                               task->bufs_num = bufidx;
-                               break;
-                       }
-                       rwbuf->from_cma = 0;
-                       task->buffer_size += rwbuf->buffer_size;
-               }
-
-               kfifo_put(&task->freefifo, (const void *)rwbuf);
-               task->bufs_num = bufidx + 1;
-       }
-       if (start_idx > 0 ||/*have buffers before*/
-               task->bufs_num >= 3 ||
-               task->bufs_num == new_num) {
-               if (!task->def_block_size)
-                       task->def_block_size = task->buf[0].buffer_size;
-               return 0;       /*must >=3 for swap buffers. */
-       }
-       if (task->bufs_num > 0)
-               free_task_buffers(task);
-       return -1;
-}
-
-static int free_task_buffers(struct threadrw_write_task *task)
-{
-       int i;
-
-       for (i = 0; i < MAX_MM_BUFFER_NUM; i++) {
-               if (task->codec_mm_buffer[i])
-                       codec_mm_free_for_dma(BUF_NAME,
-                               task->codec_mm_buffer[i]);
-       }
-       for (i = 0; i < task->bufs_num; i++) {
-               if (task->buf[i].vbuffer && task->buf[i].from_cma == 0)
-                       dma_free_coherent(amports_get_dma_device(),
-                               task->buf[i].buffer_size,
-                               task->buf[i].vbuffer,
-                               task->buf[i].dma_handle);
-       }
-       return 0;
-}
-
-static struct threadrw_write_task *threadrw_alloc_in(int num,
-               int block_size,
-               ssize_t (*write)(struct file *,
-                       struct stream_buf_s *,
-                       const char __user *, size_t, int),
-                       int flags)
-{
-       int max_bufs = num;
-       int task_buffer_size;
-       struct threadrw_write_task *task;
-       int ret;
-
-       if (!(flags & 1)) /*not audio*/
-               max_bufs = 300; /*can great for video bufs.*/
-       task_buffer_size = sizeof(struct threadrw_write_task) +
-                               sizeof(struct threadrw_buf) * max_bufs;
-       task = vmalloc(task_buffer_size);
-
-       if (!task)
-               return NULL;
-       memset(task, 0, task_buffer_size);
-
-       spin_lock_init(&task->lock);
-       mutex_init(&task->mutex);
-       INIT_DELAYED_WORK(&task->write_work, do_write_work);
-       init_waitqueue_head(&task->wq);
-       ret = kfifo_alloc(&task->datafifo, max_bufs, GFP_KERNEL);
-       if (ret)
-               goto err1;
-       ret = kfifo_alloc(&task->freefifo, max_bufs, GFP_KERNEL);
-       if (ret)
-               goto err2;
-       task->write = write;
-       task->file = NULL;
-       task->buffer_size = 0;
-       task->manual_write = flags & 1;
-       task->max_bufs = max_bufs;
-       mutex_lock(&task->mutex);
-       ret = alloc_task_buffers_inlock(task, num, block_size);
-       mutex_unlock(&task->mutex);
-       if (ret < 0)
-               goto err3;
-       threadrw_wq_get();      /*start thread. */
-       return task;
-
-err3:
-       kfifo_free(&task->freefifo);
-err2:
-       kfifo_free(&task->datafifo);
-err1:
-       vfree(task);
-       pr_err("alloc threadrw failed num:%d,block:%d\n", num, block_size);
-       return NULL;
-}
-
-/*
- *fifo data size;
- */
-
-void threadrw_update_buffer_level(struct stream_buf_s *stbuf,
-       int parsed_size)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-       unsigned long flags;
-
-       if (task)
-       {
-               spin_lock_irqsave(&task->lock, flags);
-               task->buffered_data_size -= parsed_size;
-               spin_unlock_irqrestore(&task->lock, flags);
-       }
-
-}
-EXPORT_SYMBOL(threadrw_update_buffer_level);
-
-int threadrw_buffer_level(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task)
-               return task->buffered_data_size;
-       return 0;
-}
-
-int threadrw_buffer_size(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task)
-               return task->buffer_size;
-       return 0;
-}
-
-int threadrw_datafifo_len(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task)
-               return kfifo_len(&task->datafifo);
-       return 0;
-}
-
-int threadrw_freefifo_len(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task)
-               return kfifo_len(&task->freefifo);
-       return 0;
-}
-int threadrw_support_more_buffers(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (!task)
-               return 0;
-       if (task->failed_onmore)
-               return 0;
-       return task->max_bufs - task->bufs_num;
-}
-
-/*
- *data len out fifo;
- */
-int threadrw_passed_len(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task)
-               return task->passed_data_len;
-       return 0;
-
-}
-/*
- *all data writed.;
- */
-int threadrw_dataoffset(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-       int offset = 0;
-
-       if (task)
-               return task->data_offset;
-       return offset;
-
-}
-
-ssize_t threadrw_write(struct file *file, struct stream_buf_s *stbuf,
-                                          const char __user *buf, size_t count)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-       ssize_t size;
-
-       if (!task->file) {
-               task->file = file;
-               task->sbuf = stbuf;
-       }
-       mutex_lock(&task->mutex);
-       size = threadrw_write_in(task, stbuf, buf, count);
-       mutex_unlock(&task->mutex);
-       return size;
-}
-
-int threadrw_flush_buffers(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-       int max_retry = 20;
-
-       if (!task)
-               return 0;
-       while (!kfifo_is_empty(&task->datafifo) && max_retry-- > 0) {
-               threadrw_schedule_delayed_work(task, 0);
-               msleep(20);
-       }
-       if (!kfifo_is_empty(&task->datafifo))
-               return -1;/*data not flushed*/
-       return 0;
-}
-int threadrw_alloc_more_buffer_size(
-       struct stream_buf_s *stbuf,
-       int size)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-       int block_size;
-       int new_num;
-       int ret = -1;
-       int old_num;
-
-       if (!task)
-               return -1;
-       mutex_lock(&task->mutex);
-       block_size = task->def_block_size;
-       if (block_size == 0)
-               block_size = 32 * 1024;
-       new_num = size / block_size;
-       old_num = task->bufs_num;
-       if (new_num == 0)
-               new_num = 1;
-       else if (new_num > task->max_bufs - task->bufs_num)
-               new_num = task->max_bufs - task->bufs_num;
-       if (new_num != 0)
-               ret = alloc_task_buffers_inlock(task, new_num,
-                       block_size);
-       mutex_unlock(&task->mutex);
-       pr_info("threadrw add more buffer from %d -> %d for size %d\n",
-               old_num, task->bufs_num,
-               size);
-       if (ret < 0 || old_num == task->bufs_num)
-               task->failed_onmore = 1;
-       return ret;
-}
-
-void *threadrw_alloc(int num,
-               int block_size,
-                       ssize_t (*write)(struct file *,
-                               struct stream_buf_s *,
-                               const char __user *,
-                               size_t, int),
-                               int flags)
-{
-       return threadrw_alloc_in(num, block_size, write, flags);
-}
-
-void threadrw_release(struct stream_buf_s *stbuf)
-{
-       struct threadrw_write_task *task = stbuf->write_thread;
-
-       if (task) {
-               wake_up_interruptible(&task->wq);
-               cancel_delayed_work_sync(&task->write_work);
-               mutex_lock(&task->mutex);
-               free_task_buffers(task);
-               mutex_unlock(&task->mutex);
-               kfifo_free(&task->freefifo);
-               kfifo_free(&task->datafifo);
-               vfree(task);
-       }
-       stbuf->write_thread = NULL;
-}
diff --git a/drivers/stream_input/parser/thread_rw.h b/drivers/stream_input/parser/thread_rw.h
deleted file mode 100644 (file)
index a91b004..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * drivers/amlogic/media/stream_input/parser/thread_rw.h
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * 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.
- *
- * 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.
- *
- */
-
-#ifndef THREAD_RW_H
-#define THREAD_RW_H
-#include "../../stream_input/parser/streambuf_reg.h"
-#include "../../stream_input/parser/streambuf.h"
-#include "../../stream_input/parser/esparser.h"
-#include "../../stream_input/amports/amports_priv.h"
-
-ssize_t threadrw_write(struct file *file,
-               struct stream_buf_s *stbuf,
-               const char __user *buf,
-               size_t count);
-
-void *threadrw_alloc(int num,
-               int block_size,
-                       ssize_t (*write)(struct file *,
-                               struct stream_buf_s *,
-                               const char __user *,
-                               size_t, int),
-                               int flags);/*flags &1: manual mode*/
-
-void threadrw_release(struct stream_buf_s *stbuf);
-
-int threadrw_buffer_level(struct stream_buf_s *stbuf);
-int threadrw_buffer_size(struct stream_buf_s *stbuf);
-int threadrw_datafifo_len(struct stream_buf_s *stbuf);
-int threadrw_freefifo_len(struct stream_buf_s *stbuf);
-int threadrw_passed_len(struct stream_buf_s *stbuf);
-int threadrw_flush_buffers(struct stream_buf_s *stbuf);
-int threadrw_dataoffset(struct stream_buf_s *stbuf);
-int threadrw_alloc_more_buffer_size(
-       struct stream_buf_s *stbuf,
-       int size);
-int threadrw_support_more_buffers(struct stream_buf_s *stbuf);
-void threadrw_update_buffer_level(struct stream_buf_s *stbuf,
-       int parsed_size);
-#endif
index 7aa8a06c34eca319f23489d0607f72c4ade12d2b..9ba65b53569084d0dbac6e343816a0ca894e1a1a 100644 (file)
 
 #include "../../frame_provider/decoder/utils/vdec.h"
 #include <linux/amlogic/media/utils/vdec_reg.h>
-#include "streambuf_reg.h"
-#include "streambuf.h"
+#include "../amports/streambuf_reg.h"
+#include "../amports/streambuf.h"
 #include <linux/amlogic/media/utils/amports_config.h>
+#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
 
 #include "tsdemux.h"
 #include <linux/reset.h>
@@ -385,6 +386,7 @@ static int reset_pcr_regs(void)
 {
        u32 pcr_num;
        u32 pcr_regs = 0;
+
        if (curr_pcr_id >= 0x1FFF)
                return 0;
        /* set paramater to fetch pcr */
@@ -1201,4 +1203,53 @@ void tsdemux_tsync_func_init(void)
                TSYNC_STBUF_SIZE, (void *)(stbuf_size));
 }
 
+static int tsparser_stbuf_init(struct stream_buf_s *stbuf,
+                              struct vdec_s *vdec)
+{
+       int ret = -1;
+
+       ret = stbuf_init(stbuf, vdec);
+       if (ret)
+               goto out;
+
+       ret = tsdemux_init(stbuf->pars.vid,
+                          stbuf->pars.aid,
+                          stbuf->pars.sid,
+                          stbuf->pars.pcrid,
+                          stbuf->is_hevc,
+                          vdec);
+       if (ret)
+               goto out;
+
+       tsync_pcr_start();
+
+       stbuf->flag |= BUF_FLAG_IN_USE;
+out:
+       return ret;
+}
+
+static void tsparser_stbuf_release(struct stream_buf_s *stbuf)
+{
+       tsync_pcr_stop();
+
+       tsdemux_release();
+
+       stbuf_release(stbuf);
+}
+
+static struct stream_buf_ops tsparser_stbuf_ops = {
+       .init   = tsparser_stbuf_init,
+       .release = tsparser_stbuf_release,
+       .get_wp = parser_get_wp,
+       .set_wp = parser_set_wp,
+       .get_rp = parser_get_rp,
+       .set_rp = parser_set_rp,
+};
+
+struct stream_buf_ops *get_tsparser_stbuf_ops(void)
+{
+       return &tsparser_stbuf_ops;
+}
+EXPORT_SYMBOL(get_tsparser_stbuf_ops);
+