#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"
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)
case 3:
adec_release(port->vformat);
case 2:
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
case 1:
;
}
return 0;
}
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
struct vdec_s *vdec = ada_ctx->vdec;
struct vdec_s *slave = NULL;
- bool is_multidec = !vdec_single(vdec);
switch (release_num) {
default:
case 2: {
if ((port->type & PORT_TYPE_FRAME) == 0)
- stbuf_release(pbuf, is_multidec);
+ stbuf_release(pbuf);
}
case 1:
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);
}
}
- 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);
}
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);
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)
#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 {
#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')
#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"
/* #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"
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) {
&& 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
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) {
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)
#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"
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) {
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));
}
}
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) {
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);
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)
#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>
#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"
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),
&& 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
}
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) {
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) &&
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);
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
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);
&& 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
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) {
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) {
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) &&
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)
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
) {
"%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));
&& 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
"%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;
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
) {
&& 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
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) {
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);
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)
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;
&& 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
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) {
#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"
#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
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 {
(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
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);
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));
}
}
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));
}
}
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);
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");*/
}
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);
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 */
}
}
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));
}
}
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);
}
}
}
*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;
+ }
}
}
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; */
#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,
/* 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"))) {
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);
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
}
#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)
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);
#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"
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;
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 */
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)
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)
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
#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"
#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);
#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>
/* #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"
#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>
#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
(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);
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;
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;
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;
vdec_release(slave);
priv->vdec = NULL;
/*fallthrough*/
- case 2:
- if ((port->type & PORT_TYPE_FRAME) == 0)
- stbuf_release(pbuf, is_multidec);
- /*fallthrough*/
case 1:
;
}
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) {
if (r < 0) {
pr_err("video_port_init %d, vdec_init failed\n",
__LINE__);
- video_port_release(priv, pbuf, 2);
return r;
}
(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;
}
}
}
}
- 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 *
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)) {
(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,
adec_release(port->vformat);
/*fallthrough*/
case 2:
- stbuf_release(pbuf, false);
+ stbuf_release(pbuf);
/*fallthrough*/
case 1:
;
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;
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;
return 0;
}
- r = stbuf_init(pbuf, NULL, false);
+ r = stbuf_init(pbuf, NULL);
if (r < 0)
return r;
r = adec_init(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) {
}
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(
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:
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();
}
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);
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);
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)
}
}
- 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 */
#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
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);
}
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],
* 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;
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;
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) {
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;
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
struct am_io_param *p = ¶
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) {
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;
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;
*/
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;
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);
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)
{
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 */
}
}
+ pbuf += show_stream_buffer_status(pbuf, show_vbuf_status_cb);
+
return pbuf - buf;
}
{
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;
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();
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>");
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/*
+ * 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 */
+
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
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)
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);
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))
fetch_done = 0;
- wmb(); /* Ensure fetchbuf contents visible */
+ wmb(); /* Ensure fetchbuff contents visible */
if (isphybuf) {
u32 buf_32 = (unsigned long)buf & 0xffffffff;
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);
#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>
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;
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);
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 {
}
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);
} 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;
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)
{
/* 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 {
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__);
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) ?
(buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
/*manul mode for audio*/
}
+
return 0;
Err_2:
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
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);
+
#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"
#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"
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);
+
#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"
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
#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>
{
u32 pcr_num;
u32 pcr_regs = 0;
+
if (curr_pcr_id >= 0x1FFF)
return 0;
/* set paramater to fetch pcr */
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);
+